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

# Errors

> The error responses the AlloMia API returns, and what to do about each one.

Every error response has a JSON body with an `error` string. Some also have `details`, which explains a validation problem, or `code`, a fixed machine-readable reason.

The shape depends on the endpoint and on which check rejected the request: the key check that runs first, the permission check, or the endpoint itself. So:

* Branch on the HTTP status, and on `code` when it is present.
* Log `error` and `details` to help you troubleshoot, but don't match on the message text in your code.

## Status codes at a glance

| Status | Meaning | What to do |
| - | - | - |
| `400` | The request is malformed or breaks a validation rule. | Fix the request. Don't retry it unchanged. |
| `401` | The key is missing or invalid, or it is the wrong kind of key for this endpoint. | Check the header and the key type. See [401](#401-unauthorized). |
| `403` | The key is valid, but the person who created it doesn't have the role this endpoint needs. | Use a key created by the right person. See [403](#403-forbidden). |
| `404` | The resource doesn't exist, or your key can't see it. | Check the ID and that it belongs to the key's clinic or partner account. |
| `409` | The request conflicts with existing data. | Read `error` and `code`, then change the request. |
| `422` | The clinic is inactive. | Use an active clinic. |
| `429` | Too many requests. | Wait, then retry. See [Rate limits](/api-reference/rate-limits). |
| `500` | A server error, or one of a few input errors that currently return `500`. | Read `error`. Retry reads with backoff; check before you retry writes. See [500](#500-internal-server-error). |

## 400 Bad Request

### Validation errors with field details

Used by [List calls](/api-reference/endpoint/list-calls) and [Create outbound call](/api-reference/endpoint/create-outbound-call).

```json theme={null}
{
  "error": "Invalid request data",
  "details": [
    {
      "field": "phoneNumber",
      "message": "Phone number must be at least 10 digits",
      "code": "too_small"
    },
    {
      "field": "assistantId",
      "message": "Invalid assistant ID format",
      "code": "invalid_format"
    }
  ]
}
```

Each item in `details` has:

* `field`: the parameter or body field with the problem.
* `message`: what is wrong.
* `code`: the kind of rule that failed, for example `invalid_type`, `invalid_value`, `invalid_format`, `too_small`, `too_big` or `custom`.

The same field can appear more than once when it breaks several rules.

### Plain messages

Some endpoints return only an `error` string:

| Endpoint | Body |
| - | - |
| [List organizations](/api-reference/endpoint/list-organizations) | `{"error": "Page must be a positive integer starting from 1."}` or `{"error": "Limit must be a positive integer between 1 and 100."}`, or the matching `... cannot be empty ...` message for an empty value |
| [Get](/api-reference/endpoint/get-organization), [Update](/api-reference/endpoint/update-organization) and [Delete organization](/api-reference/endpoint/delete-organization) | `{"error": "Invalid Organization ID format. Must be a valid UUID."}` |
| [Get call](/api-reference/endpoint/get-call) | `{"error": "Invalid Call ID format. Must be a valid UUID."}` |
| [Update organization](/api-reference/endpoint/update-organization) | `{"error": "Invalid organization data"}`. It doesn't say which field is wrong. |

### Malformed JSON

| Endpoint | Status and body |
| - | - |
| [Create](/api-reference/endpoint/create-organization) and [Update organization](/api-reference/endpoint/update-organization) | `400` `{"error": "Invalid JSON format. Please check your request body for proper JSON syntax.", "details": "Malformed JSON - ensure proper syntax with correct brackets, commas, and quoted keys"}` |
| [Update organization metadata](/api-reference/endpoint/update-organization-metadata) | `400` `{"error": "Invalid JSON format in request body"}` |
| [Create outbound call](/api-reference/endpoint/create-outbound-call) | `500` `{"error": "Internal server error"}` |

### Metadata errors

[Update organization metadata](/api-reference/endpoint/update-organization-metadata) has two more `400` bodies:

* `{"error": "Invalid request body format", "details": {"name": "ZodError", "message": "..."}}` when `metadata` is missing or isn't a JSON object. `details.message` is a JSON-encoded string that lists the problems.
* `{"error": "Schema validation failed", "details": [...]}` when the object breaks your integration's JSON Schema. Each item has `instancePath`, `schemaPath`, `keyword`, `params` and `message`.

## 401 Unauthorized

A `401` can come from three places.

**1. The key check.** Most endpoints return this when they don't accept the key:

```json theme={null}
{
  "error": "Unauthorized"
}
```

Causes: no `Authorization` header; the header doesn't start with `Bearer ` (capital B, one space); the key doesn't start with `sk-`; the key is unknown or was deleted; or the person who created the key no longer has an active AlloMia account.

**2. The identity check.** It runs on every endpoint:

```json theme={null}
{
  "error": "Unauthorized access"
}
```

The key couldn't be matched to an active clinic or partner account. Update organization metadata returns this one, instead of `Unauthorized`, for a missing, unknown or deleted key.

**3. Endpoint checks.** These mean the key is valid but is the wrong kind for the endpoint:

| `error` | Endpoints | Cause and fix |
| - | - | - |
| `Invalid authorization` | List, Create, Get, Update and Delete organization | A clinic key was used. Use a partner key. |
| `API key is not associated with the tenant` | Organization endpoints | The key in the header doesn't match your partner account. Send the key exactly as it was shown when created. |
| `Tenant ID is required` | Update organization metadata | A clinic key was used. Use a partner key. |
| `Organization ID not found in authorization` | Get outbound call status | A partner key was used. Use a clinic key, or rely on the [callback](/api-reference/webhooks). |
| `Invalid authorization identity` | Create outbound call | The key isn't linked to a clinic or partner account. Create a new key. |

## 403 Forbidden

```json theme={null}
{
  "error": "Insufficient permissions"
}
```

The key is valid, but the person who created it doesn't have the role the endpoint needs. Returned by the organization endpoints, Update organization metadata, Create outbound call and Get outbound call status. List calls and Get call accept any valid key.

Fix: create a new key from the right account. For a clinic key, that is the clinic owner or a Tenant Admin. For a partner key, it is the partner account owner or a Tenant Admin. See [Authentication](/api-reference/authentication#a-key-acts-with-the-rights-of-its-creator).

## 404 Not Found

```json theme={null}
{
  "error": "Organization not found"
}
```

The message names what wasn't found:

| `error` | Endpoints |
| - | - |
| `Organization not found` | Get, Update, Delete organization; List calls; Update organization metadata |
| `Call not found` | Get call |
| `Outbound call not found`, `Contact not found` | Get outbound call status |
| `Phone number not found`, `Assistant not found` | Create outbound call |
| `Organization metadata not found`, `Organization integration not found`, `Integration provider not found` | Update organization metadata |

A `404` also means the resource exists but your key can't see it, for example a call from another clinic, or a clinic outside your partner account. Check the ID with [Finding IDs](/api-reference/finding-ids), and check that you are using the key for the right clinic or partner account.

## 409 Conflict

| Endpoint | Body |
| - | - |
| [Create organization](/api-reference/endpoint/create-organization) | `{"error": "Organization with externalId LKS-0042 already exists"}`: another clinic already uses this `externalId`. |
| [Update organization](/api-reference/endpoint/update-organization) | `{"error": "This organization has subscription history and cannot be deleted to preserve billing and usage data.", "code": "ORG_HAS_SUBSCRIPTION_HISTORY"}`: the clinic has billing history and can't be updated through the API. Edit it in the dashboard instead. |

## 422 Unprocessable Entity

[Create outbound call](/api-reference/endpoint/create-outbound-call) returns this when the clinic that owns the phone number is inactive:

```json theme={null}
{
  "error": "Organization is inactive or not found"
}
```

## 429 Too Many Requests

```json theme={null}
{
  "error": "Too many requests",
  "retryAfter": 60
}
```

`retryAfter` and the `Retry-After` header give the number of seconds to wait. AlloMia didn't process the request, so you can send it again after waiting. See [Rate limits](/api-reference/rate-limits).

## 500 Internal Server Error

The body depends on the endpoint:

| `error` | Endpoints |
| - | - |
| `An unexpected error occurred. Please try again later.` | List, Create, Get, Update and Delete organization; List calls; Get call |
| `Failed to update organization`, `Failed to delete organization` | Update organization, Delete organization |
| `An error occurred while updating metadata` | Update organization metadata |
| `Internal server error` | Create outbound call, Get outbound call status |
| A specific message, such as `Failed to create outbound call record` | Create outbound call |

### Input errors that currently return 500

Today, a few input problems come back as `500` instead of `400`:

* [Create organization](/api-reference/endpoint/create-organization): a body that breaks a validation rule returns the generic message, without field details.
* [List organizations](/api-reference/endpoint/list-organizations): a `sort` value outside the four allowed values returns the generic message.
* [Create outbound call](/api-reference/endpoint/create-outbound-call): malformed JSON returns `Internal server error`. A destination number that can't be dialled, or a clinic number that can't place calls, returns a specific message, such as `Phone number format is invalid. Please provide a valid E.164 formatted number (e.g., +15145551234).` or `This number cannot be used as an outbound caller ID. Choose a PSTN phone number.`

Check your requests against each endpoint's rules before you send them, and read `error` on every `500`.

### Retrying after a 500

* **Reads** (`GET`): retry with exponential backoff, for example after 1, 2, 4 and 8 seconds, then stop and log the failure.
* **Create organization**: before you retry, call [List organizations](/api-reference/endpoint/list-organizations) with `search` set to the clinic's name. Clinic names don't have to be unique, so a blind retry can create a duplicate.
* **Create outbound call**: a `500` doesn't always mean no call was placed. Before you retry, check whether a call went out. Calls placed through the API appear in the dashboard under **Tools & Actions** → **Outbound**, named `API Call - ` followed by the number. Finished calls also appear in [List calls](/api-reference/endpoint/list-calls) with `callType=Outbound`.
* **Update and Delete organization**: these are safe to repeat. A `404` on a repeated delete usually means the first attempt worked.

If a `500` keeps happening, contact AlloMia with the time of the request, the endpoint and the `error` text.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.