Getting started
Errors
The API reports failure with an HTTP status code and a JSON body. The status tells you what kind of problem it is; the body tells you which. This page lists the statuses you will meet, the body shapes behind them with one example each, the numeric and named codes some operations add, and how to handle each kind. Rate limiting has its own page, Rate limits.
Status codes
| Status | When | Body |
|---|---|---|
400 |
A request the API understood but cannot act on: an unknown filter[…] or sort field, an input a domain check refused, a payment the card provider declined |
{"message": …}, with error_code on payments |
401 |
The Authorization header is missing, or the token is invalid, expired or disabled, or the user behind it has no active account |
The string "Unauthorized". From login: {"code", "error", "requirements"} |
402 |
An SMS or WhatsApp send with no credit left | {"message", "error_code": 6001, "error": "SMS_ERROR"} |
403 |
The endpoint needs an account admin, a feature NUACOM enables per account, or access to a resource the user may not see | The string "Forbidden" from the admin check; {"message": …} otherwise |
404 |
No route at that path, or no resource with that id visible to the caller | {"message": "Resource not found!", "trace": null} |
405 |
The path exists but the method is not supported there | {"message": …} |
422 |
Validation failed, or a domain rule stopped the operation (an SMS code, a closed WhatsApp window) | {"message", "errors"} for validation; a code shape for domain rules |
429 |
Too many requests, see Rate limits | {"message": "Too Many Attempts."} |
5xx |
Something failed on NUACOM's side | {"message": "Server Error"} or {"message": "An error occurred", "trace": null} |
Body shapes
Plain strings. Two checks answer a bare JSON string, not an object: 401 "Unauthorized" from the token check and 403 "Forbidden" from the account-admin check. Parse the body as JSON and test for a string before reading keys.
message only. The default shape for everything that stops before the endpoint runs: unknown routes, wrong methods, unknown filters, per-account feature checks and most access checks. A trace key is sometimes present; it is always null. A 403 from a feature check has an empty message; other 403s say why.
{"message": "Requested filter(s) `city` are not allowed. Allowed filter(s) are `contact_ids, search, group, …`."}
Validation, 422. errors maps each failing input to a list of messages. Nested inputs use dot keys (metadata.template_id, phones.0). Most endpoints add message, the first error plus a count; a few older ones send errors alone. Read errors, not message.
{
"message": "The email field must be a valid email address. (and 1 more error)",
"errors": {
"email": ["The email field must be a valid email address."],
"first_name": ["The first name field is required when last name is not present."]
},
"trace": null
}
Domain errors with a code. Operations that fail for a business reason keep a 4xx status and add a code. The key that carries it depends on the endpoint:
| Where | Status | Shape |
|---|---|---|
| Payments and purchases (top-ups, add-ons, extensions) | 400 |
{"message": …, "error_code": "PAYMENT-DECLINED"}, or {"message": …, "error_code": "PAYMENT-INCOMPLETE", "incomplete_payment": {"client_secret": …, "payment_method": …, "payment_method_types": […]}} |
POST /v2/sms/send |
422 |
{"code": 6001, "error": "Insufficient credit"}; code is an SMS code from the table below |
POST /v2/conversations |
402 for 6001, otherwise 422 |
{"message": …, "error_code": 6001, "error": "SMS_ERROR"}. A bulk send that failed for every recipient adds success_count, failed_count and total_count, with error_code 6009 (422) or 6001 (402); a partial failure answers 201 with warning_code 6008 and warning |
POST /v2/conversations/{conversation}/messages |
400, or 402 for 6001 |
{"message": …, "error_code": 6003, "resultCode": null, "error": "SMS_ERROR"} |
| Other SMS endpoints | 422 |
{"message": …, "result_code": 6004} |
WhatsApp window. A free-form WhatsApp message outside the 24-hour customer-service window is refused with 422: on POST /v2/conversations as {"message": "The Customer Service Window is closed…", "error": "WHATSAPP_CSW_CLOSED"}, on POST /v2/conversations/{conversation}/messages as a validation error on metadata.template_id. Send an approved template instead; see Conversations / WhatsApp.
Login. POST /v2/auth/login answers 401 with its own shape, {"code": 4001, "error": "…", "requirements": […]}. requirements is empty except for 4001, where it lists the account's password policy.
Code reference
Login (code in a 401 from POST /v2/auth/login)
code |
Meaning |
|---|---|
401 |
Wrong email or password, an invalid or expired two-factor code, or too many failed attempts from this IP address (five in five minutes) |
4001 |
The password has expired; requirements lists the policy. Change it and log in again |
4002 |
Password login is disabled for this account (single sign-on only) |
4004 |
Logins are not allowed from this IP address |
SMS and MMS (code, error_code or result_code, see the table above)
| Code | Meaning |
|---|---|
6001 |
Insufficient credit |
6002 |
No valid recipient |
6003 |
Invalid sender: the account has no active sender name |
6004 |
The sender name is not approved for Irish numbers |
6005 |
The US campaign is not approved |
6006 |
Delivery failed |
6007 |
Scheduling error |
6008 |
Part of a bulk send failed (warning_code on a 201) |
6009 |
The whole bulk send failed |
6010 |
Draft not found |
6011 |
Message limit reached |
6012 |
Too many requests |
6013 |
Auto top-up failed; the draft is kept so you can retry after fixing the card |
6014 |
The send failed after a successful auto top-up; the draft is kept |
6101 |
MMS is not enabled for the account |
6102 |
MMS is not supported for the destination country (US, CA and AU only) |
6103 |
Too many media files (10 per message) |
6104 |
Media not found |
6105 |
Media not approved yet, or rejected by moderation |
6106 |
The toll-free number is not verified for US recipients |
Payments (error_code in a 400)
error_code |
Meaning |
|---|---|
PAYMENT-DECLINED |
The card was declined; message carries the card provider's reason |
PAYMENT-INCOMPLETE |
The payment needs 3-D Secure confirmation. incomplete_payment.client_secret identifies the payment to confirm; the NUACOM portal completes it in the browser |
Handling errors
- Branch on the status first, then on the code key, never on
messagetext: messages are for humans and can change. 401from an endpoint: stop and fix the token; retrying does not help.401from login counts toward the per-IP lockout, five failures in five minutes.403: a role or feature problem. Check the group guide's Roles and access section.422witherrors: fix the inputs named inerrorsand resend.422,402or400with an SMS code: act on the code (top up, approve the sender, pick a template) rather than resending.429: waitRetry-Afterseconds, then repeat the same request.5xx: retry once or twice with an increasing delay; if it persists, contact support with the time, the method and the path.