Skip to main content

Webhooks

Event-driven integrations for real-time notifications.

Overview

Webhooks allow your application to receive real-time notifications when events occur in GoValid. Instead of polling the API, GoValid sends HTTP POST requests to your configured endpoint.

Base URL

https://api.govalid.org/api/v1/webhooks/

Available Events

EventDescription
qr.createdA new QR code was created
qr.scannedA QR code was scanned
qr.expiredA QR code has expired
qr.removedA QR code was removed/inactivated
qr.transferredQR code ownership was transferred
subscription.createdNew subscription started
subscription.cancelledSubscription was cancelled
payment.completedPayment was successful
payment.failedPayment failed
credit.topupCredits were added
counterfeit.detectedPotential counterfeit activity detected
institution.staff.invitedStaff member was invited

Register a Webhook

POST /api/v1/webhooks/

Request Body

{
"url": "https://your-server.com/webhook",
"events": ["qr.scanned", "qr.created", "qr.expired"],
"secret": "your_webhook_secret"
}

Fields

FieldTypeRequiredDescription
urlstringYesYour webhook endpoint URL (must be HTTPS)
eventsarrayYesList of events to subscribe to
secretstringYesSecret for signature verification
descriptionstringNoDescription for your reference
activebooleanNoEnable/disable webhook (default: true)

Response

{
"id": "wh-001",
"url": "https://your-server.com/webhook",
"events": ["qr.scanned", "qr.created", "qr.expired"],
"active": true,
"created_at": "2025-01-29T12:00:00Z"
}

List Webhooks

GET /api/v1/webhooks/

Response

{
"count": 2,
"results": [
{
"id": "wh-001",
"url": "https://your-server.com/webhook",
"events": ["qr.scanned", "qr.created"],
"active": true,
"last_triggered": "2025-01-29T15:00:00Z",
"success_count": 150,
"failure_count": 2,
"created_at": "2025-01-15T10:00:00Z"
}
]
}

Update Webhook

PATCH /api/v1/webhooks/{id}/

Delete Webhook

DELETE /api/v1/webhooks/{id}/

Webhook Payload

When an event occurs, GoValid sends a POST request to your endpoint:

{
"event": "qr.scanned",
"timestamp": "2025-01-29T12:00:00Z",
"webhook_id": "wh-001",
"data": {
"qr_id": "abc123",
"qr_title": "Product Certificate #001",
"scan_location": {
"country": "US",
"city": "New York",
"latitude": 40.7128,
"longitude": -74.0060
},
"device": "mobile",
"platform": "iOS",
"is_first_scan": false,
"scan_count": 15
},
"signature": "sha256=a1b2c3d4..."
}

Verifying Webhook Signatures

Every webhook payload includes a signature header for verification:

X-GoValid-Signature: sha256=a1b2c3d4...

Python Verification

import hashlib
import hmac

def verify_webhook(payload, signature, secret):
expected = hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()

return hmac.compare_digest(f"sha256={expected}", signature)

Node.js Verification

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

return `sha256=${expected}` === signature;
}

Retry Policy

GoValid retries failed webhook deliveries:

AttemptDelay
1Immediate
21 minute
35 minutes
415 minutes
51 hour

After 5 failed attempts, the webhook is disabled.

Best Practices

  1. Respond quickly: Return 200 OK within 5 seconds
  2. Verify signatures: Always verify the webhook signature
  3. Handle duplicates: Use event IDs to prevent duplicate processing
  4. Use HTTPS: Webhook URLs must use HTTPS
  5. Monitor failures: Check webhook delivery status in the dashboard

Testing Webhooks

Test Endpoint

POST /api/v1/webhooks/{id}/test/

Sends a test event to verify your endpoint is working.

Webhook Logs

GET /api/v1/webhooks/{id}/logs/

View delivery history for a webhook.