
# Fel & sidindelning

Den här sidan täcker två saker som varje integration behöver hantera: hur en misslyckad förfrågan ser ut och hur man bläddrar igenom slutpunkter som returnerar listor.

---

## Felmeddelande-kuvertet

När en förfrågan misslyckas är svaret alltid JSON med samma struktur — en `success`-flagga satt till `false`, ett läsbart `error`-meddelande och en numerisk `error_code` som matchar HTTP-statusen:

```json
{
  "success": false,
  "error": "Invalid cursor",
  "error_code": 400
}
```

Eftersom `success` och `error_code` alltid finns med kan du förgrena logiken baserat på dem utan att behöva inspektera råa HTTP-statuskoder om du föredrar det. Ett lyckat svar har alltid `success: true`.

---

## Statuskoder

| Status | `error_code` | Meaning | What to do |
|---|---|---|---|
| `200` | — | Success | Read the response data. |
| `201` | — | Resource created | Save the returned ID (e.g. `campaign_id`, `contactId`). |
| `400` | `400` | Bad request | A parameter is missing or invalid. Read the `error` message and fix the request. |
| `401` | `401` | Unauthorized | Your API key is missing or invalid. Check the key and how you are sending it — see [Authentication](authentication.md). |
| `403` | `403` | Forbidden | Your plan does not include API access. See [API Access](../integrations/api-access.md) or contact [<span data-t="supportEmail">hi@youraiconnector.com</span>](mailto:hi@youraiconnector.com). |
| `404` | `404` | Not found | The resource (e.g. a contact, campaign, or task ID) does not exist on your account. |
| `409` | `409` | Conflict | The resource already exists — for example, creating a contact whose phone number is already on your account. |
| `429` | `429` | Rate limited | You have exceeded 300 requests per minute (or the wider 1,200/minute account ceiling). Back off and retry shortly. |
| `500` | `500` | Server error | Something went wrong on our side. Retry after a short wait; email [<span data-t="supportEmail">hi@youraiconnector.com</span>](mailto:hi@youraiconnector.com) if it persists. |

Några exempel på hur dessa ser ut i praktiken:

```json
{
  "success": false,
  "error_code": 401,
  "error": "Invalid API key"
}
```

```json
{
  "success": false,
  "error": "A contact with this phone number already exists",
  "error_code": 409
}
```

```json
{
  "success": false,
  "error_code": 429,
  "error": "Rate limit exceeded. Please try again later."
}
```

### Hantera fel på ett bra sätt

- **Kontrollera `success` (eller statuskoden) innan du läser data.** Anta inte att en svarstext innehåller det fält du förväntar dig.
- **Försök igen vid `429` och `500` med en kort fördröjning** — vänta, försök sedan igen. Försök inte igen vid `400`, `401`, `403`, `404` eller `409`; dessa kommer att fortsätta misslyckas tills du ändrar förfrågan.
- **Läs `error`-meddelandet.** Det talar oftast om exakt vilket fält som är felaktigt.

---

## Sidindelning

List-slutpunkter (såsom `GET /contacts`, `GET /campaigns` och `GET /tasks`) returnerar resultat i sidor så att ett enskilt anrop aldrig behöver läsa in hela ditt konto. Sidindelning använder en ogenomskinlig markör (cursor).

Två frågeparametrar styr detta:

| Parameter | Beskrivning |
|---|---|
| `limit` | Hur många objekt som ska returneras per sida. Standardvärden varierar beroende på slutpunkt (ofta 50); maxvärdet är **100**. |
| `cursor` | En ogenomskinlig pekare till nästa sida. Utelämna den för den första sidan. |

Varje sida inkluderar ett `next_cursor`-fält i svaret:

- Om `next_cursor` är en sträng finns det fler resultat — skicka med den som `cursor` i din nästa förfrågan.
- Om `next_cursor` är `null` har du nått den sista sidan. Stoppa.

En enskild sida med kontakter ser ut så här:

```json
{
  "success": true,
  "contacts": [
    { "id": "abc123", "first_name": "Jane", "phone_number": "+15551234567" },
    { "id": "def456", "first_name": "John", "phone_number": "+15557654321" }
  ],
  "next_cursor": "eyJsYXN0IjoiZGVmNDU2In0"
}
```

::: note
**Obs:** En markör (cursor) är ogenomskinlig — försök inte tolka, bygga eller ändra den. Skicka endast tillbaka ett `next_cursor`-värde som du har tagit emot från ett tidigare svar.
:::


---

## Bläddra igenom alla kontakter

För att hämta en hel lista, börja utan markör och fortsätt anropa tills `next_cursor` returneras som `null`.

**cURL**

Det här exemplet går igenom de två första sidorna manuellt. Kör det första anropet, kopiera `next_cursor` från svaret till `CURSOR`, och kör sedan det andra anropet. Upprepa tills `next_cursor` är `null`.

```bash
# First page
curl "https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY&limit=100"

# Next page — paste the next_cursor from the previous response
CURSOR="eyJsYXN0IjoiZGVmNDU2In0"
curl "https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY&limit=100&cursor=$CURSOR"
```

**JavaScript**

```javascript
async function getAllContacts() {
  const all = [];
  let cursor = null;

  do {
    const url = new URL("https://api.youraiconnector.com/v1/contacts");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);

    const res = await fetch(url, {
      headers: { "X-API-Key": "YOUR_API_KEY" },
    });
    const data = await res.json();

    if (!data.success) throw new Error(data.error);

    all.push(...data.contacts);
    cursor = data.next_cursor;
  } while (cursor);

  return all;
}
```

**Python**

```python
import requests

def get_all_contacts():
    all_contacts = []
    cursor = None

    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor

        res = requests.get(
            "https://api.youraiconnector.com/v1/contacts",
            params=params,
            headers={"X-API-Key": "YOUR_API_KEY"},
        )
        data = res.json()

        if not data["success"]:
            raise Exception(data["error"])

        all_contacts.extend(data["contacts"])
        cursor = data["next_cursor"]

        if not cursor:
            break

    return all_contacts
```

Samma loop fungerar för alla paginerade slutpunkter — ändra bara sökvägen och fältet du läser från svaret (`campaigns`, `tasks`, och så vidare).

---

## Nästa steg

- [Autentisering](authentication.md) — de fyra sätten att skicka din nyckel.
- [Kontakter](contacts.md) — de fullständiga kontaktslutpunkterna som används i exemplen ovan.
- [API-nycklar](api-keys.md) — kontrollera din nuvarande användning av hastighetsbegränsningar för att undvika `429`.
