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

# Polling-endpoints

> Haal storekit-webhook-events per GET in batches op via een polling-endpoint, zonder een publieke HTTPS-URL beschikbaar te stellen. Commit de offset per batch.

Een polling-endpoint levert dezelfde stroom aan events als een webhook-endpoint, maar je haalt ze op met een GET-verzoek in plaats van dat storekit ze naar een publieke URL pusht. Elke poll geeft een batch berichten terug in de volgorde waarin ze zijn ontvangen. Je verwerkt de batch, commit hoe ver je bent gekomen, en de volgende poll gaat daar verder.

## Wanneer polling gebruiken

Polling is handig in situaties waarin een publiek HTTPS-endpoint onhandig of onnodig is:

* **Lokale ontwikkeling**, poll vanaf je laptop zonder ngrok of tunnel
* **Privénetwerken**, de consumerende service mag niet vanaf het internet bereikbaar zijn
* **Batchverwerking**, je wilt alle events van de dag in één keer, bijvoorbeeld om orders te archiveren voor compliance of om uitbetalingen 's nachts af te stemmen
* **Systemen die geen HTTP kunnen ontvangen**, een cronjob, een datapijplijn of een script

Heb je events binnen enkele seconden na ontvangst nodig, gebruik dan een gewoon webhook-endpoint. Polling- en webhook-endpoints kunnen naast elkaar draaien op hetzelfde account, gefilterd op dezelfde of andere eventtypes.

## Een polling-endpoint aanmaken

1. Open de webhookpagina (**Settings** → **Developers** → **Manage Webhooks**)
2. Voeg in de ingebouwde webhooks-portal een nieuw endpoint toe en kies het type polling-endpoint
3. Selecteer de eventtypes die je wilt ontvangen
4. Sla het endpoint op

De portal toont vervolgens twee zaken die je bij elk verzoek nodig hebt:

| Value | Example | Beschrijving |
| - | - | - |
| Polling-URL | `https://api.svix.com/api/v1/app/app_xxx/polling-endpoint/poll_xxx/consumer/{consumer_id}` | Uniek voor dit endpoint. Kopieer hem exact zoals getoond (de host is afhankelijk van de regio) en vervang `{consumer_id}` door je eigen identifier |
| API-sleutel | `sk_poll_*****` | Verstuurd als Bearer-token. Wordt eenmalig getoond, bewaar hem veilig |

> [!WARNING]
>
> De API-sleutel geeft leesrechten op elk event waarop het endpoint is geabonneerd, inclusief klantnamen en contactgegevens in orderpayloads. Behandel hem als elk ander productiesecret.

## Events ophalen

Stuur een GET-verzoek naar de polling-URL met je API-sleutel:

```bash theme={null}
curl -X GET "https://api.svix.com/api/v1/app/app_xxx/polling-endpoint/poll_xxx/consumer/kitchen-archive" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_poll_*****"
```

Het antwoord is een batch berichten. De `payload` van elk bericht is exact de JSON-body die een webhook-endpoint zou ontvangen (de `{ event, data }`-envelop uit het [payload-formaat](/docs/nl/developers/webhooks/payload-format)), aangevuld met berichtmetadata en een `offset`:

```json theme={null}
{
  "data": [
    {
      "id": "msg_2K2N9Qk...",
      "eventType": "order.created",
      "payload": {
        "event": "order.created",
        "data": {
          "id": 123456,
          "status": "created",
          "venue": { "id": 789, "name": "Pizza Palace" },
          "total": 2450
        }
      },
      "timestamp": "2025-01-17T12:00:00.000Z",
      "offset": 0
    }
  ],
  "done": true
}
```

| Field | Beschrijving |
| - | - |
| `data` | Berichten in de volgorde waarin ze zijn ontvangen. Leeg als er niets nieuws is |
| `data[].payload` | De webhook-body: `payload.event` geeft de naam van het event, `payload.data` bevat de eventdata |
| `data[].offset` | Positie van het bericht in de stroom. Commit deze waarde zodra het verwerkt is |
| `done` | `true` als deze batch het einde van de stroom heeft bereikt. `false` betekent dat je direct opnieuw moet pollen voor meer |

Handtekeningverificatie is niet van toepassing. Het verzoek wordt geauthenticeerd via je API-sleutel in plaats van via een ondertekende bezorging.

## Je positie committen

Commit na het verwerken van een batch de `offset` van het laatste bericht dat je hebt afgehandeld:

```bash theme={null}
curl -X POST "https://api.svix.com/api/v1/app/app_xxx/polling-endpoint/poll_xxx/consumer/kitchen-archive/commit" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_poll_*****" \
  -d '{ "offset": 0 }'
```

Zolang je niet committet, worden dezelfde berichten opnieuw uitgegeven zodra hun lease verloopt. Dat is bewust zo: als je worker halverwege een batch crasht, gaat er niets verloren. Het betekent ook dat je handler idempotent moet zijn. Zie [Idempotentie](/docs/nl/developers/webhooks/advanced/idempotency).

## Consumer-ID's

De `{consumer_id}` in de URL is een string die je zelf kiest. Elke consumer-ID houdt zijn eigen positie in de stroom bij, zodat twee consumers die hetzelfde endpoint lezen beide elk event ontvangen.

* Gebruik een **stabiele** ID per worker (`kitchen-archive`, `finance-reconciliation`), zodat de voortgang herstarts overleeft
* Deel nooit één consumer-ID tussen gelijktijdig draaiende clients. Twee processen die als dezelfde consumer pollen, drijven uit elkaar in de stroom en de API geeft fouten terug

> [!NOTE]
>
> De stroom begint op het moment dat het polling-endpoint wordt aangemaakt. Events die daarvoor zijn verstuurd, worden niet meegenomen.

## Een typische polling-loop

```javascript theme={null}
const URL = process.env.STOREKIT_POLL_URL;   // includes your consumer id
const KEY = process.env.STOREKIT_POLL_KEY;

async function pollOnce() {
  let done = false;
  while (!done) {
    const res = await fetch(URL, {
      headers: { Accept: 'application/json', Authorization: `Bearer ${KEY}` },
    });
    const body = await res.json();

    for (const msg of body.data) {
      await handleEvent(msg.payload.event, msg.payload.data);
    }

    if (body.data.length > 0) {
      const last = body.data[body.data.length - 1];
      const commit = await fetch(`${URL}/commit`, {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
          Authorization: `Bearer ${KEY}`,
        },
        body: JSON.stringify({ offset: last.offset }),
      });
      if (!commit.ok) throw new Error(`Commit failed: ${commit.status}`);
    }

    done = body.done;
  }
}
```

Draai `pollOnce()` op het schema dat bij je past: elke paar seconden voor bijna realtime, of eenmaal per nacht voor een dagelijkse export.

## Doorsturen naar een privéservice

Wil je liever webhook-achtige HTTP-bezorging behouden, maar staat je service in een privénetwerk, draai dan [Svix Bridge](https://github.com/svix/svix-webhooks/tree/main/bridge) binnen dat netwerk. Bridge pollt het endpoint en stuurt elk bericht door naar een interne URL, RabbitMQ of Kafka, met retries wanneer een van beide kanten tijdelijk onbereikbaar is. De pagina van het polling-endpoint in de ingebouwde portal bevat een startconfiguratie voor Bridge waarin de app-ID en endpoint-ID al zijn ingevuld.

## Gerelateerd

> **[Webhooks instellen](/docs/nl/developers/webhooks/setting-up-webhooks)**
>
> Push-bezorging naar een publiek HTTPS-endpoint

> **[Idempotentie](/docs/nl/developers/webhooks/advanced/idempotency)**
>
> Verwerk hetzelfde event meerdere keren op een veilige manier

> **[Webhook-events](/docs/nl/developers/webhooks/webhook-events)**
>
> Elk eventtype waarop je je kunt abonneren

> **[Webhooks testen](/docs/nl/developers/webhooks/testing-webhooks)**
>
> Bekijk bezorgingen en verstuur testevents


## Related topics

- [MCP-endpoint](/docs/nl/developers/agents/ordering/mcp-endpoint.md)
- [Bestellingen mislukken: kassa slaapt](/docs/nl/guides/integrations/pos/syrve/till-offline.md)
- [Retry-beleid](/docs/nl/developers/webhooks/retry-policy.md)
- [Webhooks instellen](/docs/nl/developers/webhooks/setting-up-webhooks.md)
- [Webhook-problemen oplossen](/docs/nl/developers/webhooks/troubleshooting.md)


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