> ## Documentation Index
> Fetch the complete documentation index at: https://docs.poly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error codes

> HTTP status codes and platform-specific error codes returned by PolyAI APIs.

When a request fails, PolyAI APIs return a structured JSON error response. This page documents the HTTP status codes, error response format, and platform-specific error codes you may encounter.

64 platform error codes span the categories below — jump straight to yours:

{[
    { label: 'Authentication', icon: 'key', href: '#auth' },
    { label: 'Conversations', icon: 'messages', href: '#conversations' },
    { label: 'Chat', icon: 'comment', href: '#chat' },
    { label: 'Deployments', icon: 'rocket', href: '#deployments' },
    { label: 'Flows', icon: 'diagram-project', href: '#flows' },
    { label: 'Functions', icon: 'code', href: '#functions' },
    { label: 'Knowledge base', icon: 'book', href: '#knowledge-base' },
    { label: 'Phone & connectors', icon: 'phone', href: '#phone-numbers' },
    { label: 'Variants', icon: 'shuffle', href: '#variants' },
    { label: 'Real-time config', icon: 'sliders', href: '#real-time-config' },
    { label: 'Secrets', icon: 'key', href: '#secrets' },
    { label: 'Accounts & projects', icon: 'building', href: '#accounts-projects' },
    { label: 'SMS', icon: 'comment-sms', href: '#sms' },
    { label: 'Test suite', icon: 'flask-vial', href: '#test-suite' },
    ].map((c) => (
    <a key={c.href} href={c.href} style={{
      display: 'inline-flex',
      alignItems: 'center',
      gap: '0.4rem',
      padding: '0.4rem 0.85rem',
      borderRadius: '999px',
      border: '1px solid rgba(74, 124, 16, 0.22)',
      background: 'rgba(74, 124, 16, 0.05)',
      color: '#3a6b08',
      fontSize: '0.82rem',
      fontWeight: 600,
      textDecoration: 'none',
    }}>
      <Icon icon={c.icon} iconType="solid" size={12} color="#3a6b08" />
      {c.label}
    </a>
    ))}

## Error response format

All API errors return a JSON body with the following structure:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "success": false,
  "error": "Request body failed schema validation.",
  "error_id": "550e8400-e29b-41d4-a716-446655440000",
  "error_code": "SCHEMA_VALIDATION_FAILED",
  "error_message": "Request body failed schema validation.",
  "data": null
}
```

| Field | Type | Description |
| - | - | - |
| `success` | boolean | Always `false` for error responses. |
| `error` | string | Human-readable error message. |
| `error_id` | string | Unique request identifier from the `X-PolyAI-Correlation-Id` header. Include this when contacting support. |
| `error_code` | string | Machine-readable error code in `UPPER_SNAKE_CASE`. |
| `error_message` | string | Human-readable error message. |
| `data` | null | Always `null` for error responses. |

## Standard HTTP status codes

These standard codes apply across all PolyAI APIs. Client errors (4xx) mean fix the request; server errors (5xx) mean retry or contact support.

{[
    { status: 400, meaning: 'Bad request', when: 'The request body or query parameters failed validation.' },
    { status: 401, meaning: 'Unauthorized', when: 'Missing, expired, or invalid API key or token.' },
    { status: 403, meaning: 'Forbidden', when: 'You do not have permission for the requested action.' },
    { status: 404, meaning: 'Not found', when: 'The requested resource does not exist.' },
    { status: 405, meaning: 'Method not allowed', when: 'The HTTP method is not supported for this endpoint.' },
    { status: 408, meaning: 'Request timeout', when: 'The request exceeded the server timeout.' },
    { status: 409, meaning: 'Conflict', when: 'A resource with the same identifier already exists.' },
    { status: 410, meaning: 'Gone', when: 'The resource has been permanently deleted.' },
    { status: 412, meaning: 'Precondition failed', when: 'A required precondition was not met (for example, deploying to live before pre-release).' },
    { status: 415, meaning: 'Unsupported media type', when: 'The uploaded file type is not supported.' },
    { status: 422, meaning: 'Unprocessable entity', when: 'The request is well-formed but contains semantic errors.' },
    { status: 429, meaning: 'Too many requests', when: 'Rate limit exceeded. Retry after the period indicated in the response headers.' },
    { status: 500, meaning: 'Internal server error', when: 'An unexpected error occurred on the server.' },
    { status: 501, meaning: 'Not implemented', when: 'The requested functionality is not yet available.' },
    { status: 502, meaning: 'Bad gateway', when: 'An upstream service returned an error or timed out.' },
    { status: 503, meaning: 'Service unavailable', when: 'The service is temporarily unavailable.' },
    ].map((s) => {
    const isServerError = s.status >= 500
    const fg = isServerError ? '#a02020' : '#8a4517'
    const border = isServerError ? 'rgba(190, 40, 40, 0.22)' : 'rgba(180, 90, 30, 0.22)'
    const bg = isServerError ? 'rgba(190, 40, 40, 0.045)' : 'rgba(180, 90, 30, 0.045)'
    return (
      <div key={s.status} style={{
        padding: '0.9rem 1.1rem',
        borderRadius: '14px',
        border: `1px solid ${border}`,
        background: bg,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '0.65rem', marginBottom: '0.3rem' }}>
          <span style={{ fontWeight: 800, fontSize: '1.15rem', color: fg, fontVariantNumeric: 'tabular-nums' }}>{s.status}</span>
          <strong style={{ fontSize: '0.92rem', color: '#1f2937' }}>{s.meaning}</strong>
        </div>
        <div style={{ fontSize: '0.85rem', color: '#6b7280', lineHeight: 1.45 }}>{s.when}</div>
      </div>
    )
    })}

## Platform error codes

PolyAI APIs return domain-specific error codes alongside HTTP status codes. There are 63 of them across 13 categories — search by code, ID, or keyword below, or filter by HTTP status, instead of scanning tablesre are 63 of them across 13 categories — search by code, ID, or keyword below, or filter by HTTP status, instead of scanning tables. PolyAI APIs return domain-specific error codes alongside HTTP status codes. There are 63 of them across the 13 categories below — expand the category you're hitting, or use page search (Cmd/Ctrl+F) to jump straight to a code. PolyAI APIs return domain-specific error codes alongside HTTP status codes. There are 63 of them across the 13 categories below — expand the category you're hitting, or use page search (Cmd/Ctrl+F) to jump straight to a code.

63 platform error codes span the categories below — jump straight to yours:

{[
    { label: 'Authentication', icon: 'key', href: '#auth' },
    { label: 'Conversations', icon: 'messages', href: '#conversations' },
    { label: 'Chat', icon: 'comment', href: '#chat' },
    { label: 'Deployments', icon: 'rocket', href: '#deployments' },
    { label: 'Flows', icon: 'diagram-project', href: '#flows' },
    { label: 'Functions', icon: 'code', href: '#functions' },
    { label: 'Knowledge base', icon: 'book', href: '#knowledge-base' },
    { label: 'Phone & connectors', icon: 'phone', href: '#phone-numbers' },
    { label: 'Variants', icon: 'shuffle', href: '#variants' },
    { label: 'Real-time config', icon: 'sliders', href: '#real-time-config' },
    { label: 'Accounts & projects', icon: 'building', href: '#accounts-projects' },
    { label: 'SMS', icon: 'comment-sms', href: '#sms' },
    { label: 'Test suite', icon: 'flask-vial', href: '#test-suite' },
    ].map((c) => (
    <a key={c.href} href={c.href} style={{
      display: 'inline-flex',
      alignItems: 'center',
      gap: '0.4rem',
      padding: '0.4rem 0.85rem',
      borderRadius: '999px',
      border: '1px solid rgba(74, 124, 16, 0.22)',
      background: 'rgba(74, 124, 16, 0.05)',
      color: '#3a6b08',
      fontSize: '0.82rem',
      fontWeight: 600,
      textDecoration: 'none',
    }}>
      <Icon icon={c.icon} iconType="solid" size={12} color="#3a6b08" />
      {c.label}
    </a>
    ))}

## Error response format

All API errors return a JSON body with the following structure:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "success": false,
  "error": "Request body failed schema validation.",
  "error_id": "550e8400-e29b-41d4-a716-446655440000",
  "error_code": "SCHEMA_VALIDATION_FAILED",
  "error_message": "Request body failed schema validation.",
  "data": null
}
```

| Field | Type | Description |
| - | - | - |
| `success` | boolean | Always `false` for error responses. |
| `error` | string | Human-readable error message. |
| `error_id` | string | Unique request identifier from the `X-PolyAI-Correlation-Id` header. Include this when contacting support. |
| `error_code` | string | Machine-readable error code in `UPPER_SNAKE_CASE`. |
| `error_message` | string | Human-readable error message. |
| `data` | null | Always `null` for error responses. |

## Standard HTTP status codes

These standard codes apply across all PolyAI APIs. Client errors (4xx) mean fix the request; server errors (5xx) mean retry or contact support.

{[
    { status: 400, meaning: 'Bad request', when: 'The request body or query parameters failed validation.' },
    { status: 401, meaning: 'Unauthorized', when: 'Missing, expired, or invalid API key or token.' },
    { status: 403, meaning: 'Forbidden', when: 'You do not have permission for the requested action.' },
    { status: 404, meaning: 'Not found', when: 'The requested resource does not exist.' },
    { status: 405, meaning: 'Method not allowed', when: 'The HTTP method is not supported for this endpoint.' },
    { status: 408, meaning: 'Request timeout', when: 'The request exceeded the server timeout.' },
    { status: 409, meaning: 'Conflict', when: 'A resource with the same identifier already exists.' },
    { status: 410, meaning: 'Gone', when: 'The resource has been permanently deleted.' },
    { status: 412, meaning: 'Precondition failed', when: 'A required precondition was not met (for example, deploying to live before pre-release).' },
    { status: 415, meaning: 'Unsupported media type', when: 'The uploaded file type is not supported.' },
    { status: 422, meaning: 'Unprocessable entity', when: 'The request is well-formed but contains semantic errors.' },
    { status: 429, meaning: 'Too many requests', when: 'Rate limit exceeded. Retry after the period indicated in the response headers.' },
    { status: 500, meaning: 'Internal server error', when: 'An unexpected error occurred on the server.' },
    { status: 501, meaning: 'Not implemented', when: 'The requested functionality is not yet available.' },
    { status: 502, meaning: 'Bad gateway', when: 'An upstream service returned an error or timed out.' },
    { status: 503, meaning: 'Service unavailable', when: 'The service is temporarily unavailable.' },
    ].map((s) => {
    const isServerError = s.status >= 500
    const fg = isServerError ? '#a02020' : '#8a4517'
    const border = isServerError ? 'rgba(190, 40, 40, 0.22)' : 'rgba(180, 90, 30, 0.22)'
    const bg = isServerError ? 'rgba(190, 40, 40, 0.045)' : 'rgba(180, 90, 30, 0.045)'
    return (
      <div key={s.status} style={{
        padding: '0.9rem 1.1rem',
        borderRadius: '14px',
        border: `1px solid ${border}`,
        background: bg,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '0.65rem', marginBottom: '0.3rem' }}>
          <span style={{ fontWeight: 800, fontSize: '1.15rem', color: fg, fontVariantNumeric: 'tabular-nums' }}>{s.status}</span>
          <strong style={{ fontSize: '0.92rem', color: '#1f2937' }}>{s.meaning}</strong>
        </div>
        <div style={{ fontSize: '0.85rem', color: '#6b7280', lineHeight: 1.45 }}>{s.when}</div>
      </div>
    )
    })}

## Platform error codes

PolyAI APIs return domain-specific error codes alongside HTTP status codes. There are 63 of them across 13 categories — search by code, ID, or keyword below, or filter by HTTP status, instead of scanning tablesre are 63 of them across 13 categories — search by code, ID, or keyword below, or filter by HTTP status, instead of scanning tables. PolyAI APIs return domain-specific error codes alongside HTTP status codes. There are 63 of them across the 13 categories below — expand the category you're hitting, or use page search (Cmd/Ctrl+F) to jump straight to a code. PolyAI APIs return domain-specific error codes alongside HTTP status codes. There are 63 of them across the 13 categories below — expand the category you're hitting, or use page search (Cmd/Ctrl+F) to jump straight to a code.

Showing  of  error codes

Expand the category you're hitting, or use one of the jump links above.

> [accordion] Authentication and authorization
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `AUTH_USER_NOT_FOUND` | 3001 | 401 | User not found in the auth system. |
> | `AUTH_USER_UNAUTHORISED` | 3002 | 401 | Invalid credentials or expired session. |
> | `AUTH_USER_INVALID_TOKEN` | 3003 | 401 | Token is malformed, expired, or revoked. |
> | `USER_ACCESS_FORBIDDEN` | 2 | 403 | User lacks permission for the requested action. |
> | `EXTERNAL_USER_FORBIDDEN` | 3 | 403 | External user privilege level is too low. |
> | `ACCOUNT_INSUFFICIENT_PERMISSIONS` | 1003 | 403 | User lacks permissions for this account operation. |

> [accordion] Conversations
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CONVERSATIONS_NOT_FOUND` | 5001 | 404 | Conversation ID does not exist. |
> | `CONVERSATIONS_VALIDATION_FAILED` | 5002 | 400 | Conversation request body failed validation. |
> | `CONVERSATIONS_RECORDING_NOT_FOUND` | 5003 | 404 | Audio recording not found for this conversation. |
> | `GET_CONVERSATIONS_FILTER_PARSE_ERROR` | — | 400 | Filter expression syntax is invalid. |
> | `GET_CONVERSATIONS_INVALID_SORT_PARAMETER` | — | 400 | Sort field is not in the allowed set. |

> [accordion] Chat
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CHAT_DRAFT_NOT_EXIST` | 4001 | 400 | The draft you are attempting to chat with does not exist. |
> | `CHAT_TIMEOUT` | 4002 | 400 | Chat session exceeded the timeout limit. |
> | `CHAT_DRAFT_DEPLOYMENT_FAILED` | 4003 | 500 | Draft auto-deploy failed before the chat could start. |
> | `ChatConversationEnded` | — | 410 | You sent a message to a conversation that has already ended. |

> [accordion] Deployments
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `DEPLOYMENT_NOT_FOUND` | 6001 | 404 | Deployment ID does not exist. |
> | `DEPLOYMENTS_ALREADY_PUBLISHED` | 6009 | 409 | Draft is already published to the target environment. |
> | `DEPLOYMENTS_ENVIRONMENT_ALREADY_PUBLISHED` | 6002 | 200 | Environment already has this version (idempotent). |
> | `DEPLOYMENTS_VALIDATION_FAILED` | 6007 | 400 | Request body validation failed. |
> | `DEPLOYMENTS_INVALID_ENVIRONMENT` | 6008 | 400 | Invalid or missing `environment` query parameter. |
> | `ErrPreReleaseNotReady` | — | 412 | You must deploy to pre-release before promoting to live. |

> [accordion] Flows
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FLOW_NOT_FOUND` | 8001 | 404 | Flow ID does not exist. |
> | `FLOWS_NAME_ALREADY_EXISTS` | 8003 | 409 | A flow with this name already exists. |
> | `FLOWS_FUNCTION_NAME_ALREADY_EXISTS` | 8004 | 409 | A function with this name already exists in the flow. |
> | `FLOWS_RESERVED_PARAMETER_NAME` | 8005 | 400 | You used a reserved parameter name. |
> | `FLOWS_RESERVED_FUNCTION_NAME` | 8006 | 400 | You used a reserved function name. |

> [accordion] Functions
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FUNCTION_NOT_FOUND` | 9001 | 404 | Function ID does not exist. |
> | `FUNCTIONS_DEPLOYMENT_HAS_ERRORS` | 9004 | 400 | Function code contains errors that prevent deployment. |
> | `FUNCTION_EXECUTION_FAILED` | 9006 | 400 | Function encountered a runtime execution error. |
> | `FUNCTION_FAILED_TO_PARSE` | 9007 | 400 | Function source code has parse errors. |
> | `FUNCTION_NAME_ALREADY_EXISTS` | 9009 | 409 | A function with this name already exists. |
> | `FUNCTIONS_RESERVED_NAME` | 9010 | 400 | You used a system-reserved function name. |

> [accordion] Knowledge base
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `KNOWLEDGE_BASE_TOPIC_ALREADY_EXISTS` | 11001 | 409 | A topic with this name already exists. |
> | `KNOWLEDGE_BASE_IMPORT_NO_CSV_FOUND` | 11002 | 400 | No CSV file found in the import request. |
> | `KNOWLEDGE_BASE_IMPORT_INVALID_TYPE` | 11003 | 415 | The uploaded file type is not supported. |
> | `KNOWLEDGE_BASE_IMPORT_MISSING_COLUMNS` | 11004 | 400 | Required columns are missing from the CSV import. |
> | `KNOWLEDGE_BASE_TOPICS_INVALID` | 11005 | 400 | Topic data failed validation. |
> | `KNOWLEDGE_BASE_RICH_TEXT_INVALID` | 11006 | 400 | Rich text markup is malformed or references a missing entity. |

> [accordion] Phone numbers and connectors
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `PHONE_NUMBERS_NOT_FOUND` | 14006 | 404 | Phone number does not exist. |
> | `PHONE_NUMBERS_ALREADY_EXISTS` | 14007 | 409 | Phone number has already been imported. |
> | `PHONE_NUMBERS_INVALID_PHONE_NUMBER_FORMAT` | 14003 | 400 | Number is not in valid E.164 format. |
> | `PHONE_NUMBERS_CONNECTOR_DOES_NOT_EXIST` | 14005 | 404 | Referenced connector not found. |
> | `CONNECTORS_NOT_FOUND` | 14100 | 404 | Connector ID does not exist. |
> | `CONNECTORS_VALIDATION_FAILED` | 14101 | 400 | Connector request body failed validation. |

> [accordion] Variants
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `VARIANTS_BAD_ATTRIBUTES_ERROR` | 26001 | 400 | Attribute values do not match the expected schema. |
> | `VARIANTS_DUPLICATE_NAME_ERROR` | 26002 | 409 | A variant with this name already exists. |
> | `VARIANTS_REMOVE_DEFAULT_ERROR` | 26003 | 400 | You cannot remove the default variant. |
> | `VariantsImportInvalidDelimiter` | — | 400 | CSV delimiter not recognized. |
> | `VariantImportMissingColumnsHttp` | — | 400 | CSV is missing required columns. |
> | `VariantImportDuplicateColumnsHttp` | — | 400 | CSV has duplicate column headers. |

> [accordion] Real-time configuration
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `REAL_TIME_CONFIG_FORBIDDEN_ACCESS` | 29001 | 403 | Not authorized to access real-time configs. |
> | `REAL_TIME_CONFIG_INVALID_FOR_SCHEMA` | 29002 | 400 | Config values fail JSON Schema validation. |
> | `REAL_TIME_CONFIG_INVALID_SCHEMA` | 29004 | 400 | JSON Schema definition is invalid. |
> | `REAL_TIME_CONFIG_UNKNOWN_CLIENT_ENVIRONMENT` | 29006 | 400 | Client environment is not one of `sandbox`, `pre-release`, or `live`. |

> [accordion] Secrets
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `SECRETS_NOT_FOUND` | 21001 | 404 | Secret does not exist in this account. |

> [accordion] Accounts and projects
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `ACCOUNT_NOT_FOUND` | 1002 | 404 | Account ID does not exist. |
> | `ACCOUNT_CREATE_INVALID_ID` | 1004 | 400 | Account ID contains non-alphanumeric characters or is too similar to an existing ID. |
> | `ACCOUNT_CREATE_EXISTING_ID` | 1006 | 409 | Account ID is already taken. |
> | `PROJECT_NOT_FOUND` | 15001 | 404 | Project ID does not exist. |
> | `PROJECT_ID_ALREADY_EXISTS` | 15005 | 409 | Project ID is already taken. |
> | `PROJECT_ID_INVALID` | 15006 | 400 | Project ID does not meet format requirements. |

> [accordion] SMS
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `SMS_TEMPLATE_NOT_FOUND` | 20001 | 404 | SMS template ID does not exist. |

> [accordion] Test suite
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `MissingTestCasesHttp` | — | 422 | One or more test case IDs were not found. |
> | `NoTestCasesHttp` | — | 422 | No test cases exist for this project. |

Showing  of  error codes

> [accordion] Authentication and authorization
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `AUTH_USER_NOT_FOUND` | 3001 | 401 | User not found in the auth system. |
> | `AUTH_USER_UNAUTHORISED` | 3002 | 401 | Invalid credentials or expired session. |
> | `AUTH_USER_INVALID_TOKEN` | 3003 | 401 | Token is malformed, expired, or revoked. |
> | `USER_ACCESS_FORBIDDEN` | 2 | 403 | User lacks permission for the requested action. |
> | `EXTERNAL_USER_FORBIDDEN` | 3 | 403 | External user privilege level is too low. |
> | `ACCOUNT_INSUFFICIENT_PERMISSIONS` | 1003 | 403 | User lacks permissions for this account operation. |

> [accordion] Conversations
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CONVERSATIONS_NOT_FOUND` | 5001 | 404 | Conversation ID does not exist. |
> | `CONVERSATIONS_VALIDATION_FAILED` | 5002 | 400 | Conversation request body failed validation. |
> | `CONVERSATIONS_RECORDING_NOT_FOUND` | 5003 | 404 | Audio recording not found for this conversation. |
> | `GET_CONVERSATIONS_FILTER_PARSE_ERROR` | — | 400 | Filter expression syntax is invalid. |
> | `GET_CONVERSATIONS_INVALID_SORT_PARAMETER` | — | 400 | Sort field is not in the allowed set. |

> [accordion] Chat
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CHAT_DRAFT_NOT_EXIST` | 4001 | 400 | The draft you are attempting to chat with does not exist. |
> | `CHAT_TIMEOUT` | 4002 | 400 | Chat session exceeded the timeout limit. |
> | `CHAT_DRAFT_DEPLOYMENT_FAILED` | 4003 | 500 | Draft auto-deploy failed before the chat could start. |
> | `ChatConversationEnded` | — | 410 | You sent a message to a conversation that has already ended. |

> [accordion] Deployments
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `DEPLOYMENT_NOT_FOUND` | 6001 | 404 | Deployment ID does not exist. |
> | `DEPLOYMENTS_ALREADY_PUBLISHED` | 6009 | 409 | Draft is already published to the target environment. |
> | `DEPLOYMENTS_ENVIRONMENT_ALREADY_PUBLISHED` | 6002 | 200 | Environment already has this version (idempotent). |
> | `DEPLOYMENTS_VALIDATION_FAILED` | 6007 | 400 | Request body validation failed. |
> | `DEPLOYMENTS_INVALID_ENVIRONMENT` | 6008 | 400 | Invalid or missing `environment` query parameter. |
> | `ErrPreReleaseNotReady` | — | 412 | You must deploy to pre-release before promoting to live. |

> [accordion] Flows
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FLOW_NOT_FOUND` | 8001 | 404 | Flow ID does not exist. |
> | `FLOWS_NAME_ALREADY_EXISTS` | 8003 | 409 | A flow with this name already exists. |
> | `FLOWS_FUNCTION_NAME_ALREADY_EXISTS` | 8004 | 409 | A function with this name already exists in the flow. |
> | `FLOWS_RESERVED_PARAMETER_NAME` | 8005 | 400 | You used a reserved parameter name. |
> | `FLOWS_RESERVED_FUNCTION_NAME` | 8006 | 400 | You used a reserved function name. |

> [accordion] Functions
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FUNCTION_NOT_FOUND` | 9001 | 404 | Function ID does not exist. |
> | `FUNCTIONS_DEPLOYMENT_HAS_ERRORS` | 9004 | 400 | Function code contains errors that prevent deployment. |
> | `FUNCTION_EXECUTION_FAILED` | 9006 | 400 | Function encountered a runtime execution error. |
> | `FUNCTION_FAILED_TO_PARSE` | 9007 | 400 | Function source code has parse errors. |
> | `FUNCTION_NAME_ALREADY_EXISTS` | 9009 | 409 | A function with this name already exists. |
> | `FUNCTIONS_RESERVED_NAME` | 9010 | 400 | You used a system-reserved function name. |

> [accordion] Knowledge base
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `KNOWLEDGE_BASE_TOPIC_ALREADY_EXISTS` | 11001 | 409 | A topic with this name already exists. |
> | `KNOWLEDGE_BASE_IMPORT_NO_CSV_FOUND` | 11002 | 400 | No CSV file found in the import request. |
> | `KNOWLEDGE_BASE_IMPORT_INVALID_TYPE` | 11003 | 415 | The uploaded file type is not supported. |
> | `KNOWLEDGE_BASE_IMPORT_MISSING_COLUMNS` | 11004 | 400 | Required columns are missing from the CSV import. |
> | `KNOWLEDGE_BASE_TOPICS_INVALID` | 11005 | 400 | Topic data failed validation. |
> | `KNOWLEDGE_BASE_RICH_TEXT_INVALID` | 11006 | 400 | Rich text markup is malformed or references a missing entity. |

> [accordion] Phone numbers and connectors
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `PHONE_NUMBERS_NOT_FOUND` | 14006 | 404 | Phone number does not exist. |
> | `PHONE_NUMBERS_ALREADY_EXISTS` | 14007 | 409 | Phone number has already been imported. |
> | `PHONE_NUMBERS_INVALID_PHONE_NUMBER_FORMAT` | 14003 | 400 | Number is not in valid E.164 format. |
> | `PHONE_NUMBERS_CONNECTOR_DOES_NOT_EXIST` | 14005 | 404 | Referenced connector not found. |
> | `CONNECTORS_NOT_FOUND` | 14100 | 404 | Connector ID does not exist. |
> | `CONNECTORS_VALIDATION_FAILED` | 14101 | 400 | Connector request body failed validation. |

> [accordion] Variants
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `VARIANTS_BAD_ATTRIBUTES_ERROR` | 26001 | 400 | Attribute values do not match the expected schema. |
> | `VARIANTS_DUPLICATE_NAME_ERROR` | 26002 | 409 | A variant with this name already exists. |
> | `VARIANTS_REMOVE_DEFAULT_ERROR` | 26003 | 400 | You cannot remove the default variant. |
> | `VariantsImportInvalidDelimiter` | — | 400 | CSV delimiter not recognized. |
> | `VariantImportMissingColumnsHttp` | — | 400 | CSV is missing required columns. |
> | `VariantImportDuplicateColumnsHttp` | — | 400 | CSV has duplicate column headers. |

> [accordion] Real-time configuration
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `REAL_TIME_CONFIG_FORBIDDEN_ACCESS` | 29001 | 403 | Not authorized to access real-time configs. |
> | `REAL_TIME_CONFIG_INVALID_FOR_SCHEMA` | 29002 | 400 | Config values fail JSON Schema validation. |
> | `REAL_TIME_CONFIG_INVALID_SCHEMA` | 29004 | 400 | JSON Schema definition is invalid. |
> | `REAL_TIME_CONFIG_UNKNOWN_CLIENT_ENVIRONMENT` | 29006 | 400 | Client environment is not one of `sandbox`, `pre-release`, or `live`. |

> [accordion] Accounts and projects
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `ACCOUNT_NOT_FOUND` | 1002 | 404 | Account ID does not exist. |
> | `ACCOUNT_CREATE_INVALID_ID` | 1004 | 400 | Account ID contains non-alphanumeric characters or is too similar to an existing ID. |
> | `ACCOUNT_CREATE_EXISTING_ID` | 1006 | 409 | Account ID is already taken. |
> | `PROJECT_NOT_FOUND` | 15001 | 404 | Project ID does not exist. |
> | `PROJECT_ID_ALREADY_EXISTS` | 15005 | 409 | Project ID is already taken. |
> | `PROJECT_ID_INVALID` | 15006 | 400 | Project ID does not meet format requirements. |

> [accordion] SMS
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `SMS_TEMPLATE_NOT_FOUND` | 20001 | 404 | SMS template ID does not exist. |

> [accordion] Test suite
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `MissingTestCasesHttp` | — | 422 | One or more test case IDs were not found. |
> | `NoTestCasesHttp` | — | 422 | No test cases exist for this project. |

Expand the category you're hitting, or use one of the jump links above.

> [accordion] Authentication and authorization
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `AUTH_USER_NOT_FOUND` | 3001 | 401 | User not found in the auth system. |
> | `AUTH_USER_UNAUTHORISED` | 3002 | 401 | Invalid credentials or expired session. |
> | `AUTH_USER_INVALID_TOKEN` | 3003 | 401 | Token is malformed, expired, or revoked. |
> | `USER_ACCESS_FORBIDDEN` | 2 | 403 | User lacks permission for the requested action. |
> | `EXTERNAL_USER_FORBIDDEN` | 3 | 403 | External user privilege level is too low. |
> | `ACCOUNT_INSUFFICIENT_PERMISSIONS` | 1003 | 403 | User lacks permissions for this account operation. |

> [accordion] Conversations
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CONVERSATIONS_NOT_FOUND` | 5001 | 404 | Conversation ID does not exist. |
> | `CONVERSATIONS_VALIDATION_FAILED` | 5002 | 400 | Conversation request body failed validation. |
> | `CONVERSATIONS_RECORDING_NOT_FOUND` | 5003 | 404 | Audio recording not found for this conversation. |
> | `GET_CONVERSATIONS_FILTER_PARSE_ERROR` | — | 400 | Filter expression syntax is invalid. |
> | `GET_CONVERSATIONS_INVALID_SORT_PARAMETER` | — | 400 | Sort field is not in the allowed set. |

> [accordion] Chat
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CHAT_DRAFT_NOT_EXIST` | 4001 | 400 | The draft you are attempting to chat with does not exist. |
> | `CHAT_TIMEOUT` | 4002 | 400 | Chat session exceeded the timeout limit. |
> | `CHAT_DRAFT_DEPLOYMENT_FAILED` | 4003 | 500 | Draft auto-deploy failed before the chat could start. |
> | `ChatConversationEnded` | — | 410 | You sent a message to a conversation that has already ended. |

> [accordion] Deployments
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `DEPLOYMENT_NOT_FOUND` | 6001 | 404 | Deployment ID does not exist. |
> | `DEPLOYMENTS_ALREADY_PUBLISHED` | 6009 | 409 | Draft is already published to the target environment. |
> | `DEPLOYMENTS_ENVIRONMENT_ALREADY_PUBLISHED` | 6002 | 200 | Environment already has this version (idempotent). |
> | `DEPLOYMENTS_VALIDATION_FAILED` | 6007 | 400 | Request body validation failed. |
> | `DEPLOYMENTS_INVALID_ENVIRONMENT` | 6008 | 400 | Invalid or missing `environment` query parameter. |
> | `ErrPreReleaseNotReady` | — | 412 | You must deploy to pre-release before promoting to live. |

> [accordion] Flows
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FLOW_NOT_FOUND` | 8001 | 404 | Flow ID does not exist. |
> | `FLOWS_NAME_ALREADY_EXISTS` | 8003 | 409 | A flow with this name already exists. |
> | `FLOWS_FUNCTION_NAME_ALREADY_EXISTS` | 8004 | 409 | A function with this name already exists in the flow. |
> | `FLOWS_RESERVED_PARAMETER_NAME` | 8005 | 400 | You used a reserved parameter name. |
> | `FLOWS_RESERVED_FUNCTION_NAME` | 8006 | 400 | You used a reserved function name. |

> [accordion] Functions
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FUNCTION_NOT_FOUND` | 9001 | 404 | Function ID does not exist. |
> | `FUNCTIONS_DEPLOYMENT_HAS_ERRORS` | 9004 | 400 | Function code contains errors that prevent deployment. |
> | `FUNCTION_EXECUTION_FAILED` | 9006 | 400 | Function encountered a runtime execution error. |
> | `FUNCTION_FAILED_TO_PARSE` | 9007 | 400 | Function source code has parse errors. |
> | `FUNCTION_NAME_ALREADY_EXISTS` | 9009 | 409 | A function with this name already exists. |
> | `FUNCTIONS_RESERVED_NAME` | 9010 | 400 | You used a system-reserved function name. |

> [accordion] Knowledge base
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `KNOWLEDGE_BASE_TOPIC_ALREADY_EXISTS` | 11001 | 409 | A topic with this name already exists. |
> | `KNOWLEDGE_BASE_IMPORT_NO_CSV_FOUND` | 11002 | 400 | No CSV file found in the import request. |
> | `KNOWLEDGE_BASE_IMPORT_INVALID_TYPE` | 11003 | 415 | The uploaded file type is not supported. |
> | `KNOWLEDGE_BASE_IMPORT_MISSING_COLUMNS` | 11004 | 400 | Required columns are missing from the CSV import. |
> | `KNOWLEDGE_BASE_TOPICS_INVALID` | 11005 | 400 | Topic data failed validation. |
> | `KNOWLEDGE_BASE_RICH_TEXT_INVALID` | 11006 | 400 | Rich text markup is malformed or references a missing entity. |

> [accordion] Phone numbers and connectors
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `PHONE_NUMBERS_NOT_FOUND` | 14006 | 404 | Phone number does not exist. |
> | `PHONE_NUMBERS_ALREADY_EXISTS` | 14007 | 409 | Phone number has already been imported. |
> | `PHONE_NUMBERS_INVALID_PHONE_NUMBER_FORMAT` | 14003 | 400 | Number is not in valid E.164 format. |
> | `PHONE_NUMBERS_CONNECTOR_DOES_NOT_EXIST` | 14005 | 404 | Referenced connector not found. |
> | `CONNECTORS_NOT_FOUND` | 14100 | 404 | Connector ID does not exist. |
> | `CONNECTORS_VALIDATION_FAILED` | 14101 | 400 | Connector request body failed validation. |

> [accordion] Variants
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `VARIANTS_BAD_ATTRIBUTES_ERROR` | 26001 | 400 | Attribute values do not match the expected schema. |
> | `VARIANTS_DUPLICATE_NAME_ERROR` | 26002 | 409 | A variant with this name already exists. |
> | `VARIANTS_REMOVE_DEFAULT_ERROR` | 26003 | 400 | You cannot remove the default variant. |
> | `VariantsImportInvalidDelimiter` | — | 400 | CSV delimiter not recognized. |
> | `VariantImportMissingColumnsHttp` | — | 400 | CSV is missing required columns. |
> | `VariantImportDuplicateColumnsHttp` | — | 400 | CSV has duplicate column headers. |

> [accordion] Real-time configuration
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `REAL_TIME_CONFIG_FORBIDDEN_ACCESS` | 29001 | 403 | Not authorized to access real-time configs. |
> | `REAL_TIME_CONFIG_INVALID_FOR_SCHEMA` | 29002 | 400 | Config values fail JSON Schema validation. |
> | `REAL_TIME_CONFIG_INVALID_SCHEMA` | 29004 | 400 | JSON Schema definition is invalid. |
> | `REAL_TIME_CONFIG_UNKNOWN_CLIENT_ENVIRONMENT` | 29006 | 400 | Client environment is not one of `sandbox`, `pre-release`, or `live`. |

> [accordion] Accounts and projects
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `ACCOUNT_NOT_FOUND` | 1002 | 404 | Account ID does not exist. |
> | `ACCOUNT_CREATE_INVALID_ID` | 1004 | 400 | Account ID contains non-alphanumeric characters or is too similar to an existing ID. |
> | `ACCOUNT_CREATE_EXISTING_ID` | 1006 | 409 | Account ID is already taken. |
> | `PROJECT_NOT_FOUND` | 15001 | 404 | Project ID does not exist. |
> | `PROJECT_ID_ALREADY_EXISTS` | 15005 | 409 | Project ID is already taken. |
> | `PROJECT_ID_INVALID` | 15006 | 400 | Project ID does not meet format requirements. |

> [accordion] SMS
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `SMS_TEMPLATE_NOT_FOUND` | 20001 | 404 | SMS template ID does not exist. |

> [accordion] Test suite
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `MissingTestCasesHttp` | — | 422 | One or more test case IDs were not found. |
> | `NoTestCasesHttp` | — | 422 | No test cases exist for this project. |

Showing  of  error codes

> [accordion] Authentication and authorization
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `AUTH_USER_NOT_FOUND` | 3001 | 401 | User not found in the auth system. |
> | `AUTH_USER_UNAUTHORISED` | 3002 | 401 | Invalid credentials or expired session. |
> | `AUTH_USER_INVALID_TOKEN` | 3003 | 401 | Token is malformed, expired, or revoked. |
> | `USER_ACCESS_FORBIDDEN` | 2 | 403 | User lacks permission for the requested action. |
> | `EXTERNAL_USER_FORBIDDEN` | 3 | 403 | External user privilege level is too low. |
> | `ACCOUNT_INSUFFICIENT_PERMISSIONS` | 1003 | 403 | User lacks permissions for this account operation. |

> [accordion] Conversations
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CONVERSATIONS_NOT_FOUND` | 5001 | 404 | Conversation ID does not exist. |
> | `CONVERSATIONS_VALIDATION_FAILED` | 5002 | 400 | Conversation request body failed validation. |
> | `CONVERSATIONS_RECORDING_NOT_FOUND` | 5003 | 404 | Audio recording not found for this conversation. |
> | `GET_CONVERSATIONS_FILTER_PARSE_ERROR` | — | 400 | Filter expression syntax is invalid. |
> | `GET_CONVERSATIONS_INVALID_SORT_PARAMETER` | — | 400 | Sort field is not in the allowed set. |

> [accordion] Chat
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `CHAT_DRAFT_NOT_EXIST` | 4001 | 400 | The draft you are attempting to chat with does not exist. |
> | `CHAT_TIMEOUT` | 4002 | 400 | Chat session exceeded the timeout limit. |
> | `CHAT_DRAFT_DEPLOYMENT_FAILED` | 4003 | 500 | Draft auto-deploy failed before the chat could start. |
> | `ChatConversationEnded` | — | 410 | You sent a message to a conversation that has already ended. |

> [accordion] Deployments
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `DEPLOYMENT_NOT_FOUND` | 6001 | 404 | Deployment ID does not exist. |
> | `DEPLOYMENTS_ALREADY_PUBLISHED` | 6009 | 409 | Draft is already published to the target environment. |
> | `DEPLOYMENTS_ENVIRONMENT_ALREADY_PUBLISHED` | 6002 | 200 | Environment already has this version (idempotent). |
> | `DEPLOYMENTS_VALIDATION_FAILED` | 6007 | 400 | Request body validation failed. |
> | `DEPLOYMENTS_INVALID_ENVIRONMENT` | 6008 | 400 | Invalid or missing `environment` query parameter. |
> | `ErrPreReleaseNotReady` | — | 412 | You must deploy to pre-release before promoting to live. |

> [accordion] Flows
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FLOW_NOT_FOUND` | 8001 | 404 | Flow ID does not exist. |
> | `FLOWS_NAME_ALREADY_EXISTS` | 8003 | 409 | A flow with this name already exists. |
> | `FLOWS_FUNCTION_NAME_ALREADY_EXISTS` | 8004 | 409 | A function with this name already exists in the flow. |
> | `FLOWS_RESERVED_PARAMETER_NAME` | 8005 | 400 | You used a reserved parameter name. |
> | `FLOWS_RESERVED_FUNCTION_NAME` | 8006 | 400 | You used a reserved function name. |

> [accordion] Functions
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `FUNCTION_NOT_FOUND` | 9001 | 404 | Function ID does not exist. |
> | `FUNCTIONS_DEPLOYMENT_HAS_ERRORS` | 9004 | 400 | Function code contains errors that prevent deployment. |
> | `FUNCTION_EXECUTION_FAILED` | 9006 | 400 | Function encountered a runtime execution error. |
> | `FUNCTION_FAILED_TO_PARSE` | 9007 | 400 | Function source code has parse errors. |
> | `FUNCTION_NAME_ALREADY_EXISTS` | 9009 | 409 | A function with this name already exists. |
> | `FUNCTIONS_RESERVED_NAME` | 9010 | 400 | You used a system-reserved function name. |

> [accordion] Knowledge base
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `KNOWLEDGE_BASE_TOPIC_ALREADY_EXISTS` | 11001 | 409 | A topic with this name already exists. |
> | `KNOWLEDGE_BASE_IMPORT_NO_CSV_FOUND` | 11002 | 400 | No CSV file found in the import request. |
> | `KNOWLEDGE_BASE_IMPORT_INVALID_TYPE` | 11003 | 415 | The uploaded file type is not supported. |
> | `KNOWLEDGE_BASE_IMPORT_MISSING_COLUMNS` | 11004 | 400 | Required columns are missing from the CSV import. |
> | `KNOWLEDGE_BASE_TOPICS_INVALID` | 11005 | 400 | Topic data failed validation. |
> | `KNOWLEDGE_BASE_RICH_TEXT_INVALID` | 11006 | 400 | Rich text markup is malformed or references a missing entity. |

> [accordion] Phone numbers and connectors
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `PHONE_NUMBERS_NOT_FOUND` | 14006 | 404 | Phone number does not exist. |
> | `PHONE_NUMBERS_ALREADY_EXISTS` | 14007 | 409 | Phone number has already been imported. |
> | `PHONE_NUMBERS_INVALID_PHONE_NUMBER_FORMAT` | 14003 | 400 | Number is not in valid E.164 format. |
> | `PHONE_NUMBERS_CONNECTOR_DOES_NOT_EXIST` | 14005 | 404 | Referenced connector not found. |
> | `CONNECTORS_NOT_FOUND` | 14100 | 404 | Connector ID does not exist. |
> | `CONNECTORS_VALIDATION_FAILED` | 14101 | 400 | Connector request body failed validation. |

> [accordion] Variants
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `VARIANTS_BAD_ATTRIBUTES_ERROR` | 26001 | 400 | Attribute values do not match the expected schema. |
> | `VARIANTS_DUPLICATE_NAME_ERROR` | 26002 | 409 | A variant with this name already exists. |
> | `VARIANTS_REMOVE_DEFAULT_ERROR` | 26003 | 400 | You cannot remove the default variant. |
> | `VariantsImportInvalidDelimiter` | — | 400 | CSV delimiter not recognized. |
> | `VariantImportMissingColumnsHttp` | — | 400 | CSV is missing required columns. |
> | `VariantImportDuplicateColumnsHttp` | — | 400 | CSV has duplicate column headers. |

> [accordion] Real-time configuration
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `REAL_TIME_CONFIG_FORBIDDEN_ACCESS` | 29001 | 403 | Not authorized to access real-time configs. |
> | `REAL_TIME_CONFIG_INVALID_FOR_SCHEMA` | 29002 | 400 | Config values fail JSON Schema validation. |
> | `REAL_TIME_CONFIG_INVALID_SCHEMA` | 29004 | 400 | JSON Schema definition is invalid. |
> | `REAL_TIME_CONFIG_UNKNOWN_CLIENT_ENVIRONMENT` | 29006 | 400 | Client environment is not one of `sandbox`, `pre-release`, or `live`. |

> [accordion] Accounts and projects
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `ACCOUNT_NOT_FOUND` | 1002 | 404 | Account ID does not exist. |
> | `ACCOUNT_CREATE_INVALID_ID` | 1004 | 400 | Account ID contains non-alphanumeric characters or is too similar to an existing ID. |
> | `ACCOUNT_CREATE_EXISTING_ID` | 1006 | 409 | Account ID is already taken. |
> | `PROJECT_NOT_FOUND` | 15001 | 404 | Project ID does not exist. |
> | `PROJECT_ID_ALREADY_EXISTS` | 15005 | 409 | Project ID is already taken. |
> | `PROJECT_ID_INVALID` | 15006 | 400 | Project ID does not meet format requirements. |

> [accordion] SMS
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `SMS_TEMPLATE_NOT_FOUND` | 20001 | 404 | SMS template ID does not exist. |

> [accordion] Test suite
>
> | Code | ID | HTTP | Description |
> | - | - | - | - |
> | `MissingTestCasesHttp` | — | 422 | One or more test case IDs were not found. |
> | `NoTestCasesHttp` | — | 422 | No test cases exist for this project. |

## WebSocket close codesWebSocket close codes

If you are using the WebRTC Gateway or webchat WebSocket connections, you may encounter these close codes:

| Code | Meaning | When it occurs |
| - | - | - |
| 1000 | Normal closure | Connection closed cleanly. |
| 1006 | Abnormal closure | Connection dropped unexpectedly (for example, network failure). |
| 408 | Pong timeout | Server did not receive a pong response within the configured timeout. |

If you are using the WebRTC Gateway or webchat WebSocket connections, you may encounter these close codes:

| Code | Meaning | When it occurs |
| - | - | - |
| 1000 | Normal closure | Connection closed cleanly. |
| 1006 | Abnormal closure | Connection dropped unexpectedly (for example, network failure). |
| 408 | Pong timeout | Server did not receive a pong response within the configured timeout. |

## TroubleshootingTroubleshooting

> [!TIP]
>
> Every API response includes an `X-PolyAI-Correlation-Id` header. When contacting PolyAI support, include this value so the team can trace the request through the system.

### Common patterns

> [!TIP]
>
> Every API response includes an `X-PolyAI-Correlation-Id` header. When contacting PolyAI support, include this value so the team can trace the request through the system.

### Common patterns

{[
    { symptom: '401 on every request', cause: 'API key missing or malformed', resolution: <>Verify the <code>x-api-key</code> header is present and correctly formatted.</> },
    { symptom: '403 after key rotation', cause: 'Old key revoked', resolution: 'Confirm you are using the new key.' },
    { symptom: '404 for a known resource', cause: 'Wrong region', resolution: 'Verify the base URL matches your account region.' },
    { symptom: '409 on create', cause: 'Duplicate identifier', resolution: 'Use a different name or ID, or check for existing resources.' },
    { symptom: '422 on import', cause: 'Schema mismatch', resolution: <>Verify CSV columns match the expected format. Check the error <code>data</code> field for column details.</> },
    ].map((p) => (
    <div key={p.symptom} style={{
      padding: '0.9rem 1.1rem',
      borderRadius: '14px',
      border: '1px solid rgba(0,0,0,0.08)',
      background: 'rgba(0,0,0,0.015)',
    }}>
      <div style={{ fontWeight: 700, fontSize: '0.92rem', color: '#1f2937', marginBottom: '0.5rem' }}>{p.symptom}</div>
      <div style={{ fontSize: '0.76rem', textTransform: 'uppercase', letterSpacing: '0.04em', color: '#9ca3af', marginBottom: '0.15rem' }}>Likely cause</div>
      <div style={{ fontSize: '0.85rem', color: '#4b5563', marginBottom: '0.6rem' }}>{p.cause}</div>
      <div style={{ fontSize: '0.76rem', textTransform: 'uppercase', letterSpacing: '0.04em', color: '#9ca3af', marginBottom: '0.15rem' }}>Resolution</div>
      <div style={{ fontSize: '0.85rem', color: '#374151' }}>{p.resolution}</div>
    </div>
    ))}

Quick diagnostics for the errors you are most likely to hit. Expand a row to see the likely cause and how to resolve it.

> [accordion] 401 on every request
>
> **Likely cause** — API key missing or malformed.
>
> **Resolution** — Verify the `x-api-key` header is present and correctly formatted. Check for stray whitespace or missing characters when the key is copied from a secret store.

> [accordion] 403 after key rotation
>
> **Likely cause** — Old key revoked.
>
> **Resolution** — Confirm you are using the new key everywhere it is referenced — including local `.env` files, CI secrets, and any deployed services.

> [accordion] 404 for a known resource
>
> **Likely cause** — Wrong region.
>
> **Resolution** — Verify the base URL matches your account region. See [API getting started](https://docs.poly.ai/api-reference/introduction.md) for the list of regional base URLs.

> [accordion] 409 on create
>
> **Likely cause** — Duplicate identifier.
>
> **Resolution** — Use a different name or ID, or check for an existing resource with the same identifier before retrying.

> [accordion] 422 on import
>
> **Likely cause** — Schema mismatch.
>
> **Resolution** — Verify CSV columns match the expected format. Check the error `data` field for column-level details.

> [!TIP]
>
> Every API response includes an `X-PolyAI-Correlation-Id` header. When contacting PolyAI support, include this value so the team can trace the request through the system.

### Common patterns

{[
    { symptom: '401 on every request', cause: 'API key missing or malformed', resolution: <>Verify the <code>x-api-key</code> header is present and correctly formatted.</> },
    { symptom: '403 after key rotation', cause: 'Old key revoked', resolution: 'Confirm you are using the new key.' },
    { symptom: '404 for a known resource', cause: 'Wrong region', resolution: 'Verify the base URL matches your account region.' },
    { symptom: '409 on create', cause: 'Duplicate identifier', resolution: 'Use a different name or ID, or check for existing resources.' },
    { symptom: '422 on import', cause: 'Schema mismatch', resolution: <>Verify CSV columns match the expected format. Check the error <code>data</code> field for column details.</> },
    ].map((p) => (
    <div key={p.symptom} style={{
      padding: '0.9rem 1.1rem',
      borderRadius: '14px',
      border: '1px solid rgba(0,0,0,0.08)',
      background: 'rgba(0,0,0,0.015)',
    }}>
      <div style={{ fontWeight: 700, fontSize: '0.92rem', color: '#1f2937', marginBottom: '0.5rem' }}>{p.symptom}</div>
      <div style={{ fontSize: '0.76rem', textTransform: 'uppercase', letterSpacing: '0.04em', color: '#9ca3af', marginBottom: '0.15rem' }}>Likely cause</div>
      <div style={{ fontSize: '0.85rem', color: '#4b5563', marginBottom: '0.6rem' }}>{p.cause}</div>
      <div style={{ fontSize: '0.76rem', textTransform: 'uppercase', letterSpacing: '0.04em', color: '#9ca3af', marginBottom: '0.15rem' }}>Resolution</div>
      <div style={{ fontSize: '0.85rem', color: '#374151' }}>{p.resolution}</div>
    </div>
    ))}

Quick diagnostics for the errors you are most likely to hit. Expand a row to see the likely cause and how to resolve it.

> [accordion] 401 on every request
>
> **Likely cause** — API key missing or malformed.
>
> **Resolution** — Verify the `x-api-key` header is present and correctly formatted. Check for stray whitespace or missing characters when the key is copied from a secret store.

> [accordion] 403 after key rotation
>
> **Likely cause** — Old key revoked.
>
> **Resolution** — Confirm you are using the new key everywhere it is referenced — including local `.env` files, CI secrets, and any deployed services.

> [accordion] 404 for a known resource
>
> **Likely cause** — Wrong region.
>
> **Resolution** — Verify the base URL matches your account region. See [API getting started](https://docs.poly.ai/api-reference/introduction.md) for the list of regional base URLs.

> [accordion] 409 on create
>
> **Likely cause** — Duplicate identifier.
>
> **Resolution** — Use a different name or ID, or check for an existing resource with the same identifier before retrying.

> [accordion] 422 on import
>
> **Likely cause** — Schema mismatch.
>
> **Resolution** — Verify CSV columns match the expected format. Check the error `data` field for column-level details.

## Related pages

> [card] [API getting started](https://docs.poly.ai/api-reference/introduction.md)
>
> Authentication, base URLs, and API versioning.

> [card] [Conversations API](https://docs.poly.ai/api-reference/conversations/introduction.md)
>
> Retrieve conversation data and transcripts.
