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

# API introduction

> Authentication, base URL, error codes, pagination, rate limits, and idempotency keys for the Flowella REST API v1 — all you need before your first call.

The Flowella REST API lets you send WhatsApp messages, manage contacts and opt-outs, list and bulk-send templates, and pull analytics — programmatically. This page covers everything you need to know before calling an endpoint.

The full endpoint reference lives in the **API reference** sidebar (auto-generated from the [OpenAPI spec](/api-reference/openapi.json)).

## Base URL

```
https://app.flowella.io
```

All v1 endpoints are under `/api/v1`.

## Authentication

Every request needs an API key in the `Authorization` header:

```http theme={null}
Authorization: Bearer flo_xxxxxxxxxxxxxxxxxxxxxxxx
```

Keys are organisation-scoped — they act on a single Flowella org and inherit the permissions of an Admin in that org.

<Warning>
  Treat keys like passwords. Never commit them to source control, never paste them in chat or shared docs, and rotate them when teammates leave the org. See [Settings → API keys](/settings/api-keys) for rotation steps.
</Warning>

### Creating a key

You need the **Owner** or **Admin** role to manage API keys.

1. Go to **Settings → API keys** in the Flowella app.
2. Click **Create key** and give it a memorable name.
3. Copy the key once — it is shown only at creation time.

Treat keys like passwords: never commit them to source control, never paste them in chat, and rotate them when teammates leave the org.

### Verifying a key

Hit the ping endpoint to confirm a key is valid:

<CodeGroup>
  ```bash cURL theme={null}
  curl https://app.flowella.io/api/v1/ping \
    -H "Authorization: Bearer flo_xxxxxxxxxxxxxxxxxxxxxxxx"
  ```

  ```js Node.js theme={null}
  await fetch("https://app.flowella.io/api/v1/ping", {
    headers: { Authorization: `Bearer ${process.env.FLOWELLA_API_KEY}` },
  });
  ```

  ```python Python theme={null}
  import os, requests

  requests.get(
      "https://app.flowella.io/api/v1/ping",
      headers={"Authorization": f"Bearer {os.environ['FLOWELLA_API_KEY']}"},
  )
  ```
</CodeGroup>

A `200 OK` with `{ "ok": true, "organizationId": "…" }` means you are authenticated.

## Errors

All errors come back in a consistent envelope:

```json theme={null}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}
```

| HTTP status | When you'll see it                                                                 |
| ----------- | ---------------------------------------------------------------------------------- |
| `400`       | Validation failed, malformed body, or upstream Meta rejection                      |
| `401`       | Missing or invalid API key                                                         |
| `402`       | Payment required — your subscription does not cover the action                     |
| `403`       | Forbidden — for example, sending to an opted-out contact, or Meta is not connected |
| `404`       | The requested channel or resource does not exist                                   |
| `429`       | Rate limited — slow down                                                           |

The `error.code` field is stable and safe to switch on programmatically. The `error.message` is human-readable and may change.

## Rate limits

API keys are rate-limited per organisation. If you exceed the limit you will get a `429` with code `RATE_LIMITED` and the message `Too many requests`. Back off and retry with exponential delay.

If you are running large bulk sends, prefer **`POST /api/v1/templates/send`** with the `throttlePerHour` parameter — Flowella enforces the throttle server-side, so you do not need to pace requests yourself.

## Pagination

List endpoints (`/conversations`, `/contacts`, `/templates`) use **cursor pagination**:

* Pass `limit` (1–100, default 25) and an optional `cursor`.
* The response contains `items` and, when there are more results, a `nextCursor`.
* Pass `nextCursor` back as the `cursor` parameter to fetch the next page.
* When `nextCursor` is missing, you have reached the end.

```bash theme={null}
curl "https://app.flowella.io/api/v1/conversations?limit=50" \
  -H "Authorization: Bearer flo_xxxxxxxxxxxxxxxxxxxxxxxx"
```

## Date and time

All timestamps are ISO 8601 strings in UTC (for example `2025-01-15T14:30:00.000Z`). Where the API accepts dates, both date-only (`2025-01-15`) and full ISO 8601 are coerced server-side.

## Phone numbers

Pass phone numbers in **E.164** form (`+15551234567`) where possible. Flowella will normalise common variations server-side, but E.164 is safest.

## Channels

Many endpoints accept a `whatsappChannelId`. If your org has a single channel and you omit it, Flowella uses your default channel. If you have multiple channels, pass the ID explicitly to avoid sending from the wrong sender.

For the full URL pattern and channel switching, see [Multi-channel](/essentials/multi-channel).

## OpenAPI spec

The machine-readable spec lives at:

```
/api-reference/openapi.json
```

Drop it into Postman, Insomnia, or your code generator of choice.

<Tip>
  Building an integration? Pair this page with [Webhooks](/api-reference/webhooks) to react to events instead of polling for state.
</Tip>
