Errors
Qyvo error response shape, HTTP status codes, and the Meta WhatsApp error codes you may encounter.
Qyvo returns conventional HTTP status codes and a stable JSON error shape. When sending fails because Meta rejected the message, the underlying Meta error code propagates so you can handle it cleanly.
Error shape
Every error response is JSON with at least an error field:
{
"error": "Template not found"
}
Validation failures (Laravel format) include a message and a errors map keyed by field:
{
"message": "The given data was invalid.",
"errors": {
"phone": ["The phone field is required."],
"template_id": ["The template id must be a valid UUID."]
}
}
Some endpoints add structured detail to help you fix the problem in code:
{
"error": "Template requires variables that were not provided.",
"expected_placeholders": ["1", "2"],
"missing": ["2"]
}
HTTP status codes
| Code | Meaning | When you see it |
|---|---|---|
200 |
OK | Successful read or send |
201 |
Created | Resource creation (contact, sequence session, …) |
401 |
Unauthenticated | Missing or invalid Authorization header, revoked token |
403 |
Forbidden | Token valid but lacks required scope (rare today — every token has mcp) |
404 |
Not found | Resource doesn't exist or doesn't belong to your tenant |
422 |
Unprocessable | Validation failed, business rule rejected, or no WhatsApp account configured |
429 |
Too many requests | Quota exceeded — see Rate limits |
5xx |
Server error | Transient — retry with backoff |
Common Qyvo errors
| Status | error text |
Why |
|---|---|---|
401 |
Unauthenticated. |
Token missing/wrong/revoked |
404 |
Personal access client not found |
Backend install issue — contact support |
404 |
Contact not found |
The phone or contact_id doesn't match any contact in your tenant |
404 |
Template not found |
The template_id UUID doesn't exist in your tenant |
404 |
Sequence not found or not published |
The sequence is in draft — publish it first |
404 |
Flow not found or not published |
Same for flows |
422 |
No workspace configured for this account. |
The user behind the token has no tenant |
422 |
No WhatsApp account configured |
The tenant has no WabaAccount row — onboard a number first |
422 |
Either contact_id or phone is required |
Endpoint accepts either; you sent neither |
422 |
Template requires variables that were not provided. |
Body has {{1}} etc. but you didn't pass them in variables |
422 |
Template has no approved translation to send. |
The template is in PENDING or REJECTED on Meta |
Meta WhatsApp error codes
When the send actually reaches Meta and fails, the Meta error message bubbles up in the error field of a 422 response. The most frequent ones:
| Meta code | Meaning | What to do |
|---|---|---|
132001 |
Template name does not exist in this language | Sync templates and confirm the language has an APPROVED translation. See sync_templates MCP tool. |
132012 |
Parameter format does not match | Your variables count or types don't match the template body — check the template placeholders |
131026 |
Message undeliverable | The recipient phone is not on WhatsApp, or has not opted-in |
131047 |
Re-engagement message | The 24-hour customer service window is closed. Send a template instead of free-form text. |
131051 |
Unsupported message type | You sent a media URL Meta rejected (size, format, host) |
131056 |
Pair rate limit reached | Meta's per-pair (sender→recipient) throttle. Backoff and retry. |
133010 |
Phone number not registered | The WhatsApp Business number is not registered with Cloud API on Meta's side |
Idempotency
The Qyvo API does not currently support an Idempotency-Key header. Two consecutive send-template-message calls with the same payload will send two messages.
To deduplicate on your side:
- On
create-contact, the endpoint is upsert by(tenant_id, phone)— calling twice with the same phone returns the existing contact, no duplicates. - On
trigger-sequence/trigger-flow, an existing running session for the same(sequence_id, contact_id)pair returns{status: "already_running"}instead of starting a second. - On message sends, deduplicate at the application layer (e.g. lock on
order_idbefore callingsend-template-message).
Debugging tips
curl -ito see the headers —X-RateLimit-Remaining,Retry-After, request id.- The dashboard's Inbox shows the last
failedmessages with the sameerrorMeta returned. If a send returns422, the message also appears there withstatus: failedfor the audit trail. - Templates in
PENDINGorREJECTEDwon't send; check Settings → WhatsApp → Templates and resync from Meta.
