Skip to content
Developer docs
⌘ K
Dashboard ↗

Webhook events

milestone.revoked

Sent when a milestone is revoked for a person. Revoking it again while it is revoked sends nothing. After a reinstatement, the next revocation sends it again.

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.revoked",
  "data": {
    "partners": [
      {
        "partnerId": "partner-example",
        "partnerExternalId": "merchant-partner-001"
      }
    ],
    "eventId": "payment-example",
    "customerId": "customer-example",
    "milestone": "first_booking",
    "status": "revoked",
    "programIds": [
      "program-example"
    ],
    "rewardIds": [
      "reward-example"
    ],
    "reason": "Merchant review",
    "reversalCents": 500,
    "revokedAt": "2026-10-11T12:00:00.000Z"
  },
  "createdAt": "2026-10-11T12:00:00.000Z"
}

Payload fields

FieldTypeRequiredDetails
partnersarrayYes
partnerIdstringNo
partnerExternalIdstringNo
eventIdstringYes
customerIdstringYes
milestonestringYes
status"recorded", "revoked", "reinstated", "reversed"Yes
programIdsarrayYes
rewardIdsarrayYes
countintegerNominimum 0
reasonstringYes
reversalCentsintegerYesminimum 0. maximum 9007199254740991
revokedAtstringYesdate-time

partners[]

FieldTypeRequiredDetails
partners.partnerIdstringYes
partners.partnerExternalIdstringYes

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
    },
    "reason": {
      "type": "string"
    },
    "reversalCents": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "revokedAt": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": [
    "partners",
    "eventId",
    "customerId",
    "milestone",
    "status",
    "programIds",
    "rewardIds",
    "reason",
    "reversalCents",
    "revokedAt"
  ],
  "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.