Overview
The PEV Registry API is provided by PEV Connection, LLC and lets approved repair shops check whether a personal electric vehicle (e-bike, scooter, EUC, skateboard, etc.) has been registered, and whether it has been reported lost or stolen, by its serial number or motor code.
Base URL:
https://pevregistry.com/api/v1
Authentication
Every request must include your API key as a bearer token. Shop accounts are created only through the website at /portal — your business name, address, and contact info are required, and your contact email must be verified before the account is created. Account creation is not available as a public API call; it must be done through the Shop Portal UI. After verification, an API key is issued for partner API integrations.
Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keep your API key secret — it is only ever shown once, at creation. If it is compromised or lost, generate a new one from the Shop Portal.
You can view and update your business info, view your API key credentials, or generate a new key any time by signing in at /portal with your contact email and password.
SDKs
A Node.js SDK is published on npm as
@pevregistry/sdk,
and a PHP SDK is published on Packagist as
pevregistry/sdk.
Both cover lookup, possession reports, service logs, photo fetches, account updates, API-key rotation, and
webhook configuration. Every code example below has Node SDK and PHP SDK tabs alongside the raw
curl request.
npm install @pevregistry/sdk
const { PevRegistryClient } = require("@pevregistry/sdk");
const client = new PevRegistryClient({
apiKey: process.env.PEV_REGISTRY_API_KEY,
});
Shop Account
Once you have a key (created via /portal), manage your account programmatically with:
GET /api/partners/me # returns your current business info (bearer auth)
PATCH /api/partners/me # update business info (bearer auth)
POST /api/partners/me/rotate-key # generates a brand new API key, immediately invalidating the old one (shop login required)
PATCH /api/partners/me accepts companyName, contactName,
contactEmail, contactPhone, website, addressLine1,
addressLine2, city, state, postalCode, and
listedInDirectory (boolean, controls whether your shop appears on the public
Partners directory).
Example: fetch your account
curl "https://pevregistry.com/api/partners/me" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Example: update business info
curl -X PATCH "https://pevregistry.com/api/partners/me" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "companyName": "Example Shop", "website": "https://example-shop.com" }'
Example: rotate your API key
curl -X POST "https://pevregistry.com/api/partners/me/rotate-key" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Data Sharing Disclosure
When a device owner registers their PEV, they are informed that if the device is later reported lost or stolen and a repair shop reports having it in their possession, PEV Connection may contact the owner directly (by SMS and/or email) with the device's location and the shop's contact information, solely for the purpose of verifying ownership and assisting with recovery.
To protect owner privacy, the API never discloses an owner's name or contact information to partners directly. Instead:
- If a device is registered but not reported lost or stolen, the API only confirms
"registered": true— no other details are returned. - If a device has been reported lost or stolen, the API returns the device's make/model/type, status, and reference photos — but no owner information.
- If your shop has physical possession of a device that's been reported lost or stolen, call
POST /api/v1/possessionwith the device's identifier. PEV Connection will then contact the owner on your behalf, sharing your shop's registered address and contact information so they can reach you.
Partners must not use registry data for marketing, resale, or any purpose other than verifying ownership and assisting recovery.
Rate Limits
Each API key is limited to 60 requests per minute. Requests beyond that return an HTTP 429 with a Retry-After header (seconds).
Lookup a Device
GET /api/v1/lookup?identifier=<serial number or motor code>
Identifier matching is fuzzy-tolerant (case-insensitive, ignores punctuation/spacing, and tolerates a small number of misread characters), so partial OCR reads still match.
Example request
curl "https://pevregistry.com/api/v1/lookup?identifier=WT2500W26070581" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Response: not registered
{
"registered": false
}
Response: registered, not reported lost/stolen
{
"registered": true,
"registrationId": "6650c2f1a2b3c4d5e6f70123"
}
Response: reported lost or stolen
{
"registered": true,
"registrationId": "6650c2f1a2b3c4d5e6f70123",
"status": "stolen",
"identifierType": "motorCode",
"matchedIdentifier": "WT2500W26070581",
"device": { "brand": "Example Brand", "model": "X2 Pro", "pevType": "E-Bike" },
"reportedAt": "2026-09-01T14:32:00.000Z",
"photoUrls": [
"https://pevregistry.com/api/v1/registrations/6650.../photos/0"
],
"disclosure": "This device was registered with PEV Registry, a service of PEV Connection, and has been reported stolen. Owner contact information is never shared with API partners directly — if your shop has this device, report it via POST /api/v1/possession and PEV Connection will contact the owner on your behalf."
}
| Field | Type | Notes |
|---|---|---|
| registered | boolean | Whether any registration matches the identifier. |
| registrationId | string | Returned when registered. Can be used with service log and possession endpoints. |
| status | string | Only present when reported: lost or stolen. |
| photoUrls | string[] | Only present when reported lost/stolen. Requires the same bearer token to fetch. No owner information is ever included in this response. |
Device Photos
Photo URLs returned by /lookup require the same Authorization: Bearer header and
return the raw image bytes. Photos are only ever served for devices that have been reported lost or
stolen — registered-only devices never expose photos through the API.
GET /api/v1/registrations/{registrationId}/photo
GET /api/v1/registrations/{registrationId}/photos/{index}
Example request
curl "https://pevregistry.com/api/v1/registrations/6650c2f1a2b3c4d5e6f70123/photos/0" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-o photo-0.jpg
Report Possession
POST /api/v1/possession
If your shop has a device in your possession that has been reported lost or stolen, call this endpoint. PEV Connection will then contact the owner directly by SMS and/or email from our own systems — reporting that their device has potentially been located, the city/state on file for your business, and your shop's name and contact information so they can reach you. The device's status in the owner's account is also updated with the same information. You can also do this directly from your dashboard at /portal instead of calling the API.
This does not disclose any owner information back to your shop — it only confirms whether the owner was notified.
Example request
curl -X POST "https://pevregistry.com/api/v1/possession" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"identifier": "WT2500W26070581"
}'
Response
{
"success": true,
"ownerNotified": true
}
| Field | Required | Notes |
|---|---|---|
| identifier | One of identifier / registrationId | The same serial number or motor code used with /lookup. |
| registrationId | One of identifier / registrationId | The registry's internal ID, if already known from a prior lookup. |
The city/state shared with the owner always comes from your account's registered business address (updatable any time via PATCH /api/partners/me or your dashboard) — it is never passed in the /possession request body.
ownerNotified is false if another possession report was already filed for this device in the last 15 minutes (to avoid duplicate notifications) — the location on file is still updated either way.
Service Logs
POST /api/v1/service-logs
Adds a repair or maintenance record to a registered PEV. The device must already exist in PEV Registry;
unregistered identifiers return a failure and no record is saved. Shops can submit logs by identifier or by
the registrationId returned from /lookup.
Example request
curl -X POST "https://pevregistry.com/api/v1/service-logs" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"identifier": "WT2500W26070581",
"serviceType": "Brake adjustment",
"notes": "Adjusted rear brake caliper and test rode successfully.",
"odometerReading": 842,
"servicedAt": "2026-09-22T14:30:00-04:00"
}'
Success response
{
"success": true,
"registered": true,
"registrationId": "6650c2f1a2b3c4d5e6f70123"
}
Unregistered response
{
"error": "Device is not registered",
"registered": false
}
| Field | Required | Notes |
|---|---|---|
| identifier | One of identifier / registrationId | Serial number or motor code for the registered device. |
| registrationId | One of identifier / registrationId | The registry ID returned by /lookup. |
| serviceType | Yes | Repair or maintenance type, such as tire replacement, brake adjustment, or battery diagnostic. |
| notes | No | Additional service details, up to 3000 characters. |
| odometerReading | No | Non-negative number, if available. |
| servicedAt | Yes | Date/time of service. |
Webhooks
Configure a webhook URL and signing secret from your Shop Portal (Webhook tab) or via
PATCH /api/partners/me/webhook / POST /api/partners/me/webhook/secret. PEV Registry
will then push events to your endpoint instead of you having to poll.
Example: configure your webhook
curl -X PATCH "https://pevregistry.com/api/partners/me/webhook" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "webhookUrl": "https://your-shop-system.example.com/webhooks/pev-registry" }'
curl -X POST "https://pevregistry.com/api/partners/me/webhook/secret" \
-H "Authorization: Bearer pevreg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Event: device.possession_disputed
Sent when an owner marks a device your shop reported as "Not My Device" from their PEV Registry account. You'll also receive an email to your account's contact address for the same event.
POST https://your-shop-system.example.com/webhooks/pev-registry
Content-Type: application/json
X-PEV-Registry-Event: device.possession_disputed
X-PEV-Registry-Signature: sha256=<hex-encoded HMAC>
{
"event": "device.possession_disputed",
"sentAt": "2026-09-21T18:42:03.000Z",
"registrationId": "6650c2f1a2b3c4d5e6f70123",
"device": { "brand": "Example Brand", "model": "X2 Pro", "pevType": "E-Bike" },
"reportedCity": "Clearwater",
"reportedState": "FL",
"reportedAt": "2026-09-20T14:10:00.000Z",
"disputedAt": "2026-09-21T18:42:03.000Z"
}
Verifying the signature
Compute an HMAC-SHA256 of the raw request body using your webhook secret, then compare it (constant-time)
to the value after sha256= in the X-PEV-Registry-Signature header.
const crypto = require("crypto");
function isValidPevRegistrySignature(rawBody, signatureHeader, webhookSecret) {
const expected = crypto.createHmac("sha256", webhookSecret).update(rawBody).digest("hex");
const provided = String(signatureHeader || "").replace("sha256=", "");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(provided));
}
Your endpoint should respond quickly with a 2xx status. Failed deliveries are not currently retried — the lookup/dispute data is always still visible via the API and the Shop Portal.
Registration Widget
Instead of a raw API call, new devices are registered through an embeddable widget your customers use
directly on your own website. It's a themeable <iframe> that handles phone/email
verification and the device form for you, and tags every registration with your shop's ID for your
own analytics.
<iframe
src="https://pevregistry.com/embed-register.html?shop=YOUR_SHOP_ID&primaryColor=ff8210&font=Inter"
style="width:100%;max-width:520px;height:820px;border:0;"
title="Register your PEV with PEV Registry"
></iframe>
Sign in to the Shop Portal and open Registration Widget to get your shop ID, customize colors/fonts, and copy your embed code. Registrations completed through your widget are counted on that page.
Errors
| Status | Meaning |
|---|---|
| 400 | Missing or invalid request fields. |
| 401 | Missing, invalid, or revoked API key. |
| 404 | Photo not found (or device not eligible for photo access). |
| 409 | Conflict — e.g. that serial number is already registered, or the device you're reporting possession of is not currently marked lost/stolen. |
| 429 | Rate limit exceeded (60 requests/minute per key). |
| 500 | Unexpected server error. Safe to retry. |
Questions about the API? Contact PEV Connection at [email protected].