Three endpoints, one verification layer.
A short guide for OEMs and fleet integrators: sign in, send territory-attributed batches, and consume the signed patch bundle. No SDK to install, no bespoke release schedule.
Verimap uses better-auth. Browser callers import authClient from @/lib/auth-client; non-browser callers POST a sign-in form to /api/auth/sign-in/email, persist the returned cookies, then send them on every further request. There is no bearer header — better-auth authenticates the cookie, so curl callers pass -b cookies.txt.
# 1) sign in (cookies server writes to cookies.txt)
curl -sS -c cookies.txt -X POST \
-H 'content-type: application/json' \
-d '{"email":"you@oem.eu","password":"hunter2"}' \
https://verimap.example/api/auth/sign-in/email
# 2) use the cookie on a per-user endpoint
curl -sS -b cookies.txt https://verimap.example/api/patches?limit=5Send an authenticated batch whose traffic, fleet, and roadwork items carry an explicit supported ISO territory code. The endpoint validates each item, writes the raw event and its successful receipt atomically, and derives LIVE/UNKNOWN status from those receipts.
curl -sS -X POST https://verimap.example/api/ingest \
-H 'content-type: application/json' \
-d '{
"fleet": [{
"fleetPartnerId": "fleet-demo",
"segmentId": "seg_a96_de",
"territory": "DE",
"speed": 82,
"observedAt": "2026-08-25T12:34:56Z"
}]
}'GET /api/patches is gated by the better-auth session and returns a newest-first bundle of signed MapPatch rows. Verify each signature by re-canonicalising the item's fields (sorted keys, json-stringify of strings, no whitespace) and HMAC-SHA256ing with the shared PATCH_HMAC_SECRET — that is exactly what src/lib/patches/sign.ts does server-side. Drop a tampered patch before it ever reaches the ECU uploader.
import { createHmac, timingSafeEqual } from 'node:crypto';
const SECRET = process.env.PATCH_HMAC_SECRET;
const FIELDS = [
'id','segmentId','beforeConfidence','afterConfidence',
'sourceFeedId','ingestedAt','recomputedAt',
];
function canonical(value) {
if (value === null || typeof value !== 'object') return JSON.stringify(value);
if (Array.isArray(value)) return '[' + value.map(canonical).join(',') + ']';
const keys = Object.keys(value).sort();
return '{' + keys.map(k => JSON.stringify(k) + ':' + canonical(value[k])).join(',') + '}';
}
export function verifyPatch(item, sig) {
const payload = Object.fromEntries(FIELDS.map(k => [k, item[k]]));
const mac = createHmac('sha256', SECRET).update(canonical(payload)).digest('hex');
return mac.length === sig.length && timingSafeEqual(Buffer.from(mac, 'hex'), Buffer.from(sig, 'hex'));
}Tell us your fleet size, incumbent telematics provider and the OEM you ship for. An engineer reads every intake and replies within one EU business day — usually with a worked integration plan for the three surfaces above.
Open the intake formReplay the Autobahn SVP trace