> ## 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 in the EU, or send-us.ahasend.com as a US connection point forwarding to the EU. 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](/docs/facts#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:

<AccordionGroup>
  <Accordion title="Static Scopes" icon="lock">
    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>

  <Accordion title="Global Scopes" icon="globe">
    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>

  <Accordion title="Domain-Specific Scopes" icon="at">
    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}`
  </Accordion>
</AccordionGroup>

<Note>
  The wildcard scope `*` grants all permissions and should be used with extreme caution, preferably only for development and testing.
</Note>

## 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.
</Warning>

### Message Operations

<Tabs>
  <Tab title="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>

  <Tab title="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 |
  </Tab>
</Tabs>

### Webhook Management

<Tabs>
  <Tab title="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>

  <Tab title="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 |
  </Tab>
</Tabs>

### Email Routing

<Tabs>
  <Tab title="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>

  <Tab title="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 |
  </Tab>
</Tabs>

### SMTP Credentials

<Tabs>
  <Tab title="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>

  <Tab title="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 |
  </Tab>
</Tabs>

### Suppressions

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

### 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](/docs/api-reference/sub-accounts/overview) 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` | Suspend and unsuspend sub-accounts |
| `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.
</Note>

### Statistics and Reports

<Tabs>
  <Tab title="Global Scopes">
    | Scope | Description |
    | - | - |
    | `statistics-transactional:read:all` | Read statistics for all domains |
  </Tab>

  <Tab title="Domain-Specific Scopes">
    | Scope Pattern | Description |
    | - | - |
    | `statistics-transactional:read:{domain}` | Read statistics for specific domain |
  </Tab>
</Tabs>

## 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.
</Note>

### 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
    style B fill:#4ecdc4
    style C fill:#45b7d1
    style D fill:#96ceb4
```

## Authorization Flow

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

<Steps>
  <Step title="Wildcard Check">
    If the API key has the `*` scope, access is granted immediately.
  </Step>

  <Step title="Exact Match">
    Check if the required scope exactly matches any of the API key's scopes.
  </Step>

  <Step title="Global Scope Check">
    For dynamic scopes, check if a corresponding `:all` scope exists.

    Example: `messages:send:{example.com}` is satisfied by `messages:send:all`
  </Step>

  <Step title="Domain-Specific Check">
    For domain-specific operations, check if the API key has the exact domain scope and verify domain ownership.
  </Step>
</Steps>

## Best Practices

<AccordionGroup>
  <Accordion title="Principle of Least Privilege" icon="shield-check">
    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>

  <Accordion title="Domain-Specific Scopes" icon="at">
    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>

  <Accordion title="Separate API Keys" icon="key">
    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>

  <Accordion title="Regular Scope Audits" icon="magnifying-glass">
    Regularly review your API key scopes and remove any that are no longer needed. Update scopes when your application requirements change.
  </Accordion>
</AccordionGroup>

## Related Guides

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


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