Warrant lifecycle
A warrant application is always in exactly one of four states. Everything the API does to an application is one of the transitions below.
submit sign
┌─────────┐ ─────────────► ┌───────────┐ ─────────────► ┌────────┐
│ DRAFT │ │ SUBMITTED │ │ SIGNED │
└─────────┘ └───────────┘ └────────┘
▲ │
│ │ reject
│ reopen ▼
└────────────────────── ┌──────────┐
│ REJECTED │
└──────────┘
| State | Meaning | Editable |
|---|---|---|
DRAFT | Being prepared by the applicant | Yes |
SUBMITTED | Waiting for a judge | By reviewers only |
SIGNED | Signed, and the document is rendered | No |
REJECTED | Sent back with a reason | No, reopen first |
SIGNED is terminal. REJECTED is not: it exists so a correctable problem
does not cost the applicant the whole application.
Transitions
| Transition | Operation | Who | Scope |
|---|---|---|---|
Create as DRAFT | POST /v1/warrants | Applicant | warrants:write |
DRAFT to SUBMITTED | PATCH /v1/warrants/{id}/submit | The creator only | warrants:submit |
SUBMITTED to SIGNED | PATCH /v1/warrants/{id}/sign | A judge | warrants:sign |
SUBMITTED to REJECTED | PATCH /v1/warrants/{id}/reject | A judge | warrants:sign |
REJECTED to DRAFT | PATCH /v1/warrants/{id}/reopen | Applicant or admin | warrants:write |
Attempting a transition from the wrong state returns 409
invalid_transition:
{
"error": {
"message": "Only a SUBMITTED warrant application can be signed.",
"type": "conflict_error",
"code": "invalid_transition",
"param": null,
"request_id": "req_01HZY5R2K3Q9"
}
}
Branch on code, never on the message.
Submitting
Only the person who created a draft can submit it. That rule is deliberate: it keeps authorship of an application unambiguous, and it means a role change between drafting and submitting never strands a draft.
curl -s -X PATCH "$BASE/warrants/$WARRANT_ID/submit" \
-H "x-api-key: $API_KEY" \
-H "X-On-Behalf-Of: dr.chen@example.gov" \
-H "Content-Type: application/json" \
-d '{"assigned_judge_id": "a83f5c07-2d19-4b6e-9f42-5c7a1e3d8b90"}'
The body is optional. With assigned_judge_id the application is routed to
that judge; without it, your agency's routing mode
decides. Either way the application stays actionable by any judge in the
agency: see reviewing and signing.
Signing
curl -s -X PATCH "$BASE/warrants/$WARRANT_ID/sign" \
-H "x-api-key: $API_KEY" \
-H "X-On-Behalf-Of: judge.alvarez@example.gov"
Signing applies the signing judge's stored signature, stamps signed_at, and
renders the document. It happens once: a second call returns 409
invalid_transition. If rendering fails, the application is still signed, and
the document can be rebuilt with
regeneration without re-signing anything.
Rejecting
curl -s -X PATCH "$BASE/warrants/$WARRANT_ID/reject" \
-H "x-api-key: $API_KEY" \
-H "X-On-Behalf-Of: judge.alvarez@example.gov" \
-H "Content-Type: application/json" \
-d '{"reason": "The examination time predates the reported incident. Correct the timeline and resubmit."}'
The reason is added to the comment thread, so the applicant sees what to fix in the same place they see everything else about the application.
Reopening
curl -s -X PATCH "$BASE/warrants/$WARRANT_ID/reopen" \
-H "x-api-key: $API_KEY" \
-H "X-On-Behalf-Of: dr.chen@example.gov"
The application returns to DRAFT with its document, attachments, and full
comment thread intact, including the rejection reason. Correct it and submit
again; the resubmission is routed by the current routing mode, so it does not
necessarily go back to the judge who rejected it.
Other state on an application
Three attributes move independently of the lifecycle and can be changed at any point:
- Priority (
LOW,STANDARD,URGENT) orders review queues and drives escalation. - Visibility (
PUBLIC,PRIVATE) controls whether the application has a working public link. - Trash is a reversible removal, covered in trash and restore.