Skip to content

Latest commit

 

History

History
99 lines (73 loc) · 5.54 KB

File metadata and controls

99 lines (73 loc) · 5.54 KB

subprocessor.org API: notes for the scripts in this repository

This is a working summary of subprocessor.org/docs as read on 25 September 2026, limited to what the examples here rely on. The docs page is the contract; if anything below disagrees with it, the docs page wins.

Base URLs

URL
Production https://api.subprocessor.org/v1
Sandbox https://sandbox.subprocessor.org/v1 (listed on the docs page as not built yet, see below)

Authentication

  • The register endpoints are public: no key, no account.
  • Anything about your business needs a bearer token: Authorization: Bearer sk_live_....
  • Keys are created in Settings → API, scoped to a workspace, and shown once.
  • sk_live_ keys act on your real list and, after an explicit approval call, can send notices to your customers. sk_test_ keys are documented for the sandbox.

The examples read the key from the SUBPROCESSOR_API_KEY environment variable and never print it.

Conventions

Topic What the docs say How the examples use it
Versioning Everything under /v1. Additive changes ship without a bump; breaking changes get /v2 with twelve months of overlap. Unknown fields are ignored, never treated as errors.
Pagination Cursor-based. limit up to 200 (default 50). Responses carry data, has_more, next_cursor. The docs do not name the request parameter that takes the cursor back, so the examples keep it in one constant (CURSOR_PARAM) to confirm against the docs.
Conditional reads Send the ETag back in If-None-Match; an unchanged resource answers 304 with no body, and 304s do not count against the rate limit. snapshot.py stores the last ETag per vendor.
Idempotency Every POST accepts Idempotency-Key, held for 24 hours. maintained.py sends a fresh UUID with each approval.
Rate limits Unauthenticated 60/min (burst 120); Maintained key 600/min (burst 1,200); Agency key 2,400/min (burst 4,800). Headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. A 429 carries Retry-After in seconds. Both Python scripts wait for Retry-After and retry.
Errors JSON error object with type, message, doc_url, request_id. 409 means already decided or published: treat as success. 5xx: retry with backoff. The scripts print request_id so it can be quoted to support.

Record source: maintained or observed

Every register response carries source:

  • maintained: assembled by discovery, confirmed by a named reviewer, approved by the business. reviewed is true.
  • observed: a dated copy of what the company publishes. Not reviewed, not approved. reviewed is false.

snapshot.py writes both fields into every change-log row.

Endpoints used here

Public register (no key)

Method Path Used by
GET /register/companies lookup.sh
GET /register/{domain} lookup.sh, snapshot.py
GET /register/{domain}/changes lookup.sh
GET /register/{domain}/history?at=YYYY-MM-DD lookup.sh, snapshot.py --as-of
GET /register/{domain}/feed.atom lookup.sh
GET /entities lookup.sh
GET /entities/{slug}/named-by lookup.sh
GET /changes lookup.sh
GET /ledger/{row} lookup.sh

Your business (Maintained key)

Method Path Used by
GET /me/list maintained.py list
GET /me/list.csv maintained.py annex-csv
GET /me/pending maintained.py pending
POST /me/pending/{id}/decision maintained.py approve
GET /watchlist maintained.py watchlist
GET /windows maintained.py windows

The only decision value shown verbatim in the docs is "approve". The docs also describe holding a change or sending it back to a reviewer with a question, but do not print the values for those, so maintained.py only sends approve. Use the UI for the others until the values are documented.

Webhooks

  • Signed with HMAC-SHA256; header X-Subprocessor-Signature: t=<unix>,v1=<hex>.
  • The signed string is t + "." + raw_body, keyed with your webhook secret.
  • Reject anything older than five minutes.
  • Five retries with exponential backoff; any event replayable for thirty days from the dashboard.
Event Fires when
discovery.completed A discovery finishes and is ready for you
change.detected A list moved and a reviewer confirmed it is real
change.quarantined Something moved but is held: a rebuild, or a mass removal
change.published You approved it and it went live
window.opening An objection window has started
window.closing Seven days left, then one
notice.received A vendor notice landed in your forwarding inbox

The payload body fields are not published on the docs page, so the receivers in examples/webhooks/ verify the signature and store the verified raw body without routing on fields that are not documented.

Documented but not built yet

The docs page lists these as not built at the time of reading. The examples here do not call any of them:

  • POST /v1/watchlist and DELETE /v1/watchlist/{domain} (manage the watchlist in the UI)
  • POST /v1/evidence/packs (generate packs in the UI and download them there)
  • POST /v1/discovery, /v1/me/subscribers, /v1/me/entities
  • Agency workspace endpoints
  • SDKs, the sandbox and the CI action

The docs invite requests for any of these; see subprocessor.org/docs.