Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: AhaSend API v2 API Keys 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 the account''s suppressions except protected ones (dangerous)
### Template Scopes
- `templates:read` - Read transactional templates, their drafts and their published versions, and campaign templates
- `templates:write` - Create and update transactional templates, and publish, discard and restore their drafts; create and update campaign templates
- `templates:delete` - Delete transactional templates and campaign templates
### Campaign Scopes
- `campaigns:read` - Read campaigns, their stats and their recipients
- `campaigns:write` - Create, update and duplicate campaigns
- `campaigns:delete` - Delete draft campaigns
- `campaigns:send` - Send, unschedule and test-send campaigns
### Contact Scopes
- `contacts:read` - Read contacts
- `contacts:write` - Create and update contacts
- `contacts:delete` - Delete contacts
### Contact lifecycle and attributes
Contacts are account-global. A contact created through this API joins no
list on its own; campaigns target lists, so add it to one with the Lists
endpoints before a campaign can reach it. Contact subscription state and suppression records are independent:
creating, updating, unsubscribing, resubscribing, or deleting a contact
never creates, changes, or removes complaint, permanent, or protected
suppressions. Prefer unsubscribe over delete when the goal is only to stop
marketing mail, because unsubscribe is reversible and preserves contact
history. Writable attribute keys and types come from the account''s contact-attribute
definitions managed in the dashboard; this API does not expose property
definition CRUD.'
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: API Keys
description: Manage API keys for authentication and access control
paths:
/v2/accounts/{account_id}/api-keys:
get:
summary: Get API Keys
description: Returns a list of API keys for the account
operationId: getAPIKeys
tags:
- API Keys
parameters:
- name: account_id
in: path
required: true
description: Account ID
schema:
type: string
format: uuid
- name: limit
in: query
description: Maximum number of items to return
schema:
type: integer
minimum: 1
maximum: 100
default: 100
- name: after
in: query
description: Pagination cursor for the next page. Provide the value provided in `next_cursor` from the response.
schema:
type: string
- name: before
in: query
description: Pagination cursor for the previous page.
schema:
type: string
security:
- BearerAuth:
- api-keys:read
x-code-samples:
- lang: go
label: AhaSend Go SDK
source: "package main\n\nimport (\n \"context\"\n \"fmt\"\n \"log\"\n \"os\"\n\n \"github.com/AhaSend/ahasend-go\"\n \"github.com/AhaSend/ahasend-go/api\"\n \"github.com/AhaSend/ahasend-go/models/common\"\n \"github.com/google/uuid\"\n)\n\nfunc main() {\n client := api.NewAPIClient(api.WithAPIKey(os.Getenv(\"AHASEND_API_KEY\")))\n accountID := uuid.MustParse(os.Getenv(\"AHASEND_ACCOUNT_ID\"))\n ctx := context.Background()\n\n response, _, err := client.APIKeysAPI.GetAPIKeys(ctx, accountID, &common.PaginationParams{\n Limit: ahasend.Int32(20),\n })\n if err != nil {\n log.Fatalf(\"Error getting API keys: %v\", err)\n }\n for _, key := range response.Data {\n fmt.Printf(\"%s %s\\n\", key.ID, key.Label)\n }\n}\n"
- lang: javascript
label: Node.js 22+ (AhaSend SDK)
source: 'import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
const page = await client.apiKeys.list({ limit: 20 });
console.log("API keys listed.", { count: page.data.length });
'
responses:
'200':
description: List of API keys
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedAPIKeysResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
summary: Create API Key
description: Creates a new API key with the specified scopes
operationId: createAPIKey
tags:
- API Keys
parameters:
- name: account_id
in: path
required: true
description: Account ID
schema:
type: string
format: uuid
- $ref: '#/components/parameters/IdempotencyKey'
security:
- BearerAuth:
- api-keys:write
x-code-samples:
- lang: go
label: AhaSend Go SDK
source: "package main\n\nimport (\n \"context\"\n \"fmt\"\n \"log\"\n \"os\"\n\n \"github.com/AhaSend/ahasend-go/api\"\n \"github.com/AhaSend/ahasend-go/models/requests\"\n \"github.com/google/uuid\"\n)\n\nfunc main() {\n client := api.NewAPIClient(api.WithAPIKey(os.Getenv(\"AHASEND_API_KEY\")))\n accountID := uuid.MustParse(os.Getenv(\"AHASEND_ACCOUNT_ID\"))\n ctx := context.Background()\n\n // The SDK sends a fresh Idempotency-Key with this POST and reuses it on\n // its own retries, so a retried request is not applied twice.\n response, _, err := client.APIKeysAPI.CreateAPIKey(ctx, accountID, requests.CreateAPIKeyRequest{\n Label: \"My API Key\",\n Scopes: []string{\n \"messages:read:all\",\n \"domains:read\",\n },\n // Optional: restrict this key to specific source IPs (CIDR blocks or\n // bare IPv4/IPv6 addresses). Omit it to allow any IP.\n IPAllowList: []string{\"203.0.113.0/24\", \"198.51.100.7\"},\n })\n if err != nil {\n log.Fatalf(\"Error creating API key: %v\", err)\n }\n // response.SecretKey is returned only on create: put it in your secret\n // store now, and never log it.\n fmt.Printf(\"Created API key %s (%s)\\n\", response.ID, response.Label)\n}\n"
- lang: javascript
label: Node.js 22+ (AhaSend SDK)
source: "import { AhaSendClient } from \"@ahasend/sdk\";\n\nconst client = AhaSendClient.fromEnv();\n// The SDK sends a fresh Idempotency-Key automatically and reuses it on its own retries.\nconst apiKey = await client.apiKeys.create({\n label: \"Production API key\",\n scopes: [\"messages:send:all\"],\n});\nconsole.log(\"API key created.\", { id: apiKey.id, label: apiKey.label });\n"
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateAPIKeyRequest'
responses:
'201':
description: API key created successfully
headers:
Idempotent-Replayed:
$ref: '#/components/headers/IdempotentReplayed'
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/APIKey'
- type: object
required:
- secret_key
properties:
secret_key:
type: string
readOnly: true
description: 'One-time secret key. Store it immediately. Exact
successful idempotent replays return the same secret
during the 5-minute encrypted replay window.
'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
$ref: '#/components/responses/IdempotencyConflict'
'422':
$ref: '#/components/responses/IdempotencyPayloadMismatch'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/v2/accounts/{account_id}/api-keys/{key_id}:
get:
summary: Get API Key
description: Returns a specific API key by ID
operationId: getAPIKey
tags:
- API Keys
parameters:
- name: account_id
in: path
required: true
description: Account ID
schema:
type: string
format: uuid
- name: key_id
in: path
required: true
description: API Key ID
schema:
type: string
format: uuid
security:
- BearerAuth:
- api-keys:read
x-code-samples:
- lang: go
label: AhaSend Go SDK
source: "package main\n\nimport (\n \"context\"\n \"fmt\"\n \"log\"\n \"os\"\n\n \"github.com/AhaSend/ahasend-go/api\"\n \"github.com/google/uuid\"\n)\n\nfunc main() {\n client := api.NewAPIClient(api.WithAPIKey(os.Getenv(\"AHASEND_API_KEY\")))\n accountID := uuid.MustParse(os.Getenv(\"AHASEND_ACCOUNT_ID\"))\n ctx := context.Background()\n\n keyID := uuid.MustParse(\"c5a32c40-b351-439f-8230-779daed3e42c\")\n\n response, _, err := client.APIKeysAPI.GetAPIKey(ctx, accountID, keyID)\n if err != nil {\n log.Fatalf(\"Error getting API key: %v\", err)\n }\n fmt.Printf(\"%s %s (%d scopes)\\n\", response.ID, response.Label, len(response.Scopes))\n}\n"
- lang: javascript
label: Node.js 22+ (AhaSend SDK)
source: 'import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
const keyId = "00000000-0000-4000-8000-000000000001";
const apiKey = await client.apiKeys.get(keyId);
console.log("API key found.", { id: apiKey.id, label: apiKey.label });
'
responses:
'200':
description: API key details
content:
application/json:
schema:
$ref: '#/components/schemas/APIKey'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: API key not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
summary: Update API Key
description: Updates an existing API key's label and scopes
operationId: updateAPIKey
tags:
- API Keys
parameters:
- name: account_id
in: path
required: true
description: Account ID
schema:
type: string
format: uuid
- name: key_id
in: path
required: true
description: API Key ID
schema:
type: string
format: uuid
security:
- BearerAuth:
- api-keys:write
x-code-samples:
- lang: go
label: AhaSend Go SDK
source: "package main\n\nimport (\n \"context\"\n \"fmt\"\n \"log\"\n \"os\"\n\n \"github.com/AhaSend/ahasend-go\"\n \"github.com/AhaSend/ahasend-go/api\"\n \"github.com/AhaSend/ahasend-go/models/requests\"\n \"github.com/google/uuid\"\n)\n\nfunc main() {\n client := api.NewAPIClient(api.WithAPIKey(os.Getenv(\"AHASEND_API_KEY\")))\n accountID := uuid.MustParse(os.Getenv(\"AHASEND_ACCOUNT_ID\"))\n ctx := context.Background()\n\n keyID := uuid.MustParse(\"c5a32c40-b351-439f-8230-779daed3e42c\")\n\n response, _, err := client.APIKeysAPI.UpdateAPIKey(ctx, accountID, keyID, requests.UpdateAPIKeyRequest{\n Label: ahasend.String(\"My API Key\"),\n Scopes: &[]string{\n \"messages:read:all\",\n \"domains:read\",\n },\n // Replaces the allowed source IPs. &[]string{} clears the list (any IP);\n // leaving the field nil keeps the current list.\n IPAllowList: &[]string{\"203.0.113.0/24\"},\n })\n if err != nil {\n log.Fatalf(\"Error updating API key: %v\", err)\n }\n fmt.Printf(\"Updated API key %s\\n\", response.ID)\n}\n"
- lang: javascript
label: Node.js 22+ (AhaSend SDK)
source: 'import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
const keyId = "00000000-0000-4000-8000-000000000001";
const apiKey = await client.apiKeys.update(keyId, { label: "Renamed API key" });
console.log("API key updated.", { id: apiKey.id, label: apiKey.label });
'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAPIKeyRequest'
responses:
'200':
description: API key updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/APIKey'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: API key not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Conflict — the request would lock the calling API key out of its own account. Returned only when a key updates itself with an `ip_allow_list` that does not cover the caller's current source IP. No change is persisted. This is a terminal message-only conflict; it has no server error code or idempotency headers.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
summary: Delete API Key
description: Deletes an API key
operationId: deleteAPIKey
tags:
- API Keys
parameters:
- name: account_id
in: path
required: true
description: Account ID
schema:
type: string
format: uuid
- name: key_id
in: path
required: true
description: API Key ID
schema:
type: string
format: uuid
security:
- BearerAuth:
- api-keys:delete
x-code-samples:
- lang: go
label: AhaSend Go SDK
source: "package main\n\nimport (\n \"context\"\n \"fmt\"\n \"log\"\n \"os\"\n\n \"github.com/AhaSend/ahasend-go/api\"\n \"github.com/google/uuid\"\n)\n\nfunc main() {\n client := api.NewAPIClient(api.WithAPIKey(os.Getenv(\"AHASEND_API_KEY\")))\n accountID := uuid.MustParse(os.Getenv(\"AHASEND_ACCOUNT_ID\"))\n ctx := context.Background()\n\n keyID := uuid.MustParse(\"c5a32c40-b351-439f-8230-779daed3e42c\")\n\n response, _, err := client.APIKeysAPI.DeleteAPIKey(ctx, accountID, keyID)\n if err != nil {\n log.Fatalf(\"Error deleting API key: %v\", err)\n }\n fmt.Println(response.Message)\n}\n"
- lang: javascript
label: Node.js 22+ (AhaSend SDK)
source: 'import { AhaSendClient } from "@ahasend/sdk";
const client = AhaSendClient.fromEnv();
const keyId = "00000000-0000-4000-8000-000000000001";
const result = await client.apiKeys.delete(keyId);
console.log("API key deleted.", { message: result.message });
'
responses:
'200':
description: API key deleted successfully
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
example:
message: api key {id} ({label}) deleted successfully
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: API key not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
headers:
IdempotencyInProgress:
description: 'Identifies an idempotency-key execution that is still in progress. This
header is emitted only on the specialized HTTP 409 response.
'
schema:
type: string
enum:
- 'false'
IdempotencyRetryAfter:
description: 'Positive whole number of seconds after which the in-progress execution
lease may be retried with the same key and unchanged request.
'
schema:
type: integer
minimum: 1
IdempotentReplayed:
description: 'Indicates that this response is a stored replay of a previous identical request.
When this header is absent, the response is not a stored replay. Ordinary fresh
responses do not send `false`; that value is reserved for an in-progress 409.
'
schema:
type: string
enum:
- 'true'
schemas:
APIKey:
type: object
properties:
object:
type: string
enum:
- api_key
description: Object type identifier
id:
type: string
format: uuid
description: Unique identifier for the API key
created_at:
type: string
format: date-time
description: When the API key was created
updated_at:
type: string
format: date-time
description: When the API key was last updated
last_used_at:
type:
- string
- 'null'
format: date-time
description: When the API key was last used (updates every 5-10 minutes)
account_id:
type: string
format: uuid
description: Account ID this API key belongs to
label:
type: string
description: Human-readable label for the API key
public_key:
type: string
description: Public portion of the API key
scopes:
type: array
items:
$ref: '#/components/schemas/APIKeyScope'
description: Scopes granted to this API key
ip_allow_list:
type: array
items:
type: string
description: Source IPs allowed to authenticate with this API key, as canonical CIDR blocks (a bare address is stored as a `/32` for IPv4 or `/128` for IPv6). Always present; an empty array means the key may be used from any source IP. When non-empty, an authenticated request whose client IP is not covered by an entry is rejected with HTTP 403 on every v2 endpoint, regardless of the key's scopes.
required:
- object
- id
- created_at
- updated_at
- last_used_at
- account_id
- label
- public_key
- scopes
- ip_allow_list
ErrorResponse:
type: object
description: 'Human-readable API error. The server currently sends no stable machine
error code. In particular, clients must not parse `message` to
distinguish IP-allow-list, scope, ownership, plan, self-lockout,
suppression-duplicate, or other errors that share an HTTP status.
'
additionalProperties: false
required:
- message
properties:
message:
type: string
description: Error description
example:
message: Error message
APIKeyScope:
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier for the scope
created_at:
type: string
format: date-time
description: When the scope was created
updated_at:
type: string
format: date-time
description: When the scope was last updated
api_key_id:
type: string
format: uuid
description: ID of the API key this scope belongs to
scope:
type: string
description: The scope string
domain_id:
type:
- string
- 'null'
format: uuid
description: Domain ID for domain-specific scopes; always present and null for non-domain scopes
required:
- id
- created_at
- updated_at
- api_key_id
- scope
- domain_id
PaginatedAPIKeysResponse:
type: object
required:
- object
- data
- pagination
properties:
object:
type: string
enum:
- list
description: Object type identifier
data:
type: array
items:
$ref: '#/components/schemas/APIKey'
description: Array of API keys
pagination:
$ref: '#/components/schemas/PaginationInfo'
PaginationInfo:
type: object
required:
- has_more
properties:
has_more:
type: boolean
description: Whether more items exist after the last item of this page
next_cursor:
type: string
description: Pass as `after` to fetch the next page
previous_cursor:
type: string
description: Pass as `before` to fetch the previous page; absent on a `before` page when the start of the list has been reached
example:
has_more: true
next_cursor: eyJpZCI6MTIzNH0=
CreateAPIKeyRequest:
type: object
required:
- label
- scopes
properties:
label:
type: string
minLength: 1
maxLength: 255
description: Human-readable label for the API key; must not be empty
scopes:
type: array
items:
type: string
minItems: 1
description: Array of scope strings to grant to this API key
ip_allow_list:
type: array
items:
type: string
description: Optional list of source IPs allowed to authenticate with this key. Each entry is a CIDR block (e.g. `203.0.113.0/24`) or a bare IPv4/IPv6 address (stored as a `/32` or `/128`). Entries are canonicalized (host bits are masked) and de-duplicated. The allow-all prefixes `0.0.0.0/0` and `::/0` are rejected, and at most 100 entries are allowed after de-duplication. Omit the field or pass an empty array to leave the key usable from any IP.
example:
label: Production API Key
scopes:
- messages:send:all
- domains:read
ip_allow_list:
- 203.0.113.0/24
- 198.51.100.7
SuccessResponse:
type: object
required:
- message
properties:
message:
type: string
description: Success message
example:
message: Operation completed successfully
UpdateAPIKeyRequest:
type: object
description: At least one non-null field must be provided, and at least one provided value must differ from the current value. Omitted or null fields are left unchanged.
anyOf:
- required:
- label
properties:
label:
type: string
- required:
- scopes
properties:
scopes:
type: array
- required:
- ip_allow_list
properties:
ip_allow_list:
type: array
properties:
label:
type:
- string
- 'null'
minLength: 1
maxLength: 255
description: Human-readable label for the API key. Omit to keep the existing label.
scopes:
type:
- array
- 'null'
items:
type: string
minItems: 1
description: Array of scope strings to grant to this API key
ip_allow_list:
type:
- array
- 'null'
items:
type: string
description: Replacement list of allowed source IPs (CIDR blocks or bare IPv4/IPv6 addresses; canonicalized and de-duplicated, at most 100 entries, allow-all prefixes `0.0.0.0/0` and `::/0` rejected). Omit the field or send null to leave the existing list unchanged; send an empty array to clear it (key usable from any IP); send a non-empty array to replace it.
example:
label: Updated API Key
scopes:
- messages:send:{example.com}
- domains:read
ip_allow_list:
- 203.0.113.0/24
responses:
IdempotencyConflict:
description: 'Request in progress. This response always includes
`Idempotent-Replayed: false` and a positive integer `Retry-After`.
Clients must use that header tuple, not the human-readable message, to
distinguish this retryable idempotency state from other HTTP 409s.
'
headers:
Idempotent-Replayed:
$ref: '#/components/headers/IdempotencyInProgress'
Retry-After:
$ref: '#/components/headers/IdempotencyRetryAfter'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
message: A request with this idempotency key is already in progress
IdempotencyPayloadMismatch:
description: 'Idempotency key was already used with a different HTTP method, resolved
request path, or request body. This response includes neither
`Idempotent-Replayed` nor `Retry-After`.
'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
message: idempotency key was already used with a different request payload
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
description: 'Optional idempotency key for safe request retries. Must be a unique string for each logical request.
An identical request with a completed stored outcome returns the original status and body. An in-progress
execution returns 409, a changed method/path/body returns 422, and a released 5xx execution may run again.
Keys for non-secret responses expire after 24 hours. API-key create responses include a one-time `secret_key`,
so successful encrypted replay responses for those operations expire after 5 minutes.
'
schema:
type: string
maxLength: 255
example: user-12345-create-domain-20240101
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: aha-sk-64-CHARACTER-RANDOM-STRING
description: 'API key for authentication. Non-empty Security Requirement values are
AhaSend API-key roles. Roles listed within one requirement object are
jointly required; separate requirement objects are alternatives.
'
x-provenance:
method: harvested
publisher: AhaSend
source: https://ahasend.com/docs/openapi.yaml
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)