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

# API tokens & scopes

> How to create workspace API keys, understand scopes, and use them securely.

## Overview

Voyant authenticates every API request with a workspace-scoped API key. Keys can optionally carry fine-grained scopes that the API enforces per-route.

<Tip>
  If you don't assign scopes to a key, it is treated as a legacy wide-open key. Scoped keys are recommended for production.
</Tip>

## Create a key

<Steps>
  <Step title="Open workspace settings">In the dashboard, go to Settings → API Keys.</Step>
  <Step title="Generate key">Click Generate New Key, give it a descriptive name, and optionally choose scopes.</Step>
  <Step title="Copy and store">Copy the key once and store it in a secure secrets manager or environment variable.</Step>
</Steps>

### Using a key

```bash theme={null}
curl https://api.voyantcloud.com/v1/products \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Keys automatically determine workspace context; do not send workspace IDs for customer keys. Internal
system keys may specify `x-workspace-id` when necessary.

## Scopes

Routes declare required scopes (e.g., `products:read`, `bookings:write`). The middleware allows access
when your key's scopes match using:

* Exact match: `products:read`
* Resource wildcard: `products:*` (all actions on products)
* Action wildcard: `*:read` (read all resources)
* Global wildcard: `*` (full access)

### Available scopes

<Tabs>
  <Tab title="Products & Catalog">
    * `products:read` - View products, itineraries, pricing
    * `products:write` - Create and update products
    * `products:delete` - Delete products
    * `collections:read` / `collections:write` / `collections:delete`
    * `tags:read` / `tags:write` / `tags:delete`
    * `drafts:read` / `drafts:write`
  </Tab>

  <Tab title="Bookings & Customers">
    * `bookings:read` - View bookings
    * `bookings:write` - Create and update bookings
    * `bookings:delete` - Cancel bookings
    * `customers:read` / `customers:write` / `customers:delete`
    * `payments:read` / `payments:write`
  </Tab>

  <Tab title="Inventory & Departures">
    * `inventory:read` - View availability
    * `inventory:write` - Update allocations
    * `departures:read` / `departures:write` / `departures:delete`
    * `pricing:read` / `pricing:write`
  </Tab>

  <Tab title="Media & Webhooks">
    * `media:read` / `media:write` / `media:delete`
    * `webhooks:read` / `webhooks:write` / `webhooks:delete`
  </Tab>
</Tabs>

### Scope templates

Use these predefined templates when creating keys in the dashboard:

| Template           | Scopes                                             | Use case                        |
| ------------------ | -------------------------------------------------- | ------------------------------- |
| Read Only          | `*:read`                                           | Reporting, analytics dashboards |
| Full Access        | `*`                                                | Admin integrations              |
| Booking Management | `bookings:*`, `customers:*`, `payments:read`       | Reservation systems             |
| Product Catalog    | `products:*`, `inventory:*`, `media:*`, `drafts:*` | CMS integrations                |

<Note>
  Some routes rely only on the base workspace authentication (no explicit scope) and don't require additional scopes beyond a valid API key.
</Note>

## Rotation & revocation

Rotating keys is zero-downtime:

<Steps>
  <Step title="Create a new key">Generate and deploy a new key to all services.</Step>
  <Step title="Verify">Smoke test your integrations.</Step>
  <Step title="Revoke old key">Revoke the old key in the dashboard.</Step>
</Steps>

Revocation is immediate. The dashboard also triggers a KV cache purge so the revoked key stops working right away.

## Common errors

<ResponseExample>
  ```json 401 Unauthorized - Missing or invalid Authorization token theme={null}
  { "error": "Unauthorized" }
  ```

  ```json 403 Forbidden - Insufficient scopes theme={null}
  {
    "error": "Insufficient permissions",
    "message": "This operation requires the following scopes: products:write"
  }
  ```

  ```json 429 Too Many Requests - Rate limit exceeded theme={null}
  { "error": "Rate limit exceeded", "retry_after": 30 }
  ```
</ResponseExample>

## Best practices

* Use separate keys per workspace (each workspace has its own keys)
* Use sandbox workspaces for development and testing
* Prefer scoped keys for live workspaces
* Store keys in a secrets manager; never commit to source control
* Rotate keys periodically
* Monitor usage and rate limits in the dashboard

## Related

* [Authentication basics](/authentication)
* [API reference](/api-reference/introduction)
* [Webhooks](/concepts/webhooks)
