Authentication
Every request to Anypost is authenticated with an API key. One key works for both transports: it is the bearer token for the HTTP API and the password for SMTP.
API keys
An API key has two parts, and the distinction matters:
- The key ID (
key_a1b2c3d4-e5f6-7890-abcd-ef1234567890) names the key. It appears in the dashboard and in API paths like/v1/api-keys/{id}. It is not a secret. - The secret (
ap_AbCdEf12KxLmNoPq...) authenticates your requests. Treat it like a password.
The secret is returned once, in the response to the request that creates the key. Anypost stores only a hash of it and cannot show it again. If you lose it, create a new key.
Each key also has a prefix: the first 12 characters of the secret, such
as ap_AbCdEf12Kx. Lists of keys show the prefix so you can tell them apart
without exposing the full secret.
The secret grants whatever the key is permitted to do. Keep it server-side. Never embed it in a mobile app, browser code, or a public repository.
Authenticating requests
Over the HTTP API, send the secret as a bearer token:
curl https://api.anypost.com/v1/email \
-H "Authorization: Bearer ap_AbCdEf12KxLmNoPq..." \
-H "Content-Type: application/json" \
-d '{ "from": "[email protected]", "to": ["[email protected]"],
"subject": "Hello", "text": "It worked." }'Over SMTP, authenticate with a fixed username and the secret as the password:
| Field | Value |
|---|---|
| Username | anypost |
| Password | your API key secret (ap_...) |
SMTP host, ports, and TLS settings are covered in Sending over SMTP.
Permissions
Every key has one permission level, set when you create it and changeable later:
| Permission | Can do |
|---|---|
full | Every endpoint: send mail, and manage domains, templates, webhooks, suppressions, and keys. |
send_only | Send mail (POST /v1/email, POST /v1/email/batch) and read its own identity (GET /v1/whoami). Every other endpoint returns 403. |
Give an application server that only sends mail a send_only key. It limits
what an attacker can do if the key leaks.
Restricting a key
Two optional restrictions narrow where a key can be used. Both default to unrestricted.
- allowed_domains: the sending domains a key may use in the
fromaddress. When set, a send from any other domain is rejected. Unset means all of your team's verified domains. - allowed_ips: the IP addresses or CIDR blocks that may present the key.
A request from any other address returns
403. Unset means any IP.
Creating and managing keys
Manage keys in the dashboard, or through the /v1/api-keys endpoints: POST
to create, GET to list, PATCH to update, DELETE to remove. Creating a
key over the API requires an existing full key, so your first key comes
from the dashboard.
The full secret (key) is on the create response only — store it then, as it
cannot be retrieved later:
curl https://api.anypost.com/v1/api-keys \
-H "Authorization: Bearer $ANYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production server",
"permissions": "send_only"
}'PATCH changes a key's name, permission level, and restrictions. It never
changes the secret.
Each key records when it was last used, which helps identify keys that are safe to delete. Changes to a key, including deletion, propagate within about 5 minutes; a deleted or downgraded key may keep working until then.
Rotating a key
There is no rotate operation for API keys. To rotate one:
- Create a new key with the same permissions and restrictions.
- Deploy it everywhere the old key is used.
- Delete the old key.
Running both keys during the cutover avoids downtime.
When authentication fails
| Status | Meaning |
|---|---|
401 | The Authorization header is missing, or the key is unknown. |
403 | The key is valid but not allowed here: the request came from an IP outside allowed_ips, or a send_only key called a non-send endpoint. |
Repeated failed attempts from one IP are temporarily blocked. Fix the credential rather than retrying.
Where to go next
- Domains & DNS setup: verify a domain before you can send from it.
- Sending over SMTP: host, ports, and TLS for the SMTP transport.
- Send a single email: the full
POST /v1/emailrequest.