# Kötegelt kérések

> Legfeljebb 50 kérés egy hívásban.

A `POST /batch` 1-50 API-kérést futtat egy hívásban, sorban, mindegyiket a kötegkérés tokenjével. Köteget bármely érvényes token küldhet; a benne lévő kérésekhez a saját jogaik kellenek.

## A kérés

| Kulcs | Jelentés |
|---|---|
| `requests` | 1-50 objektum `method` (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`), `path` (egy `/public/v1/` útvonal a lekérdezési részével) és szükség esetén `body` (a JSON-törzs objektumként) kulccsal. |

```bash
curl -X POST "$ECHO_API/batch" \
  -H "Authorization: Bearer $ECHO_TOKEN" -H "Content-Type: application/json" \
  -d '{"requests":[
        {"method":"GET","path":"/public/v1/subscribers/count?filter[status]=active"},
        {"method":"POST","path":"/public/v1/subscribers","body":{"email":"bence.kovacs@example.com","fields":{"city":"Sopron"}}},
        {"method":"GET","path":"/public/v1/groups/00000000-0000-0000-0000-000000000000/subscribers"}
      ]}'
```

## A válasz

`200 OK`, kérésenként egy válasszal, ugyanabban a sorrendben. A `code` a kérés HTTP-kódja, a `body` a JSON-törzse (üres válasznál `null`).

```json
{"responses":[{"code":200,"body":{"data":{"total":4714}}},{"code":200,"body":{"data":{"id":"8273ff7d-cb69-4a72-83e6-dbebbec33115","email":"bence.kovacs@example.com","status":"active","source":"import","fields":{"city":"Sopron","name":"Bence"},"groups":[{"id":"257e83a2-d55e-4a8c-b9a4-b3e939c151cc","name":"Webshop vásárlók"}],"signup_ip":null,"optin_ip":null,"subscribed_at":"2026-10-22T08:52:08.762873Z","opted_in_at":null,"unsubscribed_at":null,"timezone":null,"location_country":null,"location_city":null,"sent":0,"opens":0,"clicks":0,"open_rate":0,"click_rate":0,"created_at":"2026-10-22T08:52:08.762873Z","updated_at":"2026-10-22T08:52:10.377603Z"}}},{"code":404,"body":{"error":{"code":"not_found","message":"Not found."}}}]}
```

A köteg akkor is `200` választ ad, ha a benne lévő kérések hibáztak: minden `code` értéket ellenőrizz. Ebben a futásban a köteg előtti kérés után `X-RateLimit-Remaining: 86` maradt, a köteg válasza pedig `82` értéket mutatott: a köteg és a három kérése.

## Sebességkorlát

- Maga a köteg egy kérésnek számít, és minden benne lévő kérés is számít. Egy 50-es köteg a percenkénti 120 kérésből 51-et használ el.
- Ha a keret már elfogyott, a köteg `429` választ ad, és semmi sem fut le.
- Ha a kötegben egy kérés `429` választ kap, a többi már nem fut le: mindegyik `429 rate_limited` választ kap, a köteg válasza pedig `Retry-After` fejlécet visz.
- A köteg válaszának `X-RateLimit-Remaining` fejléce azt mutatja, mennyi maradt a köteg és az összes benne lévő kérés után.

Példa: ugyanabban a percben egy kérés, majd három 50-es köteg. Az első két köteg válaszában az `X-RateLimit-Remaining` értéke `68` és `17`. A harmadik:

```http
HTTP/1.1 200 OK
Content-Type: application/json
Retry-After: 56
X-Ratelimit-Limit: 120
X-Ratelimit-Remaining: 0
```

A törzsében az első 16 válasz `200`, az utolsó 34 pedig `{"code":429,"body":{"error":{"code":"rate_limited","message":"Too many requests with this API token. Wait a minute and try again, or send several requests in one batch."}}}`.

## Szabályok

- Nem atomi: minden kérés saját tranzakcióban fut. Ha a 3. kérés hibázik, az 1. és a 2. érvényben marad.
- A kérések egymás után, a megadott sorrendben futnak, így egy későbbi kérés látja egy korábbi változásait.
- A kötegben nem lehet `/public/v1/batch` vagy `/public/v1/openapi.yaml`, és az útvonal csak egyszerű `/public/v1/` útvonal lehet (hoszt és `..` nélkül):

```json
{"error":{"code":"validation","message":"Please check the highlighted fields.","fields":{"requests.0":"Use GET, POST, PUT, PATCH or DELETE on a /public/v1/ path (not the batch itself)."}}}
```

- A kötegkérés `Accept-Language` fejléce minden benne lévő kérésre érvényes.
- Az 1 MB-os törzskorlát az egész kötegre vonatkozik, ezért a tömeges import a [saját végpontjára](https://docs.uptools.io/hu/echo/developer-guide/import/) való.
