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

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.

HTTPcodeMeaning
400validationInvalid request
401unauthenticatedAuthentication required
402plan_limitPlan limit reached
403forbiddenNot allowed
404not_foundNot found
409conflictConflict
409policyRefused by policy
422idempotency_mismatchIdempotency key reused with a different request
429rate_limitedToo many requests
500internalRequest 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.