> ## Documentation index
> Fetch the complete documentation index at: https://docs.prescientai.com/llms.txt
> Use this file to discover all available pages before exploring further. Add `.md` to any page URL to get that page as Markdown.

# Pull modeled metrics for a date range

> Steps and code that copy each modeled metric row of a date range from the Prescient GraphQL API, one page at a time.

To copy the modeled metrics of a date range, send the [`modeledMetrics`](https://docs.prescientai.com/api/queries/modeled-metrics) query, then send it again with the cursor of each response until no page is left. One response has 5,000 rows at most.

## How do you pull the rows?

1. Choose the date range. `startDate` and `endDate` use the `YYYY-MM-DD` format, and both dates are in the range. If you leave them out, the range is the last 30 days.

2. Choose the fields that you need. Select `pageInfo` in each request, because it has the cursor.

   ```graphql title="Query"
   query ModeledMetrics(
     $startDate: ISO8601Date
     $endDate: ISO8601Date
     $after: BigInt
   ) {
     modeledMetrics(startDate: $startDate, endDate: $endDate, after: $after) {
       data {
         reportedDate
         sourceChannelName
         sourceCampaignId
         target
         metricName
         metricValue
       }
       pageInfo {
         endCursor
         hasNextPage
       }
     }
   }
   ```

3. Send the first request with no `after` value.

4. If `pageInfo.hasNextPage` is `true`, send the same query with `after` set to `pageInfo.endCursor`. Keep each other variable the same.

5. Stop when `hasNextPage` is `false`.

## What does the full loop look like?

Save the query of step 2 as a string, then run the loop. In each example, the key comes from the `PRESCIENT_API_KEY` environment variable.

**JavaScript**

```js
const QUERY = `
  query ModeledMetrics($startDate: ISO8601Date, $endDate: ISO8601Date, $after: BigInt) {
    modeledMetrics(startDate: $startDate, endDate: $endDate, after: $after) {
      data { reportedDate sourceChannelName sourceCampaignId target metricName metricValue }
      pageInfo { endCursor hasNextPage }
    }
  }`;

async function pullModeledMetrics(startDate, endDate) {
  const rows = [];
  let after = null;
  do {
    const response = await fetch('https://api.prescient-ai.io/graphql', {
      method: 'POST',
      headers: {
        Authorization: `apikey ${process.env.PRESCIENT_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query: QUERY, variables: { startDate, endDate, after } }),
    });
    const { data, errors } = await response.json();
    if (errors) throw new Error(errors[0].message);

    const page = data.modeledMetrics;
    rows.push(...page.data);
    after = page.pageInfo.hasNextPage ? page.pageInfo.endCursor : null;
  } while (after !== null);
  return rows;
}

const rows = await pullModeledMetrics('2026-01-01', '2026-01-31');
```

**Python**

```python
import os
import requests

QUERY = """
query ModeledMetrics($startDate: ISO8601Date, $endDate: ISO8601Date, $after: BigInt) {
  modeledMetrics(startDate: $startDate, endDate: $endDate, after: $after) {
    data { reportedDate sourceChannelName sourceCampaignId target metricName metricValue }
    pageInfo { endCursor hasNextPage }
  }
}
"""


def pull_modeled_metrics(start_date, end_date):
    rows = []
    after = None
    while True:
        response = requests.post(
            "https://api.prescient-ai.io/graphql",
            headers={"Authorization": f"apikey {os.environ['PRESCIENT_API_KEY']}"},
            json={
                "query": QUERY,
                "variables": {"startDate": start_date, "endDate": end_date, "after": after},
            },
        )
        body = response.json()
        if body.get("errors"):
            raise RuntimeError(body["errors"][0]["message"])

        page = body["data"]["modeledMetrics"]
        rows.extend(page["data"])
        if not page["pageInfo"]["hasNextPage"]:
            return rows
        after = page["pageInfo"]["endCursor"]


rows = pull_modeled_metrics("2026-01-01", "2026-01-31")
```

## How do you narrow the result?

Each filter is an argument of the query. You can use more than one filter in a request.

- To get the rows of some campaigns, set `campaignIds` to a list of campaign IDs. The IDs are the IDs of your campaigns in their source channels.
- To get one sales channel, set `salesChannel` to `[ECOMMERCE]` or `[RETAIL]`. If you leave it out, the query returns both.
- To get only the rows that changed, set `processDate`. See [Sync only the rows that changed](https://docs.prescientai.com/api/sync-only-changed-rows).

## How do you read a row?

- `target` is the name of the model that produced the row. The [`models`](https://docs.prescientai.com/api/queries/models) query gives the unit of each model.
- `metricName` tells you what `metricValue` measures. See [`MetricName`](https://docs.prescientai.com/api/types#metricname).
- `targetChannelName` can be `null`. The schema says that the field applies only to second order metrics.
- `sourceCampaignName` and `sourceCampaignTactic` can be `null`. The tactic is the label that the campaign has in the Data Center. See [Label campaigns with tactics](https://docs.prescientai.com/data-center/label-campaigns-with-tactics).
