Fleet API · For car rental companies

ParkedIn Fleet API — developer guide

How your rental system integrates with ParkedIn: send licence plates to manage parking operators' whitelists (Feature 1), and receive licence plate scan events from those operators (Feature 2).

Base URL
https://api.parkedin.net
Format
JSON over HTTPS
Auth
Bearer API key

Overview

Access is set up by ParkedIn after a contract is signed — there is no self-service sign-up. At onboarding we create your company account, link it to your parking operators, give you your API key and, if you use scan events, register your webhook URL and give you its signing secret.

DirectionWhatHow
You → ParkedInAdd / remove licence plates (Feature 1)POST /vehicles, DELETE /vehicles, GET /vehicles
ParkedIn → youLicence plate scan events (Feature 2)Signed POST to your webhook URL

Base URL & authentication

All requests go to https://api.parkedin.net and must carry your API key in the Authorization header using the Bearer scheme:

Authorization: Bearer fpk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Licence plate format

Add vehicles

POST/vehicles

Adds one or more licence plates to your active fleet. Each new or re-activated plate is passed on to every parking operator linked to your account.

Request

curl -X POST https://api.parkedin.net/vehicles \
  -H "Authorization: Bearer $PARKEDIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vehicles": [
      { "plate": "ZH-123-AB" },
      { "plate": "zh 456 cd" },
      { "plate": "BE-789-EF" }
    ]
  }'
FieldTypeNotes
vehiclesarray, 1–1000 itemsRequired
vehicles[].platestringRequired. See plate format

Response 200

{
  "added": ["ZH-123-AB", "ZH-456-CD"],
  "reactivated": ["BE-789-EF"],
  "already_active": [],
  "summary": { "requested": 3, "newly_active": 3, "unchanged": 0 }
}

Remove vehicles

DELETE/vehicles

Removes one or more licence plates from your active fleet. The removal is passed on to every linked parking operator. Note the body is a plain list of plate strings.

Request

curl -X DELETE https://api.parkedin.net/vehicles \
  -H "Authorization: Bearer $PARKEDIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "vehicles": ["ZH-123-AB", "ZH-999-ZZ"] }'
FieldTypeNotes
vehiclesarray of strings, 1–1000 itemsRequired. Plates to remove

Response 200

{
  "removed": ["ZH-123-AB"],
  "not_found": ["ZH-999-ZZ"],
  "already_inactive": [],
  "summary": { "requested": 2, "newly_inactive": 1, "unchanged": 1 }
}

List vehicles

GET/vehicles

Returns your own vehicle list — useful to reconcile ParkedIn against your fleet system.

curl "https://api.parkedin.net/vehicles?status=active&limit=500&offset=0" \
  -H "Authorization: Bearer $PARKEDIN_API_KEY"
Query parameterValuesDefault
statusactive, inactive, allactive
limit1–500500
offset0 or more0
{
  "vehicles": [
    { "plate": "ZH-456-CD", "status": "active",
      "added_at": "2026-11-14T09:12:03.000Z", "updated_at": "2026-11-14T09:12:03.000Z" }
  ],
  "count": 1, "limit": 500, "offset": 0
}

Results are newest first. To page through a larger fleet, increase offset by limit until count is less than limit.

Batches & call volume

Rate limits: no fixed per-minute or per-hour limit is enforced today. If you plan regular high-volume traffic (for example a full-fleet sync every few minutes), tell us first so we can plan for it.

Errors

Errors return JSON with an error code and a readable message. Validation errors also list each problem in details:

{
  "error": "bad_request",
  "message": "Validation failed",
  "details": [ { "path": "vehicles.0.plate", "message": "Plate number contains invalid characters" } ]
}
StatuserrorMeaningWhat to do
200—Success—
400bad_requestInvalid JSON, invalid plate, empty list, or more than 1000 itemsFix the request; do not retry unchanged
401unauthorizedMissing, malformed or wrong API keyCheck the Authorization header
403unauthorizedYour account is not activeContact ParkedIn
500internal_server_errorProblem on our side; we are alerted automaticallyRetry later with backoff — repeating a request is safe

Scan event webhook

When a linked parking operator's camera reads one of your active plates and the operator sends that scan to ParkedIn, we send it to the HTTPS webhook URL registered for your company. Your webhook URL and signing secret are set up at onboarding; contact us to change them.

Payload

POST <your webhook url>
Content-Type: application/json
X-Event-Type: vehicle.scanned
X-Event-Id: 7f3d1e6a-8b2c-4d9e-a1f0-2c3b4a5d6e7f
X-Signature: 9c1e…   # HMAC-SHA256 of the raw body, hex

{
  "event_id": "7f3d1e6a-8b2c-4d9e-a1f0-2c3b4a5d6e7f",
  "event_type": "vehicle.scanned",
  "plate_number": "ZH-123-AB",
  "location_id": "zn-01",
  "location_name": "Zurich Nord",
  "scanned_at": "2026-07-04T14:32:07.000Z",
  "scan_type": "entry",
  "operator_id": "…",
  "operator_name": "Zurich Parking Nord"
}
FieldMeaning
event_idUnique per scan, and the same on every retry. Use it to ignore repeats
plate_numberNormalised plate, as on your vehicle list
scanned_atWhen the camera read the plate (ISO 8601, UTC). Use it for vehicle location and as the return time
scan_typeentry, exit or unknown
location_id, location_nameThe operator's facility
operator_id, operator_nameThe parking operator that sent the scan

Events can arrive out of order — order them by scanned_at.

Verify the signature

Compute HMAC-SHA256 of the raw request body (the exact bytes received, not re-serialised JSON) with your webhook secret, hex-encode it, and compare it to X-Signature in constant time. Reject the request if they differ.

// Node.js
import crypto from "node:crypto";
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const ok = expected.length === signature.length &&
  crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
# Python
import hmac, hashlib
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, signature_header)

Retries & duplicates

Answer with any 2xx as soon as you have stored the event, and do the processing afterwards. We wait up to 8 seconds.

Your responseWhat ParkedIn does
any 2xxDelivered; this event_id is not sent again
408, 429, any 5xx, timeout, connection errorRetried automatically — up to 5 attempts over about 12 minutes, then held and our on-call team is alerted
any other 4xx, or a redirect (3xx)Treated as rejected; not retried, our on-call team is alerted

What happens after a call

Operator connectionWhen your plate changes reach the operator
REST APIUsually within about a minute of your call
SFTP fileIn the next nightly file (full current list, delivered between 00:30 and 07:00 Zurich time)

Which operators you are linked to, and how each is connected, is agreed at onboarding. Questions? hello@parkedin.io