Skip to content

Qrona Newsletter API · guide

Batch and idempotency

Many calls in one, and calls that can safely be sent again after a network error – without anyone getting two confirmation emails or an order being counted twice.

POST /batch

Up to 500 calls in one, in order. Each operation has a method, a path under /api/v1 and a body, and is checked and run exactly as if it had been sent on its own: with the key's scopes, the same rules and the same errors. The response has the status and body of each operation, in the same order. One that fails does not stop the others – check results[].status.

Request
curl -X POST https://newsletter.qrona.se/api/v1/batch \
  -H "Authorization: Bearer $QRONA_NEWSLETTER_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4f0c2b8e-3a1d-4c5e-9f7a-6b2d8e0c1a3f" \
  -d '{
    "operations": [
      { "method": "PUT", "path": "/stores/butik-se/customers/1042", "body": { "email": "anna@example.se" } },
      { "method": "PUT", "path": "/stores/butik-se/orders/50087", "body": { "customer": { "id": "1042", "email": "anna@example.se" }, "order_total": 548, "lines": [{ "id": "1", "product_id": "731", "quantity": 2, "price": 249 }] } },
      { "method": "GET", "path": "/stores/butik-se/orders?limit=10" }
    ]
  }'
Response 200
{
  "results": [
    {
      "status": 201,
      "body": {
        "id": "1042",
        "email": "anna@example.se",
        "orders_count": 0
      }
    },
    {
      "status": 201,
      "body": {
        "id": "50087",
        "financial_status": "paid",
        "order_total": 548
      }
    },
    {
      "status": 200,
      "body": {
        "data": [
          "…"
        ],
        "has_more": false,
        "next_cursor": null
      }
    }
  ],
  "succeeded": 3,
  "failed": 0
}
  • The body may be up to 5 MB. A batch counts as one call towards the per-minute limit, but at most 20 batches per minute per key.
  • A batch cannot contain a batch. Read more in the reference: POST /batch.

PUT is always safe to repeat

Stores, customers, products, orders and carts are written with PUT using the shop's own IDs. The same call twice gives the same result, so an interrupted import can be rerun from the start, and an order is sent again each time it changes. The same applies to contacts with POST /contacts/upsert.

Idempotency-Key

For other POST requests – a new contact, a sign-up to a list, a batch – send the Idempotency-Key header with a new UUID for each new request. If you get no response (timeout, network error): send exactly the same request with the same key. If the first one has already gone through, you get its response again, with the Idempotent-Replayed: true header, instead of it being done twice.

curl -X POST https://newsletter.qrona.se/api/v1/lists/3f1c2a4e-8b7d-4c1e-9f0a-2d6b5e7c8a91/members \
  -H "Authorization: Bearer $QRONA_NEWSLETTER_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0d6e1c4a-9b2f-4e7d-8a3c-5f1b7e9d2c4a" \
  -d '{ "email": "anna@example.se", "consent": { "text": "Yes, I would like to receive newsletters from Exempel AB." } }'
  • The key is valid for 24 hours and is tied to your API key. It can be 1–255 visible ASCII characters.
  • The same key with a different path or body returns 422 idempotency_key_reused.
  • If the first call is still running, a new one returns 409 idempotency_in_progress: wait and try again.
  • A 5xx response is not saved, so the call is made for real the next time.