Verify a server-attested webhook delivery
OAuth-only callback proof endpoint for approved automation connectors.
It binds the parsed event and retention-bounded Perkstar delivery headers to
the exact outbound attempt committed before dispatch. Authenticated
proof failures deliberately return the same { "verified": false }
response so webhook IDs, delivery IDs, and proof state cannot be
enumerated. Ordinary client-managed HMAC integrations do not use this
endpoint.
curl --request POST \
--url https://dashboard.perkstar.co.uk/api/v1/webhooks/deliveries/verify \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"webhook_id": "<string>",
"delivery_id": "<string>",
"timestamp": 1,
"signature": "<string>",
"event": {
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"cardId": "card_123",
"type": "STAMP",
"delta": 1,
"balanceAfter": 6,
"occurredAt": "2026-07-30T10:00:00.000Z"
}
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
webhook_id: '<string>',
delivery_id: '<string>',
timestamp: 1,
signature: '<string>',
event: {
id: 'whd_01JEXAMPLE',
type: 'transaction.created',
created: 1785312000,
orgId: 'org_123',
data: {
transactionId: 'txn_123',
enrollmentId: 'enr_123',
cardId: 'card_123',
type: 'STAMP',
delta: 1,
balanceAfter: 6,
occurredAt: '2026-07-30T10:00:00.000Z'
}
}
})
};
fetch('https://dashboard.perkstar.co.uk/api/v1/webhooks/deliveries/verify', 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/deliveries/verify"
payload = {
"webhook_id": "<string>",
"delivery_id": "<string>",
"timestamp": 1,
"signature": "<string>",
"event": {
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"cardId": "card_123",
"type": "STAMP",
"delta": 1,
"balanceAfter": 6,
"occurredAt": "2026-07-30T10:00:00.000Z"
}
}
}
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/deliveries/verify",
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([
'webhook_id' => '<string>',
'delivery_id' => '<string>',
'timestamp' => 1,
'signature' => '<string>',
'event' => [
'id' => 'whd_01JEXAMPLE',
'type' => 'transaction.created',
'created' => 1785312000,
'orgId' => 'org_123',
'data' => [
'transactionId' => 'txn_123',
'enrollmentId' => 'enr_123',
'cardId' => 'card_123',
'type' => 'STAMP',
'delta' => 1,
'balanceAfter' => 6,
'occurredAt' => '2026-07-30T10:00:00.000Z'
]
]
]),
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;
}{
"verified": false
}{
"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
Three-legged OAuth 2.0 with PKCE for marketplace integrations.
Endpoints (NOT under /api/v1):
• Authorization: https://dashboard.perkstar.co.uk/oauth/authorize
• Token: https://dashboard.perkstar.co.uk/api/oauth/token
• Revocation: https://dashboard.perkstar.co.uk/api/oauth/revoke
Access tokens last 1 hour; refresh tokens last 90 days and rotate on each use. Reuse of a rotated refresh token revokes the entire grant per RFC 6749 §10.4.
Body
120120Unix seconds copied from X-Perkstar-Timestamp.
x >= 0Exact value copied from X-Perkstar-Signature.
100^t=\d{1,12},v1=[a-fA-F0-9]{64}$Show child attributes
Show child attributes
{
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"cardId": "card_123",
"type": "STAMP",
"delta": 1,
"balanceAfter": 6,
"occurredAt": "2026-07-30T10:00:00.000Z"
}
}
Response
Verified event or a generic authenticated proof failure
- Option 1
- Option 2
Was this page helpful?
curl --request POST \
--url https://dashboard.perkstar.co.uk/api/v1/webhooks/deliveries/verify \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"webhook_id": "<string>",
"delivery_id": "<string>",
"timestamp": 1,
"signature": "<string>",
"event": {
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"cardId": "card_123",
"type": "STAMP",
"delta": 1,
"balanceAfter": 6,
"occurredAt": "2026-07-30T10:00:00.000Z"
}
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
webhook_id: '<string>',
delivery_id: '<string>',
timestamp: 1,
signature: '<string>',
event: {
id: 'whd_01JEXAMPLE',
type: 'transaction.created',
created: 1785312000,
orgId: 'org_123',
data: {
transactionId: 'txn_123',
enrollmentId: 'enr_123',
cardId: 'card_123',
type: 'STAMP',
delta: 1,
balanceAfter: 6,
occurredAt: '2026-07-30T10:00:00.000Z'
}
}
})
};
fetch('https://dashboard.perkstar.co.uk/api/v1/webhooks/deliveries/verify', 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/deliveries/verify"
payload = {
"webhook_id": "<string>",
"delivery_id": "<string>",
"timestamp": 1,
"signature": "<string>",
"event": {
"id": "whd_01JEXAMPLE",
"type": "transaction.created",
"created": 1785312000,
"orgId": "org_123",
"data": {
"transactionId": "txn_123",
"enrollmentId": "enr_123",
"cardId": "card_123",
"type": "STAMP",
"delta": 1,
"balanceAfter": 6,
"occurredAt": "2026-07-30T10:00:00.000Z"
}
}
}
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/deliveries/verify",
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([
'webhook_id' => '<string>',
'delivery_id' => '<string>',
'timestamp' => 1,
'signature' => '<string>',
'event' => [
'id' => 'whd_01JEXAMPLE',
'type' => 'transaction.created',
'created' => 1785312000,
'orgId' => 'org_123',
'data' => [
'transactionId' => 'txn_123',
'enrollmentId' => 'enr_123',
'cardId' => 'card_123',
'type' => 'STAMP',
'delta' => 1,
'balanceAfter' => 6,
'occurredAt' => '2026-07-30T10:00:00.000Z'
]
]
]),
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;
}{
"verified": false
}{
"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>"
}
}
