# CarAPI.io

> A vehicle-data API for Denmark, Norway, Sweden and the Netherlands. One call turns a
> registration plate or a VIN into the national registry's record for that vehicle.

CarAPI.io is a paid HTTP API with a free tier. It returns vehicle data only: no owner, keeper
or other personal data is available from it, for any country.

## Try it now: no signup, no human needed

Working for someone who already has a CarAPI.io account? Use that account's key
(https://carapi.io/api-keys) and go straight to step 2: every `POST /v1/signup` creates a new,
separate account.

1. Get a working API key with 10 free tokens (10 basic lookups):

   `curl -X POST https://api.carapi.io/v1/signup`

   It is an ordinary key on an ordinary account, not a sandbox: the same endpoints, the same
   responses and the same prices as a full integration, so what you test is what you build on.
2. Look up a real vehicle. These plates exist:

   `curl https://api.carapi.io/v1/se/reg/YYO555 -H "Authorization: Bearer YOUR_API_KEY"`

   Sweden `YYO555`, Denmark `AP15244`, Norway `DN88050`, the Netherlands `79NFN3`.
3. To keep the key and get the free plan's 100 tokens a month, the account needs your user's
   e-mail address:

   `curl -X POST https://api.carapi.io/v1/signup/email -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" -d '{"email":"name@example.com"}'`

   We send that address a link. Its owner confirms it and chooses a password, and the same key
   keeps working. Opening that e-mail is all your user has to do: signing up or logging in at
   carapi.io with the same address only sends the link again. A key whose address is never
   confirmed stops working 30 days after it was created. A person can also sign up at
   https://carapi.io/signup and create keys there.

   Once the 10 tokens are spent, lookups answer `403 EMAIL_NOT_VERIFIED` until the address is
   confirmed; the message says what to do next.

Without any key, `GET https://api.carapi.io/v1/se/reg/CARAPI-DEMO` answers with sample data
in the exact shape of a real response (also for dk, no and nl). It costs nothing and never
calls the registry. If you can only make GET requests, that is what you can test on your own;
for a real lookup, your user can run the `curl -X POST` above, or sign up.

Limits on new keys: 3 per IP address per day and 10 per month. Free lookups by accounts
without a confirmed address share a daily ceiling; past it the API answers 503
FREE_LIMIT_REACHED until 00:00 UTC.

## Basics

- Base URL: https://api.carapi.io/v1
- Auth: `Authorization: Bearer <api_key>` (or `X-API-Key: <api_key>`).
- Countries: `dk`, `no`, `se`, `nl`.
- Free tier: 100 tokens a month, 10 credited when the key is created and the rest when the
  e-mail address is confirmed. 20 requests and 10 tokens per minute.
- Paid plans (EUR a month): Starter 20 (2,500 tokens), Developer 40 (5,000), Business 134
  (25,000); token packs from 7 EUR per 1,000. Online checkout is not open yet: a paid plan is
  set up on request at https://carapi.io/contact-sales.
- Failed lookups are not billed: a plate that does not exist, a combination the registry does
  not offer, and a registry outage all cost 0 tokens.

## Endpoints

- `GET /v1/{country}/reg/{plate}`: the registry record, plus `summary` (1 token)
- `GET /v1/{country}/vin/{vin}`: the same record by VIN (1 token; not available for nl)
- `GET /v1/{country}/reg/{plate}/inspection`: inspection history (2 tokens; dk, se)
- `GET /v1/{country}/reg/{plate}/debt`: registered liens, tinglysning (2 tokens; dk)
- `GET /v1/{country}/reg/{plate}/complete`: vehicle + inspections + debt + emissions
  (5 tokens; dk, se). `meta.partial` / `meta.missing` name any slice the registry failed to
  deliver.
- `POST /v1/signup`: a new key with 10 free tokens, no authentication
- `POST /v1/signup/email`: attach the e-mail address that keeps the key (authenticated with it)
- `GET /v1`: a public index, no key required
- `GET /v1/openapi.json`: the OpenAPI 3.1 spec

Coverage differs per country. A combination the registry does not offer answers 503 and is
not billed, as is a plate that does not exist.

## Things worth knowing

- `data` is the registry's own record, passed through. Field names and language vary by
  country, and Denmark and the Netherlands nest it under `data.data`.
- `summary`, next to `data` on vehicle lookups and `/complete`, is the same facts in one shape
  for every country: `registration`, `brand`, `model`, `vin` (null for nl),
  `first_registration { date, year }` and `fuel { normalized, raw }`. `fuel.normalized` is one
  of petrol, diesel, electric, hybrid, plugin_hybrid, lpg, cng, hydrogen, ethanol, or null,
  never a guess; `raw` keeps the registry's own value.
- `meta.tokensRemaining` on every answer is the live balance after the call.
- Two rate limits, per minute. The request limit is per API key and sends the draft-6
  `RateLimit-*` headers (`RateLimit-Reset` in seconds). The token limit is per account and
  sends `X-RateLimit-*` (`X-RateLimit-Reset` is an ISO timestamp). Both 429s, and a 503
  UPSTREAM_ERROR, carry `Retry-After` in seconds: honour it rather than retrying in a loop.
- Every error has a machine-readable `code`, a `retryable` flag and a `docs` link; switch on
  the code, not on the message.
- Spaces, dashes and case in a plate are ignored.
- A key is server-side only by default: browser calls are refused unless that key has been
  opened up to named origins.

## Links

- Documentation: https://carapi.io/docs (also as Markdown: https://carapi.io/docs.md)
- API reference: https://carapi.io/docs/reference
- OpenAPI: https://api.carapi.io/v1/openapi.json
- Pricing: https://carapi.io/pricing
- Sign up as a person: https://carapi.io/signup
- Contact: https://carapi.io/contact-sales
