Error format
All error responses return a JSON body with anerror field. Some include
a machine-readable code for programmatic handling.
HTTP status codes
Send Message errors (POST /api/messages)
These are the specific errors you may encounter when sending a message.
Pre-send checks like line limits, time windows, device gaps, and contact gaps
never return errors. The message is accepted with
201 and the status
field indicates the outcome (pending, scheduled, etc.).400 — Message and attachments both empty
400 — Message and attachments both empty
Neither Fix: Include at least one of: a non-empty
message nor attachmentUrls was provided (or both were empty).message string, or an attachmentUrls array with up to 2 URLs.400 — Invalid messageType
400 — Invalid messageType
The Fix: Use
messageType value is not one of the accepted values."imessage", "sms", or "email". Or omit it entirely to
default to "imessage".400 — No active lines in workspace
400 — No active lines in workspace
No Fix: Provision at least one line in your workspace, or pass
fromLineId was provided and the workspace has no active lines to
round-robin from.fromLineId
explicitly.400 — Missing recipient
400 — Missing recipient
No Fix: Provide at least one of
recipientPhone, recipientEmail, or leadId was provided, and the
resolved lead (if any) has no contact details.recipientPhone, recipientEmail, or a
leadId that has stored contact details.400 — Fallback not configured
400 — Fallback not configured
sendFallbackSmsOnFailed was set to true but the workspace doesn’t have
Twilio fallback configured.PATCH /api/workspace/fallback-config, or set sendFallbackSmsOnFailed
to false.402 — READ_ONLY (subscription past due)
402 — READ_ONLY (subscription past due)
The workspace subscription is past due and write operations are blocked.Fix: Update your billing in the Tuco dashboard.
404 — Lead not found
404 — Lead not found
A Fix: Verify the
leadId was provided but no matching lead exists in the workspace.leadId exists and belongs to the same workspace as
the API key.Status vs error — key distinction
Rate limits
Tuco applies per-workspace rate limits to protect the platform. When you hit a limit:- You receive a
429response. - The
Retry-Afterheader tells you how many seconds to wait before retrying. - No data is modified — safe to retry.
All limits are per workspace (organization), regardless of how many API keys or users are calling the endpoint.
POST /api/drip is exempt from the 60/min send limit and never returns 429
for a normal blast — that is the whole point of the endpoint (a 429 would trigger
your CRM’s retry storm and duplicate sends). It applies only a very high infra
backstop on the buffered intake (~1,000 req/sec sustained / 10,000 burst per workspace) that
trips solely on runaway/abuse; if you ever hit it you get 429 + Retry-After and
can safely retry. Real send pacing (150/day, ~3–7 new conversations/hr per line) is
handled automatically by the per-line ban protector at send time, not at intake. See
Drip.Availability checks have two limits:
- 200 req/min API rate limit (token bucket, per workspace)
- 70 checks/day per line hard cap (each check hits a real device). With 3 lines = 210/day total.
200 with { "available": false, "verified": false, "reason": "daily_quota_exhausted" }
(or "reason": "no_healthy_line") — not a 429. This keeps CRM workflow steps from failing
on an un-checkable contact. Use verified: false to tell “couldn’t check” apart from a confirmed
not-on-iMessage result (available: false with no verified flag). Only the per-minute rate
limit (#1 above) returns 429 with Retry-After.Availability checks do not consume your daily send quota — they use separate counters.