Pulsewave authenticates requests using API keys. Every request must include an Authorization header with a bearer token:
curl https://api.pulsewave.dev/v1/messages \
-H "Authorization: Bearer pw_live_8f2k9q3m1n7r5t6y4u2i0o8p" \
-H "Content-Type: application/json"
Keep your API keys out of client-side code. Anyone with a live key can send messages and incur charges on your account.
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, 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:
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:
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "The API key provided is not valid",
"param": null
}
}
See Errors for the complete list of error types.