PassPassPassPass
DOCS
Documentatie
Updates
Evenement maken
Home
PassPassPassPass

De ticketservice voor evenement organisatoren.

Ontdek PassPass Pro →

Documentatie

Snelle startAlle thema'sAlle artikelenUpdates

Snelle links

PassPass ProVeelgestelde vragenTicket openenNeem contact op

Snelle toegang

© 2024 PassPass. Alle rechten voorbehouden.
Mentions légalesPassPass - Evenement ticketing

Webhooks: technische referentie

Technische referentie voor het ontvangen en verwerken van de webhooks PassPass. Structuur van de payloads, machtigingen, handtekening, herhalingen.

Laatst bijgewerkt : 7 augustus 2026

Dit artikel is bedoeld voor de persoon die de ontvangst van PassPass-webhooks implementeert. Voor een overzicht en de configuratie vanuit het dashboard, raadpleeg Publieke API en Webhooks.


De gegevens begrijpen

Elke webhook bevat een of meer gegevensblokken. Hier is wat elk vertegenwoordigt.

Order (bestelling) : een transactie uitgevoerd door een koper. Bevat het totale bedrag, de betalingsstatus, de identiteit van de koper, de details van de gekochte tickets (line_items), en eventueel de bedrijfsfacturatiegegevens (billing).

Attendees (deelnemers) : een item per ticket in de bestelling. Als een koper 3 tickets neemt, zullen er 3 vermeldingen in attendees zijn. Elke vermelding bevat het type ticket, de status van het ticket, en afhankelijk van uw permissies: de contactgegevens van de deelnemer, de betaalde prijs, de antwoorden op het formulier, en de toegangstoken van het ticket.

Event (evenement) : de basisinformatie van uw PassPass-evenement (titel, data, locatie, status). Dit blok is identiek in alle typen webhooks.

Billing (facturatie) : de bedrijfsgegevens van de koper (naam, BTW, adres). Alleen aanwezig als de koper "ik bestel namens een bedrijf" heeft aangevinkt bij het afrekenen. Anders null.

Form answers (formulierantwoorden) : de antwoorden op de aangepaste velden die u hebt geconfigureerd. Aanwezig op twee niveaus: op bestelniveau (form_answers in order) en op deelnemersniveau (form_answers in elke attendee).

Access token (toegangstoken) : de geheime identificatie achter de QR-code van een ticket, gelezen door de mobiele applicatie PassPass Organizer bij de toegangscontrole. Deze token kan bijvoorbeeld opnieuw worden toegewezen op een badge om een QR-code te repliceren die leesbaar is door de PassPass-ticketcontrole. Wees voorzichtig bij het gebruik ervan: het doorgeven van deze token komt neer op het geven van toegang tot het ticket.


Beschikbare evenementen

Elk type evenement stuurt verschillende gegevensblokken:

  • order.created : bestelling aangemaakt (voor betaling) → order, event, attendees

  • order.paid : betaling bevestigd (inclusief ook voltooide gratis bestellingen) → order, event, attendees

  • order.cancelled : bestelling geannuleerd → order, event, attendees

  • order.expired : winkelwagen verlopen (25 min zonder betaling) → order, event, attendees (leeg)

  • ticket.validated : ticket gescand bij de ingang → scan, participant

  • event.published : evenement gepubliceerd → event

  • event.updated : evenement gewijzigd → event, changed_fields


Permissies (scopes)

De gegevens die in de payload zijn opgenomen, zijn afhankelijk van de permissies die op uw endpoint zijn geconfigureerd. Een niet-geautoriseerd veld is afwezig in de payload, niet null.

  • events:read : event-blok (titel, data, locatie, status)

  • orders:read : basis order-blok (bedrag, koper, billing, line items, status)

  • orders:read:financial : service_fee, payout_amount, refundable_amount, historical_service_fee

  • orders:read:form_answers : antwoorden op het bestelformulier

  • attendees:read : minimaal deelnemersblok (ID, ticket, status, data)

  • attendees:read:contact : first_name, last_name, email

  • attendees:read:financial : ticket_price

  • attendees:read:form_answers : antwoorden op het deelnemersformulier

  • attendees:read:full : access_token (inclusief automatisch contact en financieel)

access_token is de geheime identificatie achter de QR-code van het ticket. Vraag attendees:read:full alleen aan als uw systeem het echt nodig heeft.


Structuur van een payload

Elke webhook is een POST JSON met deze enveloppe:

{
  "type": "order.paid",
  "created_at": "2026-04-17T10:00:00.000Z",
  "data": { }
}

Conventies:

  • Alle velden zijn in snake_case

  • De bedragen zijn in euro's (niet in centen). 25 = 25,00€

  • De datums zijn in ISO 8601 UTC

  • Meertalige velden zijn objecten {"fr": "...", "en": "...", "nl": "..."}

  • Uitzondering: de blokken buyer en billing zijn in camelCase

  • De payload kan nieuwe velden ontvangen zonder voorafgaande kennisgeving. Weiger geen onbekend veld


Volledig voorbeeld: order.paid

Geactiveerd wanneer een betaling is bevestigd, of wanneer een gratis bestelling is voltooid. Dit is het meest gebruikte evenement: het bevestigt dat een deelnemer zijn inschrijving heeft voltooid. Gebruiksscenario: voeg de deelnemer toe aan uw CRM, stuur een welkomstmail, werk uw boekhouding bij, start een workflow in Zapier/Make/n8n.

{
  "type": "order.paid",
  "created_at": "2026-04-17T10:00:00.000Z",
  "data": {
    "order": {
      "id": 65817,
      "event_id": 1535,
      "status": "paid",
      "origin": "online",
      "currency": "EUR",
      "amount_total": 200,
      "buyer": {
        "firstName": "Marie",
        "lastName": "Dupont",
        "email": "marie@example.com"
      },
      "billing": {
        "identifierType": "vat",
        "companyName": "Demo Corp SRL",
        "vat": "BE0123456789",
        "vatCountry": "BE",
        "addressStreet": "Rue de la Loi 1",
        "addressCity": "Bruxelles",
        "addressZip": "1000",
        "addressCountry": "BE"
      },
      "line_items": [
        {
          "type": "ticket",
          "ticket_id": 4525,
          "name": {"fr": "Entrée Standard"},
          "quantity": 2,
          "unit_amount": 100,
          "subtotal": 200
        }
      ],
      "form_answers": null,
      "paid_at": "2026-04-17T10:00:00.000Z",
      "cancelled_at": null,
      "created_at": "2026-04-17T10:00:00.000Z",
      "updated_at": "2026-04-17T10:00:00.000Z",
      "service_fee": 4.6,
      "payout_amount": 195.4,
      "refundable_amount": 4.6,
      "historical_service_fee": 4.6
    },
    "event": {
      "id": 1535,
      "title": {"fr": "Mon événement"},
      "short_description": {"fr": "Description courte"},
      "address_label": {"fr": "Bruxelles"},
      "locality_type": "physical",
      "start_at": "2026-06-01T18:00:00.000Z",
      "end_at": "2026-06-01T23:00:00.000Z",
      "timezone": "Europe/Brussels",
      "currency": "EUR",
      "status": "published",
      "visibility": "public"
    },
    "attendees": [
      {
        "id": "019fdb0d-...",
        "event_id": 1535,
        "order_id": 65817,
        "status": "active",
        "ticket": {
          "id": 4525,
          "type": "ticket",
          "name": {"fr": "Entrée Standard"}
        },
        "first_name": "Marie",
        "last_name": "Dupont",
        "email": "marie@example.com",
        "ticket_price": 100,
        "access_token": "019fdb0d-...",
        "created_at": "2026-04-17T10:00:00.000Z",
        "updated_at": "2026-04-17T10:00:00.000Z",
        "form_answers": [
          {
            "type": "selection",
            "field_id": "abc123...",
            "question_title": {"fr": "Quel est votre statut actuel ?"},
            "answer": {"fr": "Indépendant"}
          },
          {
            "type": "unique-choice",
            "field_id": "def456...",
            "question_title": {"fr": "Régime alimentaire"},
            "answer": {"fr": "Végétarien"}
          },
          {
            "type": "short-text",
            "field_id": "ghi789...",
            "question_title": {"fr": "Nom entreprise"},
            "answer": "Demo Corp"
          },
          {
            "type": "formatted-field",
            "field_id": "jkl012...",
            "question_title": {"fr": "Téléphone"},
            "answer": "+32400000000"
          },
          {
            "type": "formatted-field",
            "field_id": "mno345...",
            "question_title": {"fr": "Code postal"},
            "answer": "1000"
          }
        ]
      }
    ]
  }
}

Voorbeeld: ticket.validated

Geactiveerd wanneer een ticket wordt gescand via de mobiele applicatie PassPass Organizer. Gebruiksscenario: een aanwezigheidsbord in realtime bijwerken, een badge afdrukken, een melding naar uw team sturen bij de aankomst van een VIP.

{
  "type": "ticket.validated",
  "created_at": "2026-04-17T10:00:00.000Z",
  "data": {
    "scan": {
      "id": "019d-...",
      "type": "scan",
      "direction": "enter",
      "created_at": "2026-04-17T10:00:00.000Z"
    },
    "participant": {
      "id": "019fdb0d-...",
      "event_id": 1535,
      "order_id": 65817,
      "status": "active",
      "ticket": {
        "id": 4525,
        "type": "ticket",
        "name": {"fr": "Entrée Standard"}
      },
      "first_name": "Marie",
      "last_name": "Dupont",
      "email": "marie@example.com",
      "ticket_price": 100,
      "created_at": "2026-04-17T10:00:00.000Z",
      "updated_at": "2026-04-17T10:00:00.000Z"
    }
  }
}

Voorbeeld: event.updated

Geactiveerd wanneer een gevolgd veld van uw evenement wordt gewijzigd (titel, data, locatie, beschrijving, status...). De payload bevat de status van het evenement na wijziging en de lijst met gewijzigde velden. Gebruiksscenario: synchroniseer de evenementinformatie op uw website, informeer uw team over een datum- of locatieverandering.

{
  "type": "event.updated",
  "created_at": "2026-04-17T10:00:00.000Z",
  "data": {
    "event": {
      "id": 1535,
      "title": {"fr": "Mon événement (modifié)"},
      "short_description": {"fr": "Nouvelle description"},
      "address_label": {"fr": "Bruxelles"},
      "locality_type": "physical",
      "start_at": "2026-06-01T18:00:00.000Z",
      "end_at": "2026-06-01T23:00:00.000Z",
      "timezone": "Europe/Brussels",
      "currency": "EUR",
      "status": "published",
      "visibility": "public"
    },
    "changed_fields": ["title", "short_description"]
  }
}

Handtekeningverificatie

Elke aanvraag bevat een handtekeningheader:

x-passpass-signature: t=1776412800,v1=9f2c...

De handtekening is een HMAC-SHA256 berekend met uw geheim (whsec_...) op de string <timestamp>.<ruwe inhoud van de aanvraag>.

Node.js :

const crypto = require('crypto');

function verify(rawBody, header, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(
    header.split(',').map((kv) => kv.split('='))
  );
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  const a = Buffer.from(expected, 'hex');
  const b = Buffer.from(parts.v1 || '', 'hex');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Python :

import hmac, hashlib, time

def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(kv.split("=", 1) for kv in header.split(","))
    ts = int(parts.get("t", 0))
    if not ts or abs(time.time() - ts) > tolerance:
        return False
    expected = hmac.new(
        secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Weiger aanvragen waarvan de timestamp ouder is dan 5 minuten.


HTTP-headers

Elke webhook-aanvraag bevat deze headers:

  • x-passpass-event : type evenement (bijv. order.paid). Maakt routering mogelijk zonder de inhoud te parseren

  • x-passpass-signature : HMAC-handtekening om de authenticiteit te verifiëren

  • x-passpass-timestamp : Unix-timestamp (seconden) gebruikt in de handtekening

  • x-passpass-idempotency-key : deduplicatiesleutel. Stabiel voor hetzelfde evenement, inclusief bij herhalingen. Dedupliceer op dit veld aan de ontvangende kant

  • x-passpass-delivery-id : unieke identificatie van de leveringspoging. Handig voor debugging


Herhalingen en deactivering

Uw endpoint moet antwoorden HTTP 2xx binnen 10 seconden. Elke andere code, een timeout of een netwerkfout telt als een mislukking.

Bij een mislukking probeert PassPass 6 keer opnieuw met een exponentiële backoff: 1, 2, 4, 8, 16, 32 minuten.

Na 20 opeenvolgende mislukkingen, wordt het endpoint automatisch gedeactiveerd. Het moet handmatig opnieuw worden geactiveerd vanuit uw dashboard. Een succes reset de teller naar nul.

Bevestig onmiddellijk ontvangst (HTTP 200) en verwerk op de achtergrond. Als de verwerking lang duurt, laat PassPass dan niet wachten.


Test uw endpoint

Vanuit uw dashboard (Instellingen → Ontwikkelaars), klik op Testen op uw endpoint. PassPass stuurt een demonstratiepayload naar uw URL om de verbinding en handtekeningverificatie te valideren.

De testpayloads gebruiken herkenbare identificaties: ID's vanaf 9 999 000, email demo@passpass.be, namen "Demo ...".

De leveringsgeschiedenis is toegankelijk vanuit uw dashboard. Elke verzending (succesvol of mislukt) wordt daar geregistreerd met de antwoordcode van uw server.


Voor technische vragen of behoefte aan begeleiding, neem gerust contact op met onze support.

Neem contact met ons op

Gerelateerde artikelen

3 artikelen in deze categorie