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

# Conventions

> What every api.flowiq.live/v1 endpoint has in common: request ids, error codes, rate limits and idempotency keys.

The endpoints under `https://api.flowiq.live/v1` (Calling, Webhook deliveries, Subscriptions, Reports) share these rules. Older endpoints (`/send-text`, `/broadcast`, `/contact`, …) keep their own, simpler shapes.

## Request ids

Every response carries an `X-Request-Id` header, and every error body repeats it as `request_id`. Quote it when you write to support: it finds the exact request in FlowIQ's logs.

## Errors

Errors are JSON with a short label, a **stable machine-readable code**, a sentence for a person, and the request id. Branch on `code`, never on `message`.

```json theme={null}
{
  "error": "Forbidden",
  "code": "call_permission_missing",
  "message": "Contact has not granted callback permission",
  "request_id": "6f1e0d1c-…"
}
```

| Code | HTTP | Meaning |
| - | - | - |
| `validation_error` | 400 | A parameter is missing or malformed; the message names it |
| `invalid_cursor` | 400 | `cursor` is not one this API issued |
| `unauthorized` | 401 | Missing or invalid API key |
| `forbidden_scope` | 403 | The key lacks the scope the call needs (`read`, `send`, `write`) |
| `organisation_key_required` | 400 | The connection is not tied to one organisation |
| `not_found` | 404 | No such resource on this account |
| `call_not_found` | 404 | No such call on your number |
| `call_not_ringing` | 409 | The call was already answered, declined or ended |
| `contact_not_found` | 404 | No contact with that number or id on your account |
| `no_whatsapp_number` | 404 | The organisation has no connected WhatsApp number |
| `call_permission_missing` | 403 | The customer has not given permission to be called |
| `call_permission_expired` | 403 | The customer's call permission has expired |
| `outside_service_window` | 409 | More than 24 hours since the customer last wrote; use a template |
| `whatsapp_rejected` | 400 | WhatsApp refused the request; `whatsapp_error_code` carries [its code](https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes) |
| `delivery_in_flight` | 409 | The webhook delivery is being attempted right now |
| `idempotency_key_reused` | 422 | The `Idempotency-Key` was already used with a different request |
| `idempotency_in_progress` | 409 | A request with this `Idempotency-Key` is still running |
| `rate_limited` | 429 | Too many requests; wait `Retry-After` seconds |
| `upstream_error` | 502 | A service FlowIQ depends on did not answer properly; safe to retry |
| `internal_error` | 500 | Something went wrong on FlowIQ's side; quote `request_id` to support |

The `401` for a missing or invalid key comes from the shared key check and carries `error` and `message` only.

## Rate limits

Limits are per API key: **240 reads a minute** and **60 actions a minute** (anything that sends, calls or changes settings). Every response says where you stand:

| Header | Meaning |
| - | - |
| `X-RateLimit-Limit` | The limit for this kind of call |
| `X-RateLimit-Remaining` | Calls left in the current minute |
| `X-RateLimit-Reset` | When the window resets (Unix seconds) |
| `Retry-After` | On `429` only: seconds to wait |

## Idempotency keys

Send an `Idempotency-Key` header (any string up to 255 characters, a UUID is a good choice) on a `POST` or `PATCH` and FlowIQ remembers the response for **24 hours** per API key. A retry with the same key and the same body gets the same response back, with `Idempotent-Replayed: true`, without doing the work again: a network glitch can never start a call twice or send two permission requests.

* The same key with a **different** body is refused: `422 idempotency_key_reused`.
* A retry while the first request is still running: `409 idempotency_in_progress`.
* `5xx` answers are not remembered, so a retry after a FlowIQ-side failure runs again.

```bash theme={null}
curl -X POST "https://api.flowiq.live/v1/calls" \
  -H "Authorization: Bearer fiq_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3b2f6c5e-1a9d-4c1a-9e0a-7b7d2e6f1c44" \
  -d '{"to": "27820000000", "sdp": "v=0…"}'
```

## Paging

Lists are cursor-paged: pass `limit` (max 100) and, for the next page, the `next_cursor` from `pagination` as `?cursor=`. A page with `has_more: false` is the last one. Cursors are opaque; a cursor you did not get from the API answers `400 invalid_cursor`. (The Subscriptions endpoints still use `page`.)


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