Skip to content
Qrivo Docs

Merchant webhooks

Subscribe to Qrivo changes and verify every delivery with HMAC-SHA256.

Eligible merchants can subscribe a public HTTPS endpoint to QR and campaign changes.

Supported events

  • qr.created
  • qr.updated
  • qr.deleted
  • campaign.created
  • campaign.updated

Create a subscription

Create subscriptions in Qrivo → Settings in the Merchant webhooks section, or use the Merchant API with the webhooks:write scope. The production API origin is https://app.qrivo.solidcraftlabs.com.

export QRIVO_API_ORIGIN=https://app.qrivo.solidcraftlabs.com

curl "$QRIVO_API_ORIGIN/api/v1/webhooks" \
  --request POST \
  --header "Authorization: Bearer $QRIVO_API_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://integrations.example.com/qrivo/events",
    "events": ["qr.created", "qr.updated"]
  }'

Copy the signing secret when the subscription is created and store it securely. Qrivo does not return signing secrets when subscriptions are listed.

Delivery format

Deliveries are JSON POST requests. Read the event name from X-Qrivo-Event and the lowercase hexadecimal HMAC from X-Qrivo-Signature.

{
  "apiVersion": "2026-01",
  "event": "qr.updated",
  "occurredAt": "2026-09-06T16:20:00.000Z",
  "data": {
    "id": "qr_123",
    "entityType": "qr_code",
    "status": "active"
  }
}

data contains the public QR or campaign fields for the changed record. Internal storage keys are omitted.

Verify every delivery

Preserve the raw body

Read the exact request bytes before JSON parsing. Re-serialized JSON may not produce the same signature.

Compute the expected signature

Compute HMAC-SHA256 over the raw bytes using the subscription secret, then encode the result as lowercase hexadecimal.

Compare securely

Compare the expected value with X-Qrivo-Signature using a constant-time comparison. Reject a missing or different signature.

Accept before processing

Safely record or enqueue the event, return a successful HTTP response, and process it idempotently.

Receiver requirements

  • Use a public HTTPS URL on the standard TLS port.
  • Do not use embedded credentials in the subscription URL.
  • Do not redirect webhook requests.
  • Set a short request timeout and process longer work asynchronously.
  • Expect retries and make processing idempotent.
  • Revoke subscriptions you no longer use.

Treat the secret like a password

Never place a webhook signing secret in browser code, Git, screenshots, URLs, or application logs.