Skip to content

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.

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"
}
}
}
}
}

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.

[
{
"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._:/-]+$"
}
}
]
{
"$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"
}
}
}
}
}

GET /v1/drafts — List owned drafts

Created time then ID descending. Optional status filter; ownership applies to every page.

[
{
"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"
}
}
}
}
}

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.

[
{
"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._:/-]+$"
}
}
]
{
"$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"
}
}
}
}
}

GET /v1/drafts/{draft}/revisions — List revision history

Revision number then ID descending.

[
{
"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"
}
}
}
}
}

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.

[
{
"name": "draft",
"in": "path",
"required": true,
"description": "Immutable ID from a previous service response.",
"schema": {
"type": "string",
"format": "uuid"
}
}
]
{
"$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"
}
}
}
}
}

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.

[
{
"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"
}
}
}
}
}

GET /v1/drafts/{draft} — Read current content and status

Read current content and status

[
{
"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"
}
}
}
}
}

GET /v1/drafts/{draft}/revisions/{revision} — Read an immutable revision

Read an immutable revision

[
{
"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"
}
}
}
}
}

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.

[
{
"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"
}
}
}
}
}

References such as #/components/schemas/CreateDraft refer to these components in the downloadable OpenAPI document.

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 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 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 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 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 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 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 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 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 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
}