{"openapi":"3.1.0","info":{"title":"Airmail API","version":"1.0.0","description":"Tenant-scoped transactional email API. HTTP 202 means Airmail durably accepted the logical message; it does not mean final recipient delivery."},"servers":[{"url":"https://api.airmailai.tech","description":"Production"}],"externalDocs":{"description":"Airmail developer guide","url":"https://airmailai.tech/developers"},"tags":[{"name":"Messages","description":"Accept and inspect transactional email."},{"name":"Suppressions","description":"Create tenant-scoped recipient suppressions."},{"name":"Inbound","description":"Inspect explicitly routed inbound email."}],"paths":{"/v1/messages":{"post":{"operationId":"sendMessage","summary":"Durably accept a transactional message","tags":["Messages"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Strongly recommended stable key for one logical send. Use 8-128 letters, numbers, dots, underscores, colons, or hyphens.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"}}}},"responses":{"202":{"description":"Logical message accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedMessage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/UpstreamUnavailable"}}}},"/v1/messages/{id}":{"get":{"operationId":"getMessage","summary":"Get tenant-scoped message status","tags":["Messages"],"security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/MessageId"}],"responses":{"200":{"description":"Message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/messages/{id}/events":{"get":{"operationId":"listMessageEvents","summary":"List normalized lifecycle events","tags":["Messages"],"security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/MessageId"}],"responses":{"200":{"description":"Lifecycle events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEventList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/suppressions":{"post":{"operationId":"createSuppression","summary":"Suppress a recipient for this tenant","tags":["Suppressions"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSuppressionRequest"}}}},"responses":{"202":{"description":"Recipient suppressed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/inbound/messages":{"get":{"operationId":"listInboundMessages","summary":"List tenant-scoped inbound messages","tags":["Inbound"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"classification","in":"query","schema":{"type":"string","enum":["message","reply","auto_reply","uncorrelated"]}},{"name":"recipient","in":"query","schema":{"type":"string","format":"email"}},{"name":"original_message_id","in":"query","schema":{"type":"string","pattern":"^msg_[A-Za-z0-9_-]{1,64}$"}},{"name":"after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Inbound message summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundMessageList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/inbound/messages/{id}":{"get":{"operationId":"getInboundMessage","summary":"Get one tenant-scoped inbound message","tags":["Inbound"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^inb_[A-Za-z0-9_-]+$"}}],"responses":{"200":{"description":"Inbound message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundMessage"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Airmail API key"}},"parameters":{"MessageId":{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^msg_[A-Za-z0-9_-]+$"}}},"responses":{"BadRequest":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"API key missing, invalid, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Tenant, domain, policy, quota, or entitlement rejected the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Idempotency key conflicts with another payload or operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Configured request or email rate exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Object not found in the authenticated tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamUnavailable":{"description":"A downstream submission dependency is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Address":{"type":"object","additionalProperties":false,"required":["email"],"properties":{"email":{"type":"string","format":"email","maxLength":320},"name":{"type":"string","minLength":1,"maxLength":255}}},"MessageAddress":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"},"name":{"type":["string","null"]}}},"SendMessageRequest":{"type":"object","additionalProperties":false,"required":["from","to","subject"],"anyOf":[{"required":["text"]},{"required":["html"]}],"properties":{"from":{"$ref":"#/components/schemas/Address"},"to":{"type":"array","minItems":1,"maxItems":50,"items":{"$ref":"#/components/schemas/Address"}},"reply_to":{"type":"string","format":"email","maxLength":320},"subject":{"type":"string","minLength":1,"maxLength":998},"category":{"type":"string","enum":["transactional","otp","marketing"],"default":"transactional","description":"OTP and marketing require separate operator policy approval. Marketing uses the lower-priority outreach lane and requires one recipient plus one-click unsubscribe."},"text":{"type":"string","maxLength":262144},"html":{"type":"string","maxLength":262144},"headers":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"List-Unsubscribe":{"type":"string","minLength":1,"maxLength":1000},"List-Unsubscribe-Post":{"const":"List-Unsubscribe=One-Click"}}},"tags":{"type":"object","propertyNames":{"type":"string","maxLength":64},"additionalProperties":{"type":"string","maxLength":128}}}},"AcceptedMessage":{"type":"object","required":["id","status","recipients"],"properties":{"id":{"type":"string","pattern":"^msg_[A-Za-z0-9_-]+$"},"status":{"type":"string"},"recipients":{"type":"array","items":{"type":"object","required":["email","status"],"properties":{"email":{"type":"string","format":"email"},"status":{"type":"string"}}}}}},"Message":{"type":"object","required":["id","status","recipients"],"properties":{"id":{"type":"string","pattern":"^msg_[A-Za-z0-9_-]+$"},"status":{"type":"string","description":"Current logical lifecycle state."},"category":{"type":"string"},"from":{"$ref":"#/components/schemas/MessageAddress"},"reply_to":{"type":["string","null"],"format":"email"},"subject":{"type":"string"},"created_at":{"type":["string","null"],"format":"date-time"},"submitted_at":{"type":["string","null"],"format":"date-time"},"delivered_at":{"type":["string","null"],"format":"date-time"},"failed_at":{"type":["string","null"],"format":"date-time"},"recipients":{"type":"array","items":{"$ref":"#/components/schemas/MessageRecipient"}}}},"MessageRecipient":{"allOf":[{"$ref":"#/components/schemas/MessageAddress"},{"type":"object","required":["id","status"],"properties":{"id":{"type":"string"},"status":{"type":"string"},"delivered_at":{"type":["string","null"],"format":"date-time"},"bounced_at":{"type":["string","null"],"format":"date-time"},"failed_at":{"type":["string","null"],"format":"date-time"}}}]},"MessageEventList":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","type","occurred_at"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"occurred_at":{"type":["string","null"],"format":"date-time"},"details":{"type":"object","additionalProperties":true}}}}}},"CreateSuppressionRequest":{"type":"object","additionalProperties":false,"required":["email","reason"],"properties":{"email":{"type":"string","format":"email","maxLength":320},"reason":{"type":"string","enum":["hard_bounce","complaint","unsubscribe","invalid","manual","abuse"]},"source":{"type":"string","minLength":1,"maxLength":64}}},"Suppression":{"type":"object","required":["status","email","reason"],"properties":{"status":{"const":"suppressed"},"email":{"type":"string","format":"email"},"reason":{"type":"string"}}},"InboundMessageList":{"type":"object","required":["object","data"],"properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/InboundMessageSummary"}}}},"InboundMessageSummary":{"type":"object","required":["id","classification","from","to","correlated"],"properties":{"id":{"type":"string"},"classification":{"type":"string","enum":["message","reply","auto_reply","uncorrelated"]},"from":{"$ref":"#/components/schemas/MessageAddress"},"to":{"type":"string","format":"email"},"subject":{"type":["string","null"]},"received_at":{"type":["string","null"],"format":"date-time"},"spam_status":{"type":["string","null"]},"correlated":{"type":"boolean"},"original_message_id":{"type":["string","null"]}}},"InboundMessage":{"allOf":[{"$ref":"#/components/schemas/InboundMessageSummary"},{"type":"object","properties":{"in_reply_to":{"type":["string","null"]},"auto_submitted":{"type":["string","null"]},"attachment_count":{"type":"integer"},"content_expired":{"type":"boolean"},"text":{"type":["string","null"]},"html":{"type":["string","null"],"description":"Untrusted HTML; sanitize before rendering."}}}]},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}}}}}}}