Webhook events
milestone.reversed
Sent when a report is reversed. Reversing a report that is already reversed sends nothing. rewardIds lists every reward for the person and milestone. The report's own rewards and bonuses whose count fell below their saved threshold reverse and also send reward.reversed.
Example payload
This illustrative payload follows the current event validator. Amounts use minor units.
json
{
"id": "00000000-0000-4000-8000-000000000001",
"companyId": "company-example",
"type": "milestone.reversed",
"data": {
"partners": [
{
"partnerId": "partner-example",
"partnerExternalId": "merchant-partner-001"
}
],
"eventId": "payment-example",
"customerId": "customer-example",
"milestone": "first_booking",
"status": "reversed",
"programIds": [
"program-example"
],
"rewardIds": [
"reward-example"
],
"reportEventId": "reportEventId-example",
"reversalCents": 500,
"reversedAt": "2026-10-11T12:00:00.000Z"
},
"createdAt": "2026-10-11T12:00:00.000Z"
}Payload fields
| Field | Type | Required | Details |
|---|---|---|---|
partners | array | Yes | |
partnerId | string | No | |
partnerExternalId | string | No | |
eventId | string | Yes | |
customerId | string | Yes | |
milestone | string | Yes | |
status | "recorded", "revoked", "reinstated", "reversed" | Yes | |
programIds | array | Yes | |
rewardIds | array | Yes | |
count | integer | No | minimum 0 |
reportEventId | string | Yes | |
reason | string | No | |
reversalCents | integer | Yes | minimum 0. maximum 9007199254740991 |
reversedAt | string | Yes | date-time |
partners[]
| Field | Type | Required | Details |
|---|---|---|---|
partners.partnerId | string | Yes | |
partners.partnerExternalId | string | Yes |
Payload schema
json
{
"type": "object",
"properties": {
"partners": {
"type": "array",
"items": {
"type": "object",
"properties": {
"partnerId": {
"type": "string",
"minLength": 1
},
"partnerExternalId": {
"type": "string",
"minLength": 1
}
},
"required": [
"partnerId",
"partnerExternalId"
],
"additionalProperties": true
}
},
"partnerId": {
"type": "string",
"minLength": 1
},
"partnerExternalId": {
"type": "string",
"minLength": 1
},
"eventId": {
"type": "string",
"minLength": 1
},
"customerId": {
"type": "string",
"minLength": 1
},
"milestone": {
"type": "string",
"minLength": 1
},
"status": {
"type": "string",
"enum": [
"recorded",
"revoked",
"reinstated",
"reversed"
]
},
"programIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"rewardIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"count": {
"type": "integer",
"minimum": 0
},
"reportEventId": {
"type": "string",
"minLength": 1
},
"reason": {
"type": "string"
},
"reversalCents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"reversedAt": {
"type": "string",
"format": "date-time"
}
},
"required": [
"partners",
"eventId",
"customerId",
"milestone",
"status",
"programIds",
"rewardIds",
"reportEventId",
"reversalCents",
"reversedAt"
],
"additionalProperties": true
}Handle delivery
Verify the signature over the raw body before parsing JSON. Check that the body ID matches Grizzlee-Event-Id. Process each ID once, since delivery can repeat.