Source Material Curator

API reference

62 endpoints, 35of them consumer-facing. Generated from SMC's route manifest — a route cannot ship without an entry here, and an entry cannot outlive its route.

Authentication

Send X-SMC-API-Key, and optionally X-SMC-Consumer-App to identify which app is calling. Some endpoints additionally require a scoped credential carrying the named capability — a shared key is refused on those.

buckets

GET/api/smc/bucketsread:buckets

Organisation buckets visible to the calling credential.

Returns: { buckets: [...] }

Auth: API key or scoped key · audited

GET/api/smc/buckets/{bucketId}/materialsread:bucket_materials

Materials in a bucket. Membership survives takedown — eligibility is re-checked per read, so a member may be withheld.

Returns: { materials: [...] } with withheld members reported rather than silently dropped.

Auth: API key or scoped key · audited

chunks

GET/api/smc/chunks

Chunks across materials.

Returns: { chunks: [...] }

Auth: API key · audited

GET/api/smc/chunks/{id}

One chunk by id.

Returns: { chunk }

Auth: API key · audited

citations

GET/api/smc/citations/chunk/{id}read:citation

Durable citation payload for a chunk, bound by content hash.

Returns: { citation }

Auth: API key or scoped key · audited

GET/api/smc/citations/material/{key}

Durable citation payload for a material.

Returns: { citation }

Auth: API key · audited

classifications

GET/api/smc/classificationsread:classification_receipts

Approved and stale classification receipts for one exact authority/subject identity.

subject_authority(query)
Exact HTTP(S) authority; required once.
subject_id(query)
Exact stable subject id; required once.

Returns: { subject_authority, subject_id, items, total }; items contain approved or stale receipts only. Out-of-scope and unknown subjects are both 404.

Auth: API key or scoped key · audited

curation requests

GET/api/smc/curation-requests

Curation requests a consumer has raised.

status(query)
`fulfilled` also returns the linked material keys.

Returns: { requests: [...] }

Auth: API key · audited

POST/api/smc/curation-requests

Raise an open-ended curation request ("find me documents about X").

Returns: The created request.

Auth: API key · audited

GET/api/smc/curation-requests/{id}

One curation request.

Returns: { request }

Auth: API key

GET/api/smc/curation-requests/recent-fulfilments

Cursored poll of recently fulfilled requests, for consumers that bind results back.

Returns: { fulfilments: [...], next_cursor }

Auth: API key

materials

GET/api/smc/materials

List materials, filtered by country, review status, source and an active exact taxonomy pin.

country(query)
ISO 3166-1 alpha-2. Alpha-3 matches nothing — SMC stores alpha-2.
review_status(query)
Consumer-facing review status, not the internal status column.
classification(query)
Exact schemeKey:notation. Resolves the scheme's active release pin and matches approved assignments only.
limit(query)
Page size.

Returns: { materials: [...] } — review_status replaces the internal status field.

Auth: API key · audited

POST/api/smc/materials

Register a material.

Returns: The created material row.

Auth: API key · audited

GET/api/smc/materials/{key}read:material

One material with its artefacts, chunk count, source and provenance.

key(path)
shared_material_key.

Returns: { material, artefacts, chunkCount, source, acquisitionProvenance, latestConversionAttempt }

Auth: API key or scoped key · audited

PATCH/api/smc/materials/{key}

Update a material's metadata.

Returns: The updated material.

Auth: API key · audited

POST/api/smc/materials/{key}/accept

Accept a material into the served corpus.

Returns: The updated row — note it carries the internal `status` field, unlike the list endpoints.

Auth: API key

GET/api/smc/materials/{key}/chunksread:material_chunks

A material's chunks, for retrieval and citation.

granularity(query)
Chunk granularity; compound is the shipped default.
fields(query)
Projection. `chunk_id,hash_sha256` returns a manifest with no text (contract v1.9).
conversion_id(query)
Pin to one conversion. Undocumented before this batch.

Returns: { chunks: [...] }

Auth: API key or scoped key · audited

GET/api/smc/materials/{key}/citation

Citation payload for a material. An alias — the handler is the citations route.

Returns: Same as the citations endpoint.

Auth: API key · audited · alias of GET /api/smc/citations/material/[key]

GET/api/smc/materials/{key}/markdown

The converted markdown, subject to the material's reuse policy.

Returns: Markdown, or 403 when the reuse policy withholds it.

Auth: API key · audited

GET/api/smc/materials/{key}/previewsread:material_previews

Page previews of the source document, bound to one conversion (contract v1.16 candidate). Metadata and locators only.

conversion_id(query)
Pin to one conversion. Defaults to the material's current one.

Returns: { material_key, conversion_id, is_current_conversion, reuse_decision, previews: [...], total }. `previews` is empty when the recorded rights decision withholds page images.

Auth: API key or scoped key · audited

GET/api/smc/materials/{key}/previews/{previewId}/contentread:material_previews

The preview image bytes. Proxied, never redirected or signed, so authorisation is re-decided on every retrieval.

Returns: image/webp or image/png with ETag, Last-Modified and Content-Length; 304 on If-None-Match; 404 for anything withheld.

Auth: API key or scoped key · audited

POST/api/smc/materials/{key}/reject

Reject a material.

Returns: The updated row (carries the internal `status` field).

Auth: API key

POST/api/smc/materials/{key}/score

Record authority, relevance and normativity scores.

Returns: The updated row (carries the internal `status` field).

Auth: API key

GET/api/smc/materials/{key}/versions

The version chain for a material.

Returns: { versions: [...] }

Auth: API key

mutations

GET/api/smc/mutations

Change feed, for consumers keeping a local mirror in step.

since(query)
ISO timestamp or cursor.
event_types(query)
Comma-separated filter.
limit(query)
Page size.

Returns: { events: [...] }

Auth: API key · audited

source requests

GET/api/smc/source-requests

Source requests raised by consumers.

Returns: { requests: [...] }

Auth: API key · audited

POST/api/smc/source-requests

Ask SMC to consider a specific publisher.

Returns: The created request.

Auth: API key · audited

GET/api/smc/source-requests/recent-approvals

Cursored poll of recently approved source requests.

Returns: { approvals: [...], next_cursor }

Auth: API key

sources

GET/api/smc/sources

List curated sources.

Returns: { sources: [...] }

Auth: API key · audited

POST/api/smc/sources

Register a source.

Returns: The created source.

Auth: API key · audited

GET/api/smc/sources/{id}

One source with its materials.

Returns: { source, materials } — materials are returned unprojected; treat extra fields as internal.

Auth: API key · audited

PATCH/api/smc/sources/{id}

Update a source.

Returns: The updated source.

Auth: API key · audited

POST/api/smc/sources/{id}/approve

Approve a candidate source.

Returns: { ok: true }

Auth: API key

POST/api/smc/sources/{id}/reject

Reject a candidate source.

Returns: { ok: true }

Auth: API key

vocabularies

GET/api/smc/vocabularies/{vocabulary}read:vocabulary

The terms of a governed vocabulary, retired ones included and flagged. Only material_type is served — jurisdiction_level has rows but nothing reads them, so publishing them would advertise a list that is not the one in force.

vocabulary(path)
material_type (the only vocabulary served today; anything else is a 404 naming what is available).

Returns: { vocabulary, terms: [{ value, label, description, deprecated, deprecated_reason }], total } — unpaginated, with an ETag; send If-None-Match for a 304.

Auth: API key or scoped key · audited

Internal endpoints

These live on the same URL prefix but are not part of the consumer contract — scheduler dispatchers, admin-only operations, and reads whose shape is not promised. They are listed rather than hidden: an endpoint that exists but is undocumented is how one ends up on the public surface by accident, which is exactly what happened to the source-check history.