Errors
Every error from the Email API has a stable error code + a
human-readable message. Build retry / error-handling logic against
the code, not the message.
Response shape
{
"success": false,
"error": "INSUFFICIENT_BALANCE",
"message": "Wallet balance ₹0.00 — recharge to continue sending."
}success: false is always present. error is the stable code.
message is for display + may change for clarity over time.
400 Bad Request
| Code | Cause | Fix |
|---|---|---|
INVALID_REQUEST | Malformed JSON or missing required field | Read message |
INVALID_AMOUNT | Non-positive amount on a wallet recharge | Pass amount > 0 |
INVALID_PARAM | Path / query param doesn’t parse | Check the URL |
MISSING_PARAM | Required param missing | Read message |
FROM_NOT_VERIFIED | from address not on a verified identity | Verify domain via POST /identities |
BILLING_INCOMPLETE | Partner profile missing required fields | Fill PUT /partner/self/billing |
BILLING_NOT_SET_UP | Zoho customer not yet created | Save billing once via PUT /partner/self/billing |
INVALID_SIGNATURE | HMAC check on payment-verify failed | Don’t tamper with payment widget output |
BAD_RECIPIENT | Recipient address malformed | Validate before send |
TOO_MANY_RECIPIENTS | Per-message recipient cap exceeded (50) | Split into multiple sends |
401 Unauthorized
| Code | Cause | Fix |
|---|---|---|
MISSING_AUTH | No Authorization header | Add Authorization: Bearer pk_live_... |
INVALID_KEY_FORMAT | Key doesn’t match pk_live_... | Regenerate from partner panel |
KEY_NOT_FOUND | Key was revoked or never existed | Regenerate |
KEY_INACTIVE | Account suspended | Contact support |
402 Payment Required
| Code | Cause | Fix |
|---|---|---|
INSUFFICIENT_BALANCE | Wallet balance < send price | Recharge wallet |
403 Forbidden
| Code | Cause | Fix |
|---|---|---|
IP_BLOCKED | Your IP isn’t on your account’s IP allowlist | Add to allowlist or call from an allowed IP |
SENDING_PAUSED | Account paused (admin OR reputation auto-pause) | Contact support / clean lists |
SANDBOX_QUOTA_REACHED | Daily 200/day sandbox cap hit | Request production access |
FEATURE_LOCKED | Plan doesn’t include this feature | Upgrade plan |
404 Not Found
| Code | Cause | Fix |
|---|---|---|
PARTNER_NOT_FOUND | Partner ID doesn’t exist | Check the ID |
IDENTITY_NOT_FOUND | Identity hasn’t been created | Create via POST /identities |
CONFIG_SET_NOT_FOUND | Configuration set name unknown | Check name spelling |
TEMPLATE_NOT_FOUND | Template name not registered | Create via POST /templates |
MESSAGE_NOT_FOUND | message_id doesn’t match any send | Check the ID + day_bucket |
409 Conflict
| Code | Cause | Fix |
|---|---|---|
EMAIL_ALREADY_REGISTERED | Signup with already-used email | Use forgot-password to recover |
IDENTITY_EXISTS | Already verified — duplicate POST | Idempotent — existing row returned |
CONFIG_SET_NAME_TAKEN | Another set with that name exists | Pick a unique name |
429 Too Many Requests
| Code | Cause | Fix |
|---|---|---|
RATE_LIMITED | Per-second send rate exceeded | Backoff and retry |
OTP_RATE_LIMITED | OTP resend before cooldown | Wait 60 seconds |
500 Internal Server Error
| Code | Cause | Fix |
|---|---|---|
DB_ERROR | Database query failed | Retry with backoff — usually transient |
INTERNAL_ERROR | Catch-all | Retry once; if persistent, contact support |
PAYMENT_GATEWAY_ERROR | Zoho upstream returned 5xx | Retry — usually transient |
502 Bad Gateway
| Code | Cause | Fix |
|---|---|---|
PAYMENT_GATEWAY_ERROR | Zoho returned an error response | Wait + retry; check Zoho status |
503 Service Unavailable
| Code | Cause | Fix |
|---|---|---|
DB_UNAVAILABLE | Database connection issue | Retry — should clear within seconds |
SMTP errors (in webhook payloads)
When a Bounce event fires, the bounce.bouncedRecipients[].diagnosticCode
field carries the SMTP diagnostic from the recipient’s MX. Common ones:
| Code | Meaning |
|---|---|
550 5.1.1 user unknown | Recipient doesn’t exist (hard bounce) |
550 5.1.10 No such user | Same — different MX wording |
550 5.7.1 spam policy | Receiver classified as spam (treat as complaint) |
552 5.2.2 mailbox full | Soft bounce — retry |
421 4.7.0 try again later | Greylisting / load — retry |
554 5.7.1 sender rejected | Sender domain blocked by recipient — list cleaning needed |
Retry strategy
Rule of thumb:
- 400-class errors: don’t retry. Fix the request.
- 402: don’t retry. Recharge first.
- 403 + 404: don’t retry. Fix configuration first.
- 429: retry with exponential backoff (start 1s, double up to 60s).
- 500 / 502 / 503: retry up to 3 times with exponential backoff.
Idempotency: /send is NOT idempotent on retry — duplicate calls
with the same body will produce duplicate email sends. Implement
your own dedup against your business identifier (charge_id, etc.)
before calling /send.
When to contact support
- 500-class errors persist > 5 minutes
- 402 even though wallet balance shows positive
- 403 SENDING_PAUSED with no clear cause in
/reputation
Email support@splashifypro.in or open a ticket from the partner panel.