API reference
Generated from the same route definitions and schemas as the live API.
Base URL: https://countersign.cristianmartinez.co. All operations require Authorization: Bearer <agent key>. Get that key from the human’s authenticated Connect page. Reviewer cookies do not authenticate the API. There is no agent approval or send endpoint.
Download OpenAPI JSON, or read the agent workflow for limits, retries, recipient rules and polling. The live service at https://countersign.cristianmartinez.co/openapi.json is authoritative for its deployed version.
getIdentity
Section titled “getIdentity”GET /v1/me — Discover identity, fixed sender, allowed recipients and limits
Discover identity, fixed sender, allowed recipients and limits
Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Identity" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}createDraft
Section titled “createDraft”POST /v1/drafts — Create a private draft
Requires Idempotency-Key. Persist key/body before dispatch. Exact successful replays return the original result for 24 hours, even after later edits.
Parameters
Section titled “Parameters”[ { "name": "Idempotency-Key", "in": "header", "required": true, "description": "Persist one key with the exact body per intended create/revise operation. Reuse both after response loss. Successful replay protection lasts 24 hours.", "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9._:/-]+$" } }]Request body
Section titled “Request body”{ "$ref": "#/components/schemas/CreateDraft"}Example:
{ "to": [ "delivered@resend.dev" ], "subject": "A human-approved thank you", "html": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html dir=\"ltr\" lang=\"en\"><head><meta content=\"text/html; charset=UTF-8\" http-equiv=\"Content-Type\"/><meta name=\"x-apple-disable-message-reformatting\"/><title>Your email approval workflow is ready to review.</title></head><body dir=\"ltr\" lang=\"en\" style=\"background-color:#f5f5f4\"><!--$--><!--html--><!--head--><div style=\"display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0\" data-skip-in-text=\"true\">Your email approval workflow is ready to review.<div> </div></div><!--body--><table border=\"0\" width=\"100%\" cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\" align=\"center\"><tbody><tr><td dir=\"ltr\" lang=\"en\" style=\"background-color:#f5f5f4;font-family:Arial, sans-serif;color:#1c1917\"><table align=\"center\" width=\"100%\" border=\"0\" cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\" style=\"max-width:560px;margin:32px auto;background-color:#ffffff\"><tbody><tr style=\"width:100%\"><td style=\"padding:32px\"><p style=\"font-size:12px;line-height:24px;letter-spacing:2px;margin-top:16px;margin-bottom:16px\">COUNTERSIGN</p><h1>Thank you, <!-- -->reviewer<!-- -->.</h1><table align=\"center\" width=\"100%\" border=\"0\" cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\"><tbody><tr><td><p style=\"font-size:14px;line-height:24px;margin-top:16px;margin-bottom:16px\">Thank you for trying Countersign. Please review this example before approving it.</p><p style=\"font-size:14px;line-height:24px;margin-top:16px;margin-bottom:16px\">This email was prepared as a draft. A human must approve the recipients and both body versions before it can be sent.</p></td></tr></tbody></table><hr style=\"width:100%;border:none;border-color:transparent;border-top:1px solid #eaeaea\"/><p style=\"font-size:12px;line-height:24px;color:#57534e;margin-top:16px;margin-bottom:16px\">Prepared with React Email. Sent through Resend only after approval.</p></td></tr></tbody></table></td></tr></tbody></table><!--/$--></body></html>", "text": "COUNTERSIGN\n\n\nTHANK YOU, REVIEWER.\n\nThank you for trying Countersign. Please review this example before approving it.\n\nThis email was prepared as a draft. A human must approve the recipients and both body versions before it can be sent.\n\n----------------------------------------\n\nPrepared with React Email. Sent through Resend only after approval."}Responses
{ "201": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Mutation" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Revision/state/idempotency conflict. Follow error.code and hint.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "Entire JSON exceeds 256 KiB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "Invalid or disallowed fields/recipient. Correct details.fields.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}listDrafts
Section titled “listDrafts”GET /v1/drafts — List owned drafts
Created time then ID descending. Optional status filter; ownership applies to every page.
Parameters
Section titled “Parameters”[ { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }, { "name": "cursor", "in": "query", "description": "Opaque, context-bound next_cursor returned by the previous page; URL-encode and preserve unchanged.", "schema": { "type": "string" } }, { "name": "status", "in": "query", "schema": { "type": "string", "enum": [ "drafted", "in_review", "rejected", "approved", "sending", "sent", "delivered", "bounced", "failed" ] } }]Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DraftPage" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}reviseDraft
Section titled “reviseDraft”POST /v1/drafts/{draft}/revisions — Create a full replacement revision
Requires Idempotency-Key and current base_revision_id. Allowed only before approval; stale bases conflict. A rejection needs a new revision before resubmission.
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }, { "name": "Idempotency-Key", "in": "header", "required": true, "description": "Persist one key with the exact body per intended create/revise operation. Reuse both after response loss. Successful replay protection lasts 24 hours.", "schema": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9._:/-]+$" } }]Request body
Section titled “Request body”{ "$ref": "#/components/schemas/ReviseDraft"}Example:
{ "to": [ "delivered@resend.dev" ], "subject": "A human-approved thank you", "html": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html dir=\"ltr\" lang=\"en\"><head><meta content=\"text/html; charset=UTF-8\" http-equiv=\"Content-Type\"/><meta name=\"x-apple-disable-message-reformatting\"/><title>Your email approval workflow is ready to review.</title></head><body dir=\"ltr\" lang=\"en\" style=\"background-color:#f5f5f4\"><!--$--><!--html--><!--head--><div style=\"display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0\" data-skip-in-text=\"true\">Your email approval workflow is ready to review.<div> </div></div><!--body--><table border=\"0\" width=\"100%\" cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\" align=\"center\"><tbody><tr><td dir=\"ltr\" lang=\"en\" style=\"background-color:#f5f5f4;font-family:Arial, sans-serif;color:#1c1917\"><table align=\"center\" width=\"100%\" border=\"0\" cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\" style=\"max-width:560px;margin:32px auto;background-color:#ffffff\"><tbody><tr style=\"width:100%\"><td style=\"padding:32px\"><p style=\"font-size:12px;line-height:24px;letter-spacing:2px;margin-top:16px;margin-bottom:16px\">COUNTERSIGN</p><h1>Thank you, <!-- -->reviewer<!-- -->.</h1><table align=\"center\" width=\"100%\" border=\"0\" cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\"><tbody><tr><td><p style=\"font-size:14px;line-height:24px;margin-top:16px;margin-bottom:16px\">Thank you for trying Countersign. Please review this example before approving it.</p><p style=\"font-size:14px;line-height:24px;margin-top:16px;margin-bottom:16px\">This email was prepared as a draft. A human must approve the recipients and both body versions before it can be sent.</p></td></tr></tbody></table><hr style=\"width:100%;border:none;border-color:transparent;border-top:1px solid #eaeaea\"/><p style=\"font-size:12px;line-height:24px;color:#57534e;margin-top:16px;margin-bottom:16px\">Prepared with React Email. Sent through Resend only after approval.</p></td></tr></tbody></table></td></tr></tbody></table><!--/$--></body></html>", "text": "COUNTERSIGN\n\n\nTHANK YOU, REVIEWER.\n\nThank you for trying Countersign. Please review this example before approving it.\n\nThis email was prepared as a draft. A human must approve the recipients and both body versions before it can be sent.\n\n----------------------------------------\n\nPrepared with React Email. Sent through Resend only after approval.", "base_revision_id": "11111111-1111-4111-8111-111111111111"}Responses
{ "201": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Mutation" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Revision/state/idempotency conflict. Follow error.code and hint.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "Entire JSON exceeds 256 KiB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "Invalid or disallowed fields/recipient. Correct details.fields.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}listRevisions
Section titled “listRevisions”GET /v1/drafts/{draft}/revisions — List revision history
Revision number then ID descending.
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }, { "name": "cursor", "in": "query", "description": "Opaque, context-bound next_cursor returned by the previous page; URL-encode and preserve unchanged.", "schema": { "type": "string" } }]Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RevisionPage" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}submitDraft
Section titled “submitDraft”POST /v1/drafts/{draft}/submit — Submit the current revision for human review
Repeated submission returns current state without resetting review, reopening rejection or restarting sending. Return review_url to the human.
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }]Request body
Section titled “Request body”{ "$ref": "#/components/schemas/SubmitDraft"}Example:
{ "revision_id": "11111111-1111-4111-8111-111111111111"}Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Status" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "409": { "description": "Revision/state/idempotency conflict. Follow error.code and hint.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "413": { "description": "Entire JSON exceeds 256 KiB.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "422": { "description": "Invalid or disallowed fields/recipient. Correct details.fields.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}getDraftStatus
Section titled “getDraftStatus”GET /v1/drafts/{draft}/status — Check review, sending and delivery status
Follow next.action and poll_after_seconds: five seconds in wait states, at most two minutes per waiting session. Then hand back the link/status. contact_operator means stop; never create a replacement automatically. sent means provider acceptance, not delivery.
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }]Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Status" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}getDraft
Section titled “getDraft”GET /v1/drafts/{draft} — Read current content and status
Read current content and status
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }]Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Draft" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}getRevision
Section titled “getRevision”GET /v1/drafts/{draft}/revisions/{revision} — Read an immutable revision
Read an immutable revision
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }, { "name": "revision", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }]Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Revision" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}listEvents
Section titled “listEvents”GET /v1/drafts/{draft}/events — Inspect verified delivery evidence
Newest occurrence time then Svix ID descending. Bounce outranks failure/suppression, delivered, then sent. Complaint/delay are details only. Sent alone cannot clear reconciliation.
Parameters
Section titled “Parameters”[ { "name": "draft", "in": "path", "required": true, "description": "Immutable ID from a previous service response.", "schema": { "type": "string", "format": "uuid" } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 } }, { "name": "cursor", "in": "query", "description": "Opaque, context-bound next_cursor returned by the previous page; URL-encode and preserve unchanged.", "schema": { "type": "string" } }]Responses
{ "200": { "description": "Successful result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/EventPage" } } } }, "400": { "description": "Malformed JSON/headers, missing key or invalid pagination.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "401": { "description": "Missing or invalid agent credential.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "404": { "description": "Unknown or out-of-scope object.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "500": { "description": "Transient service failure. Retry mutations with the identical key/body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }}Schemas
Section titled “Schemas”References such as #/components/schemas/CreateDraft refer to these components in the downloadable OpenAPI document.
CreateDraft
Section titled “CreateDraft”CreateDraft JSON Schema
{ "type": "object", "properties": { "to": { "type": "array", "prefixItems": [ { "type": "string", "description": "One plain address. Allowed inbox/test recipients come from GET /v1/me. Outer whitespace is trimmed and only the domain is lowercased." } ], "items": false, "minItems": 1, "maxItems": 1 }, "subject": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\r\\n]+$" }, "text": { "type": "string", "description": "Final supplied body, unchanged after approval. Maximum 100 KiB UTF-8; this byte limit is enforced by the service.", "x-max-utf8-bytes": 102400 }, "html": { "type": "string", "description": "Final supplied body, unchanged after approval. Maximum 100 KiB UTF-8; this byte limit is enforced by the service.", "x-max-utf8-bytes": 102400 } }, "required": [ "to", "subject" ], "additionalProperties": false, "description": "Supply text, HTML or both; at least one must be nonempty. Strict fields: no from, JSX, templates, CC/BCC, attachments or Reply-To. Entire uncompressed JSON is bounded to 256 KiB while streaming.", "anyOf": [ { "required": [ "text" ], "properties": { "text": { "type": "string", "minLength": 1 } } }, { "required": [ "html" ], "properties": { "html": { "type": "string", "minLength": 1 } } } ], "x-max-request-bytes": 262144}ReviseDraft
Section titled “ReviseDraft”ReviseDraft JSON Schema
{ "type": "object", "properties": { "to": { "type": "array", "prefixItems": [ { "type": "string", "description": "One plain address. Allowed inbox/test recipients come from GET /v1/me. Outer whitespace is trimmed and only the domain is lowercased." } ], "items": false, "minItems": 1, "maxItems": 1 }, "subject": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\r\\n]+$" }, "text": { "type": "string", "description": "Final supplied body, unchanged after approval. Maximum 100 KiB UTF-8; this byte limit is enforced by the service.", "x-max-utf8-bytes": 102400 }, "html": { "type": "string", "description": "Final supplied body, unchanged after approval. Maximum 100 KiB UTF-8; this byte limit is enforced by the service.", "x-max-utf8-bytes": 102400 }, "base_revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" } }, "required": [ "to", "subject", "base_revision_id" ], "additionalProperties": false, "description": "Supply text, HTML or both; at least one must be nonempty. Strict fields: no from, JSX, templates, CC/BCC, attachments or Reply-To. Entire uncompressed JSON is bounded to 256 KiB while streaming. Full replacement against the current base revision; omitted bodies are removed. Approval locks the draft permanently.", "anyOf": [ { "required": [ "text" ], "properties": { "text": { "type": "string", "minLength": 1 } } }, { "required": [ "html" ], "properties": { "html": { "type": "string", "minLength": 1 } } } ], "x-max-request-bytes": 262144}SubmitDraft
Section titled “SubmitDraft”SubmitDraft JSON Schema
{ "type": "object", "properties": { "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" } }, "required": [ "revision_id" ], "additionalProperties": false}Mutation
Section titled “Mutation”Mutation JSON Schema
{ "type": "object", "properties": { "draft_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "status": { "type": "string", "enum": [ "drafted", "in_review", "rejected", "approved", "sending", "sent", "delivered", "bounced", "failed" ] }, "review_url": { "type": "string", "format": "uri" } }, "required": [ "draft_id", "revision_id", "status", "review_url" ], "additionalProperties": false}Revision
Section titled “Revision”Revision JSON Schema
{ "type": "object", "properties": { "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "draft_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "number": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "author_agent_id": { "type": "string" }, "author_reviewer_id": { "type": [ "string", "null" ] }, "base_revision_id": { "anyOf": [ { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, { "type": "null" } ] }, "from": { "type": "string" }, "to": { "type": "array", "prefixItems": [ { "type": "string" } ], "items": false, "minItems": 1, "maxItems": 1 }, "subject": { "type": "string" }, "text": { "type": "string" }, "html": { "type": "string" }, "content_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, "created_at": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "revision_id", "draft_id", "number", "author_agent_id", "author_reviewer_id", "base_revision_id", "from", "to", "subject", "content_hash", "created_at" ], "additionalProperties": false}Status
Section titled “Status”Status JSON Schema
{ "type": "object", "properties": { "draft_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "status": { "type": "string", "enum": [ "drafted", "in_review", "rejected", "approved", "sending", "sent", "delivered", "bounced", "failed" ] }, "current_revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "review_url": { "type": "string", "format": "uri" }, "review": { "anyOf": [ { "type": "object", "properties": { "decision": { "type": "string", "enum": [ "approved", "rejected" ] }, "reason": { "type": [ "string", "null" ] }, "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" } }, "required": [ "decision", "reason", "revision_id" ], "additionalProperties": false }, { "type": "null" } ] }, "send": { "anyOf": [ { "type": "object", "properties": { "state": { "type": "string", "enum": [ "queued", "sending", "retry_wait", "sent", "failed" ] }, "error": { "type": [ "string", "null" ] }, "needs_reconciliation": { "type": "boolean" }, "resend_email_id": { "type": [ "string", "null" ] }, "delivery_status": { "anyOf": [ { "type": "string", "enum": [ "sent", "delivered", "bounced", "failed", "suppressed" ] }, { "type": "null" } ] }, "events_url": { "type": "string", "format": "uri" } }, "required": [ "state", "error", "needs_reconciliation", "resend_email_id", "delivery_status", "events_url" ], "additionalProperties": false }, { "type": "null" } ] }, "next": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "submit", "revise", "wait", "done", "contact_operator" ] }, "message": { "type": "string" } }, "required": [ "action", "message" ], "additionalProperties": false }, "poll_after_seconds": { "anyOf": [ { "type": "number", "const": 5 }, { "type": "null" } ] } }, "required": [ "draft_id", "status", "current_revision_id", "review_url", "review", "send", "next", "poll_after_seconds" ], "additionalProperties": false}Draft JSON Schema
{ "type": "object", "properties": { "draft_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "status": { "type": "string", "enum": [ "drafted", "in_review", "rejected", "approved", "sending", "sent", "delivered", "bounced", "failed" ] }, "current_revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "review_url": { "type": "string", "format": "uri" }, "review": { "anyOf": [ { "type": "object", "properties": { "decision": { "type": "string", "enum": [ "approved", "rejected" ] }, "reason": { "type": [ "string", "null" ] }, "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" } }, "required": [ "decision", "reason", "revision_id" ], "additionalProperties": false }, { "type": "null" } ] }, "send": { "anyOf": [ { "type": "object", "properties": { "state": { "type": "string", "enum": [ "queued", "sending", "retry_wait", "sent", "failed" ] }, "error": { "type": [ "string", "null" ] }, "needs_reconciliation": { "type": "boolean" }, "resend_email_id": { "type": [ "string", "null" ] }, "delivery_status": { "anyOf": [ { "type": "string", "enum": [ "sent", "delivered", "bounced", "failed", "suppressed" ] }, { "type": "null" } ] }, "events_url": { "type": "string", "format": "uri" } }, "required": [ "state", "error", "needs_reconciliation", "resend_email_id", "delivery_status", "events_url" ], "additionalProperties": false }, { "type": "null" } ] }, "next": { "type": "object", "properties": { "action": { "type": "string", "enum": [ "submit", "revise", "wait", "done", "contact_operator" ] }, "message": { "type": "string" } }, "required": [ "action", "message" ], "additionalProperties": false }, "poll_after_seconds": { "anyOf": [ { "type": "number", "const": 5 }, { "type": "null" } ] }, "revision": { "type": "object", "properties": { "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "draft_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "number": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "author_agent_id": { "type": "string" }, "author_reviewer_id": { "type": [ "string", "null" ] }, "base_revision_id": { "anyOf": [ { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, { "type": "null" } ] }, "from": { "type": "string" }, "to": { "type": "array", "prefixItems": [ { "type": "string" } ], "items": false, "minItems": 1, "maxItems": 1 }, "subject": { "type": "string" }, "text": { "type": "string" }, "html": { "type": "string" }, "content_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, "created_at": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "revision_id", "draft_id", "number", "author_agent_id", "author_reviewer_id", "base_revision_id", "from", "to", "subject", "content_hash", "created_at" ], "additionalProperties": false } }, "required": [ "draft_id", "status", "current_revision_id", "review_url", "review", "send", "next", "poll_after_seconds", "revision" ], "additionalProperties": false}Identity
Section titled “Identity”Identity JSON Schema
{ "type": "object", "properties": { "agent_id": { "type": "string" }, "name": { "type": "string" }, "scope": { "type": "string", "const": "own_drafts" }, "from": { "type": "string" }, "allowed_recipients": { "type": "array", "items": { "type": "string" } }, "test_aliases_supported": { "type": "boolean", "const": false }, "limits": { "type": "object", "properties": { "subjectCodePoints": { "type": "number", "const": 200 }, "bodyBytes": { "type": "number", "const": 102400 }, "requestBytes": { "type": "number", "const": 262144 }, "defaultPageSize": { "type": "number", "const": 20 }, "maxPageSize": { "type": "number", "const": 100 }, "pollSeconds": { "type": "number", "const": 5 }, "pollBudgetSeconds": { "type": "number", "const": 120 }, "requestTimeoutMs": { "type": "number", "const": 10000 }, "leaseSeconds": { "type": "number", "const": 60 }, "maxSendAttempts": { "type": "number", "const": 20 }, "retryWindowSeconds": { "type": "number", "const": 82800 }, "maxBackoffSeconds": { "type": "number", "const": 900 }, "sessionSeconds": { "type": "number", "const": 86400 } }, "required": [ "subjectCodePoints", "bodyBytes", "requestBytes", "defaultPageSize", "maxPageSize", "pollSeconds", "pollBudgetSeconds", "requestTimeoutMs", "leaseSeconds", "maxSendAttempts", "retryWindowSeconds", "maxBackoffSeconds", "sessionSeconds" ], "additionalProperties": false } }, "required": [ "agent_id", "name", "scope", "from", "allowed_recipients", "test_aliases_supported", "limits" ], "additionalProperties": false}DraftPage
Section titled “DraftPage”DraftPage JSON Schema
{ "type": "object", "properties": { "items": { "type": "array", "items": { "type": "object", "properties": { "draft_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "status": { "type": "string", "enum": [ "drafted", "in_review", "rejected", "approved", "sending", "sent", "delivered", "bounced", "failed" ] }, "current_revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "created_at": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "updated_at": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "review_url": { "type": "string", "format": "uri" } }, "required": [ "draft_id", "status", "current_revision_id", "created_at", "updated_at", "review_url" ], "additionalProperties": false } }, "next_cursor": { "type": [ "string", "null" ] } }, "required": [ "items", "next_cursor" ], "additionalProperties": false}RevisionPage
Section titled “RevisionPage”RevisionPage JSON Schema
{ "type": "object", "properties": { "items": { "type": "array", "items": { "type": "object", "properties": { "revision_id": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "number": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "author_agent_id": { "type": "string" }, "author_reviewer_id": { "type": [ "string", "null" ] }, "created_at": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "revision_id", "number", "author_agent_id", "author_reviewer_id", "created_at" ], "additionalProperties": false } }, "next_cursor": { "type": [ "string", "null" ] } }, "required": [ "items", "next_cursor" ], "additionalProperties": false}EventPage
Section titled “EventPage”EventPage JSON Schema
{ "type": "object", "properties": { "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "type": { "type": "string" }, "occurred_at": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "detail": { "anyOf": [ { "type": "string", "maxLength": 4000 }, { "type": "null" } ] } }, "required": [ "id", "type", "occurred_at", "detail" ], "additionalProperties": false } }, "next_cursor": { "type": [ "string", "null" ] } }, "required": [ "items", "next_cursor" ], "additionalProperties": false}Error JSON Schema
{ "type": "object", "properties": { "error": { "type": "object", "properties": { "code": { "type": "string", "enum": [ "bad_request", "unauthorized", "not_found", "revision_conflict", "revision_changed", "idempotency_conflict", "invalid_state", "validation_error", "payload_too_large", "internal_error" ] }, "message": { "type": "string" }, "hint": { "type": "string" }, "details": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} } }, "required": [ "code", "message", "hint", "details" ], "additionalProperties": false } }, "required": [ "error" ], "additionalProperties": false}