Export (CSV / JSON)
Export gives you a whole dataset — or the slice you filtered to — as one file: every licence, every operator, or every domain ↔ operator link we hold. The rows are the same records the rest of the API serves, and each one carries its own provenance, so a spreadsheet you hand to an auditor still says where every status came from and when we read it.
Export is part of Pro (and Business and Enterprise). On Starter the Export button and the endpoint are there, but they answer with what Pro includes, never with data — not even a sample. Pro isn’t open yet: email founder@igregulator.io to get access or to hear when it opens.
From the dashboard
Section titled “From the dashboard”Signed in, both Explore views carry an export: csv · json control beside the sort:
- Operators / Licenses (
app.igregulator.io/) exports the licences the current filters match — search, jurisdiction, status, category, licence type, enforcement flags — every page of them, in the table’s sort. - Domains (
app.igregulator.io/domains) exports the domain links of the domains the current filters match. A domain is exported with every link it has, as its table row shows it, so a brand licensed by two entities never comes out half-way.
The file has the same columns as the API export below.
From the API
Section titled “From the API”curl -s -OJ "https://api.igregulator.io/v1/export/licences?format=csv&jurisdiction=UKGC,MGA" \ -H "Authorization: Bearer $IGREGULATOR_KEY"# → igregulator-licences-2026-09-30.csvGET /v1/export/{dataset} — a key is required (no anonymous exports).
| Dataset | One row per | Joins on |
|---|---|---|
licences | licence (licenses is accepted too) | operator_slug |
operators | legal entity | operator_slug |
domains | domain ↔ operator link | operator_slug, license_id |
| Parameter | Values |
|---|---|
format | csv (default) or json — NDJSON, one object per line (ndjson works too). |
jurisdiction | Comma-separated codes (UKGC,MGA), case-insensitive; repeating the parameter works too. licences: the licence’s jurisdiction. operators: holds a licence there. domains: the jurisdiction of the licence the link’s status comes from. An unknown code is a 400. |
status | Comma-separated licence statuses (active, suspended, revoked, expired, pending, unknown, surrendered, not_in_register). operators: holds a licence with that status (in the jurisdiction given, when both are). domains: the status of the licence the link answers to. |
Any other parameter is a 400 rather than being silently ignored — a filter we
dropped would hand you more rows than you asked for. as_of is not supported
(400, details.reason: "as_of_not_supported"): an export is the current state.
For a status on a past date, use ?as_of= on /v1/licenses/{id},
/v1/operators/{slug} or /v1/check (point-in-time).
Response headers
Section titled “Response headers”| Header | Meaning |
|---|---|
Content-Disposition | attachment; filename="igregulator-<dataset>-<YYYY-MM-DD>.<csv|ndjson>" |
X-Dataset-Generated-At | When the rows were read (ISO-8601 UTC). |
X-Export-Row-Count | Rows in the file (the CSV header / NDJSON _meta line not counted). |
X-Export-Daily-Limit / -Used / -Remaining / -Reset | Your export allowance today — see limits. |
The body is streamed. The row count and the rows come from one database
statement, so they describe the same moment; if the lines you received are fewer
than X-Export-Row-Count, the download was cut off — fetch it again.
Formats
Section titled “Formats”CSV — RFC 4180: UTF-8 without a byte-order mark, CRLF line ends, a header
row, a field quoted when it contains a comma, quote or line break. A list
(license_types, jurisdictions) is |-joined; an object (upstream_ids) is
its JSON text; null is an empty cell. A text value that starts with =, +,
- or @ gets a leading ' so a spreadsheet shows it instead of running it as
a formula — a UKGC trading name really is @gamingfun. In Excel, open the file
with Data → From Text/CSV so accented names come through as UTF-8.
JSON (format=json) — NDJSON. Line 1 is a metadata object; every other line
is one row, keys in the column order below, values untouched (lists as arrays,
nulls as null, no formula guard):
{"_meta":{"dataset":"licences","generated_at":"2026-09-30T18:00:00.000Z","row_count":6664,"filters":{"jurisdiction":null,"status":null},"source":"api","format":"ndjson","columns":["license_id","license_number","…"],"as_of":null,"note":"…"}}{"license_id":"4db0141c-…","license_number":"039028-R-319297-013","license_number_kind":"regulator","jurisdiction_code":"UKGC","status":"active","status_source_url":"https://www.gamblingcommission.gov.uk/downloads/business-licence-data.zip","status_observed_at":"2026-09-30T03:10:12.000Z","…":"…"}No row has a _meta key, so skip the line that has one:
tail -n +2 igregulator-licences-2026-09-30.ndjson | jq -r 'select(.status != "active") | [.license_number, .status, .status_source_url] | @tsv'import pandas as pddf = pd.read_json("igregulator-domains-2026-09-30.ndjson", lines=True).iloc[1:]What a row says
Section titled “What a row says”Every row carries the same truth the API serves — and no more:
- A status comes with where and when we read it.
status_source_urlis the page that published THIS status (an enforcement register, a revoked-licences list, an advisory notice), which is often not the register the licence is listed in (source_url);status_observed_atis when we read it. Citestatus_source_url. - Only
activemeans licensed now.not_in_registermeans the register stopped listing the licence and published no reason —not_listed_sincesays since when andlast_listed_atwhen we last saw it. It is not a revocation, and neither aresurrenderedorunknown. How we verify says which regulator page sets which status. - Kahnawake, Tobique and the Isle of Man publish no licence number. For KH,
TGC and IOM the
license_numberis a reference we assigned (KH/IG/…,TGC/B2C/…,IOM/OGRA/…), andlicense_number_kindsays so:igregulator_reference, notregulator. Never quote it as the regulator’s number. - A domain row is a link, with the link’s own status.
domain_statusis the domain’s status under THAT operator (delisted= the regulator removed it from that licensee); the same domain can beactiveon one row anddelistedon another. The licence columns are the operator’s best licence —activefirst, then the most recently verified — the same one/v1/checkreports. upstream_statusis the register’s own word, left out where it would contradict the status, exactly as on/v1/check.
licences columns
Section titled “licences columns”| Column | Meaning |
|---|---|
license_id | Our licence id — what /v1/licenses/{id} takes. |
license_number | The licence number; for KH, TGC and IOM our reference. |
license_number_kind | regulator or igregulator_reference. |
jurisdiction_code | UKGC, MGA, CW, KH, AN, TGC, IOM. |
operator_slug, operator_name | The licensee. |
status | The licence status. |
status_qualifier | provisional_under_assessment for a Curaçao licence under the CGA’s final assessment; else empty. |
upstream_status | The register’s own word, where it doesn’t contradict status. |
status_source_url, status_observed_at | Where and when this status was read. |
last_listed_at | When we last saw the licence listed. |
not_listed_since | When the register stopped listing it; empty while listed. |
license_types, license_type_raw, license_category | Types as named, the raw string, and our cross-jurisdiction category. |
issued_date, expiry_date | Where the register publishes them. |
last_verified_at | When we last read the register for it. |
source_url | The register it is listed in. |
operators columns
Section titled “operators columns”| Column | Meaning |
|---|---|
operator_id, operator_slug, operator_name | The legal entity. |
registered_name | The name the register gives next to it (UKGC: often a trading name). |
country | ISO country code, where known. |
upstream_ids | Its id per register; for KH, TGC and IOM a key made from the name. |
jurisdictions | Where we hold a licence record for it, any status. |
active_jurisdictions | Where it holds an active licence. |
licences_total, licences_active | Licence records; those active. |
licences_last_verified_at | When we last read a register about it. |
domains_total, domains_active | Domain links; those whose own status is active (says nothing about the licence). |
created_at, updated_at | When we first recorded it; when its own record last changed. |
There is no operator-level status: an operator licensed in two jurisdictions is
never collapsed into one. The licences export has each licence.
domains columns
Section titled “domains columns”| Column | Meaning |
|---|---|
domain | As the register lists it. |
operator_slug, operator_name | The operator this link is to. |
domain_status | The link’s own status: active, delisted, … |
domain_association | direct (the licensee runs it) or white_label. |
verification_url | The regulator’s own page for this domain (Curaçao certificate, Tobique seal), where one exists. |
standing | licensed (link and licence both active), licence_not_active, delisted, or other — derived from domain_status and license_status on the same row. |
link_first_seen, link_last_verified | When we first saw the link; when a source last confirmed it. |
license_id, jurisdiction_code, license_number, license_number_kind | The licence the link’s status comes from. |
license_status, status_qualifier, upstream_status | That licence’s status, as in licences. |
status_source_url, status_observed_at | Where and when that status was read. |
license_last_verified_at | When we last read that licence’s register. |
Limits
Section titled “Limits”| Plan | Exports per UTC day |
|---|---|
| Starter, legacy trial | None — 402 |
| Pro | 10 |
| Business | 100 |
| Enterprise | Unlimited |
- The allowance is per account, and the dashboard and the API share it.
- An API export counts as one request against your monthly quota, whatever its size. A dashboard export doesn’t touch the API quota.
- A refused request (
400,402,429) uses neither. An export whose query failed before the first byte is given back. - Today’s counter resets at 00:00 UTC.
Errors
Section titled “Errors”Below Pro — 402, with X-Upgrade-URL:
{ "error": "CSV/JSON export is a Pro feature", "code": "payment_required", "details": { "reason": "export_requires_pro", "plan_tier": "starter", "required_plan": "pro", "suggestion": "CSV/JSON export is part of Pro. Pro isn't open yet — email founder@igregulator.io to get access or to hear when it opens." }}Over today’s allowance — 429, with Retry-After (seconds to 00:00 UTC):
{ "error": "Daily export limit reached", "code": "rate_limited", "details": { "reason": "export_daily_limit_reached", "current_usage": 10, "limit": 10, "reset_at": "2026-10-01T00:00:00.000Z", "plan_tier": "pro", "suggestion": "…" }}400 invalid_query for a bad format, jurisdiction, status or an unknown
parameter (details.field names it), 400 as_of_not_supported, and 404
dataset_not_found for a dataset other than the three. The full list is on
error handling.
Not included
Section titled “Not included”as_of— exports are the current state (see above).- Licence history — use
/v1/licenses/{id}/history, or/v1/operators/{slug}/licenses?include_history=true. - Regulatory actions —
/v1/operators/{slug}/regulatory-actions. - MCP — there is no export tool on the MCP server; a file download isn’t a tool call. Use the API.