Errors
The status codes and error strings the REST API, SMTP, and HTTP inject return.
A failed REST request returns a JSON body with an error string. Match on error, not on the message text. Language clients raise an error carrying the same error, field, and message.
Error shapes
Send endpoints return error, the field it applies to, and a short message. A firewall error also has rule. throttled, inject_failed, inject_unavailable, inject_timeout_unknown, and the idempotency_in_progress, idempotency_outcome_unknown, and idempotency_unavailable errors also have retryable, which is true only when nothing was sent and the same request can go again.
Other endpoints return {"error": "..."}. Validation failures on create and update return a list instead. IP pools return both an error and the list:
Authentication and access
| Status | error |
Meaning |
|---|---|---|
401 |
Invalid token or no user signed in |
The Bearer token is missing, invalid, or deleted. |
403 |
forbidden |
A Send only or Support key called an endpoint it can't use. See Create an API key and Team roles. |
403 |
team_suspended |
The account is suspended. Reads and deletes still work. Creating or changing clusters, IP pools, domains, tenants, SMTP credentials, inboxes, webhooks, and templates doesn't. |
404 |
team_mismatch |
The team id in the path isn't the token's team. A cluster id, a malformed id, and another team's id all return this. |
404 |
Not found |
The record doesn't exist or belongs to another team. |
Sending
| Status | error |
Meaning |
|---|---|---|
403 |
kyc_required |
Your account is pending production approval. Until then you can send only to team member emails, live inbox addresses, and inbox forward-to addresses. Also returned for a second cluster while pending. |
403 |
cluster_not_ready |
No cluster is sending_ready, or the one you chose isn't. |
403 |
domain_unverified |
from isn't on a verified sending domain. |
403 |
domain_suspended |
The From domain is paused. Resume it from Managing domains or with POST /api/v1/sending_domains/:id/resume. |
403 |
credential_missing |
The cluster has no live SMTP credential for that tenant. |
403 |
suppressed |
Every recipient is on the suppression list. If only some are, the send goes to the rest and lists the skipped addresses in suppressed. |
403 |
firewall |
A recipient failed a firewall check. rule names the check. |
409 |
idempotency_conflict |
An Idempotency-Key was reused with a different body, cluster, or sandbox flag on POST /sends. |
409 |
idempotency_in_progress |
A request with the same Idempotency-Key is still running. Retry in a few seconds. |
409 |
idempotency_outcome_unknown |
A request with the same Idempotency-Key timed out and may have been queued. PostShiba won't send it again with that key. Check the message's events before you use a new key. |
422 |
invalid |
A field is missing or wrong, for example no to, an unknown tenant, or html together with template. field names it. |
422 |
too_many_recipients |
to, cc, and bcc together have more than 50 addresses. Split the send, or use SMTP or HTTP inject for larger batches. |
429 |
rate_limited |
Over the REST request budget, per key or across the team. See Rate limits. |
429 |
throttled |
The cluster hit its hourly throttle or 24-hour cap, including any active boost. |
413 |
payload_too_large |
The request body is over 36 MB (field body), attachments are over 18 MB in total, or the composed message is over 25 MB. |
502 |
inject_failed |
The cluster didn't accept the message, or accepted no recipients. |
502 |
inject_timeout_unknown |
The cluster didn't answer in time. The message may have been queued, so a plain retry can send it twice. Retry with the same Idempotency-Key on POST /sends. |
503 |
inject_unavailable |
The cluster couldn't be reached. Nothing was sent. Retry. |
503 |
idempotency_unavailable |
POST /sends had an Idempotency-Key, and PostShiba couldn't store it. Nothing was sent. Retry. |
A throttled send stays rejected until the cluster has room again, so retrying straight away hits the same cap. Language clients raise the error and don't retry. SMTP answers 451 4.7.0 instead and does not keep the message. See What happens at your cap.
Clusters, domains, and tenants
| Status | error |
Meaning |
|---|---|---|
403 |
payment_required |
The team has no payment method. Returned by cluster create, plan or size changes, capacity boosts, and paid IP adds. |
403 |
operator_hold |
Our abuse team paused the tenant. Contact support. |
403 |
dbl_listed |
The domain is on the Spamhaus Domain Block List. Resume it after the listing is removed. |
403 |
extensions_disabled |
Boost extensions are turned off. |
404 |
feature_disabled |
Capacity boosts aren't enabled for your team. |
422 |
archived |
The cluster is deprovisioned. |
503 |
dbl_unavailable |
The Spamhaus listing couldn't be rechecked. Try again shortly. |
Network
| Status | error |
Meaning |
|---|---|---|
422 |
empty_inventory |
No IP of that class is available. |
422 |
class_mismatch |
The IP's class doesn't match the cluster's classification. |
422 |
cluster_required |
Shared IPs need a cluster_id. |
422 |
already_claimed |
Another team took that IP first. |
422 |
cooling_down |
That dedicated IP was released recently and isn't for sale yet. Pick another one. |
422 |
dedicated_taken |
The cluster already has a dedicated IP. |
422 |
not_dedicated |
Only dedicated IPs can be released. |
422 |
last_ip |
A cluster needs at least one sending IP. |
422 |
weights |
The traffic split across the cluster's IPs is invalid. |
422 |
sku_unprovisioned |
That IP product has no price yet. Contact support. |
422 |
in_ip_pool |
The IP is in one of your IP pools. Remove it from its pools before you put it on a cluster. |
IP pools
| Status | error |
Meaning |
|---|---|---|
404 |
Not found |
The pool, IP, or cluster doesn't belong to your team, the IP isn't a dedicated IP you own, or the cluster is deprovisioned. |
422 |
invalid |
The name or classification is invalid. errors lists why. |
422 |
name_taken |
Your team already has a pool with that name. |
422 |
class_mismatch |
The IP's or cluster's class doesn't match the pool's classification. |
422 |
in_default_pool |
The IP sends from a cluster's default pool. Unassign it from the cluster first. |
422 |
ip_unusable |
The IP is released or quarantined. |
422 |
weight |
weight isn't a whole number from 1 to 100. |
422 |
last_ip |
The pool is attached to a cluster and this is its last live IP. Detach the pool first. |
422 |
empty_pool |
A pool needs at least one live IP, not released or quarantined, before you attach it. |
422 |
dedicated_cluster |
Pools attach only to shared clusters. |
422 |
pool_attached |
Detach the pool from every cluster before you delete it. |
SMTP and HTTP inject
SMTP AUTH PLAIN on port 587 and HTTP Basic on HTTP inject use the same username and password. A correct password always logs in. After too many wrong passwords in a minute, SMTP answers further failures with 454 4.7.0 too many failed logins, try again later.
SMTP replies with the codes below. HTTP inject runs the same checks.
| Reply | Meaning |
|---|---|
| AUTH fails | Wrong username or password, a disabled credential, or too many failed logins. HTTP inject returns 401. |
530 5.7.0 Authentication required |
Port 587 got MAIL FROM before a successful login. |
550 authentication required |
The message was sent without logging in. |
550 sending disabled |
The cluster isn't allowed to send right now, for example because it's suspended. |
550 unverified domain |
The MAIL FROM domain isn't a verified domain for that credential's tenant. |
550 domain_suspended |
The MAIL FROM domain is paused. |
550 from header not aligned with verified domain |
The From header is missing or uses a domain that isn't verified. |
550 kyc_required |
Your account is pending production approval and the recipient isn't allowed yet. |
550 suppressed |
The recipient is on the suppression list. SMTP refuses it at RCPT TO, and the message still goes to the other recipients. |
550 5.7.1 X-Capsule-Ip is not a sending IP on this cluster |
X-Capsule-Ip named an IP that isn't on the cluster, in an attached pool, or in the pool named by X-Capsule-Pool. |
550 5.7.1 X-Capsule-Pool is not a sending pool on this cluster |
X-Capsule-Pool named a pool that doesn't exist, isn't attached to the cluster, or has no live IPs. The message isn't sent from the default pool instead. |
550 firewall: <rule> |
The recipient failed a firewall check. See Email firewall. |
550 5.7.1 message contains malware |
An attachment is a virus, an Office file with macros, or a file Spamhaus lists as malicious. |
550 5.7.1 message references a domain listed for phishing or malware |
A link or domain in the message is on the Spamhaus Domain Block List for phishing, malware, or botnets. |
451 temporary filter delay |
The spam filter wants another look. Retry later. |
550 5.7.1 blocked using dbl.spamhaus.org |
The From domain is on the Spamhaus Domain Block List. |
550 5.7.1 blocked using authbl.spamhaus.org |
The IP your app connects from is on the Spamhaus AuthBL. |
451 4.4.5 too many sessions, slow down |
Too many new sessions for one username. Reuse connections and retry. |
429 hourly send limit reached |
HTTP inject only. The cluster is at its hourly throttle. |
429 daily send limit reached |
HTTP inject only. The cluster is at its 24-hour cap. |
451 4.7.0 hourly send limit reached |
SMTP only. The cluster is at its hourly throttle. The message was not kept. |
451 4.7.0 daily send limit reached |
SMTP only. The cluster is at its 24-hour cap. The message was not kept. |
552 5.3.4 message too large |
HTTP inject only. The built message is over 25 MB. |
Inbound mail to your inboxes gets 451 hourly inbound limit reached when the team is over its hourly receiving allowance. The sending server retries later.