ANPR Webhooks: Real-Time Plate Event Pipelines

Aug 7, 2026 · 13 min read

Why Polling an ANPR API Is the Wrong Pattern

When developers first integrate a number plate recognition API, the instinct is to poll: send an image, wait for the response, then immediately query again for the next plate read. For simple scripts or one-off lookups, that works adequately. In production, it falls apart quickly. Polling introduces an artificial delay between the moment a camera captures a plate and the moment your application can act on it. In access control, that latency is the difference between a barrier rising smoothly as a vehicle approaches and a driver waiting at a closed gate. In forecourt management, it is the gap between a vehicle pulling onto a pump and the pump being enabled. Every poll cycle you wait is latency you have introduced yourself.

Webhooks invert that relationship. Instead of your application repeatedly asking whether anything has happened, the NPR API notifies your endpoint the instant a plate-read event is ready. Your code reacts rather than hunts. This guide walks you through building a production-ready ANPR event pipeline on top of NPR API webhooks: payload anatomy, signature verification, retry handling, queue patterns and three concrete wiring examples you can deploy today.

How NPR API Webhooks Work

The flow begins at the camera. Your edge device or server-side capture process POSTs an image to the NPR API recognition endpoint at https://nprapi.com/api/v1/recognise, authenticated with your API key in the X-API-Key header. The API processes the image, runs optical character recognition, optionally enriches the result with DVSA vehicle data when you include vehicle=true as a form field or query parameter, and then, rather than only returning the result in the synchronous HTTP response, also dispatches a signed HTTP POST to your registered webhook URL. Your endpoint receives the event payload in near real time, typically within a few hundred milliseconds of the original image submission.

This means you can use the synchronous response for lightweight, low-volume flows while relying on the webhook for everything that needs to trigger downstream action asynchronously. The two are not mutually exclusive. For high-throughput lanes with multiple cameras firing simultaneously, the webhook pipeline is the architecture you want.

Anatomy of an NPR API Webhook Payload

Understanding the payload structure is essential before you write a single line of handler code. The core fields in a standard single-plate webhook event mirror those of the synchronous API response, extended with event-level metadata added by the webhook dispatcher.

A unique event identifier serves as your idempotency key; hold onto it and record it before doing anything else. An event type string distinguishes successful reads from other notification categories. A timestamp indicates when recognition occurred. The registration field contains the plate string itself, for example AB12 CDE. The confidence field is an integer from 0 to 100 representing the API's certainty about the read. A score above 85 is typically reliable enough for automated action, though you should tune this threshold against your specific camera environment and lighting conditions. A credits_used field reflects the credit cost of the operation. When you have enabled vehicle=true on the originating request, the payload also includes a vehicle object with fields such as make, model and colour, drawn from DVSA data. An image reference field, where present, provides a pointer to the submitted image that is useful for audit trails without requiring your pipeline to store the raw image.

When multiple=true is set on the originating request, the payload contains a plates array in place of a single registration field. Each element in the array carries its own registration, confidence and country value (an ISO 3166-1 alpha-2 code where the plate's origin is identifiable), along with a top-level processing_time_ms value for the whole frame.

Registering and Configuring Your Webhook Endpoint

Webhook endpoints are registered through the NPR API dashboard. Navigate to the Webhooks section, add your HTTPS endpoint URL and select the event types you wish to receive. You will be issued a signing secret at this point. Store it immediately and treat it like a password; it cannot be retrieved again from the dashboard, only rotated. You can register multiple endpoints for different environments such as staging and production, and scope each to different event types or camera groups depending on how you have structured your integration. The full configuration reference is available at https://nprapi.com/docs.

Your endpoint must be publicly reachable over HTTPS. Self-signed certificates are not accepted. Respond with an HTTP 2xx status code as quickly as possible, ideally within two seconds, to acknowledge receipt. Any non-2xx response or a connection timeout is treated as a failed delivery and triggers the retry schedule.

Securing Your Endpoint: HMAC Signature Verification

Your webhook endpoint is a public URL. Without verification, anyone who discovers it can POST forged plate events and trigger real-world actions such as opening a barrier or enabling a pump. HMAC-SHA256 signature verification is the mechanism that prevents this. The NPR API signs every delivery using your shared secret and sends the hex-encoded digest in a dedicated signature request header. It is your responsibility to verify that signature before acting on any payload.

The process works as follows. The NPR API computes an HMAC-SHA256 hash of the raw request body using your signing secret, then sends the hex-encoded digest in the signature header. On your side, you recompute the same hash over the raw request body bytes and compare the two values using a constant-time comparison function. The raw body comparison is critical: parse the JSON only after verification passes, because any middleware that re-encodes or reformats the body before you hash it will invalidate the check.

Here is a minimal Python example using Flask:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
WEBHOOK_SECRET = b"your_signing_secret_here"  # load from env, never hardcode

@app.route("/webhook/npr", methods=["POST"])
def npr_webhook():
    raw_body = request.get_data()
    received_sig = request.headers.get("X-NPR-Signature", "")
    expected_sig = hmac.new(WEBHOOK_SECRET, raw_body, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected_sig, received_sig):
        abort(403)

    event = request.get_json()
    # safe to process event here
    return "", 200

Always use hmac.compare_digest, or the equivalent constant-time function in your language. Standard string equality operators are vulnerable to timing attacks that can leak information about the value of your secret. Also reject any delivery whose timestamp field is more than five minutes old; this prevents replay attacks in which a valid but captured payload is resubmitted later. Store your signing secret in an environment variable or a secrets manager such as AWS Secrets Manager or HashiCorp Vault, and never commit it to version control.

Handling Retries, Failures and Idempotency

Webhook delivery is an at-least-once contract, not exactly-once. The NPR API will retry failed deliveries with exponential back-off when your endpoint returns a non-2xx status or times out. This is the correct behaviour; a dropped plate event in a barrier or watchlist context is far worse than receiving a duplicate. However, it means your handler must be idempotent.

The unique event identifier included in every payload is your idempotency key. Before processing any event, check whether that identifier already exists in your deduplication store. A Redis key with a time-to-live set to exceed the full retry window works well for this, as does a database table with a unique constraint on the event identifier column. If the identifier is already present, return HTTP 200 immediately without re-executing the business logic. This produces effectively exactly-once behaviour on the application side regardless of how many times the delivery arrives.

For your deduplication check and your business-logic write to be safe under concurrent load, they must be atomic. A check-then-write pattern with a gap between the two steps contains a race condition that production traffic will eventually find. Use an atomic insert with a conflict clause, or an equivalent transactional primitive, so the first delivery wins and subsequent ones are silently discarded.

Set your idempotency store's expiry to comfortably outlast the retry window. If the NPR API retries for 24 hours, your deduplication cache must live for at least that long, or late retries will slip through as if they were fresh events.

Queue Patterns for High-Volume Deployments

At low volume, your webhook handler can do everything inline: verify the signature, look up the plate against your authorised list and trigger the barrier controller, all within the HTTP request lifecycle. At scale, this approach collapses. If your endpoint takes too long to respond, the NPR API marks the delivery as failed and schedules a retry. A camera lane with a queue of vehicles, or a multi-site deployment with dozens of cameras, can produce bursts that overwhelm a synchronous handler.

The correct pattern is to decouple the receiver from the business logic using a message queue. Your webhook endpoint does exactly three things: verify the signature, enqueue the raw payload and return HTTP 200. All processing happens downstream in a worker that consumes from the queue asynchronously. This keeps your receiver response time well under any timeout threshold regardless of what the downstream logic does.

Message queue technologies such as RabbitMQ, AWS SQS and Redis Streams all fit this pattern well; choose based on your existing infrastructure. The queue also acts as a buffer during outages of your downstream services: NPR API events are safely held and processed when your worker recovers, rather than being lost or causing the retry schedule to pile up. For events that fail repeatedly after exhausting retries, route them to a dead-letter queue so they can be inspected and replayed once the root cause is resolved.

Wiring Example 1: Instant Barrier Release on Plate Match

A car park or secure site needs to raise a barrier the moment an authorised vehicle is recognised, with no perceptible delay for the driver. A camera at the entry lane captures a frame and your edge device POSTs it to https://nprapi.com/api/v1/recognise with the X-API-Key header. The NPR API recognises the plate, returns the synchronous JSON response and fires a plate-recognised webhook event to your registered endpoint.

Your webhook handler verifies the HMAC signature, checks the event identifier against your deduplication store and then queries your access control database for the returned registration value. If the plate is on the authorised list and the confidence score meets your threshold (88 or above is a reasonable starting point), your handler sends a relay command to the barrier controller. The entire path from camera capture to barrier signal should complete in well under two seconds in a well-tuned deployment. Including vehicle=true in the original request lets you cross-reference make and colour as a secondary check against cloned plates, without any additional API call.

Wiring Example 2: Real-Time Watchlist Hit Notification

A logistics depot or car park operator needs to be alerted the moment a vehicle of interest appears on site. The watchlist is maintained in your own database: stolen vehicles, banned drivers, vehicles linked to outstanding invoices or any custom category you define.

When a plate-recognised webhook arrives, your handler verifies the signature and then queries the watchlist table for the registration value. On a hit, the handler publishes a message to your alerting queue. A downstream worker picks up the message and dispatches a notification: a push alert to a security staff mobile app, an SMS via your messaging provider or a POST to a Slack or Microsoft Teams incoming webhook. Because the NPR API webhook fires as soon as the plate is read, the notification reaches staff within seconds of the vehicle entering the camera's field of view, rather than at the end of a polling cycle. The vehicle object (make, model, colour) enriches the alert with context that helps staff locate the correct vehicle quickly, particularly on a busy site where multiple similar plates may be present.

Wiring Example 3: Forecourt Pump Hold and Release

A fuel retailer wants to authorise a pump the instant a known fleet vehicle pulls up, and hold it for all others until payment is confirmed. This requires low latency and idempotent pump control; enabling the same pump twice would be a serious operational fault.

A forecourt camera POSTs each captured frame to the NPR API. The resulting webhook carries the registration and confidence values. Your handler checks the event identifier for deduplication first, then looks up the registration in your fleet contract database. On a match, it calls your pump controller API with the pump number derived from the camera identifier embedded in the webhook metadata, enabling that pump for the matched account. Because the idempotency check runs before any pump command is issued, a retried delivery of the same event is safely discarded rather than triggering a second enable signal. Unrecognised plates leave the pump in the default hold state, prompting the standard payment flow at the terminal.

Testing Webhooks Locally During Development

Your local development server is not publicly accessible, so the NPR API cannot deliver webhooks to localhost. The standard solution is a tunnelling tool that exposes a local port on a public HTTPS URL you can register in the NPR API dashboard. Cloudflare Tunnel is a strong choice here: it is free, supports persistent custom-domain URLs and imposes no bandwidth limits or session timeouts, meaning your registered webhook URL remains stable across restarts. ngrok is a well-established alternative with a built-in request inspection dashboard at 127.0.0.1:4040, though its free tier is more restrictive. Start your local server, start the tunnel, copy the generated HTTPS URL into the Webhooks configuration, and deliveries will arrive at your local handler in real time.

For testing signature verification specifically, capture a real delivery via the tunnel and replay it directly against your handler using curl or a tool such as Postman. Vary the body slightly and confirm that your handler rejects the manipulated payload with a 403. This gives you confidence that your HMAC check is working against real NPR API signed payloads, not just unit-test stubs. Test your idempotency logic by replaying the same captured payload twice and confirming your handler returns 200 both times but only executes the business logic once.

UK GDPR and Data Minimisation

The ICO's position is that a vehicle registration mark (VRM) is personal data in most circumstances, particularly when it is processed as part of a system designed to identify or take action against an individual, such as issuing a parking fine or controlling access. When your ANPR pipeline combines a VRM with a timestamp, location and a vehicle description, the resulting record is personal data under UK GDPR. You must have a lawful basis for processing it, and you must not retain it beyond the period necessary for your stated purpose. If your deployment uses ANPR cameras visible to the public, clear and prominent signage is also a regulatory expectation.

Design your pipeline with data minimisation in mind from the outset. If your barrier control logic only needs the registration string and confidence score, do not persist the full payload. Drop the image reference field immediately after the access decision is made if your use case does not require an audit image. Anonymise or aggregate records as soon as they are no longer operationally necessary. If you are using the watchlist pattern, ensure your retention schedule for hit records is documented and defensible. For higher-risk deployments, completing a Data Protection Impact Assessment before going live is prudent and may be legally required. The NPR API's image processing is stateless; the API does not retain submitted images on your behalf, so your data exposure is limited to what your own pipeline stores.

Start Building Your ANPR Event Pipeline

Moving from synchronous polling to a webhook-driven event pipeline is one of the highest-leverage architectural decisions you can make in an ANPR integration. Latency drops, your application becomes reactive rather than procedural, and your infrastructure scales to camera volume without proportionally increasing your API call rate. The patterns covered here: signature verification, idempotent deduplication, queue-decoupled receivers and direct actuator wiring, are the same ones used in production deployments across access control, fleet management and retail forecourt automation.

The NPR API provides a straightforward starting point. A single POST to https://nprapi.com/api/v1/recognise with an image file and your API key returns structured JSON containing a confidence score and optional DVSA vehicle data, and triggers a webhook delivery to your endpoint moments later. Register your first endpoint in the dashboard, fire a test plate event through your tunnel and follow the patterns in this guide to take a working proof of concept through to a production-ready real-time ANPR event system. Full documentation is at https://nprapi.com/docs.

Ready to integrate number plate recognition?

Get Started Free