4xx or 5xx status and a JSON body containing a machine-readable error code:
{ "error": "campaign_no_phone_numbers" }
| Field | When |
|---|---|
requiredPermission | 403 forbidden: the scope the key needs. |
message | A human-readable explanation. Don’t parse it; it may change. |
issues or detail | Validation errors: the fields that failed and why. |
requestId | Present on many errors. Quote it when contacting support. |
upstreamStatus | 502 provider_error: the status returned by the calling service. |
error (and the HTTP status), never on message.
One exception:
POST /v1/campaigns/{campaignId}/leads returns campaign_not_accepting under the key code rather
than error.Retrying
| Status | Retry? |
|---|---|
400, 401, 403, 404, 409, 410, 422 | No. Fix the request first. |
402 | After topping up the wallet. |
429 | After Retry-After seconds. |
500, 502, 503 | Yes, with exponential back-off. On billed endpoints, reuse the same Idempotency-Key. |
Authentication & permissions
| Status | error | Meaning | Fix |
|---|---|---|---|
| 401 | unauthorized | No Authorization: Bearer header, or an empty token. | Send Authorization: Bearer pk_live_…. |
| 401 | invalid_api_key | The API key is unknown, revoked or expired, or its workspace was deleted. | Check the key; ask Pineyard for a new one if it was revoked or expired. |
| 403 | api_key_not_scoped | A key issued without scopes was used outside /v1. | Ask Pineyard to add scopes to the key, or use the /v1 endpoints. |
| 403 | api_key_owner_inactive | The member the key acts for was removed or suspended. | Ask Pineyard to re-assign the key to an active member, or issue a new key. |
| 403 | workspace_pending_approval | The workspace has not been approved yet. | Wait for approval; contact support if it is taking long. |
| 403 | workspace_suspended | The workspace is suspended. | Contact support to reactivate the workspace. |
| 403 | forbidden | The key lacks the permission named in requiredPermission, or the resource belongs to another workspace. | Ask Pineyard to add the scope, or check that the member the key acts for has that permission. |
| 403 | api_key_not_allowed | This action needs a person signed in to the dashboard (sign-ins, payments, email, and similar). | Do it from the dashboard. |
| 403, 404 | feature_not_available | This feature is not enabled for your workspace or plan. | Contact Pineyard to enable it. |
| 403 | prompt_access_forbidden | Prompt text is not available to this caller. | Not available to API keys. |
| 403 | operator_only | Overriding lead metrics is reserved for Pineyard staff. | Contact support. |
Requests, limits & server
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400, 422 | invalid_body | The request body (or query) failed validation. Details are in issues (or detail). 422 on POST /v1/campaigns/{campaignId}/leads. | Fix the listed fields and resend. |
| 400 | invalid_query | Query string failed validation. | Fix the query parameters listed in issues/detail. |
| 400 | invalid_params | Commerce query parameters invalid. | Fix the parameters listed in issues. |
| 400 | invalid_request | The input was rejected. | Correct the input described in message. |
| 404 | not_found | The resource does not exist in your workspace, or the feature is not enabled for it. | Check the ID and path. |
| 400 | no_fields_to_update | PATCH body empty. | Send at least one field. |
| 409 | name_taken | An agent, campaign or campaign type with that name already exists (unique constraint). | Choose a different name. |
| 409 | concurrent_modification | Resource changed concurrently (optimistic lock); workflows include currentRevision. | Reload and retry with the latest revision. |
| 429 | rate_limited | Too many requests. | Wait for Retry-After seconds, then retry. See Rate limits. |
| 500, 400, 404, 413 | internal_error | An unexpected error. A 400 with this code usually means the body is not valid JSON; a 413 means the body is larger than 1 MB. | Check the body. For 500, retry, then contact support with the requestId. |
| 503 | database_unavailable | The service is temporarily unavailable. | Retry after Retry-After seconds. |
| 502 | provider_error | The calling service rejected the request (upstreamStatus 4xx) or was unavailable (5xx). | For 4xx, check the settings named in message. For 5xx, retry in a minute. |
| 500 | LIMIT_FILE_SIZE | The uploaded file is larger than the endpoint allows. Currently returned as 500. | Upload a smaller file. |
| 413, 400 | file_too_large | The file is over the size limit. | Upload a smaller file. |
| 400 | file_required | Multipart request had no file. | Attach the file in the expected form field. |
| 400 | no_files | No files uploaded. | Attach files. |
| 400 | upload_error | Malformed multipart upload. | Send a single ‘file’ field. |
| 500 | upload_failed | Fallback when an upload error has no message. | Retry; contact support if persistent. |
| 502 | suggestion_failed | AI suggestion generation failed (any error). | Retry. |
| 422 | rewrite_too_long | POST /campaigns/suggest-metric-prompt: the AI-generated or rewritten metric prompt came out longer than the 5,000-character limit. | Try again, or shorten the original prompt. |
Idempotency
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400, 422 | idempotency_key_required | A billed endpoint was called without an Idempotency-Key header (400), or a /v1 lead push without idempotencyKey in the body (422). | Send a unique key per action. See Idempotency. |
| 400 | idempotency_key_invalid | Idempotency-Key is over 200 chars or has non-printable or non-ASCII characters. | Use up to 200 printable ASCII characters. |
| 409 | idempotency_in_progress | A request with the same Idempotency-Key is still running. | Retry the same request after Retry-After (1s). |
| 422, 409 | idempotency_key_reused | The Idempotency-Key was already used for a different request (422). On POST /calls/test, 409 means a call with this key already exists. | Use a new key for a new request. |
| 503 | idempotency_unavailable | The idempotency check could not run. Nothing was done. | Retry shortly with the same key. |
Leads & results (/v1)
| Status | error | Meaning | Fix |
|---|---|---|---|
| 409 | campaign_not_accepting | The campaign is not a running API campaign. Returned as {"code": "campaign_not_accepting", "reason": …}; reason is not_api or the campaign status. | Push leads only to a running campaign whose source is API. |
| 422, 400 | invalid_phone | Phone number could not be normalised. | Send a valid phone number, preferably E.164 (for example +15555550100). |
| 429 | journey_campaign_live_cap | Journey campaign has too many leads pending or in flight. | Retry the same push later. |
| 403 | api_results_not_enabled | API lead results are not enabled for this workspace. | Ask support to enable API results. |
| 404 | lead_not_found | No lead (campaign contact) with that id in this workspace or campaign. | Use the leadId returned when the lead was pushed. |
| 410 | result_expired | The retained result for this lead has expired. | Fetch results sooner, or rely on result webhooks. |
| 404 | result_not_found | No result with that id (or it expired). | Check the resultId. |
Campaigns
| Status | error | Meaning | Fix |
|---|---|---|---|
| 404 | campaign_not_found | No campaign with that id in this workspace. | Check the campaign id. |
| 409 | campaign_not_draft | Campaign can only be changed in DRAFT (or PAUSED/CREDIT_EXHAUSTED for edits; contacts only in DRAFT). | Pause the campaign, or create a new one. |
| 409 | campaign_delete_active | Only DRAFT, CANCELED or COMPLETED campaigns can be deleted. | Stop the campaign first. |
| 409 | campaign_delete_import_in_progress | A CRM import for this campaign is still pending or running. | Wait for the import to finish, then delete. |
| 400 | campaign_not_running | The campaign is not running (also returned for an unknown campaign ID). | Only pause running campaigns. |
| 400 | campaign_not_paused | UNCLEAR: mapped in the /v1 resume handler but never thrown by resumeCampaign/startCampaign in this snapshot. | See message. |
| 400 | campaign_not_startable | Campaign status is not DRAFT, PAUSED or CREDIT_EXHAUSTED (or a journey or inbound campaign is in a non-startable state). | Only start or resume DRAFT/PAUSED campaigns; use restart for finished ones. |
| 400 | invalid_reserved_concurrency | reservedConcurrency value out of range. | Send a valid reservedConcurrency. |
| 402 | workspace_not_active | Workspace is not ACTIVE, so no billable activity is allowed. | Contact support to reactivate the workspace. |
| 402 | activity_frozen | Workspace activity is frozen. | Contact support or billing. |
| 402 | insufficient_credits | Wallet balance too low (and no active trial). | Top up the wallet and retry. |
| 404 | workflow_not_found | No workflow with that id (or workflows not enabled). | Check the workflowId and that workflows are enabled. |
| 409 | workflow_not_active | Workflow is not ACTIVE (not published or archived). | Activate (publish) the workflow first. |
| 400 | campaign_workflow_not_active | Journey campaign’s workflow is missing or not ACTIVE at start. | Activate the workflow, then start the campaign. |
| 400 | campaign_no_pending_contacts | Campaign has no PENDING contacts to dial or enrol. | Add contacts before starting. |
| 400 | campaign_schedule_expired | Campaign’s scheduledEndAt is in the past. | Extend or clear the schedule end date. |
| 400 | campaign_is_inbound_misconfigured | An outbound-style campaign uses an INBOUND agent and has no contacts. | Use an outbound agent, or create an inbound campaign on a number. |
| 400 | campaign_channel_needs_workflow | CUSTOM-channel campaign has no workflow attached. | Attach a workflow or change the channel. |
| 400 | campaign_channel_needs_email_sender | EMAIL campaign has no sender mailbox. | Attach an email sender. |
| 400 | campaign_channel_needs_email_template | EMAIL campaign has no email template. | Attach at least one email template. |
| 400 | campaign_channel_needs_agent | Voice-leg campaign has no agent. | Set agentId. |
| 400 | campaign_channel_needs_sender | Message-leg campaign has no WhatsApp sender. | Connect or select a WhatsApp sender. |
| 400 | campaign_channel_needs_template | Message-leg campaign has no outreach template, or the template id does not exist. | Set an approved outreach template. |
| 400 | outreach_template_not_approved | Outreach template is not APPROVED. | Get the template approved before starting. |
| 400 | outreach_template_needs_runtime_context | Outreach template has bindings that can only be filled at runtime. | Use a template without runtime-only bindings for first-touch outreach. |
| 400 | campaign_no_phone_numbers | Voice campaign has no phone numbers on an enabled carrier attached. | Attach phone numbers (POST /campaigns/{id}/phone-numbers). |
| 400 | reserved_exceeds_allocation | Running campaigns would reserve more concurrent calls than your workspace has. | Lower reservedConcurrency, pause another campaign, or ask Pineyard for more capacity. |
| 400 | inbound_did_unavailable | Inbound campaign’s phone number is missing, not assigned to this workspace, or its carrier is disabled. | Choose an assigned phone number. |
| 400 | inbound_did_has_no_agent | The number has no ACTIVE INBOUND agent assigned. | Assign an active inbound agent to the number. |
| 409 | inbound_did_already_in_campaign | The number already belongs to a non-terminal inbound campaign. | Stop the other inbound campaign or use another number. |
| 400 | inbound_agent_has_no_number | Inbound agent chosen but no number routes to it. | Assign a number to the inbound agent, or pass phoneNumberId. |
| 400 | inbound_agent_has_many_numbers | Inbound agent has several numbers and none was specified. | Pass phoneNumberId. |
| 400 | inbound_campaign_action_not_supported | Operation is not valid for INBOUND campaigns (uploads, pause/resume/restart, source switch, re-engage, remessage, outreach). | Do not perform this action on inbound campaigns. |
| 400 | journey_campaign_source_unsupported | Journey (workflow) campaigns only support CSV or API sources. | Use source CSV or API. |
| 400 | journey_campaign_contact_cap | Too many contacts for a journey campaign. | Split the contacts across campaigns. |
| 400 | journey_campaign_action_unsupported | Restart or contact-retry is not supported for journey campaigns. | Use workflow run controls instead. |
| 400 | campaign_type_not_found | campaignTypeId does not exist or is not ACTIVE. | Use an active campaign type id. |
| 400 | reserved_extraction_key | A custom extraction key uses a built-in signal name (key field included on the dashboard route). | Rename the field. |
| 400 | reserved_metric_key | An evaluation metric key uses a built-in signal name. | Rename the metric. |
| 400 | metric_key_collision | A metric key collides with an extraction field name. | Rename the metric or the field. |
| 400 | default_crm_connection_required | CRM_WEBHOOK campaign created without defaultCrmConnectionId. | Pass defaultCrmConnectionId. |
| 409 | campaign_source_locked | Campaign source cannot change once it has contacts or API deliveries, or is not DRAFT. | Create a new campaign with the desired source. |
| 404, 400 | agent_not_found | Agent id missing or not in this workspace (400 on POST /v1/campaigns, inbound-number assignment and suggest routes). | Use an agent id from GET /agents or /v1/agents. |
| 400 | phone_number_not_in_workspace | Phone number id not owned or assigned to this workspace, or its carrier is disabled. | Use ids from GET /phone-numbers. |
| 409 | campaign_running_no_remove | Cannot detach a number from a RUNNING campaign. | Pause the campaign first. |
| 422 | workflow_invalid | Stored or submitted workflow definition fails parsing or validation (details included). | Fix the workflow per details and republish. |
| 404 | upload_not_found_or_expired | The uploadId is unknown or expired. On some endpoints currently returned as internal_error. | Upload the CSV again and use the new uploadId. |
| 422 | excel_mangled_phone | Phone column contains scientific-notation numbers (Excel lost the digits). | Format the phone column as text and re-export the CSV. |
| 400 | invalid_csv_format | The CSV needs a header row and at least one data row. Returned with the message as error. | Fix the CSV. |
| 415 | unsupported_brief_type | Brief file is not PDF, TXT or Markdown. | Upload a PDF, TXT or Markdown file. |
| 400 | brief_required | No brief text and no file content. | Paste text or upload a brief. |
| 422 | brief_unusable | A campaign could not be drafted from the brief. | Provide a fuller brief. |
| 409 | campaign_not_editable | Campaign status does not allow this live edit (schedule, outreach, metrics). | See message. |
| 409 | campaign_not_reengageable | Campaign is in a state where re-engage is not allowed. | See message. |
| 409 | incomplete_retry_disabled | Finish-interrupted requested but incompleteRetryEnabled is off. | Enable incomplete-call retry in the schedule first. |
| 409 | campaign_channel_not_message_followup | Remessage requested on a campaign without a message leg. | Use a campaign whose channel includes WhatsApp messaging. |
| 400 | campaign_channel_switch_not_supported | The requested channel switch is not allowed on outreach edit. | See message. |
| 400 | campaign_channel_has_no_rules | Outreach rules were sent for a channel that has none. | See message. |
| 404, 400 | template_not_found | Template id not in this workspace (400 in order-notification rules). | Use an existing template id. |
| 400 | template_not_approved | Template is not APPROVED. | Wait for approval or pick an approved template. |
| 400 | campaign_has_no_journey | Campaign does not run a workflow. | Use journey endpoints only on journey campaigns. |
| 404 | workflow_run_not_found | No workflow run for that lead or run id. | Check the id. |
| 400 | no_extraction_data | Campaign has no extraction data to analyse. | Wait for completed calls with extractions, then analyse. |
| 502 | analysis_failed | Campaign analysis generation failed. | Retry. |
| 404 | contact_not_found | Campaign contact not found. | Check contactId. |
| 400 | campaign_not_active | Retry requested but the campaign is not active. | Resume or start the campaign first. |
| 400 | contact_not_failed | Only FAILED contacts can be retried. | Retry only failed contacts. |
| 400 | campaign_not_in_draft | Adding contacts or CRM import requires a DRAFT campaign (or a live CRM_WEBHOOK campaign for imports). | Create a new draft campaign. |
| 400 | empty_message | Chat message is blank. | Send a non-empty message. |
| 429 | message_limit_reached | Campaign chat session hit its fair-use message cap. | Start a new campaign conversation. |
| 500 | chat_failed | Chat send failed (also returned for invalid input on non-stream POST /campaigns/:id/chat). | Retry. |
| 410 | expired | Export job artifact has expired. | Create a new export. |
| 400 | campaign_already_terminal | Stop requested on an already finished campaign. | No action needed. |
| 400 | campaign_not_restartable | Only stopped (COMPLETED or CANCELED) campaigns can be restarted. | Stop the campaign first, or use resume for a paused one. |
| 400 | agent_not_found_or_not_provisioned | Agent missing, not ACTIVE, or not provisioned. | Use an active, provisioned agent. |
| 422 | excel_row_limit_exceeded | Too many rows for an XLSX export. | Choose CSV or a shorter range. |
| 409 | contact_opted_out | Contact opted out of messages. | Do not message this contact. |
Agents, calls & phone numbers
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400 | prompt_required | Agent create has no prompt after assembly. | Provide a prompt or studioConfig. |
| 400 | invalid_transfer_number | Transfer number is not E.164. | Use E.164, for example +15555550100. |
| 400 | transfer_number_required | Transfer enabled without a number. | Set a transfer number or disable transfer. |
| 404 | background_audio_not_found | Background audio id not owned by this workspace or not available. | Use an id from GET /background-audio. |
| 409 | agent_limit_reached | Agent quota reached on duplicate. | Remove an unused agent or contact support. |
| 409 | in_use | Agent is referenced by campaigns, so it cannot be permanently deleted. | Archive instead, or remove the campaigns. |
| 500 | sandbox_from_number_not_configured | Test calls without your own number are not available. | Pass fromPhoneNumberId. |
| 400, 409 | agent_not_provisioned | The agent is still being set up. | Wait a moment, or save the agent again. |
| 503 | sandbox_from_number_unavailable | The shared test number is unavailable. | Retry later, or pass fromPhoneNumberId. |
| 501 | web_session_not_supported | Web test sessions are not available. | Use a phone test call. |
| 501 | not_supported | This operation is not available for your workspace. | Contact Pineyard. |
| 404 | dictionary_not_found | Dictionary not found. | Check the id. |
| 404 | function_not_found | Function not found. | Check the id. |
| 400 | invalid_export_period | period is not one of today, last_7_days, this_month, last_month, all_time, custom. | Use a supported period. |
| 400 | invalid_export_range | Custom range missing from/to, or to ≤ from. | Send valid from < to. |
| 400 | unknown_metric | Metric key is not defined for this campaign. | Use a defined metric key. |
| 400 | invalid_value | Value is not in the metric’s allowed list. | Use one of ‘allowed’. |
| 400 | no_transcript | Call has no transcript to translate. | Only translate calls with transcripts. |
| 409 | no_contact_for_call | No contact is linked to this call. | See message. |
| 409 | phone_number_released_upstream | The caller-ID number is no longer available. | Use a different phone number. |
| 409 | do_not_call | Destination is on the do-not-call list. | Remove it from DNC or call another number. |
| 404 | phone_number_not_found | Phone number not in this workspace. | Check the id. |
| 409 | phone_number_not_synced | The phone number is still being set up. | Retry later. |
| 400 | agent_archived | Agent is archived. | Use an active agent. |
| 400 | agent_type_not_inbound | Agent is not INBOUND type. | Use an inbound agent. |
| 501 | preview_not_supported | A preview is not available for this voice. | Pick another voice. |
| 404 | call_not_found | Speech analysis or dialer call not found. | Check the id. |
Documents, chatbots & knowledge bases
| Status | error | Meaning | Fix |
|---|---|---|---|
| 404 | document_not_found | Document not found. | Check the id. |
| 400 | no_external_id | The document upload was not completed. | Start the upload again. |
| 400 | document_not_provisioned | The document upload has not been confirmed. | Confirm the upload first. |
| 404 | chatbot_not_found | Chatbot not found. | Check the id. |
| 404 | knowledge_base_not_found | Knowledge base not found or not owned. | Check the knowledge base ids. |
| 409 | knowledge_base_in_use | Knowledge base is attached to a live chatbot. | Detach it first. |
| 409 | rotation_conflict | Another key rotation won the race. | Re-read the chatbot and retry. |
| 404 | session_not_found | Chat session not found. | Check sid. |
| 413 | document_too_large | KB document over the size limit. | Upload a smaller file. |
| 400 | empty_document | KB document is empty. | Upload a non-empty file. |
| 415 | unsupported_document_type | KB document type not supported. | Upload a supported document type. |
| 503 | document_storage_unavailable | Document storage is unavailable. | Contact support. |
| 502 | document_storage_failed | Storing the document failed. | Retry. |
| 502 | document_ingest_unavailable | The document could not be queued for processing. | Retry. |
| 404 | kb_document_not_found | KB document not found. | Check docId. |
Billing
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400 | invalid_cursor | Ledger cursor invalid. | Use nextCursor from the previous page. |
| 400 | invalid_custom_range | Custom ledger range missing or reversed. | Send from < to. |
| 409 | no_recharge_found | ’Since last recharge’ range requested but no recharge exists. | Choose another range. |
| 400 | invalid_order_id | orderId path param invalid. | Use a valid order id. |
| 404 | recharge_not_found | Recharge not found in this workspace. | Check orderId. |
| 409 | receipt_not_available | Recharge not CREDITED yet. | Wait until payment is credited. |
CRM & integrations
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400, 404 | crm_connection_not_found | CRM connection not found (400 on campaign create: missing or not ACTIVE; 404 on CRM routes). | Use an active CRM connection id. |
| 400 | crm_connection_not_active | CRM connection exists but is not ACTIVE. | Reconnect the CRM. |
| 404 | unknown_crm | CRM slug not recognised. | Use a slug from GET /crm/providers. |
| 400 | provider_not_api_key | This CRM uses OAuth, not API-key connect. | Use the OAuth connect flow. |
| 400 | invalid_credentials | The credentials for the connected service (CRM, integration or messaging account) were rejected. message has details. | Re-enter valid credentials. |
| 404 | crm_resource_not_found | The CRM returned not found. | Check the resource or segment in the CRM. |
| 502 | crm_upstream_unavailable | CRM unreachable. | Retry later. |
| 502 | crm_upstream_error | Unexpected CRM response. | Retry; contact support if persistent. |
| 400 | webhooks_not_supported | This CRM does not support webhooks. | Use manual imports. |
| 400 | invalid_mapping_target | Field mapping target invalid. | See message. |
| 400 | invalid_mapping_source | Field mapping source invalid. | See message. |
| 404 | crm_import_not_found | CRM import not found. | Check the import id. |
| 400 | template_or_preset_required | Order-notification rule has neither template nor preset. | Set templateId or preset. |
| 400 | invalid_redirect_uri | Integration redirect URL not allowed. | Use an allowed redirect URL. |
| 400 | tool_requires_oauth | Integration uses OAuth, not API key. | Use the connect link flow. |
| 400 | invalid_tool | Integration slug not available. | Use a listed integration. |
| 400 | invalid_input | Integration input rejected. | Fix the input per message. |
| 409 | workspace_archived | Integration sub-account archived. | Contact support. |
Calendar & live sheets
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400 | google_oauth_not_configured | Google OAuth client not configured. | Contact support. |
| 400 | google_not_connected | No Google Calendar connection. | Connect Google Calendar first. |
| 400 | google_token_unavailable | Stored Google token has no refresh token. | Reconnect Google. |
| 400 | sheets_not_connected | No active Google Sheets connection. | Connect Google Sheets. |
| 400 | invalid_sheet_url | Spreadsheet URL not parseable. | Paste a full Google Sheets URL. |
| 409 | sheet_already_linked | Campaign already has a sheet. | Unlink first. |
| 404 | sheet_not_linked | Campaign has no sheet link. | Create or attach a sheet first. |
| 400 | sheet_rebuild_attached_forbidden | Attached (client-owned) sheets cannot be rebuilt. | Only rebuild generated sheets. |
| 502 | sheet_rebuild_tab_not_created | New tab creation failed on rebuild. | Retry. |
| 400 | sheet_columns_required | Layout has no columns. | Add columns. |
| 400 | sheet_phone_column_required | Layout lacks a phone column. | Include the phone column. |
| 400 | sheet_column_label_required | A column has an empty label. | Label every column. |
| 400 | duplicate_sheet_column | Duplicate column key. | Remove the duplicate. |
| 400 | duplicate_sheet_header | Duplicate header label. | Use unique labels. |
| 400 | unknown_sheet_column | Column key not in the field catalog. | Use keys from /sheet/configuration. |
| 400 | attached_identity_column_not_writable | Identity column not writable on attached sheets. | Remove that column. |
| 400 | sheet_match_column_required | Attached sheet needs a valid matchColumn. | Pass a matchColumn that exists in the header. |
| 400 | sheet_header_collision | Managed labels collide with existing sheet headers. | Rename the columns. |
| 409 | sheet_match_column_missing | Match column no longer in the sheet. | Restore the column or update matchColumn. |
| 409 | sheet_lead_id_missing | Sheet rows lack lead ids. | See message. |
| 400 | sheet_not_found | Google says the spreadsheet does not exist. | Check the link. |
| 400 | sheet_forbidden | Connected Google account cannot access the sheet. | Share the sheet with the connected account. |
| 400 | google_sheets_error | Other Google Sheets write or read failure. | Read message; retry. |
Result webhooks
| Status | error | Meaning | Fix |
|---|---|---|---|
| 404 | webhook_endpoint_not_found | Result webhook endpoint not found. | Check the id. |
| 404 | webhook_delivery_not_found | Delivery not found. | Check the id. |
| Status | error | Meaning | Fix |
|---|---|---|---|
| 502 | llm_not_configured | AI analysis is not available right now. | Contact support. |
| 404 | sender_not_found | WhatsApp sender not found. | Check the id. |
| 400 | cannot_disconnect_shared | Shared or platform senders cannot be disconnected. | None. |
| 400 | tag_required | Collection tag missing. | Provide a tag. |
| 404 | collection_not_found | Media collection not found. | Check the id. |
| 404 | media_item_not_found | Media item not found. | Check the id. |
| 404 | item_not_found | Media item not found. | Check itemId. |
| 400 | invalid_url | Media URL not https. | Use an https URL. |
| 400 | invalid_kind | TEXT is not a media kind. | Use IMAGE, DOCUMENT, VIDEO or AUDIO. |
| 400 | unsupported_type | File type not allowed. | Upload image, document, video or audio. |
| 404 | preset_not_found | Template preset not found. | Check the id. |
| 409 | template_already_exists | Template name already exists. | Choose another name. |
| 400 | template_sender_invalid | Template’s sender is invalid. | Pick a valid sender. |
| 400 | template_already_approved | Template is already approved. | No action needed. |
| 400 | template_invalid | Template components fail validation (issues included). | Fix the issues and resubmit. |
| 400 | template_media_missing | Media-header template has no uploaded attachment. | Upload the attachment first. |
| 400 | template_media_review_failed | The attachment was saved but could not be prepared for review. | Re-upload the attachment and submit again. |
| 400 | status_is_provider_managed | Template status is synced automatically and cannot be set by hand. | Use POST /whatsapp/templates/{id}/sync-status. |
| 400 | no_file | No file uploaded for template media. | Attach a file. |
| 404 | conversation_not_found | Conversation not found. | Check the id. |
| 400 | text_required | Message body empty. | Provide text. |
| 400 | template_required | Free-form text can’t be sent to this conversation right now. | Send an approved template. |
| 400 | unsupported_media_type | Media type not sendable. | Use a supported type. |
| 400 | media_too_large | Media exceeds the per-kind limit. | Send a smaller file. |
| 400 | window_closed | 24h customer-service window closed. | Send a template message instead. |
| 400 | no_sender_available | No usable WhatsApp sender for the workspace. | Connect a sender. |
| 400 | template_sender_mismatch | The template was approved for a different WhatsApp business account. | Use a template approved for this sender. |
| 400 | collection_empty | Collection has no items. | Add items. |
| 429 | send_cap_reached | Daily WhatsApp send cap reached. | Retry tomorrow or contact support. |
| 404 | message_not_found | Message not found. | Check the id. |
| 409 | message_not_outbound | Only outbound messages can be retried. | None. |
| 409 | message_not_failed | Only FAILED messages can be retried. | None. |
| 409 | sender_unavailable | Original sender gone or revoked. | Reconnect a sender and send anew. |
| 409 | message_already_retried | Message already retried. | Retry the newer message. |
| 400 | template_not_configured | Campaign or flow has no template configured. | Configure a template. |
| 500 | template_binding_unresolved | A template variable could not be filled. Currently returned as 500. | Provide the lead fields the template uses. |
| 402 | provider_wallet_empty | The WhatsApp messaging account has no balance. | Contact Pineyard. |
| 403 | account_restricted | The WhatsApp messaging account is restricted. | Contact Pineyard. |
| 502 | upstream_unavailable | A connected service (messaging or speech) is unavailable. | Retry later. |
| 500 | invalid_response | A connected service returned an unusable response. | Retry. |
| 500 | unknown | Unclassified upstream failure. | Retry; contact support. |
| 400 | invalid_whatsapp_media_templates | Some agent templates are not approved or have no media. | Use approved templates with media (templateIds lists the rejected ones). |
| 400 | invalid_whatsapp_payment_template | Payment template missing, not approved, or lacks a payment-link button. | Pick an approved template with a payment-link button. |
Speech analysis
| Status | error | Meaning | Fix |
|---|---|---|---|
| 400 | files_required | Bulk upload without files. | Attach files. |
| 400 | file_empty | Uploaded recording is empty. | Upload a non-empty file. |
| 404 | rep_not_found | Rep not found. | Check the id. |
| 404 | scorecard_not_found | Scorecard not found. | Check the id. |
| 409 | not_retryable | Only FAILED analyses can be retried. | None. |
| 409 | audio_missing | Stored recording gone. | Upload again. |
| 400 | name_required | Team or rep name missing. | Provide a name. |
| 400 | email_required | Rep email missing. | Provide an email. |
| 409 | team_exists | Team name already used. | Choose another name. |
| 404 | team_not_found | Team not found. | Check the id. |
| 409 | rep_exists | Rep email already used. | Use another email. |
| 502 | provider_no_member_id | The rep could not be created. | Retry. |
| 400 | call_required | Neither callId nor campaignContactId was given. | Pass one. |
| 409 | already_analysed | Call already analysed. | None. |
| 422 | no_recording | Call has no available recording. | Only analyse recorded calls. |
| 422 | no_agent | Call has no agent. | None. |
| 502 | recording_fetch_failed | Recording download failed. | Retry. |
| 503 | not_configured | Speech analysis is not available right now. | Contact support. |
| 502 | conflict | Speech analysis could not complete the request. | Retry; contact support if it persists. |
| 502 | upstream_error | Speech analysis failed unexpectedly. | Retry. |

