> ## 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.

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

<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', margin: '1.25rem 0 2rem' }}>
  {[
    { 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>
    ))}
</div>

## 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.

<div
  style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))',
gap: '0.75rem',
margin: '1rem 0 1.5rem',
}}
>
  {[
    { 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>
    )
    })}
</div>

## Platform error codes

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

<AccordionGroup>
  <Accordion id="auth" title="Authentication and authorization" icon="key">
    | 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>

  <Accordion id="conversations" title="Conversations" icon="messages">
    | 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>

  <Accordion id="chat" title="Chat" icon="comment">
    | 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>

  <Accordion id="deployments" title="Deployments" icon="rocket">
    | 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>

  <Accordion id="flows" title="Flows" icon="diagram-project">
    | 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>

  <Accordion id="functions" title="Functions" icon="code">
    | 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>

  <Accordion id="knowledge-base" title="Knowledge base" icon="book">
    | 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>

  <Accordion id="phone-numbers" title="Phone numbers and connectors" icon="phone">
    | 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>

  <Accordion id="variants" title="Variants" icon="shuffle">
    | 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>

  <Accordion id="real-time-config" title="Real-time configuration" icon="sliders">
    | 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>

  <Accordion id="accounts-projects" title="Accounts and projects" icon="building">
    | 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>

  <Accordion id="sms" title="SMS" icon="comment-sms">
    | Code                     | ID    | HTTP | Description                     |
    | ------------------------ | ----- | ---- | ------------------------------- |
    | `SMS_TEMPLATE_NOT_FOUND` | 20001 | 404  | SMS template ID does not exist. |
  </Accordion>

  <Accordion id="test-suite" title="Test suite" icon="flask-vial">
    | Code                   | ID | HTTP | Description                               |
    | ---------------------- | -- | ---- | ----------------------------------------- |
    | `MissingTestCasesHttp` | —  | 422  | One or more test case IDs were not found. |
    | `NoTestCasesHttp`      | —  | 422  | No test cases exist for this project.     |
  </Accordion>
</AccordionGroup>

## WebSocket 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. |

## Troubleshooting

<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.
</Tip>

### Common patterns

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

<AccordionGroup>
  <Accordion title="401 on every request" icon="key" iconType="regular">
    **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>

  <Accordion title="403 after key rotation" icon="arrows-rotate" iconType="regular">
    **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>

  <Accordion title="404 for a known resource" icon="globe" iconType="regular">
    **Likely cause** — Wrong region.

    **Resolution** — Verify the base URL matches your account region. See [API getting started](/api-reference/introduction) for the list of regional base URLs.
  </Accordion>

  <Accordion title="409 on create" icon="copy" iconType="regular">
    **Likely cause** — Duplicate identifier.

    **Resolution** — Use a different name or ID, or check for an existing resource with the same identifier before retrying.
  </Accordion>

  <Accordion title="422 on import" icon="file-csv" iconType="regular">
    **Likely cause** — Schema mismatch.

    **Resolution** — Verify CSV columns match the expected format. Check the error `data` field for column-level details.
  </Accordion>
</AccordionGroup>

## Related pages

<CardGroup cols={2}>
  <Card title="API getting started" icon="key" href="/api-reference/introduction">
    Authentication, base URLs, and API versioning.
  </Card>

  <Card title="Conversations API" icon="messages" href="/api-reference/conversations/introduction">
    Retrieve conversation data and transcripts.
  </Card>
</CardGroup>
