Docs
API reference (v1)
Base URL https://sourcefinch.com. Machine-readable description: OpenAPI 3.1 (version 1.0.0). New to SourceFinch? Start with getting started.
Authentication
Create a project API key in API & access and send it as Authorization: Bearer sec_…. Read keys can call GET operations; write keys can also create and update. A key is bound to one project, so you never pass a project id.
curl https://sourcefinch.com/v1/sources \ -H "Authorization: Bearer $SOURCEFINCH_API_KEY"
Conventions
- JSON with snake_case fields, UUID ids and ISO-8601 UTC timestamps.
- Lists return
{ data, next_cursor }. Passcursorto get the next page andlimit(1–100, default 50) to size it.next_cursorisnullon the last page. - Send an
Idempotency-Keyheader with any POST to make retries safe for 24 hours. A retry returns the original response (withIdempotent-Replayed: true) and creates nothing. Reusing a key with a different request returns 422. - Every response carries
X-Request-Id. Send your own (8–100 characters fromA–Z a–z 0–9 . _ -) to correlate logs. Quote it when you contact support. - v1 changes are additive only. A breaking change would ship as v2, with at least six months of overlap.
Errors
Errors are RFC 9457 problem details (application/problem+json). Branch on code, never on the message text. Validation errors list field paths in issues.
| HTTP | code | Meaning |
|---|---|---|
| 400 | validation | Invalid request |
| 401 | unauthenticated | Authentication required |
| 402 | plan_limit | Plan limit reached |
| 403 | forbidden | Not allowed |
| 404 | not_found | Not found |
| 409 | conflict | Conflict |
| 409 | policy | Refused by policy |
| 422 | idempotency_mismatch | Idempotency key reused with a different request |
| 429 | rate_limited | Too many requests |
| 500 | internal | Request failed |
Operations
Meta
GET /v1
API version and the project this credential is scoped to.
Scope: read. Success: 200 JSON.
Sources
GET /v1/sources
List sources.
Scope: read. Success: 200 JSON. Parameters: limit (query), cursor (query).
POST /v1/sources
Create a source. The source's origin must be approved for the workspace. Version 1 of the recipe is recorded.
Scope: write. Success: 201 JSON. Body: SourceCreate.
GET /v1/sources/{source_id}
Get a source.
Scope: read. Success: 200 JSON. Parameters: source_id (path, required).
PATCH /v1/sources/{source_id}
Update a source. Changing url or recipe creates a new version (unchanged values create none). name, schedule and key_field change without a new version.
Scope: write. Success: 200 JSON. Body: SourceUpdate. Parameters: source_id (path, required).
GET /v1/sources/{source_id}/versions
List a source's recipe versions.
Scope: read. Success: 200 JSON. Parameters: source_id (path, required), limit (query), cursor (query).
GET /v1/sources/{source_id}/versions/{version}
Get one recipe version.
Scope: read. Success: 200 JSON. Parameters: source_id (path, required), version (path, required).
Records
GET /v1/sources/{source_id}/records
Current records. Records from the source's latest validated run, in extraction order, with their evidence ids.
Scope: read. Success: 200 JSON. Parameters: source_id (path, required), limit (query), cursor (query).
GET /v1/changes
Change feed. Field-level record changes (added, changed, removed) across the project's sources, oldest first. Store `next_cursor` and pass it back as `cursor` to receive only newer changes.
Scope: read. Success: 200 JSON. Parameters: limit (query), cursor (query), source_id (query).
GET /v1/runs/{run_id}/export
Export a validated run's records. CSV, JSON, NDJSON or XLSX. Every row carries its record key, evidence id and evidence link; JSON/NDJSON/XLSX add the manifest SHA-256, acquisition path and usage rights (XLSX: Records, Data dictionary and Provenance sheets).
Scope: read. Success: 200 redirect. Parameters: run_id (path, required), format (query).
Runs
GET /v1/sources/{source_id}/runs
List a source's runs.
Scope: read. Success: 200 JSON. Parameters: source_id (path, required), limit (query), cursor (query).
POST /v1/sources/{source_id}/runs
Queue a run. Queues an acquisition of the source's current recipe version. Poll the run until it completes.
Scope: write. Success: 202 JSON. Parameters: source_id (path, required).
GET /v1/runs
List runs.
Scope: read. Success: 200 JSON. Parameters: limit (query), cursor (query), source_id (query), status (query).
GET /v1/runs/{run_id}
Get a run. Status, validation, source health, metrics and change summary.
Scope: read. Success: 200 JSON. Parameters: run_id (path, required).
POST /v1/runs/{run_id}:accept
Accept a degraded run. Confirms a degraded run (its output departed from recent healthy runs) is correct. It becomes current and joins future baselines. Only the newest output of a source can be accepted.
Scope: write. Success: 200 JSON. Parameters: run_id (path, required).
GET /v1/runs/{run_id}/events
A run's events.
Scope: read. Success: 200 JSON. Parameters: run_id (path, required).
Evidence
GET /v1/runs/{run_id}/claims
A run's claims. One claim per extracted record, each linked to the evidence it came from.
Scope: read. Success: 200 JSON. Parameters: run_id (path, required), limit (query), cursor (query).
GET /v1/runs/{run_id}/evidence
A run's evidence.
Scope: read. Success: 200 JSON. Parameters: run_id (path, required).
GET /v1/runs/{run_id}/manifest
A run's signed manifest. The run's receipt: every capture hash, claim value and locator, validation and compliance state, signed with SourceFinch's evidence key and anchored with an RFC 3161 timestamp. Verify offline with the evidence bundle verifier.
Scope: read. Success: 200 JSON. Parameters: run_id (path, required).
GET /v1/runs/{run_id}/bundle
Download the run's evidence bundle. A WACZ package with the retained captures, the signed manifest, the RFC 3161 timestamp and the public key, verifiable offline by a third party (pnpm verify-bundle). Requires the manifest (available a few seconds after the run finishes).
Scope: read. Success: 200 redirect. Parameters: run_id (path, required).
GET /v1/evidence/{evidence_id}
Evidence metadata.
Scope: read. Success: 200 JSON. Parameters: evidence_id (path, required).
GET /v1/evidence/{evidence_id}/content
Download a capture. Redirects (302) to a signed URL valid for 60 seconds. Recompute the SHA-256 to verify it.
Scope: read. Success: 302 redirect. Parameters: evidence_id (path, required).
Delivery
GET /v1/destinations
List destinations.
Scope: read. Success: 200 JSON. Parameters: limit (query), cursor (query).
POST /v1/destinations
Create a destination. Webhooks: every successful run of the selected sources is POSTed to the URL, signed (Standard Webhooks) and retried with backoff for 24 hours. The signing secret is returned once.
Scope: write. Success: 201 JSON. Body: DestinationCreate.
GET /v1/destinations/{destination_id}
Get a destination.
Scope: read. Success: 200 JSON. Parameters: destination_id (path, required).
PATCH /v1/destinations/{destination_id}
Rename, pause, resume or disable a destination. Disabling cancels deliveries that have not been made yet.
Scope: write. Success: 200 JSON. Body: DestinationUpdate. Parameters: destination_id (path, required).
POST /v1/destinations/{destination_id}:test
Send a test delivery. Queues a signed `destination.test` delivery through the normal delivery path. Poll the delivery for its receipt.
Scope: write. Success: 202 JSON. Parameters: destination_id (path, required).
GET /v1/deliveries
Delivery receipts.
Scope: read. Success: 200 JSON. Parameters: limit (query), cursor (query), destination_id (query), run_id (query).
POST /v1/deliveries/{delivery_id}:redeliver
Redeliver. Sends the same payload again with the same idempotency key (receivers dedupe on it).
Scope: write. Success: 202 JSON. Parameters: delivery_id (path, required).
Example: create a source and run it
curl -X POST https://sourcefinch.com/v1/sources \
-H "Authorization: Bearer $SOURCEFINCH_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name":"Rules","url":"https://example.gov/rules.json","rights":true,
"recipe":{"format":"json","items":"$.results[*]","fields":{"id":"$.id","title":"$.title"}},
"schedule":"daily","key_field":"id"}'
curl -X POST https://sourcefinch.com/v1/sources/<source id>/runs \
-H "Authorization: Bearer $SOURCEFINCH_API_KEY" -H "Idempotency-Key: $(uuidgen)"The source's origin must be approved for your workspace first (the console does this when you add a source). Questions? Email hello@sourcefinch.com.