API & integrations · updated 2026-05-02
Webhooks — sign-verify-deliver
Receive HMAC-signed POSTs on every scan, profile update, billing event.
Webhooks
QR NFC Tap POSTs events to your URL when interesting things happen.
Events
qr.scanned— every scan of any of your QRsqr.created,qr.updated,qr.deletedlead-form.submitted— when someone fills your Lead Form QRbooking.created,booking.cancelledsubscription.upgraded,subscription.cancelledwallet-pass.installed
Configure
Dashboard → API → Webhooks → Add endpoint. Pick:
- URL (HTTPS only)
- Events to subscribe to
- Signing secret — auto-generated, shown once
Signature verification
Every POST has X-Tapcard-Signature header:
X-Tapcard-Signature: t=1714665600,v1=ab23cd45...
t = unix timestamp; v1 = HMAC-SHA256 of {t}.{body} using your signing secret.
To verify (PHP example):
$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $signingSecret);
$valid = hash_equals($expected, $signatureFromHeader);
Reject if invalid OR if t is more than 5 minutes old (replay protection).
Delivery + retries
- Initial delivery: within 1 second of the event
- Retry on non-2xx: at 1m, 5m, 30m, 2h, 6h, 12h, 24h (7 attempts)
- After 7 failures: webhook is paused; we email you. Re-enable in dashboard once your endpoint is back.
Idempotency
Each event has an id in the body. Use this to deduplicate — we may re-send under network conditions; idempotency keys mean your handler stays safe.
Tier availability
- Free / Pro: read-only signed webhooks (delivery, no security guarantees)
- Business+: full HMAC-signed webhooks with replay protection (the version described above)
Security recommendations
- Use HTTPS endpoints only — we will not POST to plain HTTP
- Verify signature on every request, never trust the body alone
- Enforce
tfreshness (we recommend ≤ 5 minutes) - Log webhook deliveries for at least 30 days for incident response
Was this helpful?
Thanks — logged.