{"openapi":"3.1.0","info":{"title":"gork.email API","version":"1.0.0","description":"Programmable email infrastructure for AI agents. Provision inboxes, send and receive mail, manage threads, webhooks, domains, keys, and suppressions. All responses are wrapped as `{ \"data\": ... }`; errors as `{ \"error\": { \"code\", \"message\" } }`.","contact":{"name":"gork.email","url":"https://gork.email/docs"}},"servers":[{"url":"https://api.gork.email","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Inboxes"},{"name":"Messages"},{"name":"Threads"},{"name":"Webhooks"},{"name":"Keys"},{"name":"Domains"},{"name":"Suppressions"},{"name":"Unsubscribe"},{"name":"Organization"},{"name":"Drafts"},{"name":"Attachments"},{"name":"Analytics"}],"paths":{"/v1/organization":{"get":{"operationId":"getOrganization","summary":"Get the authenticated organization profile","description":"Returns the org bound to the API key: name, plan, quota counters, sending approval state.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Organization profile","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Organization not found"}}}},"/v1/organization/members":{"get":{"operationId":"listOrganizationMembers","summary":"List human members of the organization","description":"Members with role and joinedAt for the org bound to the API key.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Member roster","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"Missing organization:read scope"}}}},"/v1/inboxes":{"post":{"tags":["Inboxes"],"summary":"Create inbox","description":"Provision a programmed agent inbox. Reserved brand/role names return 422.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username"],"properties":{"username":{"type":"string","minLength":2,"maxLength":48,"pattern":"^[a-z0-9._-]+$","example":"sdr-alex"},"name":{"type":"string","maxLength":100},"agentId":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"}}},"get":{"tags":["Inboxes"],"summary":"List inboxes","responses":{"200":{"description":"Inbox list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/inboxes/{id}":{"get":{"tags":["Inboxes"],"summary":"Get inbox","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Inboxes"],"summary":"Deactivate inbox","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Inboxes"],"summary":"Update inbox","description":"Currently updates the friendly display name.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"nullable":true}}}}}},"responses":{"200":{"description":"Updated inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Inbox-bound key cannot modify this inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/messages/send":{"post":{"tags":["Messages"],"summary":"Send email","description":"Sends from an owned inbox through approval, quota, daily-cap, suppression, and bulk-tripwire guards. Supports Idempotency-Key header.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["inboxId","to"],"properties":{"inboxId":{"type":"string"},"to":{"type":"array","items":{"type":"string","format":"email"},"minItems":1,"maxItems":50},"cc":{"type":"array","items":{"type":"string","format":"email"},"default":[]},"bcc":{"type":"array","items":{"type":"string","format":"email"},"default":[]},"subject":{"type":"string","maxLength":500,"default":"(no subject)"},"text":{"type":"string"},"html":{"type":"string"},"inReplyTo":{"type":"string","description":"Message-ID header to thread under"},"sendAt":{"type":"string","format":"date-time","description":"Schedule for later instead of sending now (1 minute to 30 days ahead)."},"attachments":{"type":"array","maxItems":20,"description":"Attachments as `{ filename, contentType, content (base64) }` objects.","items":{"type":"object","required":["filename","content"],"properties":{"filename":{"type":"string"},"contentType":{"type":"string"},"content":{"type":"string","description":"Base64-encoded file bytes"}}}}}}}}},"responses":{"201":{"description":"Accepted for delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"402":{"description":"Quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Not approved or bulk-paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Suppressed recipient","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/messages":{"get":{"tags":["Messages"],"summary":"List messages","parameters":[{"name":"inboxId","in":"query","schema":{"type":"string"}},{"name":"threadId","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Full-text match over subject and body"},{"name":"direction","in":"query","schema":{"type":"string","enum":["inbound","outbound"]},"description":"Filter by direction"},{"name":"from","in":"query","schema":{"type":"string","format":"email"},"description":"Filter by sender address"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only messages received/sent at or after this time"},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only messages received/sent before this time"},{"name":"before","in":"query","schema":{"type":"string"},"description":"Opaque cursor: return messages older than this id"},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Alias for `before`"}],"responses":{"200":{"description":"Message list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/messages/{id}":{"get":{"tags":["Messages"],"summary":"Get message with attachments","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Messages"],"summary":"Delete a message","description":"Removes the message row and any R2 objects (raw MIME, offloaded HTML) it owns.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Deleted message id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"403":{"description":"Inbox-bound key cannot delete this message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/threads":{"get":{"tags":["Threads"],"summary":"List threads","responses":{"200":{"description":"Thread list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/threads/{id}":{"get":{"tags":["Threads"],"summary":"Get thread","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Thread","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/webhooks":{"post":{"tags":["Webhooks"],"summary":"Register webhook","description":"Endpoint must be HTTPS. A signing secret is generated and returned once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","pattern":"^https://"},"subscribedEvents":{"type":"array","items":{"type":"string"},"minItems":1,"default":["email.received","email.sent","email.bounced"]}}}}}},"responses":{"201":{"description":"Created (secret shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}},"get":{"tags":["Webhooks"],"summary":"List webhooks (secrets never returned)","responses":{"200":{"description":"Webhook list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/webhooks/{id}/rotate-secret":{"post":{"tags":["Webhooks"],"summary":"Rotate signing secret","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"New secret (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/webhooks/{id}":{"delete":{"tags":["Webhooks"],"summary":"Delete webhook","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/webhooks/deliveries":{"get":{"tags":["Webhooks"],"summary":"List delivery attempts","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}}],"responses":{"200":{"description":"Delivery list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/keys":{"post":{"tags":["Keys"],"summary":"Create API key (secret shown once)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":64},"scopes":{"type":"array","items":{"type":"string"},"default":["*"]}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}},"get":{"tags":["Keys"],"summary":"List keys (prefixes only)","responses":{"200":{"description":"Key list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/keys/{id}":{"delete":{"tags":["Keys"],"summary":"Revoke API key","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/domains":{"post":{"tags":["Domains"],"summary":"Register custom domain","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","example":"mail.acme.com"}}}}}},"responses":{"201":{"description":"Created with DNS instructions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"409":{"$ref":"#/components/responses/Conflict"}}},"get":{"tags":["Domains"],"summary":"List domains","responses":{"200":{"description":"Domain list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/domains/{id}/verify":{"post":{"tags":["Domains"],"summary":"Run DNS verification","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Verification report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/domains/{id}":{"delete":{"tags":["Domains"],"summary":"Delete domain","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Domains"],"summary":"Set or clear the voluntary daily sending ceiling","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dailyCap":{"type":["integer","null"],"minimum":1,"maximum":1000000,"description":"Emails per UTC day. Null removes the ceiling."}}}}}},"responses":{"200":{"description":"Updated domain with todayUsed, resetsAt and an exhaustion note","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"400":{"description":"Invalid ceiling payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/suppressions":{"get":{"tags":["Suppressions"],"summary":"List suppressed recipients","responses":{"200":{"description":"Suppression list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}},"post":{"tags":["Suppressions"],"summary":"Suppress a recipient","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"reason":{"type":"string","enum":["manual","hard_bounce","complaint","unsubscribe"],"default":"manual"}}}}}},"responses":{"201":{"description":"Suppressed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/suppressions/{id}":{"delete":{"tags":["Suppressions"],"summary":"Remove suppression","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/unsubscribe":{"get":{"tags":["Unsubscribe"],"summary":"One-click unsubscribe landing (browser)","security":[],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"HTML confirmation"}}},"post":{"tags":["Unsubscribe"],"summary":"One-click unsubscribe action (RFC 8058)","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Unsubscribed"}}}},"/v1/domains/{id}/health":{"get":{"tags":["Domains"],"summary":"Per-domain deliverability snapshot (read-only)","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Ceiling usage, 7-day bounce/complaint rates, status and guidance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/inboxes/check":{"get":{"tags":["Inboxes"],"summary":"Check whether an address is available before creating it","description":"Read-only availability probe. Always returns 200 with a `status` of available, taken, reserved, or invalid so an agent can branch without exception handling.","parameters":[{"name":"username","in":"query","schema":{"type":"string","minLength":2,"maxLength":48,"pattern":"^[a-z0-9._-]+$"},"description":"Local part to test"},{"name":"domain","in":"query","schema":{"type":"string"},"description":"Domain to test against (defaults to the platform domain)"}],"responses":{"200":{"description":"Availability result with suggested alternatives","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}}}}},"/v1/messages/{id}/schedule":{"delete":{"tags":["Messages"],"summary":"Cancel a scheduled send","description":"Marks a scheduled message `cancelled`. The record is kept for audit but can never be dispatched.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Cancelled message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"403":{"description":"Inbox-bound key cannot cancel this message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Message is not in `scheduled` state — nothing to cancel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/messages/{id}/raw":{"get":{"tags":["Messages"],"summary":"Get raw RFC 822 MIME source","description":"Returns the original MIME message, or a faithfully reconstructed synthetic equivalent if the archive object is unavailable.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Raw message source","content":{"message/rfc822":{"schema":{"type":"string"}}}},"403":{"description":"Inbox-bound key cannot read this message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/organization/stats":{"get":{"operationId":"getOrganizationStats","summary":"Workspace overview","description":"Counts of inboxes, messages, active keys and webhooks, six most recent messages, and plan/quota state for the org bound to the API key.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Workspace stats","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"Missing organization:read scope"}}}},"/v1/organization/name":{"patch":{"operationId":"updateOrganizationName","summary":"Rename the organization","description":"Sets the display name for the org bound to the API key (2–100 characters).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":2,"maxLength":100}}}}}},"responses":{"200":{"description":"Updated organization profile","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Name must be 2–100 characters"},"403":{"description":"Missing organization:write scope"}}}},"/v1/attachments/{id}":{"get":{"tags":["Attachments"],"summary":"Download an attachment","description":"Streams the stored file bytes. `?inline=1` renders safely in a browser only for image/pdf/text types; otherwise the file is sent as an attachment.","parameters":[{"$ref":"#/components/parameters/IdParam"},{"name":"inline","in":"query","schema":{"type":"string","enum":["1"]},"description":"Set to 1 to request inline rendering for safe types"}],"responses":{"200":{"description":"Attachment bytes","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"403":{"description":"Inbox-bound key cannot read this attachment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"},"410":{"description":"Record exists but the stored object is gone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Attachment storage not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/drafts":{"post":{"tags":["Drafts"],"summary":"Create a draft","description":"A draft consumes no quota and sends no mail. Build a message over several calls, then send it in one.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["inboxId"],"properties":{"inboxId":{"type":"string"},"to":{"type":"array","items":{"type":"string","format":"email"},"maxItems":50},"cc":{"type":"array","items":{"type":"string","format":"email"},"maxItems":50},"bcc":{"type":"array","items":{"type":"string","format":"email"},"maxItems":50},"subject":{"type":"string","maxLength":500},"text":{"type":"string","maxLength":10000000},"html":{"type":"string","maxLength":10000000},"inReplyTo":{"type":"string","description":"Message-ID header to thread under"}}}}}},"responses":{"201":{"description":"Created draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"400":{"description":"Invalid draft payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Workspace is at its 500 open-draft limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Inbox-bound key cannot draft to this inbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Inbox not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"get":{"tags":["Drafts"],"summary":"List drafts","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["draft","sent","discarded"],"default":"draft"}},{"name":"inboxId","in":"query","schema":{"type":"string"},"description":"Filter to one inbox (ignored for inbox-bound keys)"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100,"minimum":1}}],"responses":{"200":{"description":"Draft list, most recently updated first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"400":{"description":"Invalid status filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/drafts/{id}":{"get":{"tags":["Drafts"],"summary":"Get a draft","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Drafts"],"summary":"Edit a draft","description":"Any subset of fields. Only `draft`-status drafts are editable.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"array","items":{"type":"string","format":"email"},"maxItems":50},"cc":{"type":"array","items":{"type":"string","format":"email"},"maxItems":50},"bcc":{"type":"array","items":{"type":"string","format":"email"},"maxItems":50},"subject":{"type":"string","maxLength":500},"text":{"type":"string","maxLength":10000000},"html":{"type":"string","maxLength":10000000},"inReplyTo":{"type":"string","description":"Message-ID header to thread under"}}}}}},"responses":{"200":{"description":"Updated draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"400":{"description":"Invalid draft update","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Draft is already sent or discarded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"tags":["Drafts"],"summary":"Discard a draft","description":"Soft-deletes by marking the draft `discarded` — retained for audit, never hard-deleted.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Discarded draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Draft has already been sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/drafts/{id}/send":{"post":{"tags":["Drafts"],"summary":"Send a draft","description":"Runs the normal send pipeline, so every guardrail (approval, quota, suppression, tripwires) applies. Idempotent: re-sending a sent draft replays the original message.","parameters":[{"$ref":"#/components/parameters/IdParam"}],"responses":{"200":{"description":"Already sent — replays the original message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"201":{"description":"Accepted for delivery, with `draftId`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"400":{"description":"Draft has no recipients","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Draft was discarded and cannot be sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/analytics":{"get":{"tags":["Analytics"],"summary":"Workspace usage","description":"Storage used vs plan limit, inbound/outbound email counts, and total webhooks dispatched for the org bound to the API key.","responses":{"200":{"description":"Usage counters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataEnvelope"}}}},"403":{"description":"Missing organization:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"gork_live_... API key"}},"parameters":{"IdParam":{"name":"id","in":"path","required":true,"schema":{"type":"string"}}},"schemas":{"DataEnvelope":{"type":"object","properties":{"data":{}}},"ErrorEnvelope":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code. Branch on this, never on the message.","enum":["address_already_exists","address_in_cooldown","agent_not_found","apex_domain_reserved","attachment_bytes_missing","attachment_not_found","attachment_storage_unavailable","attachment_too_large","attachments_not_schedulable","attachments_unsupported","conflict","domain_already_registered","domain_daily_cap_reached","domain_not_found","domain_not_verified","draft_already_sent","draft_discarded","draft_incomplete","draft_limit_reached","draft_not_editable","draft_not_found","email_delivery_failed","forbidden","inbox_access_denied","inbox_not_found","insufficient_credits","insufficient_scope","internal_dispatch_failed","internal_misconfigured","internal_server_error","invalid_api_key","invalid_api_key_format","invalid_or_expired_token","invalid_payload","invalid_scopes","invalid_sender","invalid_ses_receipt","invalid_signature","invalid_sns_envelope","invalid_sns_signature","invalid_subscribe_url","invalid_topic","key_not_found","limit_reached","message_not_found","misconfigured","missing_token","not_found","not_scheduled","payload_too_large","provider_unavailable","rate_limit_exceeded","recipient_suppressed","sandbox_bulk_not_allowed","send_failed","sending_not_approved","sending_paused_bulk_review","stale_delivery","suppression_not_found","thread_not_found","unauthorized","username_reserved","validation_failed","webhook_limit_reached","webhook_not_found"],"example":"limit_reached"},"message":{"type":"string"}}}}},"Inbox":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"},"name":{"type":["string","null"]},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"Message":{"type":"object","properties":{"id":{"type":"string"},"threadId":{"type":"string"},"inboxId":{"type":"string"},"direction":{"type":"string","enum":["inbound","outbound"]},"fromAddress":{"type":"string"},"subject":{"type":"string"},"textBody":{"type":["string","null"]},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"Thread":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":"string"},"messageCount":{"type":"integer"},"lastMessageAt":{"type":"string","format":"date-time"}}},"Webhook":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"subscribedEvents":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}}},"Domain":{"type":"object","properties":{"id":{"type":"string"},"domainName":{"type":"string"},"status":{"type":"string","enum":["pending","verified"]},"dailyCap":{"type":["integer","null"],"description":"Voluntary per-domain daily sending ceiling. Null = none."},"dailySendCount":{"type":"integer"},"dailySendDate":{"type":["string","null"],"format":"date"}}}},"responses":{"NotFound":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Conflict":{"description":"Already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unprocessable":{"description":"Reserved or suppressed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"RateLimited":{"description":"Rate or ceiling exceeded (Retry-After header on 429)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}