ANPR API for Fleet Logistics: A Developer's Guide

Jul 20, 2026 · 12 min read

Why Plate Recognition Beats RFID and Driver Apps

Fleet and logistics operations have long relied on a combination of RFID fobs, driver-facing mobile apps and manual gatehouse logging to track vehicle movements at depots, distribution centres and haulage yards. Each approach carries hidden costs. RFID requires tags to be fitted to every vehicle that enters your site, which is manageable for an owned fleet but becomes a significant administrative burden when third-party hauliers represent the majority of traffic. Sourcing, fitting and managing tags for visiting subcontractors introduces coordination overhead that scales poorly with traffic volume. Driver apps introduce a different dependency: phones need charging, app versions need updating, and not every subcontractor will have the app installed at all.

Automatic number plate recognition removes all of that friction. The vehicle's registration mark is already there, fixed to the vehicle by law, requiring no pre-enrolment and no hardware issued to the driver. A camera captures an image, a cloud API returns a structured JSON response in milliseconds, and your back-end system has a verified vehicle identifier it can act on immediately. For logistics operations handling mixed traffic from multiple carriers, this tag-free approach means every inbound and outbound vehicle is identifiable without prior coordination with the carrier.

This guide walks through how to wire a REST-based ANPR API into a real fleet and logistics stack, from a single image POST through to vehicle data enrichment, watchlist checking, dwell-time computation and webhook-driven dispatch events.

Four Use Cases Worth Mapping Before You Write Any Code

Before writing a line of code, it is worth mapping the four principal use cases that ANPR covers in a typical logistics operation, because each one has slightly different data requirements at the API call level.

Depot Gate Automation

The gate is the most obvious integration point. A camera mounted at the entrance captures an image of each approaching vehicle. The image is posted to the recognition endpoint, the returned registration is checked against an allow list, and a signal is sent to the barrier controller to open or hold. The arrival event is simultaneously written to your yard management system, notifying the dock team and triggering whatever yard task comes next. Real-world deployments have recorded average entry times dropping from around two minutes per vehicle to under fifteen seconds, which at a busy multi-bay distribution centre represents a material reduction in queue time and fuel wasted idling.

Multi-Drop Delivery Confirmation

For operators managing multi-drop routes, a camera at each customer's goods-in bay provides proof of presence without relying on a driver scanning a barcode or tapping a screen. The registration read at the delivery point, timestamped and returned in the API response, can be matched back to the route plan in your transport management system to confirm the stop was completed and log the exact time.

Yard Dwell-Time Measurement

Haulage contracts frequently carry SLA clauses specifying a maximum time a vehicle may wait before being loaded or unloaded. Measuring that time accurately with manual logs is difficult. With ANPR, the entry read timestamps the start of dwell time and the exit read closes the record. The difference is your dwell time, computed entirely from plate reads with no driver interaction required.

Security and SLA Monitoring

Every vehicle entry and exit is logged in real time, creating a traceable audit trail. Vehicles that exceed a configurable dwell threshold, or that appear on a deny list, can trigger an alert or a webhook event to your operations team before a situation escalates.

How the API Call Works

The NPR API exposes a single recognition endpoint at POST https://nprapi.com/api/v1/recognise. Requests are authenticated by passing your key in the X-API-Key header. The request body is multipart/form-data, and the image is sent as a file field named image. A minimal gate entry call looks like this:

curl -X POST https://nprapi.com/api/v1/recognise \
  -H "X-API-Key: your-api-key-here" \
  -F "image=@gate_entry.jpg"

In single-plate mode the response is a JSON object containing success, registration, confidence (an integer from 0 to 100) and credits_used. A typical response looks like this:

{
  "success": true,
  "registration": "AB23 XYZ",
  "confidence": 97,
  "credits_used": 1
}

The confidence score is important in an automated gate context. A score in the high nineties indicates a reliable read under good lighting conditions. Define a threshold in your application logic, typically somewhere in the 85 to 90 range, below which the gate does not open automatically and an operator review is requested instead. Do not hard-code a single threshold across all camera positions. A camera at a poorly lit rear entrance may consistently return slightly lower scores than one at a well-lit main entrance, and your threshold logic should reflect that per-camera reality.

Adding Vehicle Data Enrichment

Appending vehicle=true as a form field or query parameter to the same call adds DVSA vehicle data, including make, model and colour, to the response. This is useful for cross-referencing the plate read against a delivery manifest that was booked with a vehicle description, or for flagging when a plate appears at the gate but the vehicle type does not match what is expected for that booking. No separate lookup call is required; the enriched data comes back in the same response object.

Handling Multiple Plates per Frame at Busy Entrances

At a wide yard entrance where a tractor unit and a trailer may each carry a visible plate, or where two lanes feed through a single camera field of view, the default single-plate mode will return only the most prominent registration. Adding multiple=true switches the API to return a plates array, where each item contains registration, confidence and country as an ISO 3166-1 alpha-2 code where the plate format can be identified. This is particularly useful for cross-border haulage where a European trailer plate may differ from the cab's UK registration.

In your gate controller logic, apply a straightforward filter: iterate the plates array, discard any entry below your confidence threshold, then look up each remaining registration against your expected arrivals list in order of descending confidence. The first match wins. If no match is found, log all returned plates to the operator review queue rather than discarding them silently.

Building a Check-In and Check-Out Loop

The dwell-time pattern requires two reads per vehicle visit: an entry read and an exit read. When the entry camera fires and the API returns a registration with confidence above threshold, write a record to your vehicle visit table:

INSERT INTO vehicle_visits (registration, entry_time, site_id, status)
VALUES ('AB23 XYZ', NOW(), 'DEPOT_NORTH', 'on_site');

When the exit camera fires for the same registration, close the record and compute dwell time:

UPDATE vehicle_visits
SET exit_time = NOW(),
    dwell_minutes = EXTRACT(EPOCH FROM (NOW() - entry_time)) / 60,
    status = 'departed'
WHERE registration = 'AB23 XYZ'
  AND site_id = 'DEPOT_NORTH'
  AND status = 'on_site';

For SLA monitoring, a scheduled job running every five minutes can query for any open visit where elapsed time exceeds the contracted threshold and fire an alert or webhook event to the relevant team. Build in a tolerance window for legitimate delays such as weighbridge checks, and make the threshold configurable per site and per carrier rather than global.

One edge case to handle carefully: camera misreads on exit. If the exit read returns a registration with no matching open entry record, do not silently discard it. Log it as an unmatched exit read with the full API response, including the raw confidence score, so that operations staff can reconcile it manually if needed.

Watchlist Integration

A watchlist is a lookup table against which every plate read is checked immediately after the API call returns. In a fleet context you will typically maintain three lists: an allow list of expected vehicles (contracted hauliers, owned fleet), a deny list of banned or suspended vehicles, and an alert list of vehicles requiring special handling, such as those that have missed a booking slot.

The lookup is cheap and should happen in application code before any gate signal is issued:

def check_watchlist(registration: str) -> dict:
    if registration in deny_list:
        return {"action": "deny", "reason": "banned_vehicle"}
    if registration in alert_list:
        return {"action": "alert", "reason": "requires_review"}
    if registration in allow_list:
        return {"action": "allow"}
    return {"action": "unknown", "reason": "not_on_manifest"}

The "unknown" case requires the most thought. In a closed depot with a strict pre-booking system, an unknown plate should hold the vehicle and trigger an operator query. In a more open logistics yard that accepts ad-hoc collections, it might be logged and allowed through with an alert sent to the duty manager. Make this behaviour configurable rather than hard-coded, as different sites within the same operator group will often have different policies.

Webhook Patterns for Dispatch and TMS Integration

Polling a database for gate events is inefficient and introduces latency. The correct pattern for integrating ANPR gate events into a TMS or WMS is event-driven: when a plate is matched, your gate service fires a webhook to a configured endpoint in your TMS, and the TMS reacts immediately. This is the same pattern used broadly across logistics platforms, where push-based events fire on delivery milestones and exception flags, eliminating the polling loops that introduce delay in batch-oriented architectures.

Your gate service should construct a structured event payload and POST it to the TMS endpoint:

import requests, json, datetime

def fire_gate_event(event_type: str, registration: str, site_id: str, confidence: int):
    payload = {
        "event": event_type,           # "gate.entry" or "gate.exit"
        "registration": registration,
        "site_id": site_id,
        "confidence": confidence,
        "timestamp": datetime.datetime.utcnow().isoformat() + "Z"
    }
    response = requests.post(
        "https://your-tms-host/webhooks/gate-events",
        json=payload,
        headers={"Authorization": "Bearer your-tms-token"},
        timeout=5
    )
    response.raise_for_status()

Your TMS webhook receiver should acknowledge the event with a 200 response immediately and process asynchronously. Build in retry logic with exponential back-off on the sending side for cases where the TMS endpoint is temporarily unavailable. Log every delivery attempt and response code so that failed events can be replayed. On the TMS side, deduplicate events using a unique event identifier to guard against double-processing on retry.

For a WMS integration, the same pattern applies. A confirmed vehicle arrival event at the gate can automatically signal the warehouse to begin staging the inbound load, updating inventory expectations and dock assignment before the driver has reached the goods-in door.

GDPR and UK Data Protection

Vehicle registration marks are personal data under UK GDPR where the organisation processing them can reasonably link a plate to an identifiable individual. The Information Commissioner's Office makes clear that vehicle registrations captured by ANPR equipment fall within its video surveillance guidance and are subject to UK GDPR and the Data Protection Act 2018. In practice, a logistics gate system that ties a plate to a booking, a carrier account, or arrival and departure times will almost certainly meet that threshold, and you should treat the data accordingly from day one.

The ICO's guidance on ANPR is equally clear on retention: you should keep data only for the minimum period necessary and delete it once you no longer need it. There is no fixed statutory retention period for commercial ANPR data, but the principle of storage limitation applies in full. In practical terms, vehicle visit records for compliant, uneventful movements should be deleted or anonymised on a rolling schedule, for example after 30 days, while records associated with incidents, SLA breaches or security events may be retained for longer with documented justification.

The most effective architectural approach to compliance at the API layer is zero-retention processing: the image is posted to the recognition endpoint, the plate string and vehicle data are returned and acted upon, and the original image is never written to persistent storage by your application. A registration string and a confidence score contain no biometric data and are far easier to manage under data minimisation principles than a set of raw vehicle images. Ensure you have prominent signage at gate entry points informing drivers that ANPR is in use, and that your privacy notice covers the purpose, lawful basis and retention period for the data collected.

Worked Example: Gate Entry with Vehicle Enrichment

The following Python snippet combines the API call, vehicle enrichment, confidence gating and watchlist check into a single gate entry handler:

import requests
import datetime

API_URL = "https://nprapi.com/api/v1/recognise"
API_KEY = "your-api-key-here"
CONFIDENCE_THRESHOLD = 88

ALLOW_LIST = {"AB23 XYZ", "CD45 LMN"}
DENY_LIST  = {"EF67 PQR"}

def handle_gate_entry(image_path: str, site_id: str) -> dict:
    with open(image_path, "rb") as img:
        response = requests.post(
            API_URL,
            headers={"X-API-Key": API_KEY},
            files={"image": img},
            data={"vehicle": "true"}
        )
    response.raise_for_status()
    data = response.json()

    if not data.get("success"):
        return {"action": "error", "detail": "Recognition failed"}

    registration = data["registration"]
    confidence   = data["confidence"]

    if confidence < CONFIDENCE_THRESHOLD:
        return {
            "action": "review",
            "registration": registration,
            "confidence": confidence,
            "detail": "Low confidence, operator review required"
        }

    if registration in DENY_LIST:
        fire_gate_event("gate.denied", registration, site_id, confidence)
        return {"action": "deny", "registration": registration}

    # Log entry and fire TMS event
    log_entry(registration, site_id, datetime.datetime.utcnow())
    fire_gate_event("gate.entry", registration, site_id, confidence)

    return {
        "action": "allow",
        "registration": registration,
        "confidence": confidence,
        "vehicle": data.get("vehicle", {})
    }

The vehicle key in the response, populated when vehicle=true is set, contains make, model and colour data from the DVSA. Log it alongside the visit record or use it in your manifest-matching logic to cross-reference the expected vehicle type for the booking.

Batch Processing and International Plates

End-of-day manifest reconciliation is a natural fit for batch processing. The NPR API provides a batch endpoint at POST https://nprapi.com/api/v1/batch, which accepts multiple images as images[] file fields in a single request. The job is processed asynchronously, and status and results are retrieved via GET https://nprapi.com/api/v1/batch/{uuid}. This is the right approach for cases such as processing a set of delivery-point images captured offline during a multi-drop route, where real-time gate control is not required.

For cross-border haulage involving European-registered vehicles, multiple-plates mode with ISO country codes provides a practical mechanism for distinguishing a UK-registered cab from a continental trailer, or for correctly routing a foreign-registered vehicle through the appropriate check-in flow. Plate format rules vary significantly across Europe, and an API that returns a country identifier alongside the plate string removes the need for your application to implement its own format-detection logic.

Next Steps

The patterns described here cover the full operational loop: single image POST, JSON response with confidence and vehicle data, dwell-time tracking, watchlist gating and webhook dispatch. All of them are achievable with a handful of standard library calls in any server-side language. The full API reference, including request and response schemas and error codes, is available at https://nprapi.com/docs. The NPR API free tier provides enough credits to build and test a complete gate entry and exit flow, including multi-plate mode and vehicle enrichment, without any upfront commitment.

Start with a single recognition call against a real camera grab from your site. Inspect the confidence score, check the vehicle fields, and trace the event through to your yard management system. Once that loop is closed, the remaining integrations follow the same pattern. The plate is already on the vehicle; the only question is how quickly your stack acts on what it reads.

Ready to integrate number plate recognition?

Get Started Free