{"openapi":"3.1.0","info":{"title":"Transmit API","version":"1.0.0","description":"Transactional email and SMS. Authenticate with an API key as a bearer token; every key carries scopes, and a call without the scope it needs is refused rather than partially served.","contact":{"name":"Transmit support","email":"support@transmit.dev","url":"https://www.transmit.dev"}},"servers":[{"url":"https://api.transmit.dev","description":"Production"}],"tags":[{"name":"Emails"},{"name":"Analytics"},{"name":"Contacts"},{"name":"Audiences"},{"name":"Campaigns"},{"name":"Templates"},{"name":"SMS"},{"name":"Webhooks"},{"name":"Compatibility"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your API key, as `Authorization: Bearer tr_v2_…`. Create one in Settings → API keys."}},"schemas":{"Error":{"type":"object","description":"The error envelope returned by authentication, authorization and validation failures","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"A stable, machine-readable code"},"message":{"type":"string"},"details":{"type":"object","description":"Present when the failure has structure worth reading, such as validation issues"}}}}}}},"paths":{"/v1/emails":{"post":{"operationId":"sendEmail","summary":"Send an email","description":"Accepts the message, charges the credits and queues it. The response is the receipt for the submission, not the delivery; delivery events arrive on your webhook.\n\nSend either a body — `subject` plus `html` or `text` — or a template, by `template_id` or `template_friendly_name` but not both. JSON Schema cannot express that, so those fields are all optional below and the API answers 422 when the combination is wrong.","tags":["Emails"],"x-scope":"email:send","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key, at most 255 characters. Replaying it returns the original result instead of billing twice.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","minLength":1,"maxLength":320},"from_name":{"type":"string","minLength":1,"maxLength":255},"to":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"minItems":1,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}}]},"cc":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"minItems":1,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}}]},"bcc":{"anyOf":[{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"minItems":1,"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}}]},"reply_to":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"subject":{"type":"string","maxLength":998},"html":{"type":"string"},"text":{"type":"string"},"template_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)$"},"template_friendly_name":{"type":"string","minLength":1,"maxLength":255},"variables":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"tags":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":256}},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"attachments":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255},"content":{"type":"string","minLength":1,"maxLength":14000000,"description":"Base64-encoded attachment body"},"type":{"type":"string","minLength":1,"maxLength":255},"contentId":{"type":"string","minLength":1,"maxLength":255},"disposition":{"default":"attachment","type":"string","enum":["attachment","inline"]}},"required":["filename","content","type"]}},"scheduled_for":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"batch_id":{"type":"string","minLength":1,"maxLength":255},"message_stream":{"default":"transactional","type":"string","enum":["transactional","broadcast"]},"track_opens":{"default":true,"type":"boolean"},"track_clicks":{"default":true,"type":"boolean"}},"required":["from","to"]},"example":{"from":"Acme <hello@yourdomain.com>","to":"you@example.com","subject":"It arrived.","html":"<p>Nobody noticed. That is the job.</p>"}}}},"responses":{"202":{"description":"Queued, or scheduled if `scheduled_for` was set","content":{"application/json":{"schema":{"type":"object","properties":{"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)$"},"from":{"type":"string"},"to":{"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"subject":{"type":"string"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"scheduled_for":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"suppressed_recipients":{"type":"array","items":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"status":{"type":"string","enum":["queued","scheduled"]},"credits_consumed":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["id","from","to","subject","created_at","scheduled_for","suppressed_recipients","status","credits_consumed"],"additionalProperties":false}}}},"400":{"description":"The `Idempotency-Key` header is missing or too long"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `email:send` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request failed validation"}}}},"/v1/analytics":{"get":{"operationId":"getAnalytics","summary":"Daily email totals","description":"Aggregates by day over the requested range. Defaults to the last 30 days; the range cannot exceed 366 days.","tags":["Analytics"],"x-scope":"analytics:read","parameters":[{"name":"from","in":"query","description":"Start of the range, inclusive. Defaults to 30 days before `to`.","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"End of the range, inclusive. Defaults to now.","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Totals for the range and a row per day","content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"totals":{"type":"object","properties":{"accepted":{"type":"integer"},"submitted":{"type":"integer"},"delivered":{"type":"integer"},"bounced":{"type":"integer"},"complained":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"credits_used":{"type":"integer"}}},"data":{"type":"array","items":{"type":"object"},"description":"One aggregate per day"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `analytics:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The range is invalid or longer than 366 days"}}}},"/v1/contacts":{"get":{"operationId":"listContacts","summary":"List contacts","tags":["Contacts"],"x-scope":"contact:read","parameters":[{"name":"limit","in":"query","description":"Rows per page, 1–500. Defaults to 100.","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"cursor","in":"query","description":"The `next_cursor` from the previous page.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"A page of contacts","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"}},"next_cursor":{"type":["string","null"]}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `contact:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"upsertContact","summary":"Create or update a contact","description":"Matches on `email` within your organization: an existing contact is updated, otherwise one is created.","tags":["Contacts"],"x-scope":"contact:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"first_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"last_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"subscribed":{"type":"boolean"},"tags":{"maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["email"]}}}},"responses":{"200":{"description":"The stored contact"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `contact:write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request failed validation"}}}},"/v1/audiences":{"get":{"operationId":"listAudiences","summary":"List audiences","tags":["Audiences"],"x-scope":"campaign:read","responses":{"200":{"description":"Every audience, each with its contact count","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"},"description":"Audiences"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `campaign:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createAudience","summary":"Create an audience","tags":["Audiences"],"x-scope":"campaign:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":1000},"contact_ids":{"default":[],"maxItems":100000,"type":"array","items":{"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":["name"]}}}},"responses":{"201":{"description":"The created audience"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `campaign:write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A contact id does not belong to your organization"}}}},"/v1/campaigns":{"get":{"operationId":"listCampaigns","summary":"List campaigns","tags":["Campaigns"],"x-scope":"campaign:read","responses":{"200":{"description":"Campaigns, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"},"description":"Campaigns"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `campaign:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createCampaign","summary":"Create and start a campaign","description":"Starts the send immediately, or holds it until `scheduled_for`.","tags":["Campaigns"],"x-scope":"campaign:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"audience_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)$"},"template_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)$"},"from":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"from_name":{"type":"string","maxLength":200},"track_opens":{"default":true,"type":"boolean"},"track_clicks":{"default":true,"type":"boolean"},"scheduled_for":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["name","audience_id","template_id","from"]}}}},"responses":{"202":{"description":"The campaign and the id of the run driving it"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `campaign:write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The audience or the template does not exist"}}}},"/v1/templates":{"get":{"operationId":"listTemplates","summary":"List templates","tags":["Templates"],"x-scope":"template:read","responses":{"200":{"description":"Templates, most recently updated first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"},"description":"Templates"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `template:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createTemplate","summary":"Create a template","tags":["Templates"],"x-scope":"template:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"friendly_name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9][a-z0-9_-]*$"},"name":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":998},"html":{"type":"string","minLength":1},"text":{"type":"string","minLength":1},"variables":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["friendly_name","name","subject"]},"example":{"friendly_name":"order-shipped","name":"Order shipped","subject":"Your order is on its way","html":"<p>Hello {{name}}, tracking: {{tracking}}.</p>"}}}},"responses":{"201":{"description":"The created template"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `template:write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request failed validation"}}}},"/v1/templates/{id}":{"get":{"operationId":"getTemplate","summary":"Retrieve a template","description":"Includes every revision and the stored body.","tags":["Templates"],"x-scope":"template:read","parameters":[{"name":"id","in":"path","description":"The template id.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The template"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `template:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template"}}},"patch":{"operationId":"updateTemplate","summary":"Update a template","description":"Changing the body cuts a new revision.","tags":["Templates"],"x-scope":"template:write","parameters":[{"name":"id","in":"path","description":"The template id.","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"friendly_name":{"type":"string","minLength":1,"maxLength":100,"pattern":"^[a-z0-9][a-z0-9_-]*$"},"name":{"type":"string","minLength":1,"maxLength":200},"subject":{"type":"string","minLength":1,"maxLength":998},"html":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"text":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"variables":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}}}},"responses":{"200":{"description":"The updated template"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `template:write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template"}}},"delete":{"operationId":"deleteTemplate","summary":"Delete a template","tags":["Templates"],"x-scope":"template:write","parameters":[{"name":"id","in":"path","description":"The template id.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `template:write` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such template"}}}},"/v1/sms":{"post":{"operationId":"sendSms","summary":"Send an SMS","description":"Transactional only. The body comes from an approved template rendered with your variables; there is no free-text body, and every send attests the consent basis.","tags":["SMS"],"x-scope":"sms:send","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key, at most 255 characters. Replaying it returns the original result instead of billing twice.","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Sender phone number in E.164 format"},"to":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Recipient phone number in E.164 format"},"template_id":{"description":"Approved template 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)$"},"template":{"description":"Approved template name (alternative to template_id)","type":"string","minLength":1,"maxLength":100},"variables":{"default":{},"type":"object","propertyNames":{"type":"string","pattern":"^[a-zA-Z][a-zA-Z0-9_]{0,31}$"},"additionalProperties":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[\\p{L}\\p{N} .,'#:\\-()/]+$"}},"consent_basis":{"type":"string","enum":["transactional"],"description":"Attestation that the recipient requested this message (transactional)"},"tags":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":256}},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["from","to","consent_basis"]},"example":{"from":"+18885550100","to":"+12025550100","template":"otp","variables":{"code":"483920"},"consent_basis":"transactional"}}}},"responses":{"202":{"description":"Queued","content":{"application/json":{"schema":{"type":"object","properties":{"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)$"},"from":{"type":"string"},"to":{"type":"string"},"template_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","const":"queued"},"segments":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"credits_consumed":{"type":"integer","minimum":0,"maximum":9007199254740991},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","from","to","template_id","status","segments","credits_consumed","created_at"],"additionalProperties":false}}}},"400":{"description":"The `Idempotency-Key` header is missing or too long"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `sms:send` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request failed validation"}}},"get":{"operationId":"listSms","summary":"List SMS messages","tags":["SMS"],"x-scope":"sms:read","parameters":[{"name":"limit","in":"query","description":"Rows per page, 1–100. Defaults to 20.","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","description":"The `next_cursor` from the previous page.","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Restrict to one direction.","required":false,"schema":{"type":"string","enum":["outbound","inbound"]}}],"responses":{"200":{"description":"A page of messages, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"},"description":"SMS messages"},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"],"description":"Pass as `cursor` to fetch the next page"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `sms:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sms/{id}":{"get":{"operationId":"getSms","summary":"Retrieve an SMS message","tags":["SMS"],"x-scope":"sms:read","parameters":[{"name":"id","in":"path","description":"The message id.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The message and its delivery attempts"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `sms:read` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such message"}}}},"/v1/webhooks":{"get":{"operationId":"listWebhooks","summary":"List webhook endpoints","tags":["Webhooks"],"x-scope":"webhook:manage","responses":{"200":{"description":"Your endpoints. Secrets are never returned here.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object"},"description":"Webhook endpoints"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `webhook:manage` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createWebhook","summary":"Create a webhook endpoint","description":"The signing secret is returned once, on creation. Store it: it cannot be read back.","tags":["Webhooks"],"x-scope":"webhook:manage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"url":{"type":"string","format":"uri"},"events":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":100}}},"required":["name","url","events"]}}}},"responses":{"201":{"description":"The endpoint, including its signing secret"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `webhook:manage` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The URL failed validation or is not reachable from the public internet"}}}},"/v1/webhooks/{id}":{"patch":{"operationId":"updateWebhook","summary":"Update a webhook endpoint","tags":["Webhooks"],"x-scope":"webhook:manage","parameters":[{"name":"id","in":"path","description":"The endpoint id.","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"url":{"type":"string","format":"uri"},"events":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":100}},"status":{"type":"string","enum":["ACTIVE","DISABLED"]}}}}}},"responses":{"200":{"description":"The updated endpoint"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `webhook:manage` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such endpoint"}}},"delete":{"operationId":"deleteWebhook","summary":"Disable a webhook endpoint","description":"Endpoints are disabled rather than destroyed, so past deliveries keep their reference.","tags":["Webhooks"],"x-scope":"webhook:manage","parameters":[{"name":"id","in":"path","description":"The endpoint id.","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Disabled"},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `webhook:manage` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such endpoint"}}}},"/emails":{"post":{"operationId":"sendEmailResendCompatible","summary":"Send an email, Resend-shaped","description":"The same send as `POST /v1/emails`, at the path and in the body shape a Resend client already uses, so migrating is a base URL and a key. `tags` name/value pairs become `name:value`, `content_type` becomes `type`, and `scheduled_at` becomes `scheduled_for` — but only as an ISO 8601 instant: Resend's relative times (\"in 1 min\") are refused rather than silently sent now. Answers with `{ id }`, as Resend does.","tags":["Compatibility"],"x-scope":"email:send","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string"},"to":{"anyOf":[{"type":"string"},{"minItems":1,"type":"array","items":{"type":"string"}}]},"subject":{"type":"string"},"bcc":{"anyOf":[{"type":"string"},{"minItems":1,"type":"array","items":{"type":"string"}}]},"cc":{"anyOf":[{"type":"string"},{"minItems":1,"type":"array","items":{"type":"string"}}]},"reply_to":{"anyOf":[{"type":"string"},{"minItems":1,"type":"array","items":{"type":"string"}}]},"html":{"type":"string"},"text":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"attachments":{"type":"array","items":{"type":"object","properties":{"filename":{"type":"string"},"content":{"type":"string"},"path":{"type":"string"},"content_type":{"type":"string"}},"required":["filename"]}},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]}},"scheduled_at":{"type":"string"}},"required":["from","to"]},"example":{"from":"Acme <hello@yourdomain.com>","to":["you@example.com"],"subject":"It arrived.","html":"<p>Nobody noticed.</p>"}}}},"responses":{"200":{"description":"Queued","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}}}}}},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `email:send` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request failed validation, or names something we will not silently ignore"}}}},"/v3/mail/send":{"post":{"operationId":"sendEmailSendGridCompatible","summary":"Send an email, SendGrid-shaped","description":"The same send as `POST /v1/emails`, at the path and in the body shape a SendGrid client already uses. Each personalization becomes one message, so a payload addressed to three queues three. `categories` become tags, `send_at` becomes `scheduled_for`, and `dynamic_template_data` becomes `variables`; a SendGrid dynamic template id (`d-…`) names a template that lives in SendGrid, so it is refused. Answers 202 with an empty body and the id in `X-Message-Id`, as SendGrid does.","tags":["Compatibility"],"x-scope":"email:send","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"personalizations":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"object","properties":{"to":{"minItems":1,"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":"string"}},"required":["email"]}},"cc":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":"string"}},"required":["email"]}},"bcc":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":"string"}},"required":["email"]}},"subject":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"dynamic_template_data":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"send_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["to"]}},"from":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":"string"}},"required":["email"]},"reply_to":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":"string"}},"required":["email"]},"subject":{"type":"string"},"content":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"string"}},"required":["type","value"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"content":{"type":"string"},"filename":{"type":"string"},"type":{"type":"string"},"disposition":{"type":"string","enum":["attachment","inline"]},"content_id":{"type":"string"}},"required":["content","filename"]}},"template_id":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"categories":{"type":"array","items":{"type":"string"}},"send_at":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["personalizations","from"]},"example":{"personalizations":[{"to":[{"email":"you@example.com"}]}],"from":{"email":"hello@yourdomain.com"},"subject":"It arrived.","content":[{"type":"text/plain","value":"Nobody noticed."}]}}}},"responses":{"202":{"description":"Queued. `X-Message-Id` carries the first id, `X-Message-Ids` all of them."},"401":{"description":"The API key is missing, malformed, expired or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The API key lacks the `email:send` scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request failed validation, or names something we will not silently ignore"}}}}}}