{"openapi":"3.0.0","info":{"version":"1.0.0","title":"mailstein API"},"servers":[{"url":"https://app.mailstein.com/api"}],"components":{"securitySchemes":{"Bearer":{"type":"http","scheme":"bearer"}},"schemas":{},"parameters":{}},"paths":{"/v1/domains":{"get":{"responses":{"200":{"description":"Retrieve domains accessible by the API key","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"The ID of the domain","example":1},"name":{"type":"string","description":"The name of the domain","example":"example.com"},"teamId":{"type":"number","description":"The ID of the team","example":1},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"region":{"type":"string","default":"us-east-1"},"clickTracking":{"type":"boolean","default":false},"openTracking":{"type":"boolean","default":false},"trackingDomain":{"type":"string","nullable":true,"description":"Custom domain used for click-tracking links. Null means links use the sending engine's shared redirect host.","example":"links.example.com"},"trackingDomainStatus":{"type":"string","nullable":true},"tlsPolicy":{"type":"string","enum":["OPPORTUNISTIC","ENFORCED"],"default":"OPPORTUNISTIC","description":"ENFORCED refuses to deliver over an unencrypted connection; OPPORTUNISTIC falls back to one.","example":"OPPORTUNISTIC"},"publicKey":{"type":"string"},"dkimStatus":{"type":"string","nullable":true},"spfDetails":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"dmarcAdded":{"type":"boolean","default":false},"isVerifying":{"type":"boolean","default":false},"errorMessage":{"type":"string","nullable":true},"subdomain":{"type":"string","nullable":true},"verificationError":{"type":"string","nullable":true},"lastCheckedTime":{"type":"string","nullable":true},"dnsRecords":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["MX","TXT","CNAME"],"description":"DNS record type","example":"TXT"},"name":{"type":"string","description":"DNS record name","example":"mail"},"value":{"type":"string","description":"DNS record value","example":"v=spf1 include:amazonses.com ~all"},"ttl":{"type":"string","description":"DNS record TTL","example":"Auto"},"priority":{"type":"string","nullable":true,"description":"DNS record priority","example":"10"},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"recommended":{"type":"boolean","description":"Whether the record is recommended"}},"required":["type","name","value","ttl","status"]}}},"required":["id","name","teamId","status","publicKey","createdAt","updatedAt","dnsRecords"]}}}}}}},"post":{"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"region":{"type":"string"}},"required":["name","region"]}}}},"responses":{"200":{"description":"Create a new domain","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"number","description":"The ID of the domain","example":1},"name":{"type":"string","description":"The name of the domain","example":"example.com"},"teamId":{"type":"number","description":"The ID of the team","example":1},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"region":{"type":"string","default":"us-east-1"},"clickTracking":{"type":"boolean","default":false},"openTracking":{"type":"boolean","default":false},"trackingDomain":{"type":"string","nullable":true,"description":"Custom domain used for click-tracking links. Null means links use the sending engine's shared redirect host.","example":"links.example.com"},"trackingDomainStatus":{"type":"string","nullable":true},"tlsPolicy":{"type":"string","enum":["OPPORTUNISTIC","ENFORCED"],"default":"OPPORTUNISTIC","description":"ENFORCED refuses to deliver over an unencrypted connection; OPPORTUNISTIC falls back to one.","example":"OPPORTUNISTIC"},"publicKey":{"type":"string"},"dkimStatus":{"type":"string","nullable":true},"spfDetails":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"dmarcAdded":{"type":"boolean","default":false},"isVerifying":{"type":"boolean","default":false},"errorMessage":{"type":"string","nullable":true},"subdomain":{"type":"string","nullable":true},"verificationError":{"type":"string","nullable":true},"lastCheckedTime":{"type":"string","nullable":true},"dnsRecords":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["MX","TXT","CNAME"],"description":"DNS record type","example":"TXT"},"name":{"type":"string","description":"DNS record name","example":"mail"},"value":{"type":"string","description":"DNS record value","example":"v=spf1 include:amazonses.com ~all"},"ttl":{"type":"string","description":"DNS record TTL","example":"Auto"},"priority":{"type":"string","nullable":true,"description":"DNS record priority","example":"10"},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"recommended":{"type":"boolean","description":"Whether the record is recommended"}},"required":["type","name","value","ttl","status"]}}},"required":["id","name","teamId","status","publicKey","createdAt","updatedAt","dnsRecords"]}}}}}}},"/v1/domains/{id}/verify":{"put":{"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":2147483647,"example":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Verify domain","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"Forbidden - API key doesn't have access to this domain","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/v1/domains/{id}":{"get":{"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":2147483647,"example":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Retrieve the domain","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"number","description":"The ID of the domain","example":1},"name":{"type":"string","description":"The name of the domain","example":"example.com"},"teamId":{"type":"number","description":"The ID of the team","example":1},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"region":{"type":"string","default":"us-east-1"},"clickTracking":{"type":"boolean","default":false},"openTracking":{"type":"boolean","default":false},"trackingDomain":{"type":"string","nullable":true,"description":"Custom domain used for click-tracking links. Null means links use the sending engine's shared redirect host.","example":"links.example.com"},"trackingDomainStatus":{"type":"string","nullable":true},"tlsPolicy":{"type":"string","enum":["OPPORTUNISTIC","ENFORCED"],"default":"OPPORTUNISTIC","description":"ENFORCED refuses to deliver over an unencrypted connection; OPPORTUNISTIC falls back to one.","example":"OPPORTUNISTIC"},"publicKey":{"type":"string"},"dkimStatus":{"type":"string","nullable":true},"spfDetails":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"dmarcAdded":{"type":"boolean","default":false},"isVerifying":{"type":"boolean","default":false},"errorMessage":{"type":"string","nullable":true},"subdomain":{"type":"string","nullable":true},"verificationError":{"type":"string","nullable":true},"lastCheckedTime":{"type":"string","nullable":true},"dnsRecords":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["MX","TXT","CNAME"],"description":"DNS record type","example":"TXT"},"name":{"type":"string","description":"DNS record name","example":"mail"},"value":{"type":"string","description":"DNS record value","example":"v=spf1 include:amazonses.com ~all"},"ttl":{"type":"string","description":"DNS record TTL","example":"Auto"},"priority":{"type":"string","nullable":true,"description":"DNS record priority","example":"10"},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"recommended":{"type":"boolean","description":"Whether the record is recommended"}},"required":["type","name","value","ttl","status"]}}},"required":["id","name","teamId","status","publicKey","createdAt","updatedAt","dnsRecords"]}}}}}},"delete":{"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":2147483647,"example":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Domain deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"number"},"success":{"type":"boolean"},"message":{"type":"string"}},"required":["id","success","message"]}}}},"403":{"description":"Forbidden - API key doesn't have access","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Domain not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"patch":{"summary":"Update a domain","description":"Any subset of the settings. Setting a tracking domain returns the CNAME to publish in the domain's `dnsRecords`; tracking only starts once it resolves.","parameters":[{"schema":{"type":"integer","nullable":true,"example":1},"required":false,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"clickTracking":{"type":"boolean"},"openTracking":{"type":"boolean"},"trackingDomain":{"type":"string","nullable":true,"description":"A subdomain of this domain, e.g. `links.example.com` or just `links`. Null clears it and puts tracked links back on the shared host.","example":"links.example.com"},"tlsPolicy":{"type":"string","enum":["OPPORTUNISTIC","ENFORCED"],"description":"ENFORCED refuses to deliver over an unencrypted connection. OPPORTUNISTIC falls back to one."},"receiving":{"type":"boolean","description":"Whether mail addressed to this domain is delivered to mailstein. Turning it on provisions inbound routing and adds an MX record to the domain's DNS records, which you then publish. The domain must be verified first. Turning it off stops mailstein accepting mail for it — remove the MX from DNS as well, or mail to the domain will be rejected rather than routed elsewhere.","example":true}}}}}},"responses":{"200":{"description":"The updated domain, with its DNS records","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"number","description":"The ID of the domain","example":1},"name":{"type":"string","description":"The name of the domain","example":"example.com"},"teamId":{"type":"number","description":"The ID of the team","example":1},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"region":{"type":"string","default":"us-east-1"},"clickTracking":{"type":"boolean","default":false},"openTracking":{"type":"boolean","default":false},"trackingDomain":{"type":"string","nullable":true,"description":"Custom domain used for click-tracking links. Null means links use the sending engine's shared redirect host.","example":"links.example.com"},"trackingDomainStatus":{"type":"string","nullable":true},"tlsPolicy":{"type":"string","enum":["OPPORTUNISTIC","ENFORCED"],"default":"OPPORTUNISTIC","description":"ENFORCED refuses to deliver over an unencrypted connection; OPPORTUNISTIC falls back to one.","example":"OPPORTUNISTIC"},"publicKey":{"type":"string"},"dkimStatus":{"type":"string","nullable":true},"spfDetails":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"dmarcAdded":{"type":"boolean","default":false},"isVerifying":{"type":"boolean","default":false},"errorMessage":{"type":"string","nullable":true},"subdomain":{"type":"string","nullable":true},"verificationError":{"type":"string","nullable":true},"lastCheckedTime":{"type":"string","nullable":true},"dnsRecords":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["MX","TXT","CNAME"],"description":"DNS record type","example":"TXT"},"name":{"type":"string","description":"DNS record name","example":"mail"},"value":{"type":"string","description":"DNS record value","example":"v=spf1 include:amazonses.com ~all"},"ttl":{"type":"string","description":"DNS record TTL","example":"Auto"},"priority":{"type":"string","nullable":true,"description":"DNS record priority","example":"10"},"status":{"type":"string","enum":["NOT_STARTED","PENDING","SUCCESS","FAILED","TEMPORARY_FAILURE"]},"recommended":{"type":"boolean","description":"Whether the record is recommended"}},"required":["type","name","value","ttl","status"]}}},"required":["id","name","teamId","status","publicKey","createdAt","updatedAt","dnsRecords"]}}}}}}},"/v1/emails/{emailId}":{"get":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"emailId","in":"path"}],"responses":{"200":{"description":"Retrieve the email","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"teamId":{"type":"number"},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"replyTo":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"from":{"type":"string"},"subject":{"type":"string"},"latestStatus":{"type":"string","nullable":true,"enum":["SCHEDULED","QUEUED","SENT","DELIVERY_DELAYED","BOUNCED","REJECTED","RENDERING_FAILURE","DELIVERED","OPENED","CLICKED","COMPLAINED","FAILED","CANCELLED","SUPPRESSED"]},"scheduledAt":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"domainId":{"type":"number","nullable":true},"html":{"type":"string","nullable":true},"text":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"emailEvents":{"type":"array","items":{"type":"object","properties":{"emailId":{"type":"string"},"status":{"type":"string","enum":["SCHEDULED","QUEUED","SENT","DELIVERY_DELAYED","BOUNCED","REJECTED","RENDERING_FAILURE","DELIVERED","OPENED","CLICKED","COMPLAINED","FAILED","CANCELLED","SUPPRESSED"]},"createdAt":{"type":"string"},"data":{"nullable":true}},"required":["emailId","status","createdAt"]}}},"required":["id","teamId","to","from","subject","latestStatus","scheduledAt","tags","domainId","html","text","createdAt","updatedAt","emailEvents"]}}}}}},"patch":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"emailId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scheduledAt":{"type":"string","format":"date-time"}},"required":["scheduledAt"]}}}},"responses":{"200":{"description":"Retrieve the user","content":{"application/json":{"schema":{"type":"object","properties":{"emailId":{"type":"string"}}}}}}}}},"/v1/emails":{"get":{"parameters":[{"schema":{"type":"string","default":"1","example":"1"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","default":"50","example":"50"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"required":false,"name":"startDate","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2024-01-31T23:59:59Z"},"required":false,"name":"endDate","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"example":"123"},"required":false,"name":"domainId","in":"query"},{"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Only emails carrying every one of these tags. Repeat the parameter to require more than one.","example":"welcome"},"required":false,"name":"tag","in":"query"}],"responses":{"200":{"description":"Retrieve a list of emails","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"replyTo":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"nullable":true}]},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"nullable":true}]},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"nullable":true}]},"from":{"type":"string"},"subject":{"type":"string"},"html":{"type":"string","nullable":true},"text":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"latestStatus":{"type":"string","nullable":true,"enum":["SCHEDULED","QUEUED","SENT","DELIVERY_DELAYED","BOUNCED","REJECTED","RENDERING_FAILURE","DELIVERED","OPENED","CLICKED","COMPLAINED","FAILED","CANCELLED","SUPPRESSED"]},"scheduledAt":{"type":"string","nullable":true,"format":"date-time"},"domainId":{"type":"number","nullable":true},"tags":{"type":"array","items":{"type":"string"}}},"required":["id","to","from","subject","html","text","createdAt","updatedAt","latestStatus","scheduledAt","domainId","tags"]}},"count":{"type":"number"}},"required":["data","count"]}}}}}},"post":{"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":256,"description":"Pass the optional Idempotency-Key header to make the request safe to retry. The key can be up to 256 characters. The server stores the canonical request body and behaves as follows:\n\n- Same key + same request body → returns the original emailId with 200 OK without re-sending.\n- Same key + different request body → returns 409 Conflict with code: NOT_UNIQUE so you can detect the mismatch.\n- Same key while another request is still being processed → returns 409 Conflict; retry after a short delay or once the first request completes.\n\nEntries expire after 24 hours. Use a unique key per logical send (for example, an order or signup ID)."},"required":false,"name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"from":{"type":"string"},"subject":{"type":"string","minLength":1,"description":"Optional when templateId is provided"},"templateId":{"type":"string","description":"ID of a template from the dashboard"},"variables":{"type":"object","additionalProperties":{"type":"string"}},"replyTo":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"text":{"type":"string","nullable":true,"minLength":1},"html":{"type":"string","nullable":true,"minLength":1},"headers":{"type":"object","additionalProperties":{"type":"string","minLength":1},"description":"Custom headers to included with the emails"},"attachments":{"type":"array","items":{"type":"object","properties":{"filename":{"type":"string","minLength":1},"content":{"type":"string","minLength":1}},"required":["filename","content"]},"maxItems":10},"scheduledAt":{"type":"string","description":"When to send. ISO 8601, or natural language like 'tomorrow 9am' or 'next monday 10:30'.","example":"2026-08-11T09:00:00Z"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":10,"description":"Labels for finding this message again. Not interpreted; filter on them with GET /v1/emails?tag=.","example":["welcome","onboarding"]},"inReplyToId":{"type":"string","nullable":true}},"required":["to","from"]}}}},"responses":{"200":{"description":"Retrieve the user","content":{"application/json":{"schema":{"type":"object","properties":{"emailId":{"type":"string"}}}}}}}}},"/v1/emails/batch":{"post":{"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":256,"description":"Pass the optional Idempotency-Key header to make the request safe to retry. The key can be up to 256 characters. The server stores the canonical request body and behaves as follows:\n\n- Same key + same request body → returns the original emailId with 200 OK without re-sending.\n- Same key + different request body → returns 409 Conflict with code: NOT_UNIQUE so you can detect the mismatch.\n- Same key while another request is still being processed → returns 409 Conflict; retry after a short delay or once the first request completes.\n\nEntries expire after 24 hours. Use a unique key per logical send (for example, an order or signup ID)."},"required":false,"name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"from":{"type":"string"},"subject":{"type":"string","minLength":1,"description":"Optional when templateId is provided"},"templateId":{"type":"string","description":"ID of a template from the dashboard"},"variables":{"type":"object","additionalProperties":{"type":"string"}},"replyTo":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"text":{"type":"string","nullable":true,"minLength":1},"html":{"type":"string","nullable":true,"minLength":1},"headers":{"type":"object","additionalProperties":{"type":"string","minLength":1},"description":"Custom headers to included with the emails"},"attachments":{"type":"array","items":{"type":"object","properties":{"filename":{"type":"string","minLength":1},"content":{"type":"string","minLength":1}},"required":["filename","content"]},"maxItems":10},"scheduledAt":{"type":"string","description":"When to send. ISO 8601, or natural language like 'tomorrow 9am' or 'next monday 10:30'.","example":"2026-08-11T09:00:00Z"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"maxItems":10,"description":"Labels for finding this message again. Not interpreted; filter on them with GET /v1/emails?tag=.","example":["welcome","onboarding"]},"inReplyToId":{"type":"string","nullable":true}},"required":["to","from"]},"maxItems":100}}}},"responses":{"200":{"description":"List of successfully created email IDs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"emailId":{"type":"string"}},"required":["emailId"]}}},"required":["data"]}}}}}}},"/v1/emails/{emailId}/cancel":{"post":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"emailId","in":"path"}],"responses":{"200":{"description":"Retrieve the user","content":{"application/json":{"schema":{"type":"object","properties":{"emailId":{"type":"string"}}}}}}}}},"/v1/contactBooks/{contactBookId}/contacts":{"post":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"properties":{"type":"object","additionalProperties":{"type":"string"}},"subscribed":{"type":"boolean"}},"required":["email"]}}}},"responses":{"200":{"description":"Retrieve the user","content":{"application/json":{"schema":{"type":"object","properties":{"contactId":{"type":"string"}}}}}}}},"get":{"parameters":[{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"emails","in":"query"},{"schema":{"type":"number"},"required":false,"name":"page","in":"query"},{"schema":{"type":"number"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ids","in":"query"}],"responses":{"200":{"description":"Retrieve multiple contacts","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"},"subscribed":{"type":"boolean","default":true},"properties":{"type":"object","additionalProperties":{"type":"string"}},"contactBookId":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","email","properties","contactBookId","createdAt","updatedAt"]}}}}}}}},"/v1/contactBooks/{contactBookId}/contacts/{contactId}":{"patch":{"parameters":[{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"},{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"properties":{"type":"object","additionalProperties":{"type":"string"}},"subscribed":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Retrieve the user","content":{"application/json":{"schema":{"type":"object","properties":{"contactId":{"type":"string"}}}}}}}},"get":{"parameters":[{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"},{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactId","in":"path"}],"responses":{"200":{"description":"Retrieve the contact","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"},"subscribed":{"type":"boolean","default":true},"properties":{"type":"object","additionalProperties":{"type":"string"}},"contactBookId":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","email","properties","contactBookId","createdAt","updatedAt"]}}}}}},"put":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"properties":{"type":"object","additionalProperties":{"type":"string"}},"subscribed":{"type":"boolean"}},"required":["email"]}}}},"responses":{"200":{"description":"Contact upserted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"contactId":{"type":"string"}},"required":["contactId"]}}}}}},"delete":{"parameters":[{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"},{"schema":{"type":"string","example":"cuiwqdj74rygf74"},"required":true,"name":"contactId","in":"path"}],"responses":{"200":{"description":"Contact deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/v1/contactBooks/{contactBookId}/contacts/bulk":{"post":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"properties":{"type":"object","additionalProperties":{"type":"string"}},"subscribed":{"type":"boolean"}},"required":["email"]},"maxItems":1000}}}},"responses":{"200":{"description":"Bulk add contacts to a contact book","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"count":{"type":"number"}},"required":["message","count"]}}}}}},"delete":{"parameters":[{"schema":{"type":"string","minLength":3,"example":"cuiwqdj74rygf74"},"required":true,"name":"contactBookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":1000}},"required":["contactIds"]}}}},"responses":{"200":{"description":"Bulk delete contacts from a contact book","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"count":{"type":"number"}},"required":["success","count"]}}}}}}},"/v1/contactBooks":{"get":{"responses":{"200":{"description":"Retrieve contact books accessible by the API key","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The ID of the contact book","example":"clx1234567890"},"name":{"type":"string","description":"The name of the contact book","example":"Newsletter Subscribers"},"teamId":{"type":"number","description":"The ID of the team","example":1},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom properties for the contact book","example":{"customField1":"value1"}},"variables":{"type":"array","items":{"type":"string"},"description":"Allowed personalization variables for contacts in this book","example":["registrationCode","company"]},"emoji":{"type":"string","description":"The emoji associated with the contact book","example":"📙"},"doubleOptInEnabled":{"type":"boolean","description":"Whether double opt-in is enabled for new contacts","example":true},"doubleOptInFrom":{"type":"string","nullable":true,"description":"From address used for double opt-in emails (must use a verified domain)","example":"Newsletter <hello@example.com>"},"doubleOptInSubject":{"type":"string","nullable":true,"description":"Subject line used for double opt-in confirmation email","example":"Please confirm your subscription"},"doubleOptInContent":{"type":"string","nullable":true,"description":"Email editor JSON content used for double opt-in confirmation"},"createdAt":{"type":"string","description":"The creation timestamp"},"updatedAt":{"type":"string","description":"The last update timestamp"},"_count":{"type":"object","properties":{"contacts":{"type":"number","description":"The number of contacts in the contact book"}},"required":["contacts"]}},"required":["id","name","teamId","properties","variables","emoji","createdAt","updatedAt"]}}}}}}},"post":{"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"emoji":{"type":"string"},"properties":{"type":"object","additionalProperties":{"type":"string"}},"doubleOptInEnabled":{"type":"boolean"},"doubleOptInFrom":{"type":"string","nullable":true},"doubleOptInSubject":{"type":"string"},"doubleOptInContent":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}}},"required":["name"]}}}},"responses":{"200":{"description":"Create a new contact book","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The ID of the contact book","example":"clx1234567890"},"name":{"type":"string","description":"The name of the contact book","example":"Newsletter Subscribers"},"teamId":{"type":"number","description":"The ID of the team","example":1},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom properties for the contact book","example":{"customField1":"value1"}},"variables":{"type":"array","items":{"type":"string"},"description":"Allowed personalization variables for contacts in this book","example":["registrationCode","company"]},"emoji":{"type":"string","description":"The emoji associated with the contact book","example":"📙"},"doubleOptInEnabled":{"type":"boolean","description":"Whether double opt-in is enabled for new contacts","example":true},"doubleOptInFrom":{"type":"string","nullable":true,"description":"From address used for double opt-in emails (must use a verified domain)","example":"Newsletter <hello@example.com>"},"doubleOptInSubject":{"type":"string","nullable":true,"description":"Subject line used for double opt-in confirmation email","example":"Please confirm your subscription"},"doubleOptInContent":{"type":"string","nullable":true,"description":"Email editor JSON content used for double opt-in confirmation"},"createdAt":{"type":"string","description":"The creation timestamp"},"updatedAt":{"type":"string","description":"The last update timestamp"},"_count":{"type":"object","properties":{"contacts":{"type":"number","description":"The number of contacts in the contact book"}},"required":["contacts"]}},"required":["id","name","teamId","properties","variables","emoji","createdAt","updatedAt"]}}}}}}},"/v1/contactBooks/{contactBookId}":{"get":{"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"contactBookId","in":"path"}],"responses":{"200":{"description":"Retrieve the contact book","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The ID of the contact book","example":"clx1234567890"},"name":{"type":"string","description":"The name of the contact book","example":"Newsletter Subscribers"},"teamId":{"type":"number","description":"The ID of the team","example":1},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom properties for the contact book","example":{"customField1":"value1"}},"variables":{"type":"array","items":{"type":"string"},"description":"Allowed personalization variables for contacts in this book","example":["registrationCode","company"]},"emoji":{"type":"string","description":"The emoji associated with the contact book","example":"📙"},"doubleOptInEnabled":{"type":"boolean","description":"Whether double opt-in is enabled for new contacts","example":true},"doubleOptInFrom":{"type":"string","nullable":true,"description":"From address used for double opt-in emails (must use a verified domain)","example":"Newsletter <hello@example.com>"},"doubleOptInSubject":{"type":"string","nullable":true,"description":"Subject line used for double opt-in confirmation email","example":"Please confirm your subscription"},"doubleOptInContent":{"type":"string","nullable":true,"description":"Email editor JSON content used for double opt-in confirmation"},"createdAt":{"type":"string","description":"The creation timestamp"},"updatedAt":{"type":"string","description":"The last update timestamp"},"_count":{"type":"object","properties":{"contacts":{"type":"number","description":"The number of contacts in the contact book"}},"required":["contacts"]}},"required":["id","name","teamId","properties","variables","emoji","createdAt","updatedAt"]}}}},"403":{"description":"Forbidden - API key doesn't have access to this contact book","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Contact book not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"patch":{"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"contactBookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"emoji":{"type":"string"},"properties":{"type":"object","additionalProperties":{"type":"string"}},"doubleOptInEnabled":{"type":"boolean"},"doubleOptInFrom":{"type":"string","nullable":true},"doubleOptInSubject":{"type":"string"},"doubleOptInContent":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Update the contact book","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The ID of the contact book","example":"clx1234567890"},"name":{"type":"string","description":"The name of the contact book","example":"Newsletter Subscribers"},"teamId":{"type":"number","description":"The ID of the team","example":1},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Custom properties for the contact book","example":{"customField1":"value1"}},"variables":{"type":"array","items":{"type":"string"},"description":"Allowed personalization variables for contacts in this book","example":["registrationCode","company"]},"emoji":{"type":"string","description":"The emoji associated with the contact book","example":"📙"},"doubleOptInEnabled":{"type":"boolean","description":"Whether double opt-in is enabled for new contacts","example":true},"doubleOptInFrom":{"type":"string","nullable":true,"description":"From address used for double opt-in emails (must use a verified domain)","example":"Newsletter <hello@example.com>"},"doubleOptInSubject":{"type":"string","nullable":true,"description":"Subject line used for double opt-in confirmation email","example":"Please confirm your subscription"},"doubleOptInContent":{"type":"string","nullable":true,"description":"Email editor JSON content used for double opt-in confirmation"},"createdAt":{"type":"string","description":"The creation timestamp"},"updatedAt":{"type":"string","description":"The last update timestamp"},"_count":{"type":"object","properties":{"contacts":{"type":"number","description":"The number of contacts in the contact book"}},"required":["contacts"]}},"required":["id","name","teamId","properties","variables","emoji","createdAt","updatedAt"]}}}},"403":{"description":"Forbidden - API key doesn't have access to this contact book","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Contact book not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"delete":{"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"contactBookId","in":"path"}],"responses":{"200":{"description":"Contact book deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"success":{"type":"boolean"},"message":{"type":"string"}},"required":["id","success","message"]}}}},"403":{"description":"Forbidden - API key doesn't have access","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Contact book not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/v1/campaigns":{"post":{"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"from":{"type":"string","minLength":1},"subject":{"type":"string","minLength":1},"previewText":{"type":"string"},"contactBookId":{"type":"string","minLength":1},"content":{"type":"string","minLength":1},"html":{"type":"string","minLength":1},"replyTo":{"anyOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"cc":{"anyOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"bcc":{"anyOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"sendNow":{"type":"boolean"},"scheduledAt":{"type":"string","description":"Timestamp in ISO 8601 format or natural language (e.g., 'tomorrow 9am', 'next monday 10:30')"},"batchSize":{"type":"integer","minimum":1,"maximum":100000}},"required":["name","from","subject","contactBookId"]}}}},"responses":{"200":{"description":"Create a campaign","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"previewText":{"type":"string","nullable":true},"contactBookId":{"type":"string","nullable":true},"html":{"type":"string","nullable":true},"content":{"type":"string","nullable":true},"status":{"type":"string"},"scheduledAt":{"type":"string","nullable":true,"format":"date-time"},"batchSize":{"type":"integer"},"batchWindowMinutes":{"type":"integer"},"total":{"type":"integer"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"},"hardBounced":{"type":"integer"},"complained":{"type":"integer"},"replyTo":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","from","subject","previewText","contactBookId","html","content","status","scheduledAt","batchSize","batchWindowMinutes","total","sent","delivered","opened","clicked","unsubscribed","bounced","hardBounced","complained","replyTo","cc","bcc","createdAt","updatedAt"]}}}}}},"get":{"parameters":[{"schema":{"type":"string","description":"Page number for pagination (default: 1)","example":"1"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","enum":["DRAFT","SCHEDULED","RUNNING","PAUSED","SENT"],"description":"Filter campaigns by status","example":"DRAFT"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","description":"Search campaigns by name or subject","example":"newsletter"},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Get list of campaigns","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"scheduledAt":{"type":"string","nullable":true,"format":"date-time"},"total":{"type":"integer"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"unsubscribed":{"type":"integer"}},"required":["id","name","from","subject","createdAt","updatedAt","status","scheduledAt","total","sent","delivered","unsubscribed"]}},"totalPage":{"type":"integer"}},"required":["campaigns","totalPage"]}}}}}}},"/v1/campaigns/{campaignId}":{"get":{"parameters":[{"schema":{"type":"string","minLength":1,"example":"cmp_123"},"required":true,"name":"campaignId","in":"path"}],"responses":{"200":{"description":"Get campaign details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"previewText":{"type":"string","nullable":true},"contactBookId":{"type":"string","nullable":true},"html":{"type":"string","nullable":true},"content":{"type":"string","nullable":true},"status":{"type":"string"},"scheduledAt":{"type":"string","nullable":true,"format":"date-time"},"batchSize":{"type":"integer"},"batchWindowMinutes":{"type":"integer"},"total":{"type":"integer"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"},"hardBounced":{"type":"integer"},"complained":{"type":"integer"},"replyTo":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","from","subject","previewText","contactBookId","html","content","status","scheduledAt","batchSize","batchWindowMinutes","total","sent","delivered","opened","clicked","unsubscribed","bounced","hardBounced","complained","replyTo","cc","bcc","createdAt","updatedAt"]}}}}}},"patch":{"summary":"Update a campaign","description":"Change a campaign that has not been sent. Only a draft can be updated — a scheduled, running or paused campaign has already committed to a send time or put mail in front of part of its list.","parameters":[{"schema":{"type":"string","minLength":1,"example":"cmp_123"},"required":true,"name":"campaignId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"from":{"type":"string","minLength":1},"subject":{"type":"string","minLength":1},"previewText":{"type":"string"},"contactBookId":{"type":"string","minLength":1},"content":{"type":"string","minLength":1},"html":{"type":"string","minLength":1},"replyTo":{"anyOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"cc":{"anyOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"bcc":{"anyOf":[{"type":"string","minLength":1},{"type":"array","items":{"type":"string","minLength":1}}]},"batchSize":{"type":"integer","minimum":1,"maximum":100000}}}}}},"responses":{"200":{"description":"The updated campaign","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"previewText":{"type":"string","nullable":true},"contactBookId":{"type":"string","nullable":true},"html":{"type":"string","nullable":true},"content":{"type":"string","nullable":true},"status":{"type":"string"},"scheduledAt":{"type":"string","nullable":true,"format":"date-time"},"batchSize":{"type":"integer"},"batchWindowMinutes":{"type":"integer"},"total":{"type":"integer"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"},"hardBounced":{"type":"integer"},"complained":{"type":"integer"},"replyTo":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","from","subject","previewText","contactBookId","html","content","status","scheduledAt","batchSize","batchWindowMinutes","total","sent","delivered","opened","clicked","unsubscribed","bounced","hardBounced","complained","replyTo","cc","bcc","createdAt","updatedAt"]}}}}}},"delete":{"parameters":[{"schema":{"type":"string","minLength":1,"example":"cmp_123"},"required":true,"name":"campaignId","in":"path"}],"responses":{"200":{"description":"Delete campaign","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"from":{"type":"string"},"subject":{"type":"string"},"previewText":{"type":"string","nullable":true},"contactBookId":{"type":"string","nullable":true},"html":{"type":"string","nullable":true},"content":{"type":"string","nullable":true},"status":{"type":"string"},"scheduledAt":{"type":"string","nullable":true,"format":"date-time"},"batchSize":{"type":"integer"},"batchWindowMinutes":{"type":"integer"},"total":{"type":"integer"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"},"hardBounced":{"type":"integer"},"complained":{"type":"integer"},"replyTo":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","from","subject","previewText","contactBookId","html","content","status","scheduledAt","batchSize","batchWindowMinutes","total","sent","delivered","opened","clicked","unsubscribed","bounced","hardBounced","complained","replyTo","cc","bcc","createdAt","updatedAt"]}}}}}}},"/v1/campaigns/{campaignId}/schedule":{"post":{"parameters":[{"schema":{"type":"string","minLength":1,"example":"cmp_123"},"required":true,"name":"campaignId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scheduledAt":{"type":"string","description":"Timestamp in ISO 8601 format or natural language (e.g., 'tomorrow 9am', 'next monday 10:30')"},"batchSize":{"type":"integer","minimum":1,"maximum":100000}}}}}},"responses":{"200":{"description":"Schedule a campaign","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/v1/campaigns/{campaignId}/pause":{"post":{"parameters":[{"schema":{"type":"string","minLength":1,"example":"cmp_123"},"required":true,"name":"campaignId","in":"path"}],"responses":{"200":{"description":"Pause a campaign","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/v1/campaigns/{campaignId}/resume":{"post":{"parameters":[{"schema":{"type":"string","minLength":1,"example":"cmp_123"},"required":true,"name":"campaignId","in":"path"}],"responses":{"200":{"description":"Resume a campaign","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/v1/templates/{templateId}/publish":{"post":{"summary":"Publish a template","description":"Freezes the current draft as a new immutable version and makes it the one that sends. Editing afterwards changes the draft only — nothing reaches a recipient until you publish again.","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"The version that is now live","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"versionNumber":{"type":"integer"},"publishedAt":{"type":"string"}},"required":["id","versionNumber","publishedAt"]}}}}}}},"/v1/templates/{templateId}/versions":{"get":{"summary":"List a template's published versions","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"Every version, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"versionNumber":{"type":"integer"},"subject":{"type":"string"},"publishedAt":{"type":"string"},"isLive":{"type":"boolean","description":"Whether this is the version currently being sent."}},"required":["id","versionNumber","subject","publishedAt","isLive"]}}},"required":["versions"]}}}}}}},"/v1/templates/{templateId}/rollback":{"post":{"summary":"Put an earlier version back into service","description":"Points at an existing version rather than copying it forward, so the history stays a record of what was published rather than filling with duplicates.","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"versionNumber":{"type":"integer","minimum":1}},"required":["versionNumber"]}}}},"responses":{"200":{"description":"The version now live","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"versionNumber":{"type":"integer"},"rolledBack":{"type":"boolean"}},"required":["id","versionNumber","rolledBack"]}}}}}}},"/v1/templates":{"get":{"summary":"List templates","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"1-based page number.","example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page, up to 100.","example":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"A page of templates","content":{"application/json":{"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"cmsm9pt1b0017vseua7veqnqi"},"name":{"type":"string","example":"Welcome"},"subject":{"type":"string","example":"Welcome to {{companyName}}"},"content":{"type":"string","nullable":true,"description":"The draft body as a TipTap JSON document."},"html":{"type":"string","nullable":true,"description":"The rendered draft. Derived from content; not settable."},"published":{"type":"object","nullable":true,"properties":{"versionNumber":{"type":"integer"},"publishedAt":{"type":"string"}},"required":["versionNumber","publishedAt"],"description":"The version sends actually use. Null means this template has never been published and cannot be sent with."},"hasUnpublishedChanges":{"type":"boolean","description":"Whether the draft has moved on since the last publish."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","subject","content","html","published","hasUnpublishedChanges","createdAt","updatedAt"]}},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":25},"total":{"type":"integer","description":"Total matching items."},"totalPage":{"type":"integer","description":"Total pages."},"hasMore":{"type":"boolean","description":"Whether another page follows this one."}},"required":["templates","page","limit","total","totalPage","hasMore"]}}}}}},"post":{"summary":"Create a template","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"subject":{"type":"string","minLength":1},"content":{"type":"string","minLength":1,"description":"TipTap JSON. Omit to create an empty template and fill it in later."}},"required":["name","subject"]}}}},"responses":{"200":{"description":"The created template","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cmsm9pt1b0017vseua7veqnqi"},"name":{"type":"string","example":"Welcome"},"subject":{"type":"string","example":"Welcome to {{companyName}}"},"content":{"type":"string","nullable":true,"description":"The draft body as a TipTap JSON document."},"html":{"type":"string","nullable":true,"description":"The rendered draft. Derived from content; not settable."},"published":{"type":"object","nullable":true,"properties":{"versionNumber":{"type":"integer"},"publishedAt":{"type":"string"}},"required":["versionNumber","publishedAt"],"description":"The version sends actually use. Null means this template has never been published and cannot be sent with."},"hasUnpublishedChanges":{"type":"boolean","description":"Whether the draft has moved on since the last publish."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","subject","content","html","published","hasUnpublishedChanges","createdAt","updatedAt"]}}}}}}},"/v1/templates/{templateId}":{"get":{"summary":"Retrieve a template","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"The template","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cmsm9pt1b0017vseua7veqnqi"},"name":{"type":"string","example":"Welcome"},"subject":{"type":"string","example":"Welcome to {{companyName}}"},"content":{"type":"string","nullable":true,"description":"The draft body as a TipTap JSON document."},"html":{"type":"string","nullable":true,"description":"The rendered draft. Derived from content; not settable."},"published":{"type":"object","nullable":true,"properties":{"versionNumber":{"type":"integer"},"publishedAt":{"type":"string"}},"required":["versionNumber","publishedAt"],"description":"The version sends actually use. Null means this template has never been published and cannot be sent with."},"hasUnpublishedChanges":{"type":"boolean","description":"Whether the draft has moved on since the last publish."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","subject","content","html","published","hasUnpublishedChanges","createdAt","updatedAt"]}}}}}},"patch":{"summary":"Update a template","description":"Any subset of the fields. Supplying `content` re-renders the HTML; the HTML itself is never settable directly.","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"subject":{"type":"string","minLength":1},"content":{"type":"string","minLength":1}}}}}},"responses":{"200":{"description":"The updated template","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cmsm9pt1b0017vseua7veqnqi"},"name":{"type":"string","example":"Welcome"},"subject":{"type":"string","example":"Welcome to {{companyName}}"},"content":{"type":"string","nullable":true,"description":"The draft body as a TipTap JSON document."},"html":{"type":"string","nullable":true,"description":"The rendered draft. Derived from content; not settable."},"published":{"type":"object","nullable":true,"properties":{"versionNumber":{"type":"integer"},"publishedAt":{"type":"string"}},"required":["versionNumber","publishedAt"],"description":"The version sends actually use. Null means this template has never been published and cannot be sent with."},"hasUnpublishedChanges":{"type":"boolean","description":"Whether the draft has moved on since the last publish."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","subject","content","html","published","hasUnpublishedChanges","createdAt","updatedAt"]}}}}}},"delete":{"summary":"Delete a template","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"The template was deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}}}}},"/v1/templates/{templateId}/duplicate":{"post":{"summary":"Duplicate a template","parameters":[{"schema":{"type":"string","minLength":1,"example":"tpl_123"},"required":true,"name":"templateId","in":"path"}],"responses":{"200":{"description":"The copy","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"cmsm9pt1b0017vseua7veqnqi"},"name":{"type":"string","example":"Welcome"},"subject":{"type":"string","example":"Welcome to {{companyName}}"},"content":{"type":"string","nullable":true,"description":"The draft body as a TipTap JSON document."},"html":{"type":"string","nullable":true,"description":"The rendered draft. Derived from content; not settable."},"published":{"type":"object","nullable":true,"properties":{"versionNumber":{"type":"integer"},"publishedAt":{"type":"string"}},"required":["versionNumber","publishedAt"],"description":"The version sends actually use. Null means this template has never been published and cannot be sent with."},"hasUnpublishedChanges":{"type":"boolean","description":"Whether the draft has moved on since the last publish."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","subject","content","html","published","hasUnpublishedChanges","createdAt","updatedAt"]}}}}}}},"/v1/suppressions":{"get":{"summary":"List suppressions","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"1-based page number.","example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page, up to 100.","example":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["HARD_BOUNCE","COMPLAINT","MANUAL"]},"required":false,"name":"reason","in":"query"}],"responses":{"200":{"description":"A page of suppressed addresses","content":{"application/json":{"schema":{"type":"object","properties":{"suppressions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"reason":{"type":"string","enum":["HARD_BOUNCE","COMPLAINT","MANUAL"],"description":"HARD_BOUNCE and COMPLAINT are recorded automatically; MANUAL is what you add yourself.","example":"MANUAL"},"source":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","email","reason","source","createdAt"]}},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":25},"total":{"type":"integer","description":"Total matching items."},"totalPage":{"type":"integer","description":"Total pages."},"hasMore":{"type":"boolean","description":"Whether another page follows this one."}},"required":["suppressions","page","limit","total","totalPage","hasMore"]}}}}}},"post":{"summary":"Suppress an address","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"reason":{"type":"string","enum":["HARD_BOUNCE","COMPLAINT","MANUAL"],"description":"HARD_BOUNCE and COMPLAINT are recorded automatically; MANUAL is what you add yourself.","example":"MANUAL"},"source":{"type":"string"}},"required":["email"]}}}},"responses":{"200":{"description":"The suppression","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"reason":{"type":"string","enum":["HARD_BOUNCE","COMPLAINT","MANUAL"],"description":"HARD_BOUNCE and COMPLAINT are recorded automatically; MANUAL is what you add yourself.","example":"MANUAL"},"source":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","email","reason","source","createdAt"]}}}}}}},"/v1/suppressions/{email}":{"get":{"summary":"Check whether an address is suppressed","description":"404 when the address is not on the list, so this doubles as a pre-send check.","parameters":[{"schema":{"type":"string","example":"someone@example.com"},"required":true,"name":"email","in":"path"}],"responses":{"200":{"description":"The suppression","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"reason":{"type":"string","enum":["HARD_BOUNCE","COMPLAINT","MANUAL"],"description":"HARD_BOUNCE and COMPLAINT are recorded automatically; MANUAL is what you add yourself.","example":"MANUAL"},"source":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","email","reason","source","createdAt"]}}}}}},"delete":{"summary":"Remove an address from the suppression list","description":"Also clears the address from the sending provider's own suppression list where one applies. Removing a hard bounce means mail will be attempted again — do it only when you know the address is good.","parameters":[{"schema":{"type":"string","example":"someone@example.com"},"required":true,"name":"email","in":"path"}],"responses":{"200":{"description":"The address is no longer suppressed","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"deleted":{"type":"boolean"}},"required":["email","deleted"]}}}}}}},"/v1/suppressions/bulk":{"post":{"summary":"Suppress many addresses","description":"For importing a list from another provider. Duplicates within the request and addresses already suppressed are both fine.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string","format":"email"},"minItems":1,"maxItems":10000},"reason":{"type":"string","enum":["HARD_BOUNCE","COMPLAINT","MANUAL"],"description":"HARD_BOUNCE and COMPLAINT are recorded automatically; MANUAL is what you add yourself.","example":"MANUAL"}},"required":["emails"]}}}},"responses":{"200":{"description":"How many addresses were submitted","content":{"application/json":{"schema":{"type":"object","properties":{"submitted":{"type":"integer"}},"required":["submitted"]}}}}}}},"/v1/suppressions/bulk/remove":{"post":{"summary":"Remove many addresses from the suppression list","description":"POST rather than DELETE: a body on DELETE is permitted by the spec and dropped by enough proxies and HTTP clients to be unreliable.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string","format":"email"},"minItems":1,"maxItems":10000}},"required":["emails"]}}}},"responses":{"200":{"description":"How many addresses were removed","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"integer"}},"required":["removed"]}}}}}}},"/v1/segments":{"get":{"summary":"List segments","responses":{"200":{"description":"Every segment on the account","content":{"application/json":{"schema":{"type":"object","properties":{"segments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contactBookId":{"type":"string"},"filters":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"firstName, lastName, email, subscribed, or the name of a contact property on the list.","example":"email"},"op":{"type":"string","example":"contains"},"value":{"type":"string","example":"@example.com"}},"required":["field","op"]},"description":"Combined with AND."}},"required":["conditions"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","contactBookId","filters","createdAt","updatedAt"]}}},"required":["segments"]}}}}}},"post":{"summary":"Create a segment","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"contactBookId":{"type":"string","minLength":1},"filters":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"firstName, lastName, email, subscribed, or the name of a contact property on the list.","example":"email"},"op":{"type":"string","example":"contains"},"value":{"type":"string","example":"@example.com"}},"required":["field","op"]},"description":"Combined with AND."}},"required":["conditions"]}},"required":["name","contactBookId","filters"]}}}},"responses":{"200":{"description":"The created segment","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contactBookId":{"type":"string"},"filters":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"firstName, lastName, email, subscribed, or the name of a contact property on the list.","example":"email"},"op":{"type":"string","example":"contains"},"value":{"type":"string","example":"@example.com"}},"required":["field","op"]},"description":"Combined with AND."}},"required":["conditions"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","contactBookId","filters","createdAt","updatedAt"]}}}}}}},"/v1/segments/{segmentId}":{"get":{"summary":"Retrieve a segment","parameters":[{"schema":{"type":"string","minLength":1,"example":"seg_123"},"required":true,"name":"segmentId","in":"path"}],"responses":{"200":{"description":"The segment, with the number of contacts it currently matches","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contactBookId":{"type":"string"},"filters":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"firstName, lastName, email, subscribed, or the name of a contact property on the list.","example":"email"},"op":{"type":"string","example":"contains"},"value":{"type":"string","example":"@example.com"}},"required":["field","op"]},"description":"Combined with AND."}},"required":["conditions"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"contactCount":{"type":"integer"}},"required":["id","name","contactBookId","filters","createdAt","updatedAt","contactCount"]}}}}}},"patch":{"summary":"Update a segment","parameters":[{"schema":{"type":"string","minLength":1,"example":"seg_123"},"required":true,"name":"segmentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"filters":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"firstName, lastName, email, subscribed, or the name of a contact property on the list.","example":"email"},"op":{"type":"string","example":"contains"},"value":{"type":"string","example":"@example.com"}},"required":["field","op"]},"description":"Combined with AND."}},"required":["conditions"]}}}}}},"responses":{"200":{"description":"The updated segment","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"contactBookId":{"type":"string"},"filters":{"type":"object","properties":{"conditions":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"firstName, lastName, email, subscribed, or the name of a contact property on the list.","example":"email"},"op":{"type":"string","example":"contains"},"value":{"type":"string","example":"@example.com"}},"required":["field","op"]},"description":"Combined with AND."}},"required":["conditions"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","contactBookId","filters","createdAt","updatedAt"]}}}}}},"delete":{"summary":"Delete a segment","description":"The contacts it matched are untouched — a segment is only a filter.","parameters":[{"schema":{"type":"string","minLength":1,"example":"seg_123"},"required":true,"name":"segmentId","in":"path"}],"responses":{"200":{"description":"The segment was deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}}}}},"/v1/segments/{segmentId}/contacts":{"get":{"summary":"List the contacts a segment matches","description":"Evaluated when you ask, not stored — a segment has no membership of its own.","parameters":[{"schema":{"type":"string","minLength":1,"example":"seg_123"},"required":true,"name":"segmentId","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1,"description":"1-based page number.","example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page, up to 100.","example":25},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"A page of matching contacts","content":{"application/json":{"schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"subscribed":{"type":"boolean"}},"required":["id","email","firstName","lastName","subscribed"]}},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":25},"total":{"type":"integer","description":"Total matching items."},"totalPage":{"type":"integer","description":"Total pages."},"hasMore":{"type":"boolean","description":"Whether another page follows this one."}},"required":["contacts","page","limit","total","totalPage","hasMore"]}}}}}}},"/v1/webhooks":{"get":{"summary":"List webhook endpoints","responses":{"200":{"description":"Every endpoint on the account","content":{"application/json":{"schema":{"type":"object","properties":{"webhooks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"description":{"type":"string","nullable":true},"eventTypes":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","url","description","eventTypes","status","createdAt","updatedAt"]}}},"required":["webhooks"]}}}}}},"post":{"summary":"Create a webhook endpoint","description":"The response includes the signing secret. It is shown once and cannot be retrieved again — store it now.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["contact.created","contact.updated","contact.deleted","domain.created","domain.verified","domain.updated","domain.deleted","email.queued","email.sent","email.delivery_delayed","email.delivered","email.bounced","email.rejected","email.rendering_failure","email.complained","email.failed","email.cancelled","email.suppressed","email.opened","email.clicked","webhook.test"],"description":"One of the event types mailstein emits.","example":"email.delivered"},"minItems":1},"description":{"type":"string"},"domainIds":{"type":"array","items":{"type":"integer"},"description":"Restrict deliveries to these domains. Omit to receive events for all of them."}},"required":["url","eventTypes"]}}}},"responses":{"200":{"description":"The created endpoint, including its secret","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"description":{"type":"string","nullable":true},"eventTypes":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"secret":{"type":"string","description":"Shown once. Used to verify delivery signatures."}},"required":["id","url","description","eventTypes","status","createdAt","updatedAt","secret"]}}}}}}},"/v1/webhooks/{webhookId}":{"get":{"summary":"Retrieve a webhook endpoint","parameters":[{"schema":{"type":"string","minLength":1,"example":"wh_123"},"required":true,"name":"webhookId","in":"path"}],"responses":{"200":{"description":"The endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"description":{"type":"string","nullable":true},"eventTypes":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","url","description","eventTypes","status","createdAt","updatedAt"]}}}}}},"patch":{"summary":"Update a webhook endpoint","parameters":[{"schema":{"type":"string","minLength":1,"example":"wh_123"},"required":true,"name":"webhookId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"eventTypes":{"type":"array","items":{"type":"string","enum":["contact.created","contact.updated","contact.deleted","domain.created","domain.verified","domain.updated","domain.deleted","email.queued","email.sent","email.delivery_delayed","email.delivered","email.bounced","email.rejected","email.rendering_failure","email.complained","email.failed","email.cancelled","email.suppressed","email.opened","email.clicked","webhook.test"],"description":"One of the event types mailstein emits.","example":"email.delivered"},"minItems":1},"description":{"type":"string","nullable":true},"domainIds":{"type":"array","items":{"type":"integer"}},"rotateSecret":{"type":"boolean","description":"Issue a new signing secret. The new one is returned; the old one stops working immediately."}}}}}},"responses":{"200":{"description":"The updated endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"description":{"type":"string","nullable":true},"eventTypes":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"secret":{"type":"string"}},"required":["id","url","description","eventTypes","status","createdAt","updatedAt"]}}}}}},"delete":{"summary":"Delete a webhook endpoint","parameters":[{"schema":{"type":"string","minLength":1,"example":"wh_123"},"required":true,"name":"webhookId","in":"path"}],"responses":{"200":{"description":"The endpoint was deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}}}}},"/v1/webhooks/{webhookId}/attempts":{"get":{"summary":"List delivery attempts","description":"What was sent, what came back, and how many times it was retried. A delivery is attempted six times with exponential backoff before it is given up on.","parameters":[{"schema":{"type":"string","minLength":1,"example":"wh_123"},"required":true,"name":"webhookId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"The `nextCursor` from the previous page."},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Delivery attempts, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"attempts":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}},"nextCursor":{"type":"string","nullable":true,"description":"Pass as `cursor` for the next page. Null at the end."}},"required":["attempts","nextCursor"]}}}}}}},"/v1/apiKeys":{"get":{"summary":"List API keys","responses":{"200":{"description":"Every key on the account, without the secrets","content":{"application/json":{"schema":{"type":"object","properties":{"apiKeys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"permission":{"type":"string","enum":["FULL","SENDING"],"description":"FULL can use every endpoint. SENDING can only send email — the right choice for a key that lives in an application."},"partialToken":{"type":"string","description":"Enough of the key to recognise it. Not enough to use it.","example":"ms_abc...x9z"},"domainId":{"type":"integer","nullable":true,"description":"When set, the key may only send from this domain."},"createdAt":{"type":"string"},"lastUsed":{"type":"string","nullable":true}},"required":["id","name","permission","partialToken","domainId","createdAt","lastUsed"]}}},"required":["apiKeys"]}}}}}},"post":{"summary":"Create an API key","description":"The full key is in the response and is not recoverable afterwards. Store it before you close the connection.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"permission":{"type":"string","enum":["FULL","SENDING"],"default":"SENDING"},"domainId":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["name"]}}}},"responses":{"200":{"description":"The created key, including the secret","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"permission":{"type":"string","enum":["FULL","SENDING"]},"token":{"type":"string","description":"The full key. Shown once."}},"required":["id","name","permission","token"]}}}}}}},"/v1/apiKeys/{apiKeyId}":{"delete":{"summary":"Delete an API key","description":"Takes effect immediately. Any request still using it starts failing.","parameters":[{"schema":{"type":"integer","nullable":true,"example":1},"required":false,"name":"apiKeyId","in":"path"}],"responses":{"200":{"description":"The key was deleted","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"deleted":{"type":"boolean"}},"required":["id","deleted"]}}}}}}},"/v1/inbound":{"get":{"summary":"List received emails","description":"Newest first. Spam is excluded unless you ask for it.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"1-based page number.","example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Items per page, up to 100.","example":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Only mail received at this address.","example":"hello@yourdomain.com"},"required":false,"name":"mailbox","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"unread","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Defaults to false."},"required":false,"name":"includeSpam","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Defaults to true."},"required":false,"name":"includeArchived","in":"query"}],"responses":{"200":{"description":"A page of received messages, without their bodies","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"mailbox":{"type":"string","description":"The address it was received at.","example":"hello@yourdomain.com"},"fromAddress":{"type":"string"},"fromName":{"type":"string","nullable":true},"toAddress":{"type":"string"},"subject":{"type":"string","nullable":true},"snippet":{"type":"string","nullable":true,"description":"The opening of the message, for a list view."},"read":{"type":"boolean"},"archived":{"type":"boolean"},"starred":{"type":"boolean"},"isSpam":{"type":"boolean"},"attachments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"type":{"type":"string","nullable":true},"size":{"type":"number","nullable":true}},"required":["name","type","size"]}},"receivedAt":{"type":"string"}},"required":["id","mailbox","fromAddress","fromName","toAddress","subject","snippet","read","archived","starred","isSpam","attachments","receivedAt"]}},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":25},"total":{"type":"integer","description":"Total matching items."},"totalPage":{"type":"integer","description":"Total pages."},"hasMore":{"type":"boolean","description":"Whether another page follows this one."}},"required":["messages","page","limit","total","totalPage","hasMore"]}}}}}}},"/v1/inbound/{messageId}":{"get":{"summary":"Retrieve a received email","description":"Includes the full text and HTML bodies.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"messageId","in":"path"}],"responses":{"200":{"description":"The message","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"mailbox":{"type":"string","description":"The address it was received at.","example":"hello@yourdomain.com"},"fromAddress":{"type":"string"},"fromName":{"type":"string","nullable":true},"toAddress":{"type":"string"},"subject":{"type":"string","nullable":true},"snippet":{"type":"string","nullable":true,"description":"The opening of the message, for a list view."},"read":{"type":"boolean"},"archived":{"type":"boolean"},"starred":{"type":"boolean"},"isSpam":{"type":"boolean"},"attachments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"type":{"type":"string","nullable":true},"size":{"type":"number","nullable":true}},"required":["name","type","size"]}},"receivedAt":{"type":"string"},"text":{"type":"string","nullable":true},"html":{"type":"string","nullable":true},"messageId":{"type":"string","nullable":true,"description":"The RFC 5322 Message-ID from the original message."},"inReplyTo":{"type":"string","nullable":true,"description":"The Message-ID this is a reply to, when it is one."}},"required":["id","mailbox","fromAddress","fromName","toAddress","subject","snippet","read","archived","starred","isSpam","attachments","receivedAt","text","html","messageId","inReplyTo"]}}}}}},"patch":{"summary":"Update a received email","description":"Mark read, archive or star. Useful for keeping mailstein's inbox in step with whatever system you route mail into.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"messageId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"read":{"type":"boolean"},"archived":{"type":"boolean"},"starred":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated message","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"mailbox":{"type":"string","description":"The address it was received at.","example":"hello@yourdomain.com"},"fromAddress":{"type":"string"},"fromName":{"type":"string","nullable":true},"toAddress":{"type":"string"},"subject":{"type":"string","nullable":true},"snippet":{"type":"string","nullable":true,"description":"The opening of the message, for a list view."},"read":{"type":"boolean"},"archived":{"type":"boolean"},"starred":{"type":"boolean"},"isSpam":{"type":"boolean"},"attachments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","nullable":true},"type":{"type":"string","nullable":true},"size":{"type":"number","nullable":true}},"required":["name","type","size"]}},"receivedAt":{"type":"string"}},"required":["id","mailbox","fromAddress","fromName","toAddress","subject","snippet","read","archived","starred","isSpam","attachments","receivedAt"]}}}}}}},"/v1/analytics/email-time-series":{"get":{"parameters":[{"schema":{"type":"string","enum":["7","30"],"description":"Number of days to retrieve data for (default: 30)","example":"30"},"required":false,"name":"days","in":"query"},{"schema":{"type":"string","description":"Filter by domain ID"},"required":false,"name":"domainId","in":"query"}],"responses":{"200":{"description":"Retrieve email time series data","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"bounced":{"type":"integer"},"complained":{"type":"integer"}},"required":["date","sent","delivered","opened","clicked","bounced","complained"]}},"totalCounts":{"type":"object","properties":{"sent":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"bounced":{"type":"integer"},"complained":{"type":"integer"}},"required":["sent","delivered","opened","clicked","bounced","complained"]}},"required":["result","totalCounts"]}}}}}}},"/v1/analytics/reputation-metrics":{"get":{"parameters":[{"schema":{"type":"string","description":"Filter by domain ID"},"required":false,"name":"domainId","in":"query"}],"responses":{"200":{"description":"Retrieve reputation metrics data","content":{"application/json":{"schema":{"type":"object","properties":{"delivered":{"type":"integer"},"hardBounced":{"type":"integer"},"complained":{"type":"integer"},"bounceRate":{"type":"number"},"complaintRate":{"type":"number"}},"required":["delivered","hardBounced","complained","bounceRate","complaintRate"]}}}}}}}}}