How to authenticate decode requests
Use X-API-Key: ovd_live_… for server-to-server integrations (keys created once in the dashboard).
Use Authorization: Bearer <accessToken> when calling from a logged-in web session —
obtain the access token via POST /auth/login and refresh it with POST /auth/refresh.
POST
/api/v1/auth/login
Public · rate limited
Login (issue JWT access token)
Email/password login. Returns a short-lived access token for the Authorization: Bearer header. Refresh token is set as an httpOnly cookie — not returned in JSON.
Request
{
"email": "user@example.com",
"password": "your-password"
}
Response 200
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresIn": 900,
"tokenType": "Bearer",
"user": {
"id": "usr_01H...",
"email": "user@example.com",
"accountState": "active"
}
}
}
Errors: 401 invalid credentials · 403 email not verified · 403 account suspended
POST
/api/v1/auth/refresh
Cookie: refreshToken
Refresh access token
Rotate the httpOnly refresh cookie and return a new access token when the current JWT expires (~15 minutes).
Request
POST /api/v1/auth/refresh
Cookie: refreshToken=<httpOnly cookie from login>
Response 200
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresIn": 900,
"tokenType": "Bearer"
}
}
Errors: 401 missing or revoked refresh token
POST
/api/v1/validate-vin
Quota: free · unlimited
Validate VIN format
Checks 17-character format and check digit. Never consumes daily quota.
Request
{
"vin": "1HGCM82633A004352"
}
Response 200
{
"success": true,
"data": {
"vin": "1HGCM82633A004352",
"isValidFormat": true,
"checkDigitValid": true
}
}
POST
/api/v1/decode
Quota: 1 per successful decode
Decode a single VIN
Returns structured USA/Canada vehicle attributes from licensed NHTSA-backed data.
Request
{
"vin": "1HGCM82633A004352"
}
Response 200
{
"success": true,
"data": {
"vin": "1HGCM82633A004352",
"modelYear": 2003,
"make": "HONDA",
"model": "Accord",
"trim": "EX",
"vehicleType": "PASSENGER CAR",
"bodyStyle": "Sedan",
"engine": { "cylinders": 4, "displacementL": 2.4, "fuelType": "Gasoline" },
"transmission": "Automatic",
"drivetrain": "FWD",
"manufacturer": { "name": "HONDA", "country": "USA" },
"safetyFeatures": []
}
}
Errors: 400 invalid format · 404 not in database · 429 quota exceeded
POST
/api/v1/decode-from-image
Quota: plan-based · OCR failure does not consume quota
Decode VIN from image (OCR)
Upload a JPEG/PNG of a VIN plate. On success returns the same vehicle payload as /decode.
Request
Content-Type: multipart/form-data
image: <file>
Errors: 400 when no VIN is detected in the image
POST
/api/v1/batch-decode
Quota: billable successes only · max 1,000 VINs
Batch decode
Decode up to 1,000 VINs in one request. Successful VINs return results even if others fail. Duplicates are deduplicated in-summary.
Request
{
"vins": ["1HGCM82633A004352", "INVALIDVIN1234567"]
}
Response 200
{
"success": true,
"data": {
"summary": {
"totalSubmitted": 2,
"successful": 1,
"failed": 1,
"duplicates": 0,
"billableCount": 1
},
"results": [
{ "vin": "1HGCM82633A004352", "status": "success", "vehicle": { } },
{ "vin": "INVALIDVIN1234567", "status": "error", "errorCode": "INVALID_VIN" }
]
}
}
GET
/api/v1/usage
Quota: unlimited (read-only)
Usage & quota status
Current plan, daily used/remaining, and overage for the authenticated account or API key.
Response 200
{
"success": true,
"data": {
"plan": "pro",
"dailyQuota": 3333,
"usedToday": 142,
"remainingToday": 3191,
"overageEnabled": true,
"overageToday": 0,
"periodEndsAt": "2026-08-01T00:00:00Z"
}
}
POST
/api/v1/webhooks
Pro and Business only
Register a webhook
Subscribe to subscription, quota threshold, and API key events. Signing secret is returned once.
Request
{
"url": "https://customer.example.com/hooks/vin-decoder",
"events": ["subscription.updated", "quota.threshold", "api_key.revoked"]
}
Response 201: webhook ID and signing secret (shown once)
Admin routes live under /api/v1/admin/* and require an admin JWT — not listed on this public docs page.
Rate limits: plan daily quota for decode; supplementary 100 req/min per user; login brute-force protection.
This page is a prototype reference aligned with docs/Architecture/api-design.md.