Paging a large result

The series and location-quotient endpoints and the list taxonomies page by an opaque cursor and a limit. Without either, a data request is answered whole.

Which endpoints page

/v2/industry/series, /v2/industry/lq, /v2/occupation/series and /v2/occupation/lq page, and so do the taxonomy lists such as /v2/taxonomies/naics. The map endpoints do not take cursor or limit: a map is one value per area, and sending either is a 400 unknown_parameter:

Request

curl "https://api.datatactical.group/v2/industry/map?naics=621&areas=state:22&year=2024&limit=2" \
  -H "Authorization: Bearer $DTG_API_KEY"

Response · replayed 2026-10-05 against vintage 20260913.

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json; charset=utf-8
​
{
  "type": "https://api.datatactical.group/problems/unknown_parameter",
  "title": "Bad Request",
  "status": 400,
  "detail": "Unknown parameter(s): limit. Allowed: naics, measure, year, qtr, ownership, areas, sum, combine, strict, vintage.",
  "code": "unknown_parameter",
  "parameters": [
    "limit"
  ]
}

How a page is made

A data request with neither cursor nor limit is answered whole, in one response. Give either and the response is one page: at most limit series, from 1 to 5,000, in the order the response would have emitted them. With only cursor, limit is 1,000. A page is a slice of the series, never of the periods inside a series: every series on a page is complete.

The taxonomy lists always page, 1,000 entries at a time unless limit says otherwise.

Reading the next page

meta.pagination says where you are. count is the number of series (or taxonomy entries) on this page, cursor echoes the cursor you sent, and next_cursor is the cursor for the next page, or null on the last page and on an unpaged request. To read the next page, send the same request again with cursor set to next_cursor, and stop when next_cursor is null. A first page of two sectors:

Request

curl "https://api.datatactical.group/v2/industry/series?areas=22&naics_level=3&from=2024&to=2025&measures=emp&limit=2" \
  -H "Authorization: Bearer $DTG_API_KEY"

Response · replayed 2026-10-05 against vintage 20260913. Trimmed: data.points to 1 in each of 2 (of up to 2).

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
​
{
  "data": [
    {
      "naics": "11",
      "area": "22",
      "ownership": "all",
      "points": [
        { "period": "2024", "emp": 7864.75, "disclosure": 1,
            "reliability": 1, "naics_restated": false,
            "fips_restated": false, "quarters_present": 4 }
      ]
    },
    {
      "naics": "21",
      "area": "22",
      "ownership": "all",
      "points": [
        { "period": "2024", "emp": 27514.75, "disclosure": 0,
            "reliability": 1, "naics_restated": false,
            "fips_restated": false, "quarters_present": 4 }
      ]
    }
  ],
  "meta": {
    "vintage": "20260913",
    "generated_at": "2026-10-05T04:26:55Z",
    "granularity": "annual",
    "provenance_boundaries": {
      "actuals": { "from": "2004q1", "to": "2026q1" },
      "ces": { "from": "2026q2", "to": "2026q3" },
      "projections": { "from": "2026q4", "to": "2036q4" }
    },
    "geography": { "requested": 1, "returned": 1, "excluded": 0 },
    "pagination": { "cursor": null, "next_cursor": "eyJvIjoyfQ", "count": 2 }
  }
}

and the page after it, sent with that next_cursor:

Request

curl "https://api.datatactical.group/v2/industry/series?areas=22&naics_level=3&from=2024&to=2025&measures=emp&limit=2&cursor=eyJvIjoyfQ" \
  -H "Authorization: Bearer $DTG_API_KEY"

Response · replayed 2026-10-05 against vintage 20260913. Trimmed: data.points to 1 in each of 2 (of up to 2).

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
​
{
  "data": [
    {
      "naics": "23",
      "area": "22",
      "ownership": "all",
      "points": [
        { "period": "2024", "emp": 149172.9, "disclosure": 1,
            "reliability": 1, "naics_restated": false,
            "fips_restated": false, "quarters_present": 4 }
      ]
    },
    {
      "naics": "31",
      "area": "22",
      "ownership": "all",
      "points": [
        { "period": "2024", "emp": 140604.68, "disclosure": 0,
            "reliability": 1, "naics_restated": false,
            "fips_restated": false, "quarters_present": 4 }
      ]
    }
  ],
  "meta": {
    "vintage": "20260913",
    "generated_at": "2026-10-05T04:26:55Z",
    "granularity": "annual",
    "provenance_boundaries": {
      "actuals": { "from": "2004q1", "to": "2026q1" },
      "ces": { "from": "2026q2", "to": "2026q3" },
      "projections": { "from": "2026q4", "to": "2036q4" }
    },
    "geography": { "requested": 1, "returned": 1, "excluded": 0 },
    "pagination": { "cursor": "eyJvIjoyfQ", "next_cursor": "eyJvIjo0fQ", "count": 2 }
  }
}

A cursor is opaque and is valid only with the query it came from: change any other parameter and start again without one. A cursor that is malformed or past the end of the result is a 400.

Paging and the cell ceiling

The per-request ceiling of 400,000 cells, a cell being one series at one period, measures the page, not the whole result. A request refused with cell_cap will pass when paged with a limit small enough that the series on one page times the periods fit under the ceiling. The rate limits page has the arithmetic, and every page counts as one request against the per-minute ceilings and is metered in points like any other response.