eusend
Getting Started

Authentication

Authenticate with API keys in the Authorization header.

All API requests must include an API key in the Authorization header.

Authorization: Bearer eu_live_xxxxxxxxxxxx

Key types

ParameterTypeDescription
eu_live_...stringProduction key. Emails are actually sent.
eu_test_...stringTest key. Emails are queued but not delivered. Use for development and CI.

Test mode keys replay the full event lifecycle — and fire the same webhooks — as live keys, without delivering to the recipient's inbox. By default a send simulates email.sentemail.deliveredemail.openedemail.clicked (opens and clicks follow the message's tracking settings). To simulate failures, send to bounced@… for a bounce or complained@… for a complaint. Ideal for integration testing.

Permissions

Every key carries a permission, chosen when you create it. It defaults to full_access.

ParameterTypeDescription
full_accessstringCan create, read, update and delete every resource. The default.
sending_accessstringCan only send emails. Every other endpoint returns 403 FORBIDDEN.

A sending_access key may call exactly these endpoints — everything else, including reading your email logs, is refused:

MethodEndpoint
POST/emailsSend an email
POST/emails/batchSend up to 100 emails
PATCH/emails/:idReschedule a scheduled send
POST/emails/:id/cancelCancel a scheduled send

SMTP submission is covered too: a sending_access key works as an SMTP password exactly like a full-access one, because the SMTP gateway relays through POST /emails.

Reads are deliberately excluded. GET /emails/:id returns the rendered body, the full recipient list and the delivery event history — that's the half of a leaked key worth stealing. Give your application server a sending_access key, and keep full_access for tooling you control.

Restricting a key to one domain

A sending_access key can be pinned to a single sending domain with domain_id. Sends from any other domain are rejected with 403 FORBIDDEN, including the shared onboarding sandbox domain. Omit domain_id and the key can send from any of your verified domains.

curl -X POST https://api.eusend.dev/api-keys \
  -H "Authorization: Bearer eu_live_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Billing service",
    "permission": "sending_access",
    "domain_id": "5e9f2c1a-..."
  }'

domain_id is only valid together with sending_access — pairing it with full_access returns 400 VALIDATION_ERROR, since a full-access key can mint itself an unrestricted key anyway.

The restriction applies to test-mode keys as well, so a scoped key behaves the same in CI as it will in production.

Deleting a domain also revokes every key restricted to it. A restriction that quietly widened to "all domains" when its domain went away would be a silent privilege escalation, so the key goes with it.

Creating API keys

API keys are managed in the API Keys section of the dashboard, which prompts for the permission and domain restriction when you create one. You can create multiple keys and revoke them individually. Free plan allows 1 key; paid plans allow unlimited keys.