Create a webhook
Direct API-key requests use the normal 24-hour idempotency response
cache. For OAuth REST-hook clients, the idempotency key remains bound
to the live subscription until DELETE. A retry with the same event set
returns that row; use PATCH to apply a current URL, card, mode, or active
state. client_hmac subscriptions return their signing secret on create
and OAuth idempotent replay. OAuth-only server_attested subscriptions
keep the signing secret inside Perkstar and omit it from every response.
Reusing the key for a different event set or verification mode returns
an idempotency conflict.
curl --request POST \
--url https://dashboard.perkstar.co.uk/api/v1/webhooks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>'})
};
fetch('https://dashboard.perkstar.co.uk/api/v1/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://dashboard.perkstar.co.uk/api/v1/webhooks"
payload = { "url": "<string>" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dashboard.perkstar.co.uk/api/v1/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"id": "<string>",
"url": "<string>",
"description": "<string>",
"events": [
"customer.enrolled"
],
"card_id": "<string>",
"mode": "all",
"verification_mode": "client_hmac",
"is_active": true,
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"secret": "<string>"
}{
"id": "<string>",
"url": "<string>",
"description": "<string>",
"events": [
"customer.enrolled"
],
"card_id": "<string>",
"mode": "all",
"verification_mode": "client_hmac",
"is_active": true,
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"secret": "<string>"
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Replay-safe request key. Repeated requests with the same value within 24h return the original response unchanged.
255Body
Empty means subscribe to every event.
Stable dotted wire-format name for an outbound event.
customer.enrolled, customer.unenrolled, customer.anonymized, customer.group_changed, wallet.installed, card.scanned, card.expired, referral.created, transaction.created, coupon.redeemed, reward.redeemed, tier.changed, ticket.purchased, ticket.cancelled, ticket.refunded, gift.purchased, gift.redeemed, multipass.purchased, membership.purchased, membership.renewed, membership.cancelled, feedback.submitted, automation.fired, broadcast.sent, booking.created, booking.confirmed, booking.attended, booking.no_show, booking.cancelled, webhook.test Optional card in the same business. Events without this card ID are not delivered.
Filter delivery by live/test activity before creating an outbound attempt. all preserves the default generic-webhook behaviour.
all, live, test server_attested is OAuth-only and never releases the signing
secret. The mode is immutable after creation.
client_hmac, server_attested Create the webhook paused when false; activate it later with PATCH.
Response
OAuth idempotent replay of the same live subscription. secret is present only for client_hmac.
Empty means subscribe to every event.
Stable dotted wire-format name for an outbound event.
customer.enrolled, customer.unenrolled, customer.anonymized, customer.group_changed, wallet.installed, card.scanned, card.expired, referral.created, transaction.created, coupon.redeemed, reward.redeemed, tier.changed, ticket.purchased, ticket.cancelled, ticket.refunded, gift.purchased, gift.redeemed, multipass.purchased, membership.purchased, membership.renewed, membership.cancelled, feedback.submitted, automation.fired, broadcast.sent, booking.created, booking.confirmed, booking.attended, booking.no_show, booking.cancelled, webhook.test Optional card filter applied before a delivery is created. Null receives matching events from every card.
Filter delivery by live/test activity before creating an outbound attempt. all preserves the default generic-webhook behaviour.
all, live, test Immutable authenticity contract. client_hmac exposes the signing
secret once so the receiver verifies the exact raw body.
OAuth-only server_attested keeps that secret inside Perkstar and
verifies the parsed event through the delivery-verification endpoint.
client_hmac, server_attested Present only for client_hmac; never returned for server_attested.
Was this page helpful?
curl --request POST \
--url https://dashboard.perkstar.co.uk/api/v1/webhooks \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "<string>"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>'})
};
fetch('https://dashboard.perkstar.co.uk/api/v1/webhooks', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://dashboard.perkstar.co.uk/api/v1/webhooks"
payload = { "url": "<string>" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dashboard.perkstar.co.uk/api/v1/webhooks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"id": "<string>",
"url": "<string>",
"description": "<string>",
"events": [
"customer.enrolled"
],
"card_id": "<string>",
"mode": "all",
"verification_mode": "client_hmac",
"is_active": true,
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"secret": "<string>"
}{
"id": "<string>",
"url": "<string>",
"description": "<string>",
"events": [
"customer.enrolled"
],
"card_id": "<string>",
"mode": "all",
"verification_mode": "client_hmac",
"is_active": true,
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"secret": "<string>"
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"code": "<string>",
"param": "<string>"
}
}
