Get started
This guide takes you from a fresh API key to a full dataset snapshot on disk.
Before you begin
Section titled “Before you begin”Your API key is delivered to you during onboarding. Keys are prefixed by environment, and each environment has a fixed base URL:
| Environment | Base URL | Key prefix |
|---|---|---|
| Staging | https://api.staging.editedsource.com | lk_test_... |
| Production | https://api.editedsource.com | lk_live_... |
The previous hostnames https://lists-api.tools.frankpenny.se (production) and https://lists-api.staging.tools.frankpenny.se (staging) are legacy hostnames that keep working for existing integrations, and they serve the same API at the same paths.
The examples below assume two environment variables in your terminal session:
export BASE_URL="https://api.staging.editedsource.com" # staging URL for lk_test_ keysexport API_KEY="lk_test_..." # your keyStep 1: Verify your key
Section titled “Step 1: Verify your key”GET /v1/whoami reports what your key can do. Use it to confirm connectivity, environment, and scopes:
curl -s "$BASE_URL/v1/whoami" -H "Authorization: Bearer $API_KEY"The response includes your tenant id, the key’s environment (test or live), the dataset scopes it grants, any per-source grants, and its rate-limit configuration.
{ "allowed_sources": [ "pep-eu", "pep-intl", "pep-swe" ], "environment": "test", "key_id": "a1b2c3d4e5f6a7b8", "prefix": "lk_test_XXXX", "rate_limits": { "rpm": 60 }, "scopes": [ "pep", "sanctions" ], "tenant_id": "acme-bank"}Step 2: Pull a full snapshot
Section titled “Step 2: Pull a full snapshot”Each dataset has a /full endpoint serving the complete current snapshot. The response streams inline:
curl -s "$BASE_URL/v1/sanctions/full?format=jsonl" \ -H "Authorization: Bearer $API_KEY" \ -o sanctions.jsonlformat=jsonl returns application/x-ndjson, one record per line. See Streaming and snapshots for the other formats, and Sanctions for the record in full.
Snapshots may be large (tens to hundreds of MB). It is recommended to disable client timeouts for the fetch and process records as they arrive rather than buffering the whole response.
{"id":"eu-fsf-1003","schema":"Person","status":"active","caption":"Nurjaman Riduan Isomuddin","topics":["sanction"],"sources":["eu-fsf"],"firstSeen":"2026-05-27T16:23:39.640799+00:00","lastSeen":"2026-07-09T01:01:26.747834+00:00","properties":{"…":"…"},"sanctions":[{"…":"…"}]}Nested properties and sanctions values are shortened to … here; responses carry them in full.
Legacy deprecated fields are omitted from this example; responses include them until the next major version.
Step 3: Process the stream
Section titled “Step 3: Process the stream”Parse one line at a time. Always inspect the final record: if the stream was cut short, the last line is an error envelope instead of an entity. See Errors.
import json
with open("sanctions.jsonl", "rb") as f: for line in f: record = json.loads(line) if "error" in record: raise RuntimeError(f"incomplete stream: {record['error']['code']}") # handle the entityNext steps
Section titled “Next steps”- Authentication: scopes and per-country PEP licensing.
- Rate limits and headers: the response headers every integration should read.
- Sanctions and PEP: dataset endpoints and record shapes.