Webhooks
Webhooks let your application receive real-time HTTP callbacks when events occur in Pointeron, such as an asset entering a geofence, a new location being received, or a device going offline. Instead of polling the API, you register a URL and Pointeron pushes events to you.
How webhooks work
- You register a webhook URL in the dashboard or via the Webhooks API and select the event types you want to receive.
- When a matching event occurs, Pointeron sends an HTTP POST request to your URL with a JSON payload describing the event.
- Your server processes the event and responds with a
2xxstatus code to acknowledge receipt.
Event types by plan
Not all event types are available on every plan. The table below shows availability by plan tier.
- Name
asset.created- Description
A new asset was created. Available on Pro and Enterprise.
- Name
asset.updated- Description
An existing asset was updated. Available on Pro and Enterprise.
- Name
asset.deleted- Description
An asset was deleted. Available on Pro and Enterprise.
- Name
device.created- Description
A new device was registered. Available on Pro and Enterprise.
- Name
device.updated- Description
An existing device was updated. Available on Pro and Enterprise.
- Name
device.deleted- Description
A device was deleted. Available on Pro and Enterprise.
- Name
location.created- Description
A new location data point was ingested. Available on Enterprise only.
- Name
geofence.created- Description
A new geofence was created. Available on Pro and Enterprise.
- Name
geofence.updated- Description
An existing geofence was updated. Available on Pro and Enterprise.
- Name
geofence.deleted- Description
A geofence was deleted. Available on Pro and Enterprise.
- Name
geofence.entered- Description
An asset entered a geofence boundary. Available on Pro and Enterprise.
- Name
geofence.exited- Description
An asset exited a geofence boundary. Available on Pro and Enterprise.
- Name
alert.created- Description
A new alert was triggered. Available on Enterprise only.
- Name
alert.updated- Description
An existing alert was updated. Available on Enterprise only.
- Name
alert.deleted- Description
An alert was deleted. Available on Enterprise only.
Webhook payload format
Every webhook delivery is an HTTP POST with a JSON body. The payload follows a consistent envelope structure.
- Name
id- Type
- string
- Description
Unique identifier for this webhook delivery.
- Name
type- Type
- string
- Description
The event type, such as
geofence.enteredorasset.created.
- Name
created_at- Type
- integer
- Description
Unix timestamp of when the event occurred.
- Name
payload- Type
- object
- Description
The full resource object associated with the event.
Example: geofence.entered
{
"id": "evt_a056V7R7NmNRjl70",
"type": "geofence.entered",
"created_at": 1710408600,
"payload": {
"asset": {
"id": "ast_WAz8eIbvDR60rouK",
"name": "Delivery Van 01",
"type": "vehicle"
},
"geofence": {
"id": "gf_kR3mNpQ9xWv2tYs",
"name": "Warehouse Zone A"
},
"location": {
"latitude": 46.0569,
"longitude": 14.5058,
"speed": 12.5,
"recorded_at": 1710408600
},
"device": {
"id": "dev_xgQQXg3hrtjh7AvZ",
"name": "Fleet Tracker 01",
"identifier": "GT06-ABC123"
}
}
}
Signature verification
Every webhook request includes an X-Pointeron-Signature header containing an HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret. Always verify this signature to confirm that the request genuinely came from Pointeron.
Verifying webhook signatures
import crypto from 'node:crypto'
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(signature, 'hex'),
)
}
// In your Express handler:
app.post(
'/webhooks/pointeron',
express.raw({ type: 'application/json' }),
(req, res) => {
const signature = req.headers['x-pointeron-signature']
const isValid = verifyWebhookSignature(
req.body,
signature,
process.env.WEBHOOK_SECRET,
)
if (!isValid) {
return res.status(401).send('Invalid signature')
}
const event = JSON.parse(req.body)
// Process event asynchronously
console.log(`Received ${event.type} event: ${event.id}`)
res.status(200).send('OK')
},
)
Always use a constant-time comparison function (such as
crypto.timingSafeEqual, hmac.compare_digest, or hash_equals) to prevent
timing attacks.
Retry policy
If your endpoint does not respond with a 2xx status code within 10 seconds, Pointeron retries the delivery with exponential backoff:
- Retry 1: 1 minute after the initial attempt
- Retry 2: 5 minutes after retry 1
- Retry 3: 30 minutes after retry 2
- Retry 4: 2 hours after retry 3
- Retry 5: 12 hours after retry 4
After 5 consecutive failures, the webhook is automatically paused and you receive an email notification. You can re-enable paused webhooks from the dashboard once your endpoint is healthy again.
Testing webhooks
You can send a test event to your webhook endpoint from the dashboard or via the API. The test event uses realistic sample data so you can verify your handler works correctly before going live.
Send a test event via API
curl -X POST https://api.pointeron.com/v2/webhooks/whk_abc123/test \
-H "Authorization: Bearer ${POINTERON_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"event_type": "geofence.entered"
}'
The test delivery includes the same X-Pointeron-Signature header as production deliveries, so you can validate your signature verification logic.
Best practices
- Respond quickly. Return a
200status code as fast as possible. Offload any heavy processing to a background job or queue. - Verify every signature. Always check the
X-Pointeron-Signatureheader to confirm the request came from Pointeron. - Handle duplicates. Although rare, the same event may be delivered more than once. Use the
idfield to deduplicate. - Use HTTPS. Webhook URLs must use HTTPS to ensure payloads are encrypted in transit.
- Monitor failures. Set up alerting for webhook delivery failures so you can fix endpoint issues before the webhook is paused.