Use the official platenexus commercial API to recognize license plates with API Key authentication.
The commercial flow stays simple: send the image, authenticate with your API Key, and receive stable JSON for your product.
Use multipart/form-data and send the file in the image field. The API was designed to integrate with backends, operators, ERPs, and automation flows.
Include the X-API-Key header on every request. The key is per client and the full value is only shown when it is created or rotated.
The response returns request_id, status, plate, confidence, and processing_time_ms, ready for operational UX and audit trails.
A commercial contract view to speed up technical understanding, QA, and the customer’s internal documentation.
Ideal integration UX: capture request_id in the first response, show status to the operator, and use the history for audit, debugging, and reconciliation.
Besides fast snippets, the documentation now exposes a public OpenAPI schema to simplify client generation, internal docs, mocks, and alignment across backend, QA, and partners.
Use this URL to import into Swagger Editor, Postman, Stoplight, QA tools, or internal pipelines.
openapi: 3.1.0
info:
title: platenexus Commercial Plate Recognition API
paths:
/api/v1/plates/recognize/:
post:
security:
- ApiKeyAuth: []
/api/v1/plates/requests/{request_id}/:
get:
security:
- ApiKeyAuth: []
The snippets below already match the format expected by the commercial API. The goal is to minimize time to the first working call.
curl -X POST "https://www.platenexus.com/api/v1/plates/recognize/" \ -H "X-API-Key: YOUR_API_KEY" \ -F "image=@/path/to/plate.jpg"
$headers = @{ "X-API-Key" = "YOUR_API_KEY" }
$form = @{ image = Get-Item "C:\\images\\plate.jpg" }
Invoke-RestMethod `
-Method Post `
-Uri "https://www.platenexus.com/api/v1/plates/recognize/" `
-Headers $headers `
-Form $form
import requests
with open("plate.jpg", "rb") as image_file:
response = requests.post(
"https://www.platenexus.com/api/v1/plates/recognize/",
headers={"X-API-Key": "YOUR_API_KEY"},
files={"image": image_file},
timeout=60,
)
print(response.status_code)
print(response.json())
const formData = new FormData();
formData.append("image", fileInput.files[0]);
const response = await fetch("https://www.platenexus.com/api/v1/plates/recognize/", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY"
},
body: formData,
});
const data = await response.json();
console.log(data);
const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");
async function recognizePlate() {
const form = new FormData();
form.append("image", fs.createReadStream("plate.jpg"));
const response = await axios.post(
"https://www.platenexus.com/api/v1/plates/recognize/",
form,
{
headers: {
"X-API-Key": "YOUR_API_KEY",
...form.getHeaders(),
},
timeout: 60000,
}
);
console.log(response.data);
}
recognizePlate();
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
public class PlateRecognitionExample {
public static void main(String[] args) throws IOException, InterruptedException {
String boundary = "----platenexus-" + UUID.randomUUID();
Path imagePath = Path.of("plate.jpg");
byte[] fileBytes = Files.readAllBytes(imagePath);
byte[] body = (
"--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"image\"; filename=\"plate.jpg\"\r\n" +
"Content-Type: image/jpeg\r\n\r\n"
).getBytes();
byte[] closing = ("\r\n--" + boundary + "--\r\n").getBytes();
byte[] payload = new byte[body.length + fileBytes.length + closing.length];
System.arraycopy(body, 0, payload, 0, body.length);
System.arraycopy(fileBytes, 0, payload, body.length, fileBytes.length);
System.arraycopy(closing, 0, payload, body.length + fileBytes.length, closing.length);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://www.platenexus.com/api/v1/plates/recognize/"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofByteArray(payload))
.build();
HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
fun main() {
val file = File("plate.jpg")
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
"image",
file.name,
file.asRequestBody("image/jpeg".toMediaType())
)
.build()
val request = Request.Builder()
.url("https://www.platenexus.com/api/v1/plates/recognize/")
.addHeader("X-API-Key", "YOUR_API_KEY")
.post(requestBody)
.build()
OkHttpClient().newCall(request).execute().use { response ->
println(response.body?.string())
}
}
using System.Net.Http;
using System.Net.Http.Headers;
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
using var form = new MultipartFormDataContent();
using var fileStream = File.OpenRead("plate.jpg");
using var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
form.Add(fileContent, "image", "plate.jpg");
var response = await client.PostAsync("https://www.platenexus.com/api/v1/plates/recognize/", form);
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
package main
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
file, _ := os.Open("plate.jpg")
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("image", "plate.jpg")
io.Copy(part, file)
writer.Close()
req, _ := http.NewRequest("POST", "https://www.platenexus.com/api/v1/plates/recognize/", body)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
payload, _ := io.ReadAll(resp.Body)
println(string(payload))
}
require "net/http"
require "json"
uri = URI("https://www.platenexus.com/api/v1/plates/recognize/")
request = Net::HTTP::Post.new(uri)
request["X-API-Key"] = "YOUR_API_KEY"
request.set_form([["image", File.open("plate.jpg")]], "multipart/form-data")
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts response.body
<?php
$ch = curl_init('https://www.platenexus.com/api/v1/plates/recognize/');
$data = [
'image' => new CURLFile(__DIR__ . '/plate.jpg'),
];
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Beyond the technical snippet, these examples help visualize what the product UX can look like in each usage context.
The user uploads an image, the backend calls the POST, persists request_id, and shows the plate, confidence, and status in the panel. Ideal for CRMs, ERPs, and vertical software.
The camera or operator sends the image, the interface receives success or not_found, and the UX guides whether to allow entry, ask for a new capture, or register an exception.
The system uses the immediate result during service and later queries the history by request_id for auditing, operational disputes, and support.
This endpoint is useful for audit, reconciliation, support, and operational screens that need to trace a specific read.
Beyond 200 success, the API also uses functional states that are useful for operator UX and support flows.
Use this path to allow entry, register an event, or continue the product’s main rule.
{
"request_id": "8c29cf32-2cae-4f79-8f2e-28a9b71ce1de",
"status": "success",
"plate": "ABC1D23",
"confidence": 0.94,
"confidence_is_estimated": false,
"country": "BR",
"timestamp": "2026-05-18T12:00:00+00:00",
"processing_time_ms": 1234
}
Good for honest UX: processing finished, but there was no usable read. This helps guide resubmission, camera setup, or positioning.
{
"request_id": "8c29cf32-2cae-4f79-8f2e-28a9b71ce1de",
"status": "not_found",
"plate": null,
"confidence": null,
"confidence_is_estimated": false,
"timestamp": "2026-05-18T12:00:00+00:00",
"message": "No plate detected",
"processing_time_ms": 980
}
Ideal for designing visual fallback, support messaging, and client telemetry without ambiguity.
{
"request_id": "8c29cf32-2cae-4f79-8f2e-28a9b71ce1de",
"status": "limit_exceeded",
"message": "Monthly request limit exceeded"
}
This summary helps teams design messaging, dashboards, logs, and billing rules without having to infer everything from the code.
| HTTP | status | Charges quota? | What it means | Recommended UX |
|---|---|---|---|---|
| 200 | success |
Yes | Plate recognized successfully. | Show the plate, confidence, and continue the product’s main flow. |
| 200 | not_found |
Yes | Image processed, but with no useful read. | Explain to the operator that the image was processed and offer a retry. |
| 400 | error |
No | Missing or invalid image. | Validate file type and payload before the POST and show a correction message. |
| 401 | error |
No | Missing, invalid, or revoked API key. | Stop the automation and trigger key rotation or validation. |
| 403 | error |
No | Inactive client. | Escalate to account management or commercial support. |
| 404 | error |
No | History was not found for the client that owns the key. | Check the request_id and the authenticated account scope. |
| 429 | limit_exceeded |
No | Monthly limit exhausted. | Show pricing or upgrade, pause automation, or contact sales. |
| 500 | error |
No | Internal recognition failure. | Log the request_id, retry, and open support if it persists. |
Designed to improve technical UX, customer stability, and support clarity from the first deploy.
It is the key piece for troubleshooting, audit, history, and conversations across product, support, and customer teams.
Not every empty read is a failure. That distinction greatly improves operator UX and product analytics.
The recommended architecture is backend-to-backend or a backend mediating the final user upload.
Checking size, extension, and MIME type reduces UX errors, operational noise, and unnecessary calls.
Storing status, request_id, and processing_time_ms improves support, SLOs, and observability.
Specific messages for authentication, limits, invalid images, and not_found make the system feel more professional.
Content shaped for searches such as ANPR API, plate OCR, REST-based plate recognition, and LPR integration for software.
A straightforward flow to send images, authenticate requests, and receive the recognized plate plus supporting data for your system.
Useful for companies that want to embed plate reading into their own product without building an engine from scratch.
Relevant to communities, remote gate ops, parking, logistics, and vehicle security with a clear commercial and technical journey.
Direct answers to the most common questions before starting a commercial integration.
These pages live on the same site, are included in the sitemap, and help Google connect platenexus with integrations, communities, parking, SaaS, local AI, and logistics.