Skip to content
Registry StackDocsDevelopment (unreleased)

Registry Casework API

View as Markdown

Look up here which route a caller uses, which headers it sends, and how a refusal recovers. Every parameter, schema, and status is in the generated Casework API operations, rendered from registry-casework.openapi.json; the service does not serve that document. API stability states the versioning contract.

The caller is the role of the access profile the call selects: requester for a producer, staff and supervisor for reviewers, administrator for the directory owner. A role that a row does not name is refused with operation.not-authorized.

MethodPathCallerReturns
GET/health, /readyAnyone, no token200; /ready answers 503 while storage or the audit journal is unavailable
GET/.well-known/jwks.jsonAnyone, no tokenKeys that verify task assertions
GET/v1/caseworkAny profileThe deployed project, without providers, calendars, or clocks for a requester
GET/v1/review-policies, /v1/review-policies/{policy_id}Any profileThe compiled ReviewPolicy closures the caller may use
POST/v1/review-requestsRequester201 with the accepted ReviewRequest, 200 on recovery
GET/v1/review-requests/{request_id}RequesterThe request’s state
POST/v1/review-requests/{request_id}/cancelRequesterThe cancellation
GET/v1/review-requests/{request_id}/resultRequester200 with the ReviewResult; bodiless 202 pending, 410 erased
GET/v1/review-resultsRequesterA resumable page of settled results
GET/v1/review-requests/{request_id}/history, /clocksReviewer or requesterHistory; clocks
POST/v1/review-requests/{request_id}/notesReviewer; requester for requester-audience notesThe entry
GET/v1/review-tasks, /next, /holdings, /own-decisionsStaff, supervisorReviewTasks
GET/v1/review-tasks/supervisionSupervisorTasks in served queues
GET/v1/review-tasks/{task_id}, /contextStaff, supervisorThe task; its review context
POST/v1/review-tasks/{task_id}/claim, /releaseStaff, supervisorThe task
POST/v1/review-tasks/{task_id}/assignSupervisor serving the queueThe task
POST/v1/review-tasks/{task_id}/delegateA reviewer whose profile decides the stageThe task
GET, PUT, DELETE/v1/review-tasks/{task_id}/draftThe holderThe private draft; 204 on delete
POST/v1/review-tasks/{task_id}/decisionsThe holder204
GET/v1/review-tasks/{task_id}/task-templatesStaff, supervisorTask grant previews
GET, POST/v1/review-tasks/{task_id}/task-grantsStaff, supervisorGrants on the task; the approved grant
POST/v1/review-tasks/{task_id}/task-grants/{grant_id}/revokeStaff, supervisorThe revocation
POST/v1/task-grants/{grant_id}/assertionThe grant’s agent, scope casework:grants:assertA signed task assertion
GET/v1/task-grants/{grant_id}/statusA service, scope casework:grants:statusCurrent status
GET/v1/review-accountability/{event_id}SupervisorThe accountability record
GET, PUT/v1/directory, /v1/directory/teams/{team_id}; POST /v1/directory/bootstrapAdministratorThe directory
GET/v1/directory/targetsBy purposeNameable people and queues
GET, POST, PUT, DELETE/v1/directory/absences, /{absence_id}Staff for self, supervisor for team, administratorAbsences
POST, GET/v1/directory/holidays, /{id}/revisions/{revision}AdministratorHoliday set revisions
POST/v1/directory/clocks/recompute/preview, /applyAdministratorPreview, then result
POST/v1/directory/caseload/preview, /applySupervisorPreview, then result

Activation has no HTTP route: caseworkctl apply activates a package (Deploy Registry Casework).

HeaderSent onRule
Authorization: Bearer <token>Every route except /health, /ready, and the key setA missing, invalid, or expired token is authentication.refused (401)
Registry-Review-ProfileThe five requester routes: submit, read, cancel, result, results feedNames the access profile; at most 128 bytes of letters, digits, and ., _, :, -
Registry-Casework-ProfileEvery other authenticated route except /v1/task-grants/*Same bounds; a profile that does not cover the route is profile.not-authorized (403)
Registry-Source-ProfileTask, history, clock, note, task grant, caseload, and clock recompute routes, by a reviewerSelects the reviewer’s source profile; work whose context comes from a context provider requires it (source-profile.required)
If-Match: "<revision>"Task mutations and directory mutationsThe revision you read, quoted; "0" creates a directory entry. Missing is precondition.required (428), stale is precondition.failed (412)
Idempotency-KeyEvery mutation except previews, the two /apply routes, and grant revocation1 to 128 printable ASCII bytes, kept with the request body for recovery
traceparentAny route, optionalW3C trace context; every response carries one

A profile selects authority the token already holds and adds no scope. The /v1/task-grants/* routes take a bare service token: either profile header there is authentication.refused. Registry-Source-Profile is source-profile.not-applicable on the requester routes, the policy routes, /v1/directory/targets, task release, and accountability, and from a requester on history, clocks, and notes. Every response carries Cache-Control: no-store.

POST /v1/review-requests names a policy id. Omit version and digest to take the ReviewPolicy active at admission, or send both to require the identity that GET /v1/review-policies/{policy_id} returned; a differing pin is review.policy-mismatch. The ReviewResult repeats the accepted binding with the subject and submissionDigest; the consumer checks that correlation and authorizes any business change itself.

After a lost response, resend the same Idempotency-Key and the same body: the first submission answered 201, the resend 200 with the same requestId. A changed body under that key is idempotency.key-reused, and a fresh key is a fresh operation. A 503 on a mutation does not say whether the change committed, so recover it the same way before you choose another operation.

A refusal is application/problem+json with type, title, status, a fixed detail, a closed code, and a traceId, and echoes nothing you sent. A validation refusal names the field and the reason in registry-casework-validation-path and registry-casework-validation-reason, plus the accepted values in registry-casework-validation-allowed when the field takes a closed set; requester routes spell the first two registry-review-validation-path and registry-review-validation-reason. Give your operator the traceId, never a token or a body.

The table lists every code the Rust, Node.js, and Python clients recognize. A code outside it comes from a newer service; treat it by its status.

CodeStatusWhen
absence.cover-cycle422Choose cover assignments that do not return to an earlier person during a shared period.
absence.invalid-period422Set until later than from.
absence.overlap422Adjust the period so this person has no overlapping absence.
absence.self-cover422Choose a different staff member as cover.
authentication.refused401The bearer credential is missing, invalid, or expired. Sign in again.
clock.recompute-preview-expired410Create a new recompute preview and review it before applying.
cursor.expired410This cursor has expired. Start again without a cursor and deduplicate entries by eventId.
cursor.invalid400The cursor is invalid for this request.
idempotency.expired410The stored response for this idempotency key has expired. Reconcile the original operation before choosing a new key.
idempotency.key-reused409This idempotency key was used for a different request.
operation.not-authorized403Your current Casework authority does not allow this operation.
precondition.failed412The item or directory changed since you loaded it. Reload and try again.
precondition.required428This mutation requires the revision that you loaded.
profile.not-authorized403The selected Casework profile does not authorize this request.
profile.not-human403This action is reserved for a human session.
request.body-too-large413The request body exceeds the one MiB limit.
request.invalid400The Casework request is invalid.
request.limit-out-of-range400The limit query parameter must be from 1 to 100, or from 1 to 1000 on the directory absence list. Omit it for the default page size.
request.method-not-allowed405This route does not accept that HTTP method.
request.not-found404The requested Casework route does not exist.
request.unprocessable422The request body does not match the Casework contract.
request.unsupported-media-type415Send a JSON request body with Content-Type application/json.
review.distinct-approver-required403Each approval in this stage must be supplied by a different reviewer.
review.initiator-excluded403You submitted this request, and this review stage excludes the person who submitted it. Another reviewer must take it.
review.initiator-required422This review policy excludes the person who submitted the request, so the request must name its initiator.
review.policy-mismatch409The expected review policy binding does not match the active policy.
review.query-too-broad422Narrow the queue or exact subject query to complete it within the configured read budget.
review.result-expired410The retained review result is no longer available. Reconcile through the producer's retained source correlation.
review.submission-conflict409The same producer, source subject, version, and policy were already submitted with different canonical content.
review.task-not-held409Claim the review task before deciding it, and decide only while the claim remains current.
runtime.failure500Casework could not complete the request.
service.unavailable503Casework storage is unavailable. Try again after the service recovers.
source-profile.not-applicable400Omit the Registry-Source-Profile header for this request.
source-profile.required400Send the Registry-Source-Profile header to select the source profile for this request.
source.bad-gateway502The source returned a response that does not match its registered contract.
source.version-mismatch502Deploy the same Registry Stack version for Casework and its source.
source.version-unavailable502The source did not report its engine version. Deploy matching Registry Stack versions.