API reference
Approvals
5 operations in this area of the contract. Every one declares the permission it requires.
Contract version 0.2.0All areas
Operations
/v1/approvalsApproval requests
Queue metadata is available with `workflow.approval.read`. A `watchlists.entry.edit` request contains protected watchlist records; unless the caller also holds `watchlists.entry.read`, its payload and maker/checker rationales are replaced with the fixed restricted representation and `payload_restricted=true`; `subject_id` is the empty string because an entry-add subject embeds the protected external id. Action, subject type, digest, status, actors and timestamps remain visible so the queue can still route the request without disclosing its entry.
Show parameters and responsesHide parameters and responses
Parameters
| Name | In | Type | Description |
|---|---|---|---|
status | query | pending | approved | rejected | withdrawn | expired | — |
action | query | string | — |
limit | query | integer | Page size, capped at 200. |
cursor | query | string | Opaque keyset cursor from a previous response. Offset pagination is deliberately not offered: `OFFSET 500000` is a table scan, and if it were offered it would be used (ADR-0012). Only the collections that document this parameter can be resumed. The rest report `truncated: true` and refuse a cursor rather than silently returning the first page again — see the `truncated` field on the page schemas. |
Responses
200Approval requests, newest firstApprovalRequestPage
/v1/approvals/{approvalID}One approval request
For `watchlists.entry.edit`, the payload and free-text rationales are disclosed only when the caller also holds `watchlists.entry.read`. Otherwise the response blanks `subject_id`, preserves the non-identifying workflow metadata and sets `payload_restricted=true` with the fixed restricted payload marker.
Show parameters and responsesHide parameters and responses
Parameters
| Name | In | Type | Description |
|---|---|---|---|
approvalIDrequired | path | string | — |
Responses
200Approval requestApprovalRequest404—
/v1/approvals/{approvalID}/approveApprove a proposed change
Refused if the caller is the maker, and refused if the payload changed after it was proposed. The approval and the application of the change happen in one transaction, so an approval can never be recorded against a change that failed to apply (ADR-0008).
Deciding a `watchlists.entry.edit` request additionally requires `watchlists.entry.read`, so a generic workflow checker cannot approve protected watchlist facts blind. Its immutable decision event contains only the safe approval envelope and payload digest, never the subject identifier, raw payload or free-text rationales.
Show parameters and responsesHide parameters and responses
Parameters
| Name | In | Type | Description |
|---|---|---|---|
approvalIDrequired | path | string | — |
Responses
200Approved and appliedApprovalRequest403—409Four-eyes violation. `type` is `.../four-eyes-violation` when the caller is the maker or the payload digest no longer matches the proposal.
/v1/approvals/{approvalID}/customer-profile-previewExplicitly reveal an encrypted customer-profile proposal for checker review
A POST-only, on-demand disclosure for `onboarding.customer.field_change` requests that carry migration 00046's encrypted profile stage. The ordinary approval detail response and its server-rendered page continue to contain only the opaque stage id, ciphertext digest and changed-field names.
The caller must hold `workflow.approval.decide`, satisfy the tenant's MFA policy for that permission, be different from the maker, and hold one of the checker roles currently configured for this exact action. The request must still be pending. Before decrypting, the service verifies the immutable workflow digest and the tenant-scoped stage's exact approval, customer, maker, ciphertext digest and changed-field linkage. Cross-tenant rows are indistinguishable from missing rows under RLS.
A successful disclosure writes `workflow.approval.customer_profile_previewed` to the tamper-evident audit chain in the same transaction and is also classified as `data.accessed` approval-review content at the HTTP boundary. Audit state contains only identifiers, field names, the ciphertext digest and fixed access-classification metadata — never the proposed values. The response is `no-store`; values must not be copied into URLs, logs, workflow JSON or server-rendered HTML.
Show parameters and responsesHide parameters and responses
Parameters
| Name | In | Type | Description |
|---|---|---|---|
approvalIDrequired | path | string | — |
Responses
200The exact staged profile values available to this checker for this reviewCustomerProfileChangePreview403—404—409—410The subject key was destroyed under an approved erasure request
/v1/approvals/{approvalID}/rejectReject a proposed change
A reason is required, so an examiner can see why a control fired. Deciding a `watchlists.entry.edit` request additionally requires `watchlists.entry.read`, so a generic workflow checker cannot reject protected watchlist facts blind. The immutable decision event retains the safe approval envelope and digest, not the raw subject identifier, payload or free-text rationales.
Show parameters and responsesHide parameters and responses
Parameters
| Name | In | Type | Description |
|---|---|---|---|
approvalIDrequired | path | string | — |
Responses
200RejectedApprovalRequest403—409—422—