> ## Documentation Index
> Fetch the complete documentation index at: https://ahasend.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> AhaSend stores all message data in the EU. See /facts.
> The API base URL is https://api.ahasend.com. Send the API key in the Authorization: Bearer header. See /api-reference/authentication.
> Use send.ahasend.com for SMTP. Ports 25, 587 and 2525 use STARTTLS. Port 465 is not supported. See /smtp.
> For send-only integrations, create an API Key v2 under Credentials → Add and scope it to messages:send:{your-domain}. See /send-api/credentials and /api-reference/scopes.

# API Key Scopes and Permissions

> Every AhaSend API key scope, from messages:send:all to domain-specific scopes for webhooks, routes and SMTP, and how each request is authorized.

AhaSend API key scopes control which operations and domains a key can access; this reference lists the scope names and their rules.

Available on Free, Pro and Max. See [plans and features](https://ahasend.com/docs/facts.md#plans-and-features).

In a domain scope such as `messages:send:{example.com}`, keep the braces and replace only `example.com` with your domain. The braces are part of the scope string.

## Types of Scopes

AhaSend supports three types of scopes:

> [accordion] Static Scopes
>
> Static scopes provide fixed permissions that don't change based on context. These are used for account-level operations and general resource access.
>
> Example: `accounts:read`, `domains:write`

> [accordion] Global Scopes
>
> Global scopes end with `:all` and provide access to all resources of a specific type across all domains in your account.
>
> Example: `messages:send:all`, `webhooks:read:all`

> [accordion] Domain-Specific Scopes
>
> Domain-specific scopes are restricted to a particular domain. They use curly braces to specify the domain name placeholder.
>
> Example: `messages:send:{example.com}`, `routes:write:{mydomain.com}`

> [!NOTE]
>
> The wildcard scope `*` grants all permissions and should be used with extreme caution, preferably only for development and testing.

## Available Scopes

### Account Management

| Scope | Description |
| - | - |
| `accounts:read` | Read account information |
| `accounts:write` | Update account settings |
| `accounts:billing` | Access billing information |
| `accounts:members:read` | View account members |
| `accounts:members:add` | Add new account members |
| `accounts:members:update` | Update member permissions |
| `accounts:members:remove` | Remove account members |

### Domain Management

| Scope | Description |
| - | - |
| `domains:read` | List and view domain information |
| `domains:write` | Add and update domains |
| `domains:delete:all` | Delete any domain in the account |
| `domains:delete:{domain}` | Delete a specific domain |

> [!WARNING]
>
> Domain deletion accepts `domains:delete:all` or the matching `domains:delete:{domain}` scope.

### Message Operations

> [tab] Global Scopes
>
> | Scope | Description |
> | - | - |
> | `messages:send:all` | Send messages from any domain |
> | `messages:cancel:all` | Cancel messages from any domain |
> | `messages:read:all` | Read messages from any domain |

> [tab] Domain-Specific Scopes
>
> | Scope Pattern | Description |
> | - | - |
> | `messages:send:{domain}` | Send messages from specific domain |
> | `messages:cancel:{domain}` | Cancel messages from specific domain |
> | `messages:read:{domain}` | Read messages from specific domain |

### Webhook Management

> [tab] Global Scopes
>
> | Scope | Description |
> | - | - |
> | `webhooks:read:all` | Read webhooks for all domains |
> | `webhooks:write:all` | Create/update webhooks for all domains |
> | `webhooks:delete:all` | Delete webhooks for all domains |

> [tab] Domain-Specific Scopes
>
> | Scope Pattern | Description |
> | - | - |
> | `webhooks:read:{domain}` | Read webhooks for specific domain |
> | `webhooks:write:{domain}` | Create/update webhooks for specific domain |
> | `webhooks:delete:{domain}` | Delete webhooks for specific domain |

Creating or updating a webhook with contact events on also needs `contacts:read`, and `lists:read` as well for the list events. See [contact events](https://ahasend.com/docs/api-reference/webhooks.md#contact-events).

### Email Routing

> [tab] Global Scopes
>
> | Scope | Description |
> | - | - |
> | `routes:read:all` | Read routes for all domains |
> | `routes:write:all` | Create/update routes for all domains |
> | `routes:delete:all` | Delete routes for all domains |

> [tab] Domain-Specific Scopes
>
> | Scope Pattern | Description |
> | - | - |
> | `routes:read:{domain}` | Read routes for specific domain |
> | `routes:write:{domain}` | Create/update routes for specific domain |
> | `routes:delete:{domain}` | Delete routes for specific domain |

### SMTP Credentials

> [tab] Global Scopes
>
> | Scope | Description |
> | - | - |
> | `smtp-credentials:read:all` | Read SMTP credentials for all domains |
> | `smtp-credentials:write:all` | Create/update SMTP credentials for all domains |
> | `smtp-credentials:delete:all` | Delete SMTP credentials for all domains |

> [tab] Domain-Specific Scopes
>
> | Scope Pattern | Description |
> | - | - |
> | `smtp-credentials:read:{domain}` | Read SMTP credentials for specific domain |
> | `smtp-credentials:write:{domain}` | Create/update SMTP credentials for specific domain |
> | `smtp-credentials:delete:{domain}` | Delete SMTP credentials for specific domain |

### Suppressions

| Scope | Description |
| - | - |
| `suppressions:read` | View suppression lists |
| `suppressions:write` | Add suppressions |
| `suppressions:delete` | Remove specific suppressions |
| `suppressions:wipe` | Clear entire suppression list |

### Templates

| Scope | Description |
| - | - |
| `templates:read` | List and view transactional templates, their drafts and their published versions, and campaign templates |
| `templates:write` | Create and update transactional templates, publish and discard their drafts, and restore their versions; create and update campaign templates |
| `templates:delete` | Delete transactional templates and campaign templates |

The `templates` scopes cover transactional templates and [campaign templates](https://ahasend.com/docs/api-reference/campaign-templates/create-campaign-template.md) together. Sending a template with [Create Template Message](https://ahasend.com/docs/api-reference/messages/create-template-message.md) needs the send scope of the sender's domain, not a `templates` scope.

### Campaigns

| Scope | Description |
| - | - |
| `campaigns:read` | List and view campaigns, their stats and their recipients |
| `campaigns:write` | Create, update and duplicate campaigns |
| `campaigns:delete` | Delete draft campaigns |
| `campaigns:send` | Send, unschedule and test campaigns |

Sending, unscheduling and testing a campaign need only `campaigns:send`. They need no `messages:send` scope, not even for the sender's domain. See the [Campaigns API](https://ahasend.com/docs/api-reference/campaigns/overview.md).

### Contacts

| Scope | Description |
| - | - |
| `contacts:read` | List and view contacts |
| `contacts:write` | Create and update contacts, one at a time or in a batch |
| `contacts:delete` | Delete contacts |

Reading the lists of a contact needs `lists:read`, not a `contacts` scope. Reading the segments of a contact needs `segments:read` and `contacts:read`. See the [Contacts API](https://ahasend.com/docs/api-reference/contacts/overview.md).

### Lists

| Scope | Description |
| - | - |
| `lists:read` | List and view lists, the contacts on a list and the lists of a contact |
| `lists:write` | Create and update lists, and add, update and remove the contacts on a list |
| `lists:delete` | Delete lists |

Removing a contact from a list needs `lists:write`, not `lists:delete`. Listing the contacts on a list with `include_contacts=true` needs `contacts:read` as well as `lists:read`. See the [Lists API](https://ahasend.com/docs/api-reference/lists/overview.md).

### Segments

| Scope | Description |
| - | - |
| `segments:read` | List and view segments, preview a definition, and list the members of a segment and the segments of a contact |
| `segments:write` | Create and update segments |
| `segments:delete` | Delete segments |

Previewing a definition, listing the members of a segment and listing the segments of a contact read contacts, so they need `contacts:read` as well as `segments:read`. See the [Segments API](https://ahasend.com/docs/api-reference/segments/overview.md).

### API Key Management

| Scope | Description |
| - | - |
| `api-keys:read` | List and view API keys |
| `api-keys:write` | Create and update API keys |
| `api-keys:delete` | Delete API keys |

### Sub-Account Management

These scopes are granted to **parent**-account API keys to manage sub-accounts and the API keys owned by those sub-accounts. See the [Sub-Accounts API](https://ahasend.com/docs/api-reference/sub-accounts/overview.md) for the full workflow.

| Scope | Description |
| - | - |
| `sub-accounts:read` | List and read sub-accounts under the parent |
| `sub-accounts:write` | Create and update sub-accounts |
| `sub-accounts:delete` | Soft-delete sub-accounts |
| `sub-accounts:suspend` | Pause and resume sub-accounts, and unpause their domains |
| `sub-accounts:usage` | Read per-sub-account usage and allocated cost |
| `sub-account-api-keys:read` | List and read API keys owned by sub-accounts |
| `sub-account-api-keys:write` | Create and update API keys owned by sub-accounts |
| `sub-account-api-keys:delete` | Delete API keys owned by sub-accounts |

> [!NOTE]
>
> Sub-account API keys are managed only with parent credentials that hold the relevant `sub-account-api-keys:*` scope. A sub-account's own credentials cannot create or manage its nested API keys.

### Statistics and Reports

> [tab] Global Scopes
>
> | Scope | Description |
> | - | - |
> | `statistics-transactional:read:all` | Read statistics for all domains |

> [tab] Domain-Specific Scopes
>
> | Scope Pattern | Description |
> | - | - |
> | `statistics-transactional:read:{domain}` | Read statistics for specific domain |

## Scope Validation and Hierarchy

### Validation Rules

1. **Domain Ownership**: Domain-specific scopes are only valid if you own the specified domain
2. **No Duplicates**: Duplicate scopes in the same API key are not allowed
3. **Redundancy Filtering**: Specific domain scopes are automatically removed if a global scope exists

> [!NOTE]
>
> If you have both `messages:send:all` and `messages:send:{example.com}`, only the global scope will be retained as it already covers the specific domain scope.

### Scope Hierarchy

```mermaid theme={null}
graph TD
    A["&ast;"] --> B[Global Scopes :all]
    B --> C[Domain-Specific Scopes]
    A --> D[Static Scopes]

    style A fill:#ff6b6b,color:#1a1a1a
    style B fill:#4ecdc4,color:#1a1a1a
    style C fill:#45b7d1,color:#1a1a1a
    style D fill:#96ceb4,color:#1a1a1a
```

## Authorization Flow

When an API request is made, the system checks scopes in the following order:

**1. Wildcard Check**

If the API key has the `*` scope, access is granted immediately.

**2. Exact Match**

Check if the required scope exactly matches any of the API key's scopes.

**3. Global Scope Check**

For dynamic scopes, check if a corresponding `:all` scope exists.

Example: `messages:send:{example.com}` is satisfied by `messages:send:all`

**4. Domain-Specific Check**

For domain-specific operations, check if the API key has the exact domain scope and verify domain ownership.

## Best Practices

> [accordion] Principle of Least Privilege
>
> Grant only the minimum scopes necessary for your application to function. This reduces security risks if an API key is compromised.
>
> ```json theme={null}
> [
>   "messages:send:{newsletter.com}",
>   "suppressions:write",
>   "statistics-transactional:read:{newsletter.com}"
> ]
> ```

> [accordion] Domain-Specific Scopes
>
> Use domain-specific scopes when working with multi-tenant applications or when you want to restrict access to specific domains.
>
> ```json theme={null}
> [
>   "messages:send:{client1.com}",
>   "messages:read:{client1.com}",
>   "webhooks:write:{client1.com}"
> ]
> ```

> [accordion] Separate API Keys
>
> Create separate API keys for different applications or environments with appropriate scopes for each.
>
> ```json theme={null}
> [
>   "messages:send:all",
>   "suppressions:write"
> ]
> ```
>
> A separate reporting or management key can use:
>
> ```json theme={null}
> [
>   "accounts:read",
>   "api-keys:read",
>   "domains:read"
> ]
> ```

> [accordion] Regular Scope Audits
>
> Regularly review your API key scopes and remove any that are no longer needed. Update scopes when your application requirements change.

## Related Guides

* [API authentication](https://ahasend.com/docs/api-reference/authentication.md), [Send-only API keys](https://ahasend.com/docs/send-api/credentials.md), [REST sending guide](https://ahasend.com/docs/send-api/send-email.md).
* [SMTP settings](https://ahasend.com/docs/smtp.md), [CLI quickstart](https://ahasend.com/docs/cli/quickstart.md), [Node.js SDK](https://ahasend.com/docs/guides/nodejs-sdk.md).
* [Go SDK](https://ahasend.com/docs/guides/go-sdk.md), [API errors](https://ahasend.com/docs/api-reference/errors.md), [API rate limits](https://ahasend.com/docs/api-reference/rate-limits.md).
* [Suppression durations](https://ahasend.com/docs/bounces.md#suppression-duration).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.