Skip to main content

Error format

All error responses return a JSON body with an error field. Some include a machine-readable code for programmatic handling.
{
  "error": "Human-readable description of the problem",
  "code": "MACHINE_READABLE_CODE"
}

HTTP status codes

CodeMeaning
200Request succeeded
201Resource created (e.g. message, lead)
400Validation error — check the error field for details
401Authentication failed — invalid or missing API key
402Workspace is read-only (e.g. subscription past due)
404Resource not found (e.g. lead, line, campaign)
429Rate limit exceeded — wait and retry
500Internal server error — retry or contact support

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.).
Neither message nor attachmentUrls was provided (or both were empty).
{ "error": "Message and attachmentUrls cannot both be empty" }
Fix: Include at least one of: a non-empty message string, or an attachmentUrls array with up to 2 URLs.
The messageType value is not one of the accepted values.
{ "error": "Invalid messageType. Must be email, sms, or imessage" }
Fix: Use "imessage", "sms", or "email". Or omit it entirely to default to "imessage".
No fromLineId was provided and the workspace has no active lines to round-robin from.
{ "error": "No active lines in workspace..." }
Fix: Provision at least one line in your workspace, or pass fromLineId explicitly.
No recipientPhone, recipientEmail, or leadId was provided, and the resolved lead (if any) has no contact details.
{ "error": "Either recipientEmail or recipientPhone is required..." }
Fix: Provide at least one of recipientPhone, recipientEmail, or a leadId that has stored contact details.
sendFallbackSmsOnFailed was set to true but the workspace doesn’t have Twilio fallback configured.
{ "error": "...", "code": "FALLBACK_NOT_CONFIGURED" }
Fix: Configure Twilio on your workspace via PATCH /api/workspace/fallback-config, or set sendFallbackSmsOnFailed to false.
The API key is missing, invalid, or expired.
{ "error": "Unauthorized" }
Fix: Check your Authorization: Bearer <key> header. Generate a new key from your workspace settings if needed.
The workspace subscription is past due and write operations are blocked.
{ "error": "READ_ONLY", "code": "READ_ONLY", "reason": "past_due" }
Fix: Update your billing in the Tuco dashboard.
A leadId was provided but no matching lead exists in the workspace.
{ "error": "Lead not found or access denied" }
Fix: Verify the leadId exists and belongs to the same workspace as the API key.

Status vs error — key distinction

A 201 response with status: "pending" or status: "scheduled" is not an error. It means the message was accepted and Tuco will send it when conditions are met (time window, line limits, device gap, etc.).Only 4xx and 5xx responses indicate actual errors.
You receivedWhat it meansAction
201 + "pending"Message accepted, sending soonNo action needed
201 + "scheduled"Message accepted, will send at scheduled timeNo action needed
201 + "sent"Message sent immediatelyNo action needed
201 + "fallback"Recipient has no iMessage, fallback may fireOptional: send via another channel
400Validation errorFix the request and retry
401Auth errorCheck API key
402Billing issueUpdate payment
404Resource not foundCheck IDs

Rate limits

Tuco applies per-workspace rate limits to protect the platform. When you hit a limit:
  • You receive a 429 response.
  • The Retry-After header (when present) tells you how long to wait.
  • No data is modified.
For high-volume sends, use campaigns instead of individual API calls. Campaigns handle pacing, line rotation, and retry logic automatically.