REST API for the Document Management domain — the central store for uploaded files and their metadata across all safety net programs.
Upload model: A document and its first version are created atomically via POST /documents (multipart/form-data). Subsequent versions are uploaded via POST /documents/{documentId}/document-versions. File content is delivered via GET /document-versions/{documentVersionId}/content (proxy by default; states may overlay to redirect).
Context passthrough: Callers attach correlation context to a document via metadata at creation or via PUT /documents/{documentId}/metadata/{domain} after the fact. Metadata is echoed in events so downstream consumers can correlate without additional lookups. Keys are structured as nested objects per domain namespace — { "intake": { "verificationId": "..." } }.
Document types: Baseline types are seeded from document-management-config.yaml. States add program-specific types at runtime via POST /document-types.
Status: Alpha — Breaking changes expected.
Base URL: https://api.example.com/document-management
Documents
Document records and file upload.
▶
GET
/documents
List documents
#
Retrieve a paginated list of documents. Filter by document type or subject via document links.
Parameters
| Name |
Type |
In |
Req |
Description |
| ▶q |
string |
query |
|
Search query using field:value syntax. Multiple conditions separated by |
Search query using field:value syntax. Multiple conditions separated by spaces are ANDed together. URL Encoding: This parameter must be URL-encoded when sent over HTTP. Most HTTP clients handle this automatically. Examples in this documentation show human-readable syntax for clarity. Syntax| Pattern | Description | Example |
|---|
term | Full-text exact match | john | term | Full-text contains | john | term* | Full-text starts with | john* | *term | Full-text ends with | *smith | field:value | Exact match on field | status:approved | field:value | Contains (case-insensitive) | name:john | field:value* | Starts with | name:john* | field:*value | Ends with | email:*@example.com | field:"value" | Quoted value (for spaces) | name:"john doe" | field.nested:value | Nested field (dot notation) | address.state:CA | field:>value | Greater than | income:>1000 | field:>=value | Greater than or equal | income:>=1000 | field:<value | Less than | income:<5000 | field:<=value | Less than or equal | income:<=5000 | field:val1,val2 | Match any value (OR) | status:approved,pending | -field:value | Exclude / negate | -status:denied | field:* | Field exists (not null) | email:* | -field:* | Field does not exist | -deletedAt:* |
Examplesjohn — exact match for "john" in searchable fieldsjohn — contains "john" in searchable fieldsname:smith — name contains "smith" (case-insensitive)email:*@example.com — email ends with "@example.com"status:approved — exact match on status fieldstatus:approved,pending — status is "approved" OR "pending"income:>=1000 — income greater than or equal to 1000created:>2024-01-01 — created after January 1, 2024status:approved income:>=1000 — approved AND income >= 1000 (multiple conditions)-status:denied — exclude records with status "denied"-deletedAt:* — only records where deletedAt does not existapplicant.state:CA — nested field filter
URL Encoding ReferenceWhen manually constructing URLs, encode these characters: | Character | Encoded |
|---|
| (space) | %20 or + | " | %22 | : | %3A | > | %3E | < | %3C | , | %2C |
Example: `` Human-readable: q=status:approved income:>=1000 URL-encoded: q=status%3Aapproved%20income%3A%3E%3D1000 `` |
| limit |
integer |
query |
|
Maximum number of items to return (1-100). |
| offset |
integer |
query |
|
Number of items to skip before collecting results. |
| ▶sort |
string |
query |
|
Comma-separated list of fields to sort the response by. Prefix a field |
Comma-separated list of fields to sort the response by. Prefix a field with - for descending order. The first field is the primary sort; subsequent fields are tie-breakers in declaration order. URL Encoding: This parameter must be URL-encoded when sent over HTTP. Most HTTP clients handle this automatically. Examples below show human-readable syntax for clarity. Which fields a given list endpoint allows is declared in the operation's x-sortable.fields extension. Sending a field name not present in that list returns 400 FIELD_NOT_SORTABLE. Sending a field name that doesn't exist on the resource schema returns 400 INVALID_SORT_FIELD. When this parameter is omitted, the operation's x-sortable.default (if declared) is applied; otherwise no client-driven sort is applied. A configured tie-breaker (default id) is always appended for stable pagination. See api-patterns.yaml#sorting for the full convention and docs/architecture/x-extensions.md for the extension shape. Syntax| Pattern | Description | Example |
|---|
fieldName | Ascending | sort=createdAt | -fieldName | Descending | sort=-createdAt | field1,field2 | Multi-field | sort=status,-priority | nested.field | Nested field via dot notation | sort=name.lastName |
Examplessort=createdAt — oldest firstsort=-createdAt — newest firstsort=-priority,dueDate — highest priority first, then oldest due datesort=name.lastName,name.firstName — alphabetical by surname, then given name
|
| documentTypeId |
string |
query |
|
|
| lifecycleState |
▶ DocumentLifecycleState |
query |
|
Filter by lifecycle state. |
Responses
200
A paginated list of documents.
▶
DocumentList
▶
items
array[Document]
required
id
string (uuid)
required
documentTypeId
string (uuid)
required
Links to the DocumentType governing retention rules for this document.
title
string
required
Human-readable label (e.g. "Jane Smith — Pay Stub March 2026"). Distinct from the upload filename.
documentDate
string (date)
The date on the document's face (e.g. a pay stub date). Required when the document type's retentionTrigger is document_date.
▶
lifecycleState
DocumentLifecycleState
required
Where the document is in its records management lifecycle.
No additional fields
legalHold
boolean
required
When true, the document cannot advance to pending_disposition regardless of retention schedule.
latestVersionId
string (uuid)
required
ID of the most recent DocumentVersion. Single authoritative pointer to the current file.
retentionDeadline
string (date)
The date when the retention period ends. Null until the document enters retained state.
metadata
object
Opaque correlation context structured as nested objects per domain namespace. Example: {"intake":{"verificationId":"ver-abc-123"},"workflow":{"taskId":"tsk-xyz-456"}}
dispositionApprovedBy
string
Identity of the records manager who authorized destruction. Null until destroyed state.
dispositionApprovedAt
string (date-time)
When destruction was authorized. Null until destroyed state.
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
400
The request is malformed or contains invalid parameters.
▶
BadRequest
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
POST
/documents
Upload a document
#
Create a document and its first version atomically. The document is immediately active. Accepts multipart/form-data with the file bytes and document metadata in a single request.
If the adapter's virus scanner rejects the file, returns 422 with error code file_rejected_by_virus_scan and no document is created.
Pass metadata as a JSON string in the multipart body to attach correlation context at creation time (e.g. { "intake": { "verificationId": "ver-abc" } }).
Request body required
file
string (binary)
required
The file to upload.
documentTypeId
string (uuid)
required
Document type — determines retention rules and classification.
title
string
required
Human-readable label for the document (e.g. "John Smith — Pay Stub March 2026"). Distinct from the upload filename.
documentDate
string (date)
The date printed on or associated with the document (e.g. the date on a pay stub). Required when the document type's retentionTrigger is document_date.
metadata
string
JSON string. Correlation context structured as nested objects per domain namespace. Example: {"intake":{"verificationId":"ver-abc-123"}}
Responses
201
Document and first version created successfully.
▶
Document
id
string (uuid)
required
documentTypeId
string (uuid)
required
Links to the DocumentType governing retention rules for this document.
title
string
required
Human-readable label (e.g. "Jane Smith — Pay Stub March 2026"). Distinct from the upload filename.
documentDate
string (date)
The date on the document's face (e.g. a pay stub date). Required when the document type's retentionTrigger is document_date.
▶
lifecycleState
DocumentLifecycleState
required
Where the document is in its records management lifecycle.
No additional fields
legalHold
boolean
required
When true, the document cannot advance to pending_disposition regardless of retention schedule.
latestVersionId
string (uuid)
required
ID of the most recent DocumentVersion. Single authoritative pointer to the current file.
retentionDeadline
string (date)
The date when the retention period ends. Null until the document enters retained state.
metadata
object
Opaque correlation context structured as nested objects per domain namespace. Example: {"intake":{"verificationId":"ver-abc-123"},"workflow":{"taskId":"tsk-xyz-456"}}
dispositionApprovedBy
string
Identity of the records manager who authorized destruction. Null until destroyed state.
dispositionApprovedAt
string (date-time)
When destruction was authorized. Null until destroyed state.
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
400
The request is malformed or contains invalid parameters.
▶
BadRequest
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
422
The request was well-formed but contained semantic errors.
▶
UnprocessableEntity
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
GET
/documents/{documentId}
Get a document
#
Retrieve a single document by identifier. Documents in destroyed state are returned with their metadata intact but file content is no longer accessible.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentId |
string |
path |
✓ |
Unique identifier of the document. |
Responses
200
Document retrieved successfully.
▶
Document
id
string (uuid)
required
documentTypeId
string (uuid)
required
Links to the DocumentType governing retention rules for this document.
title
string
required
Human-readable label (e.g. "Jane Smith — Pay Stub March 2026"). Distinct from the upload filename.
documentDate
string (date)
The date on the document's face (e.g. a pay stub date). Required when the document type's retentionTrigger is document_date.
▶
lifecycleState
DocumentLifecycleState
required
Where the document is in its records management lifecycle.
No additional fields
legalHold
boolean
required
When true, the document cannot advance to pending_disposition regardless of retention schedule.
latestVersionId
string (uuid)
required
ID of the most recent DocumentVersion. Single authoritative pointer to the current file.
retentionDeadline
string (date)
The date when the retention period ends. Null until the document enters retained state.
metadata
object
Opaque correlation context structured as nested objects per domain namespace. Example: {"intake":{"verificationId":"ver-abc-123"},"workflow":{"taskId":"tsk-xyz-456"}}
dispositionApprovedBy
string
Identity of the records manager who authorized destruction. Null until destroyed state.
dispositionApprovedAt
string (date-time)
When destruction was authorized. Null until destroyed state.
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
PATCH
/documents/{documentId}
Update a document
#
Update mutable document fields. Metadata is not patchable here — use the namespace-level metadata endpoints instead.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentId |
string |
path |
✓ |
Unique identifier of the document. |
Request body required
▶
DocumentUpdate
documentDate
string (date)
Responses
200
Document updated successfully.
▶
Document
id
string (uuid)
required
documentTypeId
string (uuid)
required
Links to the DocumentType governing retention rules for this document.
title
string
required
Human-readable label (e.g. "Jane Smith — Pay Stub March 2026"). Distinct from the upload filename.
documentDate
string (date)
The date on the document's face (e.g. a pay stub date). Required when the document type's retentionTrigger is document_date.
▶
lifecycleState
DocumentLifecycleState
required
Where the document is in its records management lifecycle.
No additional fields
legalHold
boolean
required
When true, the document cannot advance to pending_disposition regardless of retention schedule.
latestVersionId
string (uuid)
required
ID of the most recent DocumentVersion. Single authoritative pointer to the current file.
retentionDeadline
string (date)
The date when the retention period ends. Null until the document enters retained state.
metadata
object
Opaque correlation context structured as nested objects per domain namespace. Example: {"intake":{"verificationId":"ver-abc-123"},"workflow":{"taskId":"tsk-xyz-456"}}
dispositionApprovedBy
string
Identity of the records manager who authorized destruction. Null until destroyed state.
dispositionApprovedAt
string (date-time)
When destruction was authorized. Null until destroyed state.
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
422
The request was well-formed but contained semantic errors.
▶
UnprocessableEntity
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
PUT
/documents/{documentId}/metadata/{domain}
Set domain metadata on a document
#
Replace the calling domain's entire metadata namespace on a document. Other domains' namespaces are unaffected. Used for context passthrough when metadata is not known at upload time.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentId |
string |
path |
✓ |
Unique identifier of the document. |
| domain |
string |
path |
✓ |
The calling domain's namespace to set or remove. enumclient-management data-exchange document-management eligibility intake workflow |
Responses
200
Metadata set successfully. Returns the updated document.
▶
Document
id
string (uuid)
required
documentTypeId
string (uuid)
required
Links to the DocumentType governing retention rules for this document.
title
string
required
Human-readable label (e.g. "Jane Smith — Pay Stub March 2026"). Distinct from the upload filename.
documentDate
string (date)
The date on the document's face (e.g. a pay stub date). Required when the document type's retentionTrigger is document_date.
▶
lifecycleState
DocumentLifecycleState
required
Where the document is in its records management lifecycle.
No additional fields
legalHold
boolean
required
When true, the document cannot advance to pending_disposition regardless of retention schedule.
latestVersionId
string (uuid)
required
ID of the most recent DocumentVersion. Single authoritative pointer to the current file.
retentionDeadline
string (date)
The date when the retention period ends. Null until the document enters retained state.
metadata
object
Opaque correlation context structured as nested objects per domain namespace. Example: {"intake":{"verificationId":"ver-abc-123"},"workflow":{"taskId":"tsk-xyz-456"}}
dispositionApprovedBy
string
Identity of the records manager who authorized destruction. Null until destroyed state.
dispositionApprovedAt
string (date-time)
When destruction was authorized. Null until destroyed state.
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
422
The request was well-formed but contained semantic errors.
▶
UnprocessableEntity
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
DELETE
/documents/{documentId}/metadata/{domain}
Remove domain metadata from a document
#
Remove the calling domain's entire metadata namespace from a document.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentId |
string |
path |
✓ |
Unique identifier of the document. |
| domain |
string |
path |
✓ |
The calling domain's namespace to set or remove. enumclient-management data-exchange document-management eligibility intake workflow |
Responses
204
Metadata removed successfully.
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
DocumentVersions
Immutable version history for documents.
▶
POST
/documents/{documentId}/document-versions
Upload a new version
#
Upload a subsequent version of an existing document. Creates an immutable DocumentVersion record and updates Document.latestVersionId. Each upload preserves prior versions so the file that was current at any point in time is recoverable (required by 7 CFR § 272.1 and 45 CFR § 164.312).
If the adapter's virus scanner rejects the file, returns 422 with error code file_rejected_by_virus_scan and no version is created.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentId |
string |
path |
✓ |
Unique identifier of the document. |
Request body required
file
string (binary)
required
The replacement file to upload.
Responses
201
Version created successfully.
▶
DocumentVersion
id
string (uuid)
required
documentId
string (uuid)
required
Links to the parent Document.
versionNumber
integer
required
Sequential version number. 1 for the first version.
fileName
string
required
Original filename as uploaded.
mimeType
string
required
MIME type of the uploaded file.
sizeBytes
integer
required
File size in bytes.
contentHash
string
required
SHA-256 hash of the file bytes. Stored for duplicate detection; baseline enforces nothing.
uploadedById
string
required
Identity of the uploader. Required for HIPAA chain-of-custody (45 CFR § 164.312).
createdAt
string (date-time)
required
Authoritative upload timestamp.
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
422
The request was well-formed but contained semantic errors.
▶
UnprocessableEntity
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
GET
/document-versions/{documentVersionId}
Get a document version
#
Retrieve metadata for a specific document version. Does not return file bytes — use the content endpoint for that.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentVersionId |
string |
path |
✓ |
Unique identifier of the document version. |
Responses
200
Document version retrieved successfully.
▶
DocumentVersion
id
string (uuid)
required
documentId
string (uuid)
required
Links to the parent Document.
versionNumber
integer
required
Sequential version number. 1 for the first version.
fileName
string
required
Original filename as uploaded.
mimeType
string
required
MIME type of the uploaded file.
sizeBytes
integer
required
File size in bytes.
contentHash
string
required
SHA-256 hash of the file bytes. Stored for duplicate detection; baseline enforces nothing.
uploadedById
string
required
Identity of the uploader. Required for HIPAA chain-of-custody (45 CFR § 164.312).
createdAt
string (date-time)
required
Authoritative upload timestamp.
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
GET
/document-versions/{documentVersionId}/content
Get file content
#
Retrieve the file bytes for a document version. Emits a document_version.accessed audit event on every call (required by HIPAA 45 CFR § 164.312).
The baseline response is 200 with the file streamed as application/octet-stream (proxy delivery). States that prefer redirect delivery add x-content-delivery: redirect via overlay — the response then returns 302 to a time-limited signed storage URL. Both response shapes are documented here so clients handle either.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentVersionId |
string |
path |
✓ |
Unique identifier of the document version. |
Responses
200
File content (proxy delivery).
302
Redirect to signed storage URL (redirect delivery — opt-in via overlay).
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
410
File content is no longer accessible — document has been destroyed.
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
DocumentTypes
Document type catalog — retention rules and classification.
▶
GET
/document-types
List document types
#
Retrieve the catalog of document types. Includes both config-seeded (system) and runtime-created (user) types.
Parameters
| Name |
Type |
In |
Req |
Description |
| ▶q |
string |
query |
|
Search query using field:value syntax. Multiple conditions separated by |
Search query using field:value syntax. Multiple conditions separated by spaces are ANDed together. URL Encoding: This parameter must be URL-encoded when sent over HTTP. Most HTTP clients handle this automatically. Examples in this documentation show human-readable syntax for clarity. Syntax| Pattern | Description | Example |
|---|
term | Full-text exact match | john | term | Full-text contains | john | term* | Full-text starts with | john* | *term | Full-text ends with | *smith | field:value | Exact match on field | status:approved | field:value | Contains (case-insensitive) | name:john | field:value* | Starts with | name:john* | field:*value | Ends with | email:*@example.com | field:"value" | Quoted value (for spaces) | name:"john doe" | field.nested:value | Nested field (dot notation) | address.state:CA | field:>value | Greater than | income:>1000 | field:>=value | Greater than or equal | income:>=1000 | field:<value | Less than | income:<5000 | field:<=value | Less than or equal | income:<=5000 | field:val1,val2 | Match any value (OR) | status:approved,pending | -field:value | Exclude / negate | -status:denied | field:* | Field exists (not null) | email:* | -field:* | Field does not exist | -deletedAt:* |
Examplesjohn — exact match for "john" in searchable fieldsjohn — contains "john" in searchable fieldsname:smith — name contains "smith" (case-insensitive)email:*@example.com — email ends with "@example.com"status:approved — exact match on status fieldstatus:approved,pending — status is "approved" OR "pending"income:>=1000 — income greater than or equal to 1000created:>2024-01-01 — created after January 1, 2024status:approved income:>=1000 — approved AND income >= 1000 (multiple conditions)-status:denied — exclude records with status "denied"-deletedAt:* — only records where deletedAt does not existapplicant.state:CA — nested field filter
URL Encoding ReferenceWhen manually constructing URLs, encode these characters: | Character | Encoded |
|---|
| (space) | %20 or + | " | %22 | : | %3A | > | %3E | < | %3C | , | %2C |
Example: `` Human-readable: q=status:approved income:>=1000 URL-encoded: q=status%3Aapproved%20income%3A%3E%3D1000 `` |
| limit |
integer |
query |
|
Maximum number of items to return (1-100). |
| offset |
integer |
query |
|
Number of items to skip before collecting results. |
| ▶sort |
string |
query |
|
Comma-separated list of fields to sort the response by. Prefix a field |
Comma-separated list of fields to sort the response by. Prefix a field with - for descending order. The first field is the primary sort; subsequent fields are tie-breakers in declaration order. URL Encoding: This parameter must be URL-encoded when sent over HTTP. Most HTTP clients handle this automatically. Examples below show human-readable syntax for clarity. Which fields a given list endpoint allows is declared in the operation's x-sortable.fields extension. Sending a field name not present in that list returns 400 FIELD_NOT_SORTABLE. Sending a field name that doesn't exist on the resource schema returns 400 INVALID_SORT_FIELD. When this parameter is omitted, the operation's x-sortable.default (if declared) is applied; otherwise no client-driven sort is applied. A configured tie-breaker (default id) is always appended for stable pagination. See api-patterns.yaml#sorting for the full convention and docs/architecture/x-extensions.md for the extension shape. Syntax| Pattern | Description | Example |
|---|
fieldName | Ascending | sort=createdAt | -fieldName | Descending | sort=-createdAt | field1,field2 | Multi-field | sort=status,-priority | nested.field | Nested field via dot notation | sort=name.lastName |
Examplessort=createdAt — oldest firstsort=-createdAt — newest firstsort=-priority,dueDate — highest priority first, then oldest due datesort=name.lastName,name.firstName — alphabetical by surname, then given name
|
Responses
200
A paginated list of document types.
▶
DocumentTypeList
▶
items
array[DocumentType]
required
id
string (uuid)
required
retentionYears
integer
required
How many years documents of this type must be retained after the retention trigger fires.
▶
retentionTrigger
RetentionTrigger
required
The event that starts the retention clock for this document type.
No additional fields
source
string
required
read-only
"system" types are seeded from config and cannot be deleted. "user" types are created at runtime and can be deleted.
enumsystem user
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
400
The request is malformed or contains invalid parameters.
▶
BadRequest
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
POST
/document-types
Create a document type
#
Create a state-defined document type. Runtime-created types are marked source: user and can be deleted via the API. Config-seeded types cannot be deleted.
Request body required
▶
DocumentTypeCreate
retentionYears
integer
required
▶
retentionTrigger
RetentionTrigger
required
The event that starts the retention clock for this document type.
No additional fields
Responses
201
Document type created successfully.
▶
DocumentType
id
string (uuid)
required
retentionYears
integer
required
How many years documents of this type must be retained after the retention trigger fires.
▶
retentionTrigger
RetentionTrigger
required
The event that starts the retention clock for this document type.
No additional fields
source
string
required
read-only
"system" types are seeded from config and cannot be deleted. "user" types are created at runtime and can be deleted.
enumsystem user
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
422
The request was well-formed but contained semantic errors.
▶
UnprocessableEntity
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
GET
/document-types/{documentTypeId}
Get a document type
#
Retrieve a single document type by identifier.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentTypeId |
string |
path |
✓ |
Unique identifier of the document type. |
Responses
200
Document type retrieved successfully.
▶
DocumentType
id
string (uuid)
required
retentionYears
integer
required
How many years documents of this type must be retained after the retention trigger fires.
▶
retentionTrigger
RetentionTrigger
required
The event that starts the retention clock for this document type.
No additional fields
source
string
required
read-only
"system" types are seeded from config and cannot be deleted. "user" types are created at runtime and can be deleted.
enumsystem user
createdAt
string (date-time)
required
updatedAt
string (date-time)
required
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
DELETE
/document-types/{documentTypeId}
Delete a document type
#
Delete a user-created document type. Returns 409 if the type is config-seeded (source: system) or if documents of this type exist.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentTypeId |
string |
path |
✓ |
Unique identifier of the document type. |
Responses
204
Document type deleted successfully.
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
409
A conflict occurred with the current state of the resource.
▶
Conflict
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
DocumentLinks
Associations between documents and program records (applications, cases, etc.).
▶
GET
/document-links
List document links
#
Retrieve document-subject associations. Filter by documentId or subjectId to find all documents for a subject or all subjects for a document.
Parameters
| Name |
Type |
In |
Req |
Description |
| ▶q |
string |
query |
|
Search query using field:value syntax. Multiple conditions separated by |
Search query using field:value syntax. Multiple conditions separated by spaces are ANDed together. URL Encoding: This parameter must be URL-encoded when sent over HTTP. Most HTTP clients handle this automatically. Examples in this documentation show human-readable syntax for clarity. Syntax| Pattern | Description | Example |
|---|
term | Full-text exact match | john | term | Full-text contains | john | term* | Full-text starts with | john* | *term | Full-text ends with | *smith | field:value | Exact match on field | status:approved | field:value | Contains (case-insensitive) | name:john | field:value* | Starts with | name:john* | field:*value | Ends with | email:*@example.com | field:"value" | Quoted value (for spaces) | name:"john doe" | field.nested:value | Nested field (dot notation) | address.state:CA | field:>value | Greater than | income:>1000 | field:>=value | Greater than or equal | income:>=1000 | field:<value | Less than | income:<5000 | field:<=value | Less than or equal | income:<=5000 | field:val1,val2 | Match any value (OR) | status:approved,pending | -field:value | Exclude / negate | -status:denied | field:* | Field exists (not null) | email:* | -field:* | Field does not exist | -deletedAt:* |
Examplesjohn — exact match for "john" in searchable fieldsjohn — contains "john" in searchable fieldsname:smith — name contains "smith" (case-insensitive)email:*@example.com — email ends with "@example.com"status:approved — exact match on status fieldstatus:approved,pending — status is "approved" OR "pending"income:>=1000 — income greater than or equal to 1000created:>2024-01-01 — created after January 1, 2024status:approved income:>=1000 — approved AND income >= 1000 (multiple conditions)-status:denied — exclude records with status "denied"-deletedAt:* — only records where deletedAt does not existapplicant.state:CA — nested field filter
URL Encoding ReferenceWhen manually constructing URLs, encode these characters: | Character | Encoded |
|---|
| (space) | %20 or + | " | %22 | : | %3A | > | %3E | < | %3C | , | %2C |
Example: `` Human-readable: q=status:approved income:>=1000 URL-encoded: q=status%3Aapproved%20income%3A%3E%3D1000 `` |
| limit |
integer |
query |
|
Maximum number of items to return (1-100). |
| offset |
integer |
query |
|
Number of items to skip before collecting results. |
| ▶sort |
string |
query |
|
Comma-separated list of fields to sort the response by. Prefix a field |
Comma-separated list of fields to sort the response by. Prefix a field with - for descending order. The first field is the primary sort; subsequent fields are tie-breakers in declaration order. URL Encoding: This parameter must be URL-encoded when sent over HTTP. Most HTTP clients handle this automatically. Examples below show human-readable syntax for clarity. Which fields a given list endpoint allows is declared in the operation's x-sortable.fields extension. Sending a field name not present in that list returns 400 FIELD_NOT_SORTABLE. Sending a field name that doesn't exist on the resource schema returns 400 INVALID_SORT_FIELD. When this parameter is omitted, the operation's x-sortable.default (if declared) is applied; otherwise no client-driven sort is applied. A configured tie-breaker (default id) is always appended for stable pagination. See api-patterns.yaml#sorting for the full convention and docs/architecture/x-extensions.md for the extension shape. Syntax| Pattern | Description | Example |
|---|
fieldName | Ascending | sort=createdAt | -fieldName | Descending | sort=-createdAt | field1,field2 | Multi-field | sort=status,-priority | nested.field | Nested field via dot notation | sort=name.lastName |
Examplessort=createdAt — oldest firstsort=-createdAt — newest firstsort=-priority,dueDate — highest priority first, then oldest due datesort=name.lastName,name.firstName — alphabetical by surname, then given name
|
| documentId |
string |
query |
|
|
| subjectId |
string |
query |
|
Filter by subject (application, case, etc.). |
| subjectType |
string |
query |
|
|
Responses
200
A paginated list of document links.
▶
DocumentLinkList
▶
items
array[DocumentLink]
required
id
string (uuid)
required
documentId
string (uuid)
required
subjectType
string
required
The kind of record this document is linked to (e.g. application, case). States add values via overlay.
enumapplication case
subjectId
string (uuid)
required
ID of the linked record.
linkedBy
string
required
Identity of who created the link. Required for HIPAA chain-of-custody (45 CFR § 164.312).
closedAt
string (date-time)
Set when the subject closes. Used as the retention trigger timestamp for case_closure and application_denial retention types.
createdAt
string (date-time)
required
400
The request is malformed or contains invalid parameters.
▶
BadRequest
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
POST
/document-links
Link a document to a subject
#
Associate a document with a program record (application, case, etc.). Enables cross-program reuse — the same document can satisfy obligations for multiple programs without duplication.
Request body required
▶
DocumentLinkCreate
documentId
string (uuid)
required
subjectType
string
required
enumapplication case
subjectId
string (uuid)
required
Responses
201
Document link created successfully.
▶
DocumentLink
id
string (uuid)
required
documentId
string (uuid)
required
subjectType
string
required
The kind of record this document is linked to (e.g. application, case). States add values via overlay.
enumapplication case
subjectId
string (uuid)
required
ID of the linked record.
linkedBy
string
required
Identity of who created the link. Required for HIPAA chain-of-custody (45 CFR § 164.312).
closedAt
string (date-time)
Set when the subject closes. Used as the retention trigger timestamp for case_closure and application_denial retention types.
createdAt
string (date-time)
required
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
422
The request was well-formed but contained semantic errors.
▶
UnprocessableEntity
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
▶
GET
/document-links/{documentLinkId}
Get a document link
#
Retrieve a single document-subject association by identifier.
Parameters
| Name |
Type |
In |
Req |
Description |
| documentLinkId |
string |
path |
✓ |
Unique identifier of the document link. |
Responses
200
Document link retrieved successfully.
▶
DocumentLink
id
string (uuid)
required
documentId
string (uuid)
required
subjectType
string
required
The kind of record this document is linked to (e.g. application, case). States add values via overlay.
enumapplication case
subjectId
string (uuid)
required
ID of the linked record.
linkedBy
string
required
Identity of who created the link. Required for HIPAA chain-of-custody (45 CFR § 164.312).
closedAt
string (date-time)
Set when the subject closes. Used as the retention trigger timestamp for case_closure and application_denial retention types.
createdAt
string (date-time)
required
404
The requested resource was not found.
▶
NotFound
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.
500
An unexpected error occurred on the server.
▶
InternalError
code
string
required
Machine-readable error code.
message
string
required
Human-readable error description.
details
array[object]
Additional error details.