Integration API
Connect your badge and check-in system to Abundance Events: six endpoints for events, registrants, types and scan-in, plus registration webhooks.
How it works
- Give us your HTTPS webhook receiver URL. Start queuing received events before importing registrations.
- List the events granted to your key, then fetch event details and registrant types.
- Import all pages of registrants. Store each registration by event ID and registration ID, with its version.
- Apply queued and live webhooks only when their version is greater than the version you have stored. Retain deletion versions as tombstones.
- Scan the ticket QR, then PATCH the registration’s check-in with the scan time and location. Display the returned outcome and message.
- Print the badge using the registration ID as its QR text.
The paginated import is a bounded traversal, not a frozen snapshot. Webhook overlap and version checks keep changes during the import from being lost or overwritten.
Base URL
Send requests to https://api.events.abundance.institute. Paths start with /v1/integrations/events. Ask us for a test event and key before integrating with a live event.
Authentication
Authorization: Bearer ek_...We issue your API key with an expiration date and an explicit event allowlist. One vendor key can access several granted events. Keys can be revoked or rotated; disabling the integration stops both API access and webhook delivery.
| Scope | Allows |
|---|---|
checkin:read | Granted events, paginated registrants, individual registrants and registrant types. |
checkin:write | Record scan-in time and location. |
Keep the key on your server or in managed devices. Do not put it in URLs, logs or shared documents.
Quickstart
export API_KEY="ek_..."
# Discover the events granted to your integration
curl "https://api.events.abundance.institute/v1/integrations/events" -H "Authorization: Bearer $API_KEY"
export EVENT_ID="<id from the event list>"
# Import every page; pass nextCursor back as cursor until it is null
curl "https://api.events.abundance.institute/v1/integrations/events/$EVENT_ID/registrants?limit=100" -H "Authorization: Bearer $API_KEY"
export REGISTRATION_ID="<plain ID scanned from the QR>"
# Record scan-in time and location
curl -X PATCH "https://api.events.abundance.institute/v1/integrations/events/$EVENT_ID/registrants/$REGISTRATION_ID/check-in" \
-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
-d '{"time":"2027-01-20T21:04:00Z","location":"Registration desk 2"}'The API reference lists all six endpoints, fields and examples.
Conventions
- Requests and responses use JSON and camelCase field names.
- IDs are opaque CUID strings. Registrant types have stable identifiers such as
speaker; ticket products have a separateticketTypeId. - Send timestamps in ISO 8601 with Z or an explicit offset. Responses use UTC; display them in the event’s time zone.
- Registrant pages default to 100 items, with a maximum of 500. Keep the same key, event and limit when following cursors. Cursors expire after 24 hours.
- Unfinished payment registrations are excluded. Pending approval, waitlisted, cancelled and declined registrations remain visible, but only confirmed registrations can check in.
- Repeated and concurrent check-in PATCH requests return the first admission and preserve its original time and location.
The ticket QR
The QR text is exactly registrationId, with no URL, prefix or secret:
cm2k9a1bc0004reg8hd2m5k3qUse the same plain ID in the app, wallet and printed badge. Our scanners also accept previously issued legacy ep1 codes during migration. A transfer issues a replacement registration ID and deletes the previous registration; consume both webhooks so the old QR is removed from your local roster.
Offline scanning requires a recently synchronized roster. Queue scan-ins with their original time and send them when connectivity returns. Revocations and transfers cannot reach a device while it is offline.
Registration webhooks
We POST registration.created, registration.modified and registration.deleted to your configured receiver. Created and modified events contain the same Registrant object as the API; deletion events contain null data and the registration ID/version tombstone. Cancellation is a modified event with cancelled status.
{
"id": "a6ae4401-3c86-4c37-9a46-a176c03a563b",
"type": "registration.created",
"eventId": "cm2k8v3qz0001evt7jx4n2p9a",
"registrationId": "cm2k9a1bc0004reg8hd2m5k3q",
"version": 1,
"occurredAt": "2027-01-20T20:58:12.000Z",
"data": {
"registrationId": "cm2k9a1bc0004reg8hd2m5k3q",
"eventId": "cm2k8v3qz0001evt7jx4n2p9a",
"version": 1,
"qrPayload": "cm2k9a1bc0004reg8hd2m5k3q",
"status": "confirmed",
"firstName": "Maya",
"lastName": "Chen",
"organization": "Northwind Energy",
"title": "Head of Partnerships",
"kind": "attendee",
"registrantTypeId": "attendee",
"ribbonLabel": "ATTENDEE",
"isVip": false,
"ticketTypeId": "cm2k8w0de0002tkt6fh3n8r1s",
"ticketName": "General",
"sponsor": null,
"table": null,
"accessSubEventIds": [],
"badgePrintedAt": null,
"checkIns": [],
"updatedAt": "2027-01-20T20:58:12.000Z"
}
}Verify the raw body before parsing it. The headers are X-Events-Id, X-Events-Timestamp (Unix seconds) and X-Events-Signature:
sha256=<hex HMAC-SHA256(shared_secret, timestamp + "." + raw_body)>Use a constant-time signature comparison and reject timestamps outside a five-minute tolerance. The shared signing secret is separate from your API key.
Persist the event to a durable queue, then return a 2xx response within 10 seconds. Delivery is at least once; duplicates and out-of-order events are possible. Deduplicate by event ID and apply snapshots only when their registration version is newer. We retry failures with exponential backoff up to eight attempts. Contact us to replay exhausted deliveries or request a full reconciliation.
Errors
{
"error": {
"code": "validation_failed",
"message": "Some fields need attention.",
"fields": {
"time": "Invalid ISO datetime"
}
}
}| Status | Code | Means |
|---|---|---|
| 400 | validation_failed | Invalid fields or cursor. error.fields identifies the problem. |
| 401 | unauthorized | Missing, invalid, expired or revoked key, or disabled integration. |
| 403 | forbidden | Event is outside the allowlist, or the key lacks the required scope. |
| 404 | not_found | Unknown or deleted registrant, including a registration from another event. |
| 429 | rate_limited | Wait and retry. |
| 500 | internal | Retry. Repeated check-in PATCH requests do not create duplicate admissions. |
Admission outcomes such as not_confirmed are successful HTTP responses with a null checkIn. Show the message and send the attendee to the help desk.
Coming from Cvent
| Cvent | Here |
|---|---|
| Attendee ID or confirmation number | registrationId (CUID, treated as an opaque string) |
| Barcode | qrPayload, exactly equal to registrationId |
| Registration type | registrantTypeId; ticket product is ticketTypeId |
| Registration status | status |
| Check-in date and time | checkIns[].at; send time in the PATCH body |
Handling attendee data
The API exposes badge and admission information. Email, phone, notes, dietary details, answers and QR secrets are excluded. Use the data for event check-in and badge printing, protect your local roster, and delete it within 30 days after the event under your agreement with us.
Questions? Write to [email protected].