Skip to content

Latest commit

 

History

History
191 lines (155 loc) · 7.68 KB

File metadata and controls

191 lines (155 loc) · 7.68 KB

Regulation to Control API

Detect regulatory changes and map them to obligations, policies, controls, products and evidence requirements.

Regulation to Control landing page

Production API: https://controlgraph-api.com

Get a free API key · Documentation · Pricing · Status

Free tier: 50 mapped changes/month. No card required. Paid plans from $499/month.

Quickstart

Request a key. The token arrives by email; exchange it for the key, which is shown once.

curl -X POST https://controlgraph-api.com/v1/keys \
  -H 'content-type: application/json' \
  -d '{"email": "you@example.com"}'

Then call the API:

curl -X POST https://controlgraph-api.com/v1/changes \
  -H "Authorization: Bearer $KEY" \
  -H 'content-type: application/json' \
  -d '{"controls":[
        {"controlId":"CTL-014","name":"Disclosure template review",
         "owner":"Payments Compliance","status":"implemented",
         "tags":["payments","disclosure"],"lastTestedAt":"2026-07-01",
         "evidence":[{"kind":"policy_document","collectedAt":"2026-07-02"},
                     {"kind":"notification_record","collectedAt":"2026-07-14"}]}],
      "change":{
        "changeId":"REG-2026-0117","citation":"12 CFR 1026.19(e)",
        "title":"Revised cost-of-credit disclosures","jurisdiction":"US",
        "changeType":"amendment","publishedAt":"2026-03-02",
        "effectiveAt":"2026-09-01","transitionEndsAt":"2026-12-01",
        "obligations":[
          {"obligationId":"OB-1","type":"disclosure",
           "text":"Provide the revised disclosure within three business days.",
           "appliesTo":["payments","disclosure"],"enforcement":"penalty"}]}}\'

Endpoints

Regulation to Control API reference, with a live playground for every endpoint

Every endpoint below has a runnable playground on the documentation page.

Endpoint Auth Description
GET /health public Liveness and deployed version
GET / public Service index — endpoints, auth and error format
POST /v1/changes API key Map regulatory changes onto your obligations, controls, evidence and deadlines
POST /v1/demo/map public Public demo — map one change with no API key
GET /v1/obligation-types public The code catalogue: obligation types, evidence kinds, findings and the priority weights
POST /v1/checkout public Start a hosted Square checkout for a paid tier
POST /v1/keys public Request a free sandbox API key (sends a verification email)
GET /v1/keys API key List your API keys for this API
POST /v1/keys/claim public Exchange an emailed claim token for the API key
POST /v1/keys/{id}/revoke API key Revoke one of your API keys
POST /v1/keys/{id}/rotate API key Replace one of your API keys with a new secret
GET /v1/usage API key Your consumption and remaining allowance for this period
GET /v1/subscription API key Your current plan, billing window and available changes (dashboard session required)
POST /v1/subscription/plan API key Upgrade or downgrade to another plan (dashboard session required)
POST /v1/subscription/cancel API key Cancel this plan and end metered access (dashboard session required)
GET /v1/invoices API key Every invoice issued against this account, newest first (dashboard session required)
GET /v1/payments API key Every payment attempted against this account and how it went (dashboard session required)

The full machine-readable contract is openapi.json, generated from the deployed route table rather than maintained by hand. A Postman collection is included.

SDKs

Pythonsdk/python

from regulation_control import RegulationControl

client = RegulationControl()          # reads REGULATION_CONTROL_API_KEY

res = client.map_change(
    controls=[
        {"controlId": "CTL-014", "name": "Disclosure template review",
         "owner": "Payments Compliance", "status": "implemented",
         "tags": ["payments", "disclosure"], "lastTestedAt": "2026-07-01",
         "evidence": [{"kind": "policy_document", "collectedAt": "2026-07-02"},
                      {"kind": "notification_record", "collectedAt": "2026-07-14"}]},
    ],
    change={
        "changeId": "REG-2026-0117",
        "citation": "12 CFR 1026.19(e)",
        "title": "Revised cost-of-credit disclosures",
        "jurisdiction": "US",
        "changeType": "amendment",
        "publishedAt": "2026-03-02",
        "effectiveAt": "2026-09-01",
        "transitionEndsAt": "2026-12-01",
        "obligations": [
            {"obligationId": "OB-1", "type": "disclosure",
             "text": "Provide the revised disclosure within three business days.",
             "appliesTo": ["payments", "disclosure"], "enforcement": "penalty"},
        ],
    },
)

mapped = res["changes"][0]
print(mapped["summary"])   # covered / weak / gaps, and the earliest deadline

# The gaps are the work nobody has started.
for ob in mapped["obligations"]:
    if ob["coverage"] == "gap":
        open_ticket(ob["obligationId"], ob["text"], ob["complianceDate"])

# Every score is reproducible arithmetic. Print the derivation next to it.
top = mapped["obligations"][0]
print(top["priority"]["score"], top["priority"]["band"])
for line in top["priority"]["derivation"]:
    print("   ", line)

TypeScriptsdk/typescript

import { RegulationControl } from './regulation-control.js'

const client = new RegulationControl()     // reads REGULATION_CONTROL_API_KEY

const { changes } = await client.map({
  controls: [
    { controlId: 'CTL-014', name: 'Disclosure template review',
      owner: 'Payments Compliance', status: 'implemented',
      tags: ['payments', 'disclosure'], lastTestedAt: '2026-07-01',
      evidence: [{ kind: 'policy_document', collectedAt: '2026-07-02' },
                 { kind: 'notification_record', collectedAt: '2026-07-14' }] },
  ],
  change: {
    changeId: 'REG-2026-0117',
    citation: '12 CFR 1026.19(e)',
    title: 'Revised cost-of-credit disclosures',
    jurisdiction: 'US',
    changeType: 'amendment',
    publishedAt: '2026-03-02',
    effectiveAt: '2026-09-01',
    transitionEndsAt: '2026-12-01',
    obligations: [
      { obligationId: 'OB-1', type: 'disclosure',
        text: 'Provide the revised disclosure within three business days.',
        appliesTo: ['payments', 'disclosure'], enforcement: 'penalty' },
    ],
  },
})

const mapped = changes[0]
console.log(mapped.summary)   // covered / weak / gaps, and the earliest deadline

// The gaps are the work nobody has started.
for (const ob of mapped.obligations) {
  if (ob.coverage === 'gap') openTicket(ob.obligationId, ob.text, ob.complianceDate)
}

// Every score is reproducible arithmetic. Print the derivation next to it.
const top = mapped.obligations[0]!
console.log(top.priority.score, top.priority.band, top.priority.derivation)

Errors

Every failure returns the same shape. Branch on code, which is a stable enum; message is for humans and may change.

{"error": {"code": "invalid_api_key", "message": "...", "requestId": "0f3c8b12-…"}}

requestId appears on every response and in the x-request-id header. Quote it in any support request.

Support

Open an issue in this repository, or see the contact route at https://controlgraph-api.com/docs.