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
/api/smc/bucketsread:bucketsOrganisation buckets visible to the calling credential.
Returns: { buckets: [...] }
Auth: API key or scoped key · audited
/api/smc/buckets/{bucketId}/materialsread:bucket_materialsMaterials 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
/api/smc/chunksChunks across materials.
Returns: { chunks: [...] }
Auth: API key · audited
/api/smc/chunks/{id}One chunk by id.
Returns: { chunk }
Auth: API key · audited
citations
/api/smc/citations/chunk/{id}read:citationDurable citation payload for a chunk, bound by content hash.
Returns: { citation }
Auth: API key or scoped key · audited
/api/smc/citations/material/{key}Durable citation payload for a material.
Returns: { citation }
Auth: API key · audited
classifications
/api/smc/classificationsread:classification_receiptsApproved 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
/api/smc/curation-requestsCuration requests a consumer has raised.
- status(query)
- `fulfilled` also returns the linked material keys.
Returns: { requests: [...] }
Auth: API key · audited
/api/smc/curation-requestsRaise an open-ended curation request ("find me documents about X").
Returns: The created request.
Auth: API key · audited
/api/smc/curation-requests/{id}One curation request.
Returns: { request }
Auth: API key
/api/smc/curation-requests/recent-fulfilmentsCursored poll of recently fulfilled requests, for consumers that bind results back.
Returns: { fulfilments: [...], next_cursor }
Auth: API key
materials
/api/smc/materialsList 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
/api/smc/materialsRegister a material.
Returns: The created material row.
Auth: API key · audited
/api/smc/materials/{key}read:materialOne 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
/api/smc/materials/{key}Update a material's metadata.
Returns: The updated material.
Auth: API key · audited
/api/smc/materials/{key}/acceptAccept a material into the served corpus.
Returns: The updated row — note it carries the internal `status` field, unlike the list endpoints.
Auth: API key
/api/smc/materials/{key}/chunksread:material_chunksA 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
/api/smc/materials/{key}/citationCitation 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]
/api/smc/materials/{key}/markdownThe converted markdown, subject to the material's reuse policy.
Returns: Markdown, or 403 when the reuse policy withholds it.
Auth: API key · audited
/api/smc/materials/{key}/previewsread:material_previewsPage 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
/api/smc/materials/{key}/previews/{previewId}/contentread:material_previewsThe 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
/api/smc/materials/{key}/rejectReject a material.
Returns: The updated row (carries the internal `status` field).
Auth: API key
/api/smc/materials/{key}/scoreRecord authority, relevance and normativity scores.
Returns: The updated row (carries the internal `status` field).
Auth: API key
/api/smc/materials/{key}/versionsThe version chain for a material.
Returns: { versions: [...] }
Auth: API key
mutations
/api/smc/mutationsChange 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
/api/smc/source-requestsSource requests raised by consumers.
Returns: { requests: [...] }
Auth: API key · audited
/api/smc/source-requestsAsk SMC to consider a specific publisher.
Returns: The created request.
Auth: API key · audited
/api/smc/source-requests/recent-approvalsCursored poll of recently approved source requests.
Returns: { approvals: [...], next_cursor }
Auth: API key
sources
/api/smc/sourcesList curated sources.
Returns: { sources: [...] }
Auth: API key · audited
/api/smc/sourcesRegister a source.
Returns: The created source.
Auth: API key · audited
/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
/api/smc/sources/{id}Update a source.
Returns: The updated source.
Auth: API key · audited
/api/smc/sources/{id}/approveApprove a candidate source.
Returns: { ok: true }
Auth: API key
/api/smc/sources/{id}/rejectReject a candidate source.
Returns: { ok: true }
Auth: API key
vocabularies
/api/smc/vocabularies/{vocabulary}read:vocabularyThe 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.
GET /api/smc/audit/exportAdmin-session gated export of the audit log.POST /api/smc/courses/importRestricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.GET /api/smc/courses/jobsRestricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.POST /api/smc/courses/jobsRestricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.GET /api/smc/courses/jobs/{id}Restricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.POST /api/smc/courses/jobs/{id}/advanceRestricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.GET /api/smc/courses/jobs/{id}/exportRestricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.POST /api/smc/courses/jobs/{id}/receiptsRestricted to the immutable International Courses repository identity and its main catalogue workflow; ordinary consumer and MCP keys cannot write here.POST /api/smc/discovery/check-dueCloud Scheduler dispatcher for standing discovery queries.GET /api/smc/drive/browseAdmin-session gated; drives the Drive picker in the admin UI.POST /api/smc/drive/importAdmin-session gated import trigger.POST /api/smc/drive/pollCloud Scheduler dispatcher; advances in-flight Drive import batches.GET /api/smc/drive/status/{batch_id}Admin-session gated progress read.DELETE /api/smc/materials/{key}Destructive, and gated on a super-admin session rather than an API key.GET /api/smc/materials/{key}/artefactsReturns raw artefact rows including GCS object paths; no serializer yet.POST /api/smc/materials/{key}/convertTriggers the converter; an operational action, not part of the consumer contract.POST /api/smc/materials/{key}/deprecateAdmin-session gated lifecycle action.GET /api/smc/materials/{key}/obsidian-bundleReturns a zip for human download from the admin workbench.POST /api/smc/materials/{key}/supersedeAdmin-session gated lifecycle action.POST /api/smc/materials/{key}/uploadMultipart upload used by the admin UI; not a documented consumer capability.GET /api/smc/mutations/fixtureA static example payload for consumers writing an integration. Deliberately unauthenticated, and it contains no real data.POST /api/smc/notifications/digestCloud Scheduler dispatcher for the curator digest email.DELETE /api/smc/sources/{id}Destructive; admin-session gated.POST /api/smc/sources/{id}/checkTriggers a fetch of the source URL — an operational action.GET /api/smc/sources/{id}/checksOperational check history. Present on the contract-governed surface but absent from the contract (SCH-09); now serialized to an explicit field set rather than returning raw rows.POST /api/smc/sources/{id}/deprecateAdmin-session gated lifecycle action.POST /api/smc/sources/check-dueCloud Scheduler dispatcher. Also sweeps stuck materials, reaps abandoned jobs and polls crawls.