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

# Authentication

> How to authenticate requests to the Pulsewave API

Pulsewave authenticates requests using API keys. Every request must include an `Authorization` header with a bearer token:

```bash theme={null}
curl https://api.pulsewave.dev/v1/messages \
  -H "Authorization: Bearer pw_live_8f2k9q3m1n7r5t6y4u2i0o8p" \
  -H "Content-Type: application/json"
```

<Warning>
  Keep your API keys out of client-side code. Anyone with a live key can send messages and incur charges on your account.
</Warning>

## Live and test keys

Every key is prefixed to make its mode obvious:

| Prefix     | Mode | Behavior                                                                  |
| ---------- | ---- | ------------------------------------------------------------------------- |
| `pw_live_` | Live | Sends real messages and is billed                                         |
| `pw_test_` | Test | Only delivers to [verified test addresses](#test-addresses), never billed |

Use test keys in development and CI. Requests made with a test key behave identically to live requests — the same validation, the same webhook events — except nothing actually reaches a real inbox or phone unless the recipient has been added as a verified test address from your dashboard.

## Creating and revoking keys

Manage keys with the [API Keys resource](/api-reference/api-keys/create):

```bash theme={null}
curl -X POST https://api.pulsewave.dev/v1/api-keys \
  -H "Authorization: Bearer pw_live_8f2k9q3m1n7r5t6y4u2i0o8p" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production backend",
    "mode": "live",
    "scopes": ["messages:write", "messages:read"]
  }'
```

The secret value is only ever shown once, in the response to this call. If you lose it, revoke the key and create a new one.

## Scopes

Keys can be limited to a subset of the API:

| Scope             | Grants                                        |
| ----------------- | --------------------------------------------- |
| `messages:write`  | Send and cancel messages                      |
| `messages:read`   | List and retrieve messages and events         |
| `contacts:write`  | Create, update, and delete contacts and lists |
| `contacts:read`   | List and retrieve contacts and lists          |
| `domains:manage`  | Add, verify, and delete sending domains       |
| `webhooks:manage` | Create, update, and delete webhook endpoints  |

A key created without an explicit `scopes` array defaults to `["messages:write", "messages:read"]`.

## Authentication errors

Requests with a missing, malformed, or revoked key receive a `401` with an `authentication_error` type:

```json theme={null}
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The API key provided is not valid",
    "param": null
  }
}
```

See [Errors](/errors) for the complete list of error types.
