OpenAPI Specification
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:
- <p>Sample email body</p>
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