# Code examples

URL: https://igregulator.io/docs/code-examples/
Markdown: https://igregulator.io/docs/code-examples.md

> Copy-paste curl, JavaScript and Python snippets for common iGregulator tasks: verify a domain, batch-check a list, look up an operator, handle rate limits.

Copy-paste snippets for the two things every integration does first —
check a domain, then walk an authenticated list. No SDKs yet; the API
is small enough that 15 lines of `fetch` / `requests` does the job.

## Domain check — curl

```bash
curl -sG https://api.igregulator.io/v1/check \
  --data-urlencode 'domain=paddypower.com' | jq
```

## Domain check — JavaScript (fetch)

```js
const res = await fetch(
  'https://api.igregulator.io/v1/check?domain=paddypower.com'
);
const { verdict, verdict_detail, match } = await res.json();

// Branch on `verdict`, quote `verdict_detail`. Only two values mean licensed now.
switch (verdict) {
  case 'licensed':
    console.log(`Licensed: ${verdict_detail}`);
    break;
  case 'licensed_provisional':
    // In force, provisionally (a Curaçao licence under the CGA's final assessment):
    // accept it if your policy does, say so, and check again later.
    console.log(`Licensed, provisionally — recheck: ${verdict_detail}`);
    break;
  default:
    // licence_not_active, domain_not_listed, related_host_listed, name_match_only,
    // not_found, generic_term — and any value added later. Not confirmed as
    // licensed by the registers we cover. That is NOT "unlicensed": send it to a
    // person, with the sentence.
    console.log(`Not confirmed (${verdict}): ${verdict_detail}`);
}

// The fields behind the verdict, for a citation: the regulator and the page that
// published the licence status. (KH, TGC and IOM publish no licence number: when
// match.license_reference_is_ours is true, license_number is our reference.)
if (match?.status_source_url) {
  console.log(`Source: ${match.regulator_name} — ${match.status_source_url}`);
}
```

## Domain check — Python (requests)

```python
import requests

r = requests.get(
    'https://api.igregulator.io/v1/check',
    params={'domain': 'paddypower.com'},
    timeout=5,
)
r.raise_for_status()
data = r.json()

verdict, detail = data['verdict'], data['verdict_detail']
if verdict == 'licensed':
    print(f'Licensed: {detail}')
elif verdict == 'licensed_provisional':
    # In force, provisionally: accept per your policy, say so, and recheck later.
    print(f'Licensed, provisionally — recheck: {detail}')
else:
    # Every other value (and any added later): not confirmed as licensed by the
    # registers we cover. Not "unlicensed" — review it, quoting the sentence.
    print(f'Not confirmed ({verdict}): {detail}')

match = data.get('match')
if match and match.get('status_source_url'):
    print(f"Source: {match['regulator_name']} — {match['status_source_url']}")
```

## Walk all UKGC operators — JavaScript

```js
const KEY = process.env.IGREGULATOR_KEY;
const BASE = 'https://api.igregulator.io';

async function* paginate(jurisdiction) {
  let offset = 0;
  const limit = 200;
  while (true) {
    const r = await fetch(
      `${BASE}/v1/jurisdictions/${jurisdiction}/operators?limit=${limit}&offset=${offset}`,
      { headers: { Authorization: `Bearer ${KEY}` } },
    );
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    const body = await r.json();
    if (body.operators.length === 0) return;
    for (const op of body.operators) yield op;
    offset += body.operators.length;
  }
}

for await (const op of paginate('UKGC')) {
  console.log(op.slug, op.display_name);
}
```

## Walk all UKGC operators — Python

```python
import os, requests

KEY = os.environ['IGREGULATOR_KEY']
BASE = 'https://api.igregulator.io'
session = requests.Session()
session.headers['Authorization'] = f'Bearer {KEY}'

def paginate(jurisdiction):
    offset, limit = 0, 200
    while True:
        r = session.get(
            f'{BASE}/v1/jurisdictions/{jurisdiction}/operators',
            params={'limit': limit, 'offset': offset},
            timeout=10,
        )
        r.raise_for_status()
        rows = r.json()['operators']
        if not rows:
            return
        for op in rows:
            yield op
        offset += len(rows)

for op in paginate('UKGC'):
    print(op['slug'], op['display_name'])
```

## Bulk domain verification — rate-limit aware

If you're verifying a list of 500 domains as part of a nightly sweep,
[`POST /v1/check/batch`](https://igregulator.io/docs/batch/) does it in 5 requests (100
domains each). One `GET /v1/check` per domain works too: authenticate
and sleep between requests to stay under your plan's per-second limit
(Starter 5 req/s). Simpler than retry-on-429.

```python
import os, time, requests

KEY = os.environ['IGREGULATOR_KEY']
DOMAINS = open('domains.txt').read().splitlines()
S = requests.Session()
S.headers['Authorization'] = f'Bearer {KEY}'

for d in DOMAINS:
    r = S.get(
        'https://api.igregulator.io/v1/check',
        params={'domain': d}, timeout=5,
    )
    if r.status_code == 429:
        reset = int(r.headers.get('X-RateLimit-Reset', 0))
        wait = max(1, reset - int(time.time()))
        time.sleep(wait + 1)
        r = S.get(
            'https://api.igregulator.io/v1/check',
            params={'domain': d}, timeout=5,
        )
    r.raise_for_status()
    body = r.json()
    # Only 'licensed' and 'licensed_provisional' (in force, provisionally —
    # recheck) mean licensed now; everything else goes to review, with the
    # sentence. Never record a miss as "unlicensed".
    ok = body['verdict'] in ('licensed', 'licensed_provisional')
    print(d, 'OK' if ok else 'REVIEW', body['verdict'], '—', body['verdict_detail'])
    time.sleep(0.25)  # < 4 req/s: headroom under Starter's 5 req/s
```
