Getting Started
Authentication
Every API request is authenticated with an API key sent in the X-API-Key header. Keys are SHA-512 hashed before storage, so the raw secret is shown exactly once, at creation, and can never be retrieved again.
Sending your key
Pass your API key in the X-API-Key header on every request, to both POST /v1/send and GET /v1/me.
X-API-Key: a7Kd9Fq2.Xy8Lm3Pv6Rt1Zc4Nb7Wq0Es5Ug2Ih9Jk
Security model
SHA-512 hashing
When you create a key we generate a random secret, show it to you once, then store only its SHA-512 hash. Each request is hashed and compared against the stored hash with a constant-time comparison. That means:
- A database breach cannot expose your raw secrets
- Each key carries a short public label, so you can tell your keys apart in the dashboard
- A lost key cannot be recovered. Generate a replacement and revoke the old one
Key structure
Every key has two parts separated by a dot:
a7Kd9Fq2.Xy8Lm3Pv6Rt1Zc4Nb7Wq0Es5Ug2Ih9Jk └──────┘ └──────────────────────────────────┘ prefix secret 8 chars 32 chars, never stored in readable form
The prefix is stored as plain text and shown in your dashboard so you can tell keys apart at a glance. The secret is hashed. Send the whole string, dot included, a key without its secret half will not authenticate.
Expiry dates
A key can be given an optional expiry date at creation. Past that date it is rejected with 403 Forbidden. Expired keys are not deleted automatically; they stay visible in your dashboard so you keep the audit trail.
Revocation
Revoke a key from Dashboard → API Keys. Once revocation is confirmed, subsequent API requests using that key are rejected. Revocation is irreversible. The record is kept so you retain the history of what existed and when it was disabled.
Deleting a key
Each key also has a Delete action. Delete is permanent: the record, its stored hash, and its domain restrictions are removed from your account and cannot be restored by anyone, including support.
Use delete when you want a key gone from your records entirely. Use revoke when you want to disable a key quickly but keep the audit trail, during a rotation, say, or while investigating a suspected leak. Both stop the key from working immediately.
Rate limiting
Requests are rate-limited per API key at 60 requests per minute on every plan.
Exceeding it returns 429 Too Many Requests with a Retry-After header. Wait at least that many seconds before retrying. Spread requests over time to avoid exhausting the limit.
Monthly sending limits
Rate limits are separate from your plan's monthly quota:
| Plan | Sending mode | Monthly emails |
|---|---|---|
| Free BYOC | Your AWS SES, plus a Shared smoke test to your own address | 3,000 (both together) |
| BYOC | Your AWS SES | 20,000 included, up to 1,000,000 * |
| Managed Starter | Shared SES | 5,000 |
| Managed Growth | Shared SES | 25,000 |
| Managed Pro | Shared SES | 100,000 |
* Your own AWS SES sending quota also applies.
Failed authentication
A missing, invalid, revoked, or expired key returns 403 Forbidden. After 10 failed attempts from the same IP address within 60 seconds, further attempts from that address are temporarily blocked.
{
"detail": "Authentication credentials were not provided."
}Domain-scoped API keys
A key can optionally be restricted to a set of sending domains. A scoped key may only send from those domains; anything else returns 403 Forbidden with the error code domain_not_allowed.
How it works
- No restrictions (default): the key can send from every domain in your account. This is how existing keys behave.
- Scoped to specific domains: the key can send only from the exact domains you selected. Everything else is rejected.
- Domain deletion: deleting a domain removes it from every key's restrictions. If that empties a key's list, the key silently regains access to all domains, worth knowing before you delete a domain a scoped key depends on.
Setting domain scope
Domain scope is chosen when you create a key, from Dashboard → API Keys → New key. Select specific domains, or leave the selector empty for full access.
Error response when scope is violated
{
"success": false,
"error": "domain_not_allowed",
"detail": "API key Production is not authorized to send from other.com. Allowed domains: example.com, marketing.example.com."
}Frequently asked questions
How SendFleet API keys work, what happens when one is lost, and how fast revocation takes effect.
How do I authenticate with the SendFleet API?
What happens if I lose my SendFleet API key?
How quickly does API key revocation take effect?
What is the SendFleet API rate limit?
Best practices
| Practice | Why |
|---|---|
| One key per environment | Rotate or revoke staging without touching production. |
| Store keys in environment variables | Never commit them to source control or config files. |
| Set expiry dates for short-lived work | A migration script's key should not outlive the migration. |
| Revoke immediately on exposure | Revoke to stop it fast; delete as well to purge it from your records. |
| Delete keys you no longer need | Decommissioned a service? Remove its key so stale credentials don't linger. |
| Alert on 403 spikes | A sudden run of 403s with no error field often means a key is being probed or has been rotated somewhere you forgot. |