Every data endpoint answers as CSV
Send Accept: text/csv, or add .csv to the path, to any series, map or location-quotient endpoint. One row per series and period, the labels on every industry row, and a preamble that names the vintage.
Requesting CSV
Either an Accept: text/csv header or a .csv suffix on the resource path; the suffix wins if both are present. The response is text/csv in UTF-8 with a Content-Disposition file name naming the domain, the endpoint, the vintage and the time it was made, streamed as it is produced. The same entitlements, points metering and per-request ceiling apply as on the JSON path, and errors are the same problem documents. A failure after the file has started cannot become an error response: the file ends early, so a file that stops mid-row is incomplete and should be requested again.
Request
curl "https://api.datatactical.group/v2/industry/series.csv?areas=22&naics=621&from=2024&to=2025" \
-H "Authorization: Bearer $DTG_API_KEY"Response · replayed 2026-10-05 against vintage 20260913.
HTTP/1.1 200 OK
Content-Type: text/csv; charset=utf-8; header=present
Content-Disposition: attachment; filename="industry-series-20260913-20261005T042655Z.csv"
# taigan-csv: 1
# endpoint: /v2/industry/series
# vintage: 20260913
# vintage_label: DTG 2026.3
# source: Data Tactical Group, DTG 2026.3
# generated_at: 2026-10-05T04:26:55Z
# granularity: annual
# provenance_boundaries: actuals=2004q1..2026q1 ces=2026q2..2026q3 projections=2026q4..2036q4
# geography: requested=1 returned=1 excluded=0
# count: 1
# disclosure: 0 published by BLS in QCEW; 1 estimated by DTG where QCEW withheld the value; 2 carried forward past the latest QCEW release; 3 projected. A summed value carries the highest code among the values summed.
# reliability: 0 to 1: how tightly the published QCEW record constrains the value (published values are 1). Empty where the value is carried forward or projected, or there is no employment: no score is computed for those. Not a ranking of areas and not a margin of error.
# encoding: UTF-8 (import the file as UTF-8; a spreadsheet that guesses another encoding misreads accented names)
naics,area,ownership,period,emp,estabs,earnings,avg_pay,disclosure,reliability,naics_restated,fips_restated,quarters_present
621,22,all,2024,117235.33,11094.5,7634923163.23,65124.76,0,1,false,false,4
621,22,all,2025,118518.71,11449,7980832503.2,67338.17,0,1,false,false,4The same routes also answer as a spreadsheet workbook, with an .xlsx suffix; the parameters that shape a workbook are listed on each endpoint’s reference page and are refused on a CSV request.
What the file contains
Long format: one row per series and period. On a series, the key columns come first (naics or soc, area, ownership), then period, then the point’s columns in the same order and with exactly the same names as the JSON fields, so a field’s definition in the reference applies to both. A map file has one row per area. Every industry row carries disclosure and reliability; series rows also carry the two restatement flags, and location-quotient rows lq_disclosure. Occupation rows carry no labels. Values are written as the API stores them: an employment estimate below one is written as 0.27, not rounded to 0 as the app displays it; booleans as true and false; null as an empty field.
Before the header, comment lines beginning # carry the record of where the file came from: the format version, the endpoint, the vintage id and its public label, the source line naming Data Tactical Group and the vintage, the generation time, the granularity, the provenance boundaries, the geography counts, the number of series (count), and on industry files a key to the disclosure codes and the reliability score. Most readers skip comment lines with a single option; a spreadsheet import shows them as rows to delete. A file that drops those lines has lost the record of which vintage it came from, and the source line is the attribution to keep when the data is reused.