openapi: 3.1.0 info: title: AhaSend API v2 Accounts Email API description: 'The AhaSend API v2 allows you to send transactional emails, manage domains, webhooks, routes, API keys, and view statistics. ## Authentication All API requests must be authenticated using a Bearer token in the Authorization header: ``` Authorization: Bearer aha-sk-64-CHARACTER-RANDOM-STRING ``` ## Scopes API keys have specific scopes that control access to different resources and actions: ### Message Scopes - `messages:send:all` - Send messages from any domain in the account - `messages:send:{domain}` - Send messages from a specific domain - `messages:cancel:all` - Cancel messages from any domain - `messages:cancel:{domain}` - Cancel messages from a specific domain - `messages:read:all` - Read messages from any domain - `messages:read:{domain}` - Read messages from a specific domain ### Domain Scopes - `domains:read` - Read all domains - `domains:write` - Create and update domains - `domains:delete:all` - Delete any domain - `domains:delete:{domain}` - Delete a specific domain ### Account Scopes - `accounts:read` - Read account information - `accounts:write` - Update account settings - `accounts:billing` - Access billing information - `accounts:members:read` - Read account members - `accounts:members:add` - Add account members - `accounts:members:update` - Update account members - `accounts:members:remove` - Remove account members ### Webhook Scopes - `webhooks:read:all` - Read all webhooks - `webhooks:read:{domain}` - Read webhooks for a specific domain - `webhooks:write:all` - Create and update webhooks - `webhooks:write:{domain}` - Create and update webhooks for a specific domain - `webhooks:delete:all` - Delete any webhook - `webhooks:delete:{domain}` - Delete webhooks for a specific domain ### Route Scopes - `routes:read:all` - Read all routes - `routes:read:{domain}` - Read routes for a specific domain - `routes:write:all` - Create and update routes - `routes:write:{domain}` - Create and update routes for a specific domain - `routes:delete:all` - Delete any route - `routes:delete:{domain}` - Delete routes for a specific domain ### Suppression Scopes - `suppressions:read` - Read suppressions - `suppressions:write` - Create suppressions - `suppressions:delete` - Delete suppressions - `suppressions:wipe` - Delete all suppressions (dangerous) ### SMTP Credentials Scopes - `smtp-credentials:read:all` - Read all SMTP credentials - `smtp-credentials:read:{domain}` - Read SMTP credentials for a specific domain - `smtp-credentials:write:all` - Create SMTP credentials - `smtp-credentials:write:{domain}` - Create SMTP credentials for a specific domain - `smtp-credentials:delete:all` - Delete any SMTP credentials - `smtp-credentials:delete:{domain}` - Delete SMTP credentials for a specific domain ### Statistics Scopes - `statistics-transactional:read:all` - Read all transactional statistics - `statistics-transactional:read:{domain}` - Read transactional statistics for a specific domain ### API Key Scopes - `api-keys:read` - Read API keys - `api-keys:write` - Create and update API keys - `api-keys:delete` - Delete API keys ## Rate Limiting - General API endpoints: 100 requests per second, 200 burst - Statistics endpoints: 1 request per second, 1 burst ## Pagination List endpoints use cursor-based pagination with the following parameters: - `limit`: Maximum number of items to return (default: 100, max: 100) - `cursor`: Pagination cursor for the next page ## Time Formats All timestamps must be in RFC3339 format, e.g., `2023-12-25T10:30:00Z` ## Idempotency POST requests support idempotency through the optional `Idempotency-Key` header. When provided: - The same request can be safely retried multiple times - Duplicate requests return the same response with `Idempotent-Replayed: true` - In-progress requests return HTTP 409 with `Idempotent-Replayed: false` - Failed requests return HTTP 412 with `Idempotent-Replayed: false` - Idempotency keys expire after 24 hours ' version: 2.0.0 contact: email: support@ahasend.com license: name: MIT identifier: MIT servers: - url: https://api.ahasend.com description: Production server security: - BearerAuth: [] tags: - name: Email description: APIs for sending emails externalDocs: description: Find out more url: https://ahasend.com paths: /email/send: post: tags: - Email summary: AhaSend Send Emails description: You can send emails to up to 100 recipients using this API at the same time. operationId: sendEmail parameters: - in: header name: Content-Type schema: type: string description: Only application/json is supported example: application/json requestBody: description: Email object. content: application/json: schema: $ref: '#/components/schemas/Email' required: true responses: '201': description: Request was accepted. This doesn't necessarily mean immediate delivery or even queueing of the emails for delivery. It just means that the request was well-formed and accepted, but you need to check the response for success_count and fail_count to make sure about the status of your request. content: application/json: schema: $ref: '#/components/schemas/SuccessfulResponse' examples: sendEmail201Example: summary: Default sendEmail 201 response x-microcks-default: true value: success_count: 1 fail_count: 1 failed_recipients: - example_value errors: - example_value '400': description: The request is malformed and could not be validated. content: application/json: schema: $ref: '#/components/schemas/BadRequestResponse' examples: sendEmail400Example: summary: Default sendEmail 400 response x-microcks-default: true value: status: example_value '403': description: You are not allowed to send for any reason such as invalid credentials, not having access to the sending domain, etc. content: application/json: schema: $ref: '#/components/schemas/AccessDeniedResponse' examples: sendEmail403Example: summary: Default sendEmail 403 response x-microcks-default: true value: status: example_value security: - api_key: - write:email - read:email x-microcks-operation: delay: 0 dispatcher: FALLBACK components: schemas: AccessDeniedResponse: type: object example: status: invalid credentials properties: status: type: string description: The reason your request failed. examples: - invalid credentials - domain DNS config is not valid example: example_value Contact: type: object required: - email properties: email: type: string examples: - john@nasa.gov - jane@nasa.gov example: user@example.com name: type: string examples: - John Smith - Jane Williams example: Example Name BadRequestResponse: type: object example: status: bad request properties: status: type: string examples: - domain is not yours - domain DNS config is not valid example: example_value Email: required: - from - recipients - content type: object properties: from: $ref: '#/components/schemas/Contact' recipients: type: array description: Specifies the list of recipients to which message will be sent. items: $ref: '#/components/schemas/Contact' example: - email: user@example.com name: Example Name content: $ref: '#/components/schemas/Content' SuccessfulResponse: type: object properties: success_count: type: integer description: Number of messages that were queued for sending. example: 1 fail_count: type: integer description: Number of messages that failed to be queued for sending. example: 1 failed_recipients: type: array description: List of email addresses that the email was not sent to. example: - john@nasa.gov items: type: string errors: type: array example: - 'john@nasa.gov: The email account that you tried to reach does not exist.' items: type: string description: The reason the email failed to be sent to a recipient. Attachment: type: object required: - data - file_name - content_type properties: data: type: string examples: - R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 description: The attachment data. If the base64 field is true, this data must be encoded using base64. Otherwise, it will be interpreted as UTF-8. example: example_value base64: type: boolean examples: - true - false description: If set to true, data needs to be encoded using base64. Otherwise data will be interpreted as UTF-8. example: true content_type: type: string examples: - image/gif example: example_value content_id: type: string examples: - my-image description: If specified, this attachment will be added as an inline attachment and a multipart/related MIME container will be generated in the message to hold it and the textual content. example: '500123' file_name: type: string examples: - my_image.gif example: Example Name Content: type: object required: - subject properties: subject: type: string examples: - Sample subject example: example_value text_body: type: string description: Plaintext body of the email examples: - Sample email body example: example_value html_body: type: string description: HTML body of the email examples: -

Sample email body

example: example_value attachments: type: array items: $ref: '#/components/schemas/Attachment' example: - data: example_value base64: true content_type: example_value content_id: '500123' file_name: Example Name reply_to: $ref: '#/components/schemas/Contact' headers: type: object description: Specify arbitary headers. additionalProperties: type: string example: X-My-Mail-ID: '12345' X-Comment-ID: '456789' securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: aha-sk-64-CHARACTER-RANDOM-STRING description: API key for authentication