Why am I getting a restricted_api_key error?
A 401 restricted_api_key means your API key lacks permission for the action. Here is how to tell that apart from a missing User-Agent header (a 403), an unverified or mismatched domain (a 422), and new-account sending restrictions.
A 401 restricted_api_key means your request authenticated fine — the API key is valid — but the key does not have permission for the action you tried. This is the single most common cause: using a sending-only key (sending_access) to manage resources.
{
"statusCode": 401,
"name": "restricted_api_key",
"message": "This API key is restricted to only send emails. Use a full-access key to manage resources."
}401 restricted_api_key is about permissions, not authentication. A bad or revoked key returns 403 invalid_api_key, and a missing key returns 401 missing_api_key. If you are seeing one of those auth errors instead, see Authentication.Cause 1 — a sending-only key managing resources
API keys come in two permission levels:
| Permission | Can do |
|---|---|
| full_access | Send email and manage resources — domains, audiences, contacts, and campaigns. |
| sending_access | Send email only. Cannot create, update, or delete domains, audiences, contacts, or campaigns. |
If you call an endpoint like POST /domains or DELETE /audiences/:id with a sending_access key, you get 401 restricted_api_key. The fix is to use a full_access key for management calls and reserve the sending_access key for POST /emails.
POST /api-keys, PATCH /api-keys/:id, and DELETE /api-keys/:id return 403 dashboard_only for any API key — upgrading to full_access will not help, because creating, re-scoping, and revoking keys is dashboard-only by design. Do it signed in at the API Keys page; see Create an API key. Listing keys with GET /api-keys still works with a full_access key.sending_access key on your sending servers is the right security posture — do not "fix" a permission error by upgrading that key. Instead, run management tasks with a separate full_access key from a trusted environment.Cause 2 — an unverified from-domain (also a 422)
A frequent point of confusion: sending from a domain you have not verified returns a 422 validation_error, because the request body itself is rejected before any permission check on the resource.
{
"statusCode": 422,
"name": "validation_error",
"message": "The domain is not verified. Verify it before sending."
}You can only send from a domain (or a subdomain of a domain) you have added and verified by publishing its SPF/DKIM/DMARC DNS records. If the from address is not even a valid email, you instead get 422 invalid_from_address. See the full Errors reference for every name and status code.
sending.yourdomain.com) but your from uses the root (you@yourdomain.com), or vice-versa. The from domain must match a verified domain exactly, including the subdomain. Either change the from to your verified domain, or add and verify the exact domain you want to send from.Cause 3 — new-account sending restrictions
A brand-new account starts in a restricted review mode until production access is granted. While in review mode:
- You can only send to verified recipient addresses — sending to an arbitrary recipient is rejected.
- Daily send volume and send rate are capped to small starter limits.
- Your verified from-domain still works, but the recipient must also be verified.
Cause 4 — a missing User-Agent header
This one bites people who hand-roll HTTP requests (the official `mailblastr` SDK sets a User-Agent for you, so SDK users never hit this). Every call to the API surface (/emails, /domains, /audiences, /campaigns, and the rest) must include a User-Agent header. A request without one is rejected with a 403 before it reaches the endpoint logic:
{
"statusCode": 403,
"name": "validation_error",
"message": "All API requests must include a User-Agent header."
}This is confusing because the same request often works from curl (which sets a User-Agent automatically) but fails from a fetch/library call that omits it. The fix is simply to send a descriptive User-Agent:
curl -X POST 'https://www.mailblastr.com/api/emails' \
-H 'Authorization: Bearer mb_xxxxxxxxx' \
-H 'Content-Type: application/json' \
-H 'User-Agent: my-app/1.0' \
-d '{
"from": "you@yourdomain.com",
"to": "user@example.com",
"subject": "Hello",
"html": "<p>Hello</p>"
}'User-Agent. See the User-Agent note in the API introduction.Checklist
- 1Confirm the key permission
If you are calling a management endpoint, use a
full_accesskey. Asending_accesskey sending toPOST /emailsis fine; managing domains/audiences/contacts/campaigns with it returns401 restricted_api_key. If the endpoint you are calling is an API-key one and the error is403 dashboard_only, no key will work — do it in the dashboard. - 2Send a User-Agent header
If you get a
403 validation_errormentioning User-Agent, your HTTP client is omitting the header. Add a descriptiveUser-Agentto every request. - 3Verify the from-domain
If you are sending and the error is
422 validation_errorabout the domain, finish DNS verification first — and make sure thefrommatches your verified domain exactly (subdomain included). That is a separate problem from a permission error. - 4Check production access
If sends only work to verified recipients, request production access to leave review mode.