API documentation

Vehicle lookups over HTTP. Key and remote data as JSON.

Your first request

Accept your invitation, sign in, and create an API key in your account. Set up usage billing, then export your key as CATALOG_API_KEY in your server environment. Start by fetching makes, then use the returned IDs to discover models and years.

curl 'https://keys.env8.com/api/makes' \
  -H "Authorization: Bearer $CATALOG_API_KEY"

Look up a vehicle using the make and model names from discovery. This example demonstrates the request format; verify coverage for your application.

curl --get 'https://keys.env8.com/api/lookup' \
  -H "Authorization: Bearer $CATALOG_API_KEY" \
  --data-urlencode 'make=Honda' \
  --data-urlencode 'model=Accord' \
  --data-urlencode 'year=2020'

Authentication

Sign in to your account to create or revoke API keys, inspect recent requests, and manage billing. Full keys are shown once at creation. Your account password and browser session do not authenticate API calls.

Every /api/* catalog request requires Authorization: Bearer <your-key>. Keep the key in your backend environment. Your frontend should call your own backend, which forwards the request to this API.

Missing or invalid credentials return 401. API keys in query parameters are not accepted. CORS preflight requests do not require authentication. Each account starts with 25 free lookups, with no card required. Once they are used, a valid customer key returns 402 until billing is active. Payment problems or cancellation also pause access.

Rate limit

Each API key allows 60 authenticated requests per minute across all endpoints and client IPs. Discovery and requests that fail validation count toward this limit; CORS preflight requests do not. Excess requests return 429 with Retry-After: 60. Wait before retrying. Rate-limited requests do not use free lookups or incur usage charges.

Usage billing

Each successful GET /api/lookup or POST lookup operation is one billable lookup, including empty product results. Repeated calls and pagination requests count separately. Discovery, failed requests, and HEAD requests are not billed. The first 25 successful lookups per account are free, with no expiry or monthly reset. After that, lookups cost $0.05 USD each, billed monthly through Stripe with no minimum. Discovery and failed requests do not use your free credit. Use the X-Request-Id response header to find a call in your account’s 30-day request history.

Four endpoints. One lookup flow.

GET endpointParametersReturns
/api/makesNone requiredmakes with IDs and names
/api/modelsmakeIdmodels with IDs and names
/api/yearsmakeId, modelIdyears with IDs and year values
/api/lookupmake, model, yearVehicle, products, fitment metadata

Use IDs returned by discovery; do not hard-code IDs. Discovery includes vehicles with matching imported key or remote products. All four endpoints return a pagination object.

Prefer POST?

Send the same parameters as JSON to POST /api/catalog, with an operation of makes, models, years, or lookup.

curl 'https://keys.env8.com/api/catalog' \
  -H "Authorization: Bearer $CATALOG_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"operation":"lookup","make":"Honda","model":"Accord","year":2020}'

Vehicle filters

Save make, model, and year filters when creating a widget or API key. Choose makes and models from the searchable multi-selects; selected values appear as removable badges, and model choices follow your selected makes. For an existing key, choose API keys → Edit filters. These settings apply automatically to every discovery and lookup request. No selections and blank years include all supported vehicles. Discovery always includes only vehicles with matching imported key or remote products.

You can narrow any request further with a filters object. It supports makes and models as arrays of names, plus inclusive yearFrom and yearTo bounds. Names are case-insensitive exact matches; models are matched within the selected makes. Each list allows up to 100 names. Omitted fields or empty lists add no restriction.

curl 'https://keys.env8.com/api/catalog' \
  -H "Authorization: Bearer $CATALOG_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"operation":"makes","filters":{"makes":["Honda"],"models":["Accord","Civic"],"yearFrom":2015,"yearTo":2024}}'

GET requests accept the same fields using bracket notation. For example:

curl --get 'https://keys.env8.com/api/makes' \
  -H "Authorization: Bearer $CATALOG_API_KEY" \
  --data-urlencode 'filters[makes][]=Honda' \
  --data-urlencode 'filters[yearFrom]=2015' \
  --data-urlencode 'filters[yearTo]=2024'

Request filters apply only to that request; repeat them throughout discovery and pagination, or save them on the key to make them automatic. Request filters cannot widen the saved selection. Filtering happens before pagination, so an excluded branch never occupies a result slot. Discovery with no matching vehicles returns an empty list. A direct lookup outside the filters returns 403 and uses no quota. Existing keys and widgets keep their full coverage until you save filters.

A lookup response

Illustrative response with a fictional product. Available fields and actual products vary by vehicle.

{
  "vehicle": { "make": "Honda", "model": "Accord", "year": 2020 },
  "vehicleId": "example-vehicle",
  "products": [{
    "id": "example-product",
    "sku": "EXAMPLE-KEY",
    "title": "Example smart key",
    "type": null,
    "keywayType": null,
    "buttonCount": null,
    "features": [],
    "partNumbers": [],
    "requiresCutting": null,
    "requiresProgramming": null,
    "recommended": null,
    "imageUrl": ""
  }],
  "fitmentMetadata": { "decision_tree": null },
  "pagination": { "limit": 100, "offset": 0, "nextOffset": null }
}
  • Unknown is not false. Cutting, programming, and recommendation values can be null. Preserve that distinction in your interface.
  • Part numbers are structured. When available, each entry contains label and number strings.
  • Images are optional. imageUrl may be empty. Available images use temporary signed URLs; fetch a fresh lookup when a URL expires.
  • Fitment can need context. Use available fitmentMetadata.decision_tree details to present additional compatibility information.

Pagination

Send limit and offset on any catalog operation. The default limit is 100; the maximum is 500. Offset must be between 0 and 1,000,000. Follow pagination.nextOffset until it is null.

GET /api/makes?limit=100&offset=100

Errors and coverage

Errors return a JSON object with a message string. Handle the status code before rendering products.

StatusMeaning
400Invalid parameters or malformed JSON.
401Missing or invalid bearer key.
402Set up billing or resolve a payment issue in your account.
403The vehicle is outside the saved or request filters. No quota is used.
413JSON body exceeds 16 KiB.
415POST body must use application/json.
429Rate limit exceeded. Wait for the number of seconds in Retry-After before retrying. No quota is used.
503Coverage has not been imported, or the service is temporarily unavailable.

A 200 response with products: [] means the imported listing has no matching key or remote products. A 503 is not an empty match: show an unavailable state and use the message for diagnosis. Avoid repeatedly retrying missing coverage.

Build with Car Key API.

Tell us your use case, vehicle coverage, and expected request volume.

Talk API access