Docs

# Webhooks

Webhooks allow you to receive updates about vignette sales by automatically sending data to a specified URL whenever an event occurs.

During onboarding, please provide us with the webhook URL you would like to use to receive sale reports.

# Authorization

To ensure that webhook requests are secure and verifiably from us, each request includes an X-Signature header.

You can verify this signature using your Webhook Secret and the raw request payload.

import crypto from "crypto"

export function verifyWebhookSignature(receivedSignature, secret, payload) {
    const expectedSignature = crypto
        .createHmac("sha256", secret)
        .update(payload)
        .digest("hex")

    const receivedBuffer = Buffer.from(receivedSignature)
    const expectedBuffer = Buffer.from(expectedSignature)

    // Ensure both Buffers have the same length
    if (receivedBuffer.length !== expectedBuffer.length) {
        return false
    }

    // Perform constant-time comparison
    return crypto.timingSafeEqual(receivedBuffer, expectedBuffer)
}

# Request

A webhook request is sent as a JSON object with the following structure:

Parameter Description
saleId The unique identifier of the processed sale.
vignetteId The unique identifier of the vignette, generated after a successful activation.
vignetteSale An object containing details about the sale (see below).

# Sample webhook request payload

# If the sale was successful

{
  "saleId": "string",
  "vignetteId": "string",
  "vignetteSale": {
    "success": true,
    "data": {
      "id": "string",
      "total": 0,
      "currency": "BGN",
      "totalCurrencyAmount": {
        "amountBGN": 0,
        "amountEUR": 0
      },
      "createdOn": "string",
      "active": true,
      "saleRows": [
        {
          "active": true,
          "productsResponse": {
            "id": 0,
            "vehicleType": "car",
            "validityType": "year",
            "vehicleTypeText": "Light vehicle <= 3.5t, camping vehicle M1",
            "validityTypeText": "Yearly",
            "categoryDescriptionText": "Category 3"
          },
          "id": "string",
          "email": "string",
          "addEmailUrl": "string",
          "createdOn": "string",
          "kapschProperties": {
            "id": "string",
            "product": {
              "id": 0,
              "vehicleType": "car",
              "validityType": "year"
            },
            "status": 0,
            "vehicle": {
              "lpn": "string",
              "countryCode": "string"
            },
            "validity": {
              "requestedValidityStartDate": "string",
              "validityStartDateTimeUTC": "string",
              "validityEndDateTimeUTC": "string",
              "validityEndDateTimeEET": "string",
              "validityStartDateTimeEET": "string"
            },
            "price": {
              "currency": "BGN",
              "amount": 0
            },
            "purchase": {
              "purchaseDateTimeUTC": "string"
            }
          },
          "currencyAmount": {
            "amountBGN": 0,
            "amountEUR": 0
          }
        }
      ]
    }
  }
}

# If the sale failed

{
  "saleId": "string",
  "vignetteId": "string",
  "vignetteSale": {
    "success": false,
    "error": {
      "code": "string",
      "message": "string"
    }
  }
}