{"openapi":"3.1.0","info":{"title":"SendMux Sending API","version":"1.0.0","description":"Send emails programmatically via the SendMux email infrastructure. Every response carries an `X-Request-Id` header; errors include a `retryable` flag. 429 and 503 responses include `Retry-After`. Mutating endpoints accept an `Idempotency-Key` header for safe retries."},"servers":[{"url":"https://smtp.sendmux.ai/api/v1","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"SendMux API key (smx_...)"}},"schemas":{"Meta":{"type":"object","properties":{"request_id":{"type":"string","description":"Unique request identifier","example":"req_clxxxxxxxxxxxxxxxxxxxxxxxxx"}},"required":["request_id"],"additionalProperties":false},"SendSuccessData":{"type":"object","properties":{"message_id":{"type":"string","pattern":"^eml_[a-z0-9]{24}$","description":"Unique message identifier (eml_ prefix + 24 alphanumeric chars)","example":"eml_tz4a98xxat96iws9zmbrgj3a"},"status":{"type":"string","enum":["queued"],"description":"Message queuing status"}},"required":["message_id","status"],"additionalProperties":false},"SuccessEnvelope":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["ok","meta"]},"SendSuccessResponse":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SendSuccessData"}},"required":["data"]}],"unevaluatedProperties":false},"ErrorIssue":{"type":"object","properties":{"field":{"type":"string","description":"Dot-path to the failing field","example":"to.email"},"code":{"type":"string","description":"Issue code from the validator","example":"invalid_string"},"message":{"type":"string","description":"Human-readable issue message"}},"required":["field","code","message"],"additionalProperties":false},"ErrorDetail":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code","example":"validation_error"},"message":{"type":"string","description":"Human-readable error description"},"param":{"type":"string","description":"Parameter that caused the error"},"doc_url":{"type":"string","format":"uri","description":"Link to error documentation"},"retryable":{"type":"boolean","description":"True when the client may safely retry the same request. 429 and 5xx default true; 4xx default false."},"errors":{"type":"array","items":{"$ref":"#/components/schemas/ErrorIssue"},"description":"Accumulated per-field issues (validation errors)"}},"required":["code","message","retryable"],"additionalProperties":false},"ErrorResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]},"error":{"$ref":"#/components/schemas/ErrorDetail"},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["ok","error","meta"],"additionalProperties":false},"Address":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"Email address","example":"user@example.com"},"name":{"type":"string","maxLength":100,"pattern":"^[^\\r\\n]*$","description":"Display name","example":"John Smith"}},"required":["email"],"additionalProperties":false,"description":"Sender address"},"Recipient":{"type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","description":"Recipient email address"},"name":{"type":"string","maxLength":100,"pattern":"^[^\\r\\n]*$","description":"Recipient display name"}},"required":["email"],"additionalProperties":false},"Attachment":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255,"description":"Filename with allowed extension","example":"invoice.pdf"},"content":{"type":"string","minLength":1,"description":"Base64-encoded file content"},"type":{"type":"string","description":"MIME type override","example":"application/pdf"},"encoding":{"type":"string","enum":["base64"],"default":"base64"}},"required":["filename","content"],"additionalProperties":false},"EmailSendRequest":{"type":"object","properties":{"from":{"$ref":"#/components/schemas/Address"},"to":{"allOf":[{"$ref":"#/components/schemas/Address"},{"description":"Primary recipient"}]},"subject":{"type":"string","minLength":1,"maxLength":998,"pattern":"^[^\\r\\n]*$","description":"Email subject line (max 998 chars, RFC 5322)","example":"Welcome to SendMux"},"html_body":{"type":"string","minLength":1,"maxLength":26214400,"description":"HTML email content (max 25MB)"},"text_body":{"type":"string","maxLength":26214400,"description":"Plain text alternative (max 25MB)"},"reply_to":{"allOf":[{"$ref":"#/components/schemas/Address"},{"description":"Reply-To address"}]},"return_path":{"type":"string","maxLength":254,"format":"email","description":"Envelope sender for VERP support"},"cc":{"type":"array","items":{"$ref":"#/components/schemas/Recipient"},"maxItems":100,"description":"CC recipients (max 100)"},"bcc":{"type":"array","items":{"$ref":"#/components/schemas/Recipient"},"maxItems":100,"description":"BCC recipients (max 100)"},"custom_headers":{"type":"object","additionalProperties":{"type":"string","maxLength":500,"pattern":"^[^\\r\\n]*$"},"description":"Custom X-* headers to include in the email"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"},"maxItems":10,"description":"File attachments (max 10)"}},"required":["from","to","subject","html_body"],"additionalProperties":false},"BatchResultItem":{"type":"object","properties":{"index":{"type":"integer","description":"Position in the input array"},"message_id":{"type":["string","null"],"pattern":"^eml_[a-z0-9]{24}$","description":"Message ID (null if failed)"},"status":{"type":"string","enum":["queued","failed"],"description":"Result status"},"error":{"allOf":[{"$ref":"#/components/schemas/ErrorDetail"},{"description":"Error details (only if failed)"}]}},"required":["index","message_id","status"],"additionalProperties":false},"BatchSummary":{"type":"object","properties":{"total":{"type":"integer","description":"Total messages in batch"},"queued":{"type":"integer","description":"Successfully queued count"},"failed":{"type":"integer","description":"Failed count"}},"required":["total","queued","failed"],"additionalProperties":false},"BatchSendSuccessData":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchResultItem"}},"summary":{"$ref":"#/components/schemas/BatchSummary"}},"required":["results","summary"],"additionalProperties":false},"BatchSendSuccessResponse":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BatchSendSuccessData"}},"required":["data"]}],"unevaluatedProperties":false},"BatchSendRequest":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/EmailSendRequest"},"minItems":1,"maxItems":100,"description":"Array of email messages to send (max 100)"}},"required":["messages"],"additionalProperties":false}},"parameters":{}},"paths":{"/emails/send":{"post":{"operationId":"sendingSendEmail","summary":"Send a single email","description":"Queue a single email for delivery. Requires `email.send` permission.","tags":["Emails"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-zA-Z0-9_-]+$"},"description":"Optional client-generated key to make the request idempotent for 24 hours. Replays under the same key return the cached response; a reused key with a different body returns 409 idempotency_conflict.","example":"order-12345-2026-04-24"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendRequest"}}}},"responses":{"200":{"description":"Email queued successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendSuccessResponse"}}}},"400":{"description":"Malformed request (invalid JSON or syntactic parameter error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency conflict (Idempotency-Key reused with different body, or request already in flight)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request body exceeds 25 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error (schema failures, accumulated in error.errors[])","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded (Retry-After header included)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable (Retry-After header included)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/emails/send/batch":{"post":{"operationId":"sendingSendEmailBatch","summary":"Send a batch of emails","description":"Queue up to 100 emails for delivery in a single request. Uses partial success model — individual message failures do not fail the entire batch. Requires `email.send` permission.","tags":["Emails"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[a-zA-Z0-9_-]+$"},"description":"Optional client-generated key to make the request idempotent for 24 hours. Replays under the same key return the cached response; a reused key with a different body returns 409 idempotency_conflict.","example":"order-12345-2026-04-24"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSendRequest"}}}},"responses":{"200":{"description":"Batch processed (check individual results for per-message status)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSendSuccessResponse"}}}},"400":{"description":"Malformed request (invalid JSON or syntactic parameter error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Insufficient credits for entire batch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request body exceeds 25 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"All messages failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable or all messages failed with transient errors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/openapi.json":{"get":{"operationId":"sendingGetOpenApiSpec","summary":"OpenAPI 3.1 specification","description":"Auto-generated OpenAPI 3.1 spec for the SendMux Sending API. Public endpoint (no authentication). Emits a weak ETag; clients may send `If-None-Match` to receive 304 Not Modified.","tags":["Meta"],"security":[],"parameters":[{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"Weak ETag from a previous response. When it matches the current resource, the server returns 304 Not Modified with no body."}],"responses":{"200":{"description":"OpenAPI 3.1 document","headers":{"ETag":{"schema":{"type":"string"},"description":"Weak ETag of the canonical spec content"},"Cache-Control":{"schema":{"type":"string"},"description":"public, max-age=3600"}},"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"304":{"description":"Spec has not changed (matches If-None-Match). Response body is empty per RFC 7232 §4.1.","headers":{"ETag":{"schema":{"type":"string"}}}}}}}},"webhooks":{}}