> ## Documentation Index
> Fetch the complete documentation index at: https://openphone-dev.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Making requests

> The conventions every Quo API request and response follows: headers, envelopes, ids, timestamps, and cursor pagination.

Learn these conventions once and every endpoint in the reference becomes predictable.

## The basics

All requests go to one base URL, over HTTPS:

```
https://api.quo.com
```

Two headers are required on every request, a third on requests with a body:

| Header            | Value              | Notes                                                                    |
| ----------------- | ------------------ | ------------------------------------------------------------------------ |
| `Authorization`   | Your API key       | See [Authentication](/2026-03-30/authentication).                        |
| `Quo-Api-Version` | `2026-03-30`       | Required; there is no default. See [Versioning](/2026-03-30/versioning). |
| `Content-Type`    | `application/json` | Only when sending a request body.                                        |

Request and response bodies are JSON, UTF-8 encoded.

## Response envelopes

Every successful response wraps its payload in `data`. The shape of `data` tells you what you got:

```json A single resource theme={null}
{
  "data": { "id": "USu3X8sIB9", "...": "..." }
}
```

```json A list theme={null}
{
  "data": [{ "id": "USu3X8sIB9", "...": "..." }],
  "nextCursor": "Y3Vyc29yOjEwMjQ"
}
```

The envelope keeps metadata like `nextCursor` out of your data, and it lets responses gain new top-level fields without disturbing your parsing. Which leads to the standing rule: **ignore fields you don't recognize.** New optional fields are the one kind of change that ships [without a version bump](/2026-03-30/versioning#what-changes-and-what-never-does).

## Identifiers

Ids are strings with a short resource prefix. A user id starts with `US`, and other resources follow the same scheme. The prefix makes logs and error messages easier to read.

Beyond reading the prefix, treat every id as opaque: don't parse them, don't assume a length, and don't build anything that depends on their internal structure. They are stable identifiers, not data.

## Timestamps

All timestamps are ISO 8601 strings in UTC:

```json theme={null}
"createdAt": "2026-05-19T09:12:45Z"
```

The API speaks UTC exclusively. If you need local time, convert at display time.

## Pagination

Lists are cursor-paginated. Two query parameters in, one field out:

| Parameter | Type          | Behavior                                                        |
| --------- | ------------- | --------------------------------------------------------------- |
| `limit`   | integer, 1–50 | Items per page. Defaults to `10`.                               |
| `after`   | string        | The `nextCursor` from your previous page. Omit it for page one. |

Walk pages until `nextCursor` comes back `null`:

```javascript theme={null}
let cursor = null;
const users = [];

do {
  const url = new URL("https://api.quo.com/users");
  url.searchParams.set("limit", "50");
  if (cursor) url.searchParams.set("after", cursor);

  const res = await fetch(url, {
    headers: {
      Authorization: process.env.QUO_API_KEY,
      "Quo-Api-Version": "2026-03-30",
    },
  });

  const page = await res.json();
  users.push(...page.data);
  cursor = page.nextCursor;
} while (cursor);
```

Cursors are opaque strings. Pass them back exactly as received, and don't store them long-term; fetch a fresh page one instead.

## When something goes wrong

Failed requests return a structured error that names the field at fault and can include a `trace` id for support. That contract has [its own page](/2026-03-30/errors).
