Error Codes
When an API request fails, Sendiee returns a JSON response with a success: false flag, an error code, and a human-readable message. Use the error code for programmatic handling.
Error Response Format
JSON
{
"success": false,
"code": "ERROR_CODE",
"message": "Human-readable error description"
}Rate Limiting
| Error Code | HTTP | Meaning |
|---|---|---|
| RATE_LIMIT_EXCEEDED_PER_SECOND | 429 | Organisation exceeded the per-second request limit on their plan |
| RATE_LIMIT_EXCEEDED_PER_DAY | 429 | Organisation exceeded the daily request limit on their plan |
Authentication & Organisation
| Error Code | HTTP | Meaning |
|---|---|---|
| API_KEY_MISSING | 401 | No API key provided in the request |
| INVALID_API_KEY | 401 | The API key does not exist or is revoked |
| AUTHENTICATION_FAILED | 500 | Internal authentication error |
| ORG_INACTIVE | 403 | Your organisation account is inactive |
| DOMAIN_NOT_WHITELISTED | 403 | Request origin not in the allowed domains list |
| ORG_ID_MISSING | 400 | Internal: org ID could not be resolved |
| ORG_ID_REQUIRED | 400 | Organisation ID could not be resolved from the API key |
Plan Enforcement
| Error Code | HTTP | Meaning |
|---|---|---|
| LIMIT_EXCEEDED | 403 | A numeric plan limit (e.g. max contacts, max tags) has been reached. Response includes limitKey, current, and limit fields. |
| FEATURE_NOT_ENABLED | 403 | The requested feature is not available on the organisation's current plan |
WhatsApp & Messaging
| Error Code | HTTP | Meaning |
|---|---|---|
| BRAND_NUMBER_MISSING | 400 | brandNumber parameter not provided |
| WABA_NOT_FOUND | 404 | No active WhatsApp account for the given brandNumber |
| WABA_RETRIEVAL_FAILED | 500 | Internal error retrieving WhatsApp account |
| MISSING_RECIPIENT | 400 | The "to" field is required |
| INVALID_PHONE_NUMBER | 400 | Phone number failed validation |
| MISSING_TEMPLATE | 400 | Neither templateId nor templateName provided |
| TEMPLATE_NOT_FOUND | 404 | Template not found or not in APPROVED status |
| PARAMETER_VALIDATION_ERROR | 400 | Template parameters count mismatch |
| INVALID_SCHEDULE_TIME | 400 | Scheduled time is in the past |
| META_API_ERROR | 502 | Error returned by Meta's WhatsApp Cloud API |
| MESSAGE_SEND_FAILED | 500 | Internal error sending message |
| MISSING_CONTENT | 400 | Message content is empty or missing |
| MISSING_TEXT_BODY | 400 | Text message missing "body" field |
| MISSING_MEDIA_LINK | 400 | Media message missing "link" field |
| MESSAGE_NOT_FOUND | 404 | Message ID not found in this org |
| STATUS_FETCH_FAILED | 500 | Internal error fetching message status |
| SCHEDULE_NOT_CANCELLABLE | 400 | Message already sent or processing — cannot cancel |
Contacts
| Error Code | HTTP | Meaning |
|---|---|---|
| MISSING_PHONE | 400 | phone field is required but was not provided |
| INVALID_PHONE_NUMBER | 400 | The provided phone number failed validation or formatting |
| INVALID_CUSTOM_FIELDS | 400 | customFields is not a plain object |
| CONTACT_NOT_FOUND | 404 | No contact found for the given identifier |
| CONTACT_ALREADY_EXISTS | 409 | A contact with this phone number already exists (duplicate key) |
Contact Fields
| Error Code | HTTP | Meaning |
|---|---|---|
| INVALID_FIELD_TYPE_FILTER | 400 | The type query param is not one of "default", "custom", "all" |
| MISSING_FIELD_NAME | 400 | fieldName is required but was not provided |
| INVALID_FIELD_TYPE | 400 | fieldType is not one of: text, number, date, boolean, dropdown |
| MISSING_DROPDOWN_OPTIONS | 400 | options array is required and must be non-empty for dropdown type fields |
| INVALID_FIELD_KEY | 400 | A valid fieldKey could not be derived from the provided input |
| INVALID_FIELD_ID | 400 | The provided fieldId path param is not a valid MongoDB ObjectId |
| CUSTOM_FIELD_NOT_FOUND | 404 | No custom field found with the given fieldId for this organisation |
| CUSTOM_FIELD_ALREADY_EXISTS | 409 | A custom field with this fieldKey already exists for this organisation |
Contact Tags
| Error Code | HTTP | Meaning |
|---|---|---|
| MISSING_TAG_NAME | 400 | name is required but was not provided |
| INVALID_TAG_ID | 400 | The provided tagId path param is not a valid MongoDB ObjectId |
| TAG_NOT_FOUND | 404 | No tag found with the given tagId for this organisation |
| TAG_ALREADY_EXISTS | 409 | A tag with this name already exists for this organisation |
Wallet
| Error Code | HTTP | Meaning |
|---|---|---|
| WALLET_NOT_FOUND | 404 | No active wallet found for this organisation |
Channels
| Error Code | HTTP | Meaning |
|---|---|---|
| INVALID_CHANNEL | 400 | The channel query param is not one of "whatsapp", "instagram", "messenger" |
| NO_CHANNELS_FOUND | 404 | No active business accounts found for the organisation (or for the specified brandNumber) |
Generic
| Error Code | HTTP | Meaning |
|---|---|---|
| INTERNAL_SERVER_ERROR | 500 | An unexpected server-side error occurred |
Handling Errors
- 400 errors — Check your request parameters. The
messagefield will explain what's wrong. - 401 errors — Verify your API key is correct and included in the Authorization header.
- 403 errors — Check your account status, domain whitelisting, or plan limits.
- 404 errors — The requested resource (template, contact, message, field, tag, etc.) was not found.
- 409 errors — A resource with that identifier (phone, fieldKey, tag name) already exists.
- 429 errors — Rate limit exceeded. Check the
Retry-Afterheader. - 500 errors — These are server-side issues. Retry with exponential backoff. If persistent, contact Sendiee support.