API documentation
Compliance APIs for emerging-market commodity trade.
REST API reference. All endpoints under /api/v1/* with consistent { ok, data | error } shape. 29 endpoints across 11 SKU surfaces. Sandbox keys in 60 seconds; production tier via Stripe + sales-led enterprise.
For AI agents
Running a compliance agent? Paste the block below into its instructions. The pre-screen needs no key and no account.
OilFlow — counterparty compliance for physical-commodity trade.
Free fraud-cluster pre-screen (no key, no account):
curl -sX POST https://oilflow.us/api/public/check \
-H 'Content-Type: application/json' \
-d '{"query":"<counterparty name>"}'
10 requests/hour per IP. "email" is optional; omit it to stay anonymous.
Model Context Protocol (no install, no key for 4 tools):
https://oilflow.us/api/mcp
claude mcp add --transport http oilflow https://oilflow.us/api/mcp
Keyless tools: cluster_check, predeal_preview (5/day/IP),
verify_receipt, request_sandbox_key
Machine-readable API spec:
https://oilflow.us/openapi.yaml (auth: Authorization: Bearer <key>)
Full 7-step dossier, $25, no account:
https://oilflow.us/dossier
Coverage limits — state these to the user, they change the answer:
- 8 sanctions lists: OFAC SDN, OFAC Consolidated, UN, EU, UK HMT,
Canada SEMA, AU DFAT, Swiss SECO.
- PEP screening is NOT shipped. Coverage is sanctions-only: a
politically exposed person who is not also sanctioned is not flagged.
- No functioning US domestic UBO registry post-March-2025, so
beneficial-ownership coverage is partial and every result says so.
- The free check queries the fraud-cluster registry only. It is an
honest pre-screen, not a regulatory KYC.The same index, in the format agents fetch by convention, is at /llms.txt.
Authentication
Provide an API key on every request via Authorization: Bearer <key> or X-Api-Key header. Sandbox keys are read-only; production keys carry per-scope authorization.
Get a sandbox key at /sandbox or production access via [email protected].
Rate limits (defaults)
POST ubo / lc / reports limits are lower because each call runs heavy synthesis. Production tier quotas raise these per SKU; see /pricing.
Available surfaces (11)
Regulatory Matrix API
· BETA235-jurisdiction product-tradability + sanctions rules.
/api/v1/regulatory/* · 4 endpoints
Counterparty KYC-as-API
· EARLY ACCESS7-step pipeline + 8-list sanctions + cluster + regulatory checks. Realtime per-step events.
/api/v1/kyc/* · 2 endpoints
Scam Cluster Intelligence Feed
· EARLY ACCESSVerified-fraudulent counterparty clusters with severity, cross-references, webhooks.
/api/v1/clusters/* · 2 endpoints
Webhooks
· LIVEHMAC-signed delivery + DLQ. Native Slack Block Kit + Teams Adaptive Card formats.
/api/v1/webhooks/* · 5 endpoints
Regulator Reports
· LIVEFATF Rec.10, FinCEN CDD, EU 6AMLD, FCA SYSC 18, MAS 626, OFSI packages with auto cover letters.
/api/v1/reports/* · 4 endpoints
Adverse Media
· LIVEMultilingual (11 langs) daily sweeps; severity-classified findings via webhook.
/api/v1/adverse-media/* · 4 endpoints
UBO Graph
· LIVEN-hop ownership traversal with sanctions + shell-company verdict on every node.
/api/v1/ubo/* · 2 endpoints
LC Validation
· LIVEUCP 600 + cross-document discrepancy engine for letter-of-credit packages.
/api/v1/lc/* · 2 endpoints
Customer Watchlists
· LIVECSV ingest; continuous sync against adverse media, cluster upgrades, sanctions deltas.
/api/v1/watchlists/* · 2 endpoints
Audit Export
· LIVECustomer-scoped api_request_log export — JSON, CSV, or summary aggregate.
/api/v1/audit/* · 1 endpoints
Sandbox Keys
· PUBLICUnauthenticated; 7-day, 100 calls/day, read-only. Evaluate without signup.
/api/v1/keys/* · 1 endpoints
Regulatory Matrix API · BETA
/api/v1/regulatory/*
/api/v1/regulatory/countries
List all jurisdictions
Returns the 235 jurisdictions covered by the OilFlow regulatory matrix, each with the full per-product rule table (allowed / restricted / blocked + contextual notes).
Example request
curl -H "Authorization: Bearer <key>" \ https://oilflow.us/api/v1/regulatory/countries
Example response
{
"ok": true,
"data": {
"count": 235,
"version": "v1-beta",
"countries": [
{
"slug": "algeria",
"country": "Algeria",
"rules": {
"crude": { "status": "restricted", "notes": "Sonatrach controls upstream..." },
"refined": { "status": "restricted", "notes": "Sonatrach controls refining..." }
}
}
]
}
}- ▸Cached at edge for 1 hour (ISR).
/api/v1/regulatory/countries/:slug
Get jurisdiction detail
Returns the full rule set for a single jurisdiction. The slug is the lowercase, hyphenated country name (e.g. 'pakistan', 'saudi-arabia').
Parameters
- slugstring (path)required
Lowercase, hyphenated country name.
Example request
curl -H "Authorization: Bearer <key>" \ https://oilflow.us/api/v1/regulatory/countries/pakistan
Example response
{
"ok": true,
"data": {
"slug": "pakistan",
"country": "Pakistan",
"rules": {
"crude": { "status": "restricted", "notes": "..." },
"refined": { "status": "allowed", "notes": "..." }
}
}
}/api/v1/regulatory/check
Run a tradability check
Quick tradability check for a (country, product, listing_type) tuple. Returns whether the deal would be allowed and the specific blockers if not.
Parameters
- countrystringrequired
Country name (full or ISO-2).
- productstringrequired
Product label or category.
- listing_type'supply' | 'demand'
Default: 'demand'.
Example request
curl -H "Authorization: Bearer <key>" \ "https://oilflow.us/api/v1/regulatory/check?country=Kenya&product=crude&listing_type=demand"
Example response
{
"ok": true,
"data": {
"country": "Kenya",
"product": "crude",
"allowed": false,
"blockers": [{ "reason": "Private buyers in Kenya cannot independently import crude oil (OTS-only)." }]
}
}/api/v1/regulatory/products
List product categories
Normalized product categories used by the matrix and accepted by /check.
Example request
curl -H "Authorization: Bearer <key>" \ https://oilflow.us/api/v1/regulatory/products
Example response
{
"ok": true,
"data": {
"count": 5,
"products": [
{ "category": "crude", "label": "Crude oil" },
{ "category": "refined", "label": "Refined products" },
{ "category": "lpg", "label": "LPG" },
{ "category": "lng", "label": "LNG" },
{ "category": "bitumen", "label": "Bitumen" }
]
}
}Counterparty KYC-as-API · EARLY ACCESS
/api/v1/kyc/*
/api/v1/kyc/screen
Screen a counterparty
Run the 7-step KYC pipeline on a counterparty. Synchronous v0 checks: scam-cluster blocklist + regulatory tradability. Returns a screening_run_id; subscribe via Supabase realtime to stream per-step events.
Request body
- company_namestringrequired
Counterparty legal name.
- countrystring
Jurisdiction for the regulatory check.
- productstring
Product for the regulatory check.
- directorsstring[]
Names of directors to cross-check against the blocklist.
- metadataobject
Free-form metadata for your records.
Example request
curl -X POST -H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"company_name":"SSW Kafcima","country":"Singapore","directors":["Simar Chahal"]}' \
https://oilflow.us/api/v1/kyc/screenExample response
{
"ok": true,
"data": {
"screening_run_id": "00000000-...",
"verdict": "fail",
"verdict_reasoning": "Confirmed cluster blocklist match: Simar Chahal.",
"checks": { "cluster_blocklist": { "status": "fail" }, "regulatory_tradability": { "status": "pass" } }
}
}- ▸verdict='fail' on confirmed cluster match OR regulatory tradability fail.
- ▸Subscribe to realtime channel `pipeline:{screening_run_id}` for live step events.
/api/v1/kyc/rescreen
Queue a re-screen for a known entity
Asynchronously re-runs the full 7-step pipeline on a previously-screened entity. Returns 202 with a new screening_run_id. Continuous re-screen fires automatically every 90 days; this endpoint is for ad-hoc re-runs.
Request body
- entity_iduuidrequired
ID from a prior /api/v1/kyc/screen run.
Example request
curl -X POST -H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"entity_id":"00000000-0000-0000-0000-000000000001"}' \
https://oilflow.us/api/v1/kyc/rescreenExample response
{ "ok": true, "data": { "screening_run_id": "...", "status": "queued", "queued_at": "2026-06-02T..." } }- ▸202 Accepted. Subscribe to webhook event `kyc.rescreen_completed` for the final verdict.
Scam Cluster Intelligence Feed · EARLY ACCESS
/api/v1/clusters/*
/api/v1/clusters
List clusters
All verified-fraudulent counterparty clusters from the OilFlow scam blocklist. Filterable by severity, country, and timestamp.
Parameters
- severity'confirmed' | 'likely' | 'suspected'
Filter by severity tier.
- countrystring
Filter by entity country.
- sinceISO timestamp
Only return clusters added after this time.
Example request
curl -H "Authorization: Bearer <key>" \ "https://oilflow.us/api/v1/clusters?severity=confirmed"
Example response
{ "ok": true, "data": { "count": 1, "clusters": [{ "entity_name": "Simar Chahal", "severity": "confirmed", ... }] } }/api/v1/clusters/check
Check an entity
Fast lookup: is this entity in the cluster blocklist? Integrate into intake to short-circuit obvious frauds before full KYC.
Parameters
- entitystringrequired
Entity name to check.
- countrystring
Filter to matches in this country.
Example request
curl -H "Authorization: Bearer <key>" \ "https://oilflow.us/api/v1/clusters/check?entity=Simar%20Chahal"
Example response
{ "ok": true, "data": { "matched": true, "matches": [{ "severity": "confirmed", ... }], "highest_severity": "confirmed" } }Webhooks · LIVE
/api/v1/webhooks/*
/api/v1/webhooks
List webhook subscriptions
Returns the caller's active subscriptions plus the catalog of valid event types.
Example request
curl -H "Authorization: Bearer <key>" https://oilflow.us/api/v1/webhooks
Example response
{ "ok": true, "data": { "subscriptions": [...], "valid_events": ["kyc.match_detected", "cluster.entity_added", "watchlist.match_detected", ...] } }/api/v1/webhooks
Create a subscription
Subscribe a URL to one or more event types. HMAC-signed delivery with exponential-backoff retry and DLQ. delivery_format='slack'|'teams' renders payloads as Block Kit / Adaptive Card; 'raw' is the default HMAC JSON.
Request body
- urlstringrequired
HTTPS URL to POST events to (or a Slack/Teams incoming-webhook URL).
- eventsstring[]required
Event types to subscribe to. See GET /webhooks for the catalog.
- delivery_format'raw' | 'slack' | 'teams'
Default: 'raw' (HMAC-signed JSON).
- descriptionstring
Human-readable label.
Example request
curl -X POST -H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.slack.com/services/...","events":["kyc.match_detected","cluster.entity_added"],"delivery_format":"slack"}' \
https://oilflow.us/api/v1/webhooksExample response
{ "ok": true, "data": { "id": "wh_...", "secret_preview": "..." } }- ▸HMAC secret displayed once on create. Store it in your secret manager.
/api/v1/webhooks/:id
Revoke a subscription
Soft-deletes the subscription. Stops future deliveries; existing DLQ entries are retained for audit.
Example request
curl -X DELETE -H "Authorization: Bearer <key>" https://oilflow.us/api/v1/webhooks/wh_...
Example response
{ "ok": true }/api/v1/webhooks/events
Recent delivery log
Returns the caller's last 50 webhook delivery attempts with status, attempt count, and HTTP response code. Used to audit a flaky endpoint.
Example request
curl -H "Authorization: Bearer <key>" https://oilflow.us/api/v1/webhooks/events
Example response
{ "ok": true, "data": { "events": [{ "id": "...", "status": "delivered", "attempt_count": 1, "response_code": 200 }] } }/api/v1/webhooks/events/:id/replay
Replay a failed delivery
Re-queues a specific event for delivery. Useful after fixing a receiver bug.
Example request
curl -X POST -H "Authorization: Bearer <key>" https://oilflow.us/api/v1/webhooks/events/evt_.../replay
Example response
{ "ok": true, "data": { "queued_at": "..." } }Regulator Reports · LIVE
/api/v1/reports/*
/api/v1/reports
List your generated reports
Returns paginated list of regulator-ready report packages your team has generated. Filterable by template_id and status.
Parameters
- template_idstring
e.g. 'fatf_rec10', 'fincen_cdd', 'eu_6amld', 'mas_626', 'fca_sysc18', 'ofsi'.
- status'queued' | 'ready' | 'failed'
Filter by status.
Example response
{ "ok": true, "data": { "reports": [{ "id": "...", "template_id": "fatf_rec10", "status": "ready" }] } }/api/v1/reports
Generate a report
Synthesises a regulator-ready evidence package from a previous KYC run. PDF rendered server-side; webhook `report.ready` fires when complete.
Request body
- entity_iduuidrequired
Source KYC run.
- template_idstringrequired
Framework template (fatf_rec10, fincen_cdd, eu_6amld, mas_626, fca_sysc18, ofsi).
Example request
curl -X POST -H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"entity_id":"...","template_id":"fatf_rec10"}' \
https://oilflow.us/api/v1/reportsExample response
{ "ok": true, "data": { "id": "rpt_...", "status": "queued" } }/api/v1/reports/:id
Fetch a report
Returns report metadata + signed-URL download link for the PDF. Append ?include_cover_letter=true for a Claude-Haiku-synthesised regulator-officer-voice cover letter, cached after first request.
Parameters
- include_cover_letterboolean
Append a draft cover letter (cached after first fetch).
Example response
{ "ok": true, "data": { "report": {...}, "download_url": "https://...", "cover_letter": { "text": "...", "cached": false } } }/api/v1/reports/:id/audit
Report audit trail
Returns the append-only audit trail for a report (generation events, signed-URL fetches, regenerate triggers). Bank regulators ask for this directly.
Example response
{ "ok": true, "data": { "events": [{ "kind": "generated", "at": "..." }, { "kind": "downloaded", "at": "..." }] } }Adverse Media · LIVE
/api/v1/adverse-media/*
/api/v1/adverse-media/entities
List monitored entities
Your active monitoring list. Each entity is swept across 11 languages daily; matches fire `adverse_media.match_detected` webhooks.
Example response
{ "ok": true, "data": { "entities": [{ "id": "...", "entity_name": "Acme Trading FZE", "languages": ["en","ar"] }] } }/api/v1/adverse-media/entities
Add an entity to monitoring
Begins daily multilingual sweeps for the named entity. Idempotent on (member_id, entity_name).
Request body
- entity_namestringrequired
Legal name.
- aliasesstring[]
Other names to track.
- languagesstring[]
ISO codes; default: ['en']. Supported: en, ar, ru, ur, fa, zh, fr, es, de, pt, tr.
- jurisdictionsstring[]
Country filter.
Example response
{ "ok": true, "data": { "id": "mon_..." } }/api/v1/adverse-media/entities/:id
Stop monitoring an entity
Pauses daily sweeps. Soft-delete; historical findings retained.
Example response
{ "ok": true }/api/v1/adverse-media/findings
List findings
Returns adverse-media findings for your monitored entities. Filterable by entity, severity, language, and time window.
Parameters
- entity_iduuid
Filter by monitored entity.
- severity'low' | 'medium' | 'high' | 'critical'
Minimum severity.
- sinceISO timestamp
Findings discovered after this time.
Example response
{ "ok": true, "data": { "findings": [{ "id": "...", "severity": "high", "language": "ar", "source_url": "..." }] } }UBO Graph · LIVE
/api/v1/ubo/*
/api/v1/ubo/screen
Screen a UBO graph
Traverses ownership N hops from a root entity, screens every node + edge against the 8 sanctions lists + cluster blocklist, and runs shell-company detection on each entity. Returns a graph_id; the full graph fetches via /ubo/graph/{id}.
Request body
- root_entity_namestringrequired
Top of the ownership tree.
- root_jurisdictionstring
Root jurisdiction (helps narrow ambiguous matches).
- max_hopsinteger
Default: 3.
Example response
{ "ok": true, "data": { "graph_id": "...", "status": "queued" } }/api/v1/ubo/graph/:id
Fetch a UBO graph
Returns the screened ownership graph: nodes, edges, sanctions matches, shell-company verdicts, and aggregate risk score.
Example response
{ "ok": true, "data": { "nodes": [...], "edges": [...], "shell_company_verdicts": {...}, "aggregate_risk": "medium" } }LC Validation · LIVE
/api/v1/lc/*
/api/v1/lc/validate
Validate an LC + invoice + B/L
Cross-document discrepancy detection: UCP 600 rule engine + amount/currency/port/expiry consistency between letter of credit, commercial invoice, and bill of lading.
Request body
- lcobjectrequired
Letter of credit terms (amount, currency, beneficiary, ports, expiry_date).
- invoiceobjectrequired
Commercial invoice (amount, currency, seller, presentation_date).
- blobjectrequired
Bill of lading (currency, port_of_loading, issue_date, shipped_on_board).
Example response
{ "ok": true, "data": { "report_id": "lc_...", "discrepancies": [{ "rule": "UCP 600 Art. 14(d)", "severity": "major", "detail": "..." }] } }/api/v1/lc/reports/:id
Fetch an LC validation report
Returns the persisted validation report with discrepancies, UCP rule citations, and signed-URL PDF download.
Example response
{ "ok": true, "data": { "report": {...}, "download_url": "https://..." } }Customer Watchlists · LIVE
/api/v1/watchlists/*
/api/v1/watchlists
Upload a counterparty watchlist (CSV)
Ingests a CSV of counterparties you want continuously screened against new sanctions deltas, cluster upgrades, and adverse-media findings. Matches fire `watchlist.match_detected` webhooks. CSV header: entity_name,aliases,jurisdictions (aliases + jurisdictions pipe-separated within the cell).
Request body
- namestringrequired
Watchlist name.
- descriptionstring
Free-form label.
- csvstringrequired
CSV body; max 50K rows per upload.
Example response
{ "ok": true, "data": { "id": "wl_...", "name": "...", "entries_count": 1247 } }/api/v1/watchlists/:id
Fetch a watchlist + recent matches
Returns the watchlist + the first 25 entries + the 50 most recent match events.
Example response
{ "ok": true, "data": { "watchlist": {...}, "sample_entries": [...], "recent_matches": [{ "matched_at": "...", "source": "adverse_media" }] } }Audit Export · LIVE
/api/v1/audit/*
/api/v1/audit
Export your audit trail
Returns your own api_request_log rows for compliance-evidence submission. Three modes via the `format` parameter: 'json' (full rows, paginated), 'csv' (download), 'summary' (aggregate counts by SKU scope — used by the dashboard SpendForecast card).
Parameters
- format'json' | 'csv' | 'summary'
Default: 'json'.
- daysinteger
1–365; default 90.
- page_sizeinteger
1–10000; default 10000.
- cursorISO timestamp
From a prior page's last logged_at. Pages are strictly older than the cursor; no duplicates if new rows land mid-export.
Example response
{ "ok": true, "data": { "days": 90, "count": 9842, "rows": [...], "next_cursor": "2026-04-21T15:02:11Z" } }- ▸Customer-scoped to your member_id (or tenant if you're on SKU #4 Workflow Suite).
- ▸Page by passing the prior response's next_cursor; null = end of stream.
Sandbox Keys · PUBLIC
/api/v1/keys/*
/api/v1/keys/sandbox
Issue a sandbox API key
Unauthenticated. Issues a 7-day, 100 calls/day, read-only key scoped to /api/v1/regulatory/* + /api/v1/clusters/check. Use it to evaluate the API without signing up. Rate-limited by IP (3/h) and email (5/day).
Request body
- emailstringrequired
Your work email.
- companystring
Company name.
- use_casestring
Optional context.
Example request
curl -X POST -H "Content-Type: application/json" \
-d '{"email":"[email protected]","company":"Example Bank","use_case":"Evaluate /regulatory/check for Saudi crude"}' \
https://oilflow.us/api/v1/keys/sandboxExample response
{ "key": "oilflow_sk_...", "key_id": "...", "environment": "sandbox", "scopes": ["regulatory","cluster"], "expires_at": "...", "daily_call_cap": 100 }- ▸Welcome email fires on issuance with curl gallery + dashboard link.
Ready to integrate
Sandbox now, production by Friday.
Issue a sandbox key, hit the curl examples above, then upgrade in the dashboard. Enterprise scoping at your pace.