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

# Requests and responses

> The Connecta DESK API response envelope: data, meta and error. Accepted formats, status codes and the order of checks on every request.

All 150 v1 endpoints respond in the same format, which we call the envelope. This way, you write
your HTTP client once and reuse it across the whole API.

## The envelope

<Tabs>
  <Tab title="Item">
    A resource always comes inside `data`:

    ```json theme={null}
    {
      "data": {
        "id": 1042,
        "name": "Marina Alves",
        "number": "5511999999999"
      }
    }
    ```
  </Tab>

  <Tab title="List">
    Lists bring `data` as an array, plus a `meta` with the pagination details:

    ```json theme={null}
    {
      "data": [
        { "id": 1042, "name": "Marina Alves" },
        { "id": 1043, "name": "Rafael Nunes" }
      ],
      "meta": { "page": 1, "perPage": 20, "hasMore": true }
    }
    ```
  </Tab>

  <Tab title="Error">
    Errors never come in `data`. The body has a single `error` field:

    ```json theme={null}
    {
      "error": {
        "code": "ERR_API_VALIDATION",
        "message": "Informe ao menos um destes campos: name, number.",
        "details": null
      }
    }
    ```
  </Tab>
</Tabs>

<Note>
  Always read the resource from `response.data`, never from the root of the body. The envelope may
  gain new fields in the future.
</Note>

## Sending data

<ParamField header="Content-Type" type="application/json">
  The default for creating and editing. Use it on every `POST` and `PUT` that does not involve a
  file.
</ParamField>

<ParamField header="Content-Type" type="multipart/form-data">
  Required when the request carries a file, such as message media, a product image, a CRM note
  attachment or a campaign spreadsheet. The text fields go in the same form.
</ParamField>

Endpoints that receive a file accept **both formats**. Without a file, send plain JSON. With a
file, send the form. When both formats exist, the endpoint's reference shows both.

## Status codes

| Code | When it happens |
| - | - |
| `200` | Read or change completed. |
| `201` | Resource created. The body contains the new record. |
| `202` | Accepted for asynchronous processing (currently, sending a message). The body contains the `jobId`. |
| `204` | Completed, with no body in the response. Common for deletions. |
| `400` | Malformed request or a required field is missing. |
| `401` | Problem with the token. See [Authentication](/en/authentication). |
| `403` | Inactive company, plan without the API, or token without the required permission. |
| `404` | The resource does not exist or belongs to another company. |
| `409` | State conflict, including reuse of an `Idempotency-Key`. |
| `422` | The body is well formed, but it violates a business rule. |
| `429` | The company reached its limit of requests per minute. |

## Order of checks

Before it reaches the endpoint, every request goes through five checks, in this order. You get
the error from the first one that fails, which helps you find the problem faster.

<Steps>
  <Step title="Token" icon="key">
    The token exists, is valid, has not been revoked or expired, and the origin of the call is in
    the IP allowlist. If it fails, the response is `401`.
  </Step>

  <Step title="Company active" icon="building">
    The company that owns the token is active and within its validity period. If it fails, the
    response is `403`.
  </Step>

  <Step title="API enabled on the plan" icon="package-check">
    The contracted plan includes the public API. If it fails, the response is
    `403 ERR_API_NOT_ENABLED`.

    This check does not apply to on-premise installations.
  </Step>

  <Step title="Rate limit" icon="gauge">
    The company is within its limit of requests per minute. If it fails, the response is `429`.
  </Step>

  <Step title="Token permission" icon="shield-check">
    The token has permission for that method on that module. If it fails, the response is
    `403 ERR_API_FORBIDDEN_SCOPE`.
  </Step>
</Steps>

## Identifiers and scope

Every resource has a numeric id, and **each id only applies within the token's company**. If you
ask for an id that belongs to another company, you get `404`, as if the record did not exist.

<Warning>
  Ids are not global, and there is no way to predict which id a record will have in another
  environment. Do not copy staging ids into production. Look the record up by its natural field
  (contact number, product SKU, user email) and store the id that comes back in the response.
</Warning>


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