Skip to main content

API Key

  • Header: x-api-key
  • Format: lmn_prd_<28 url-safe base64 chars> (production) or lmn_stg_<28 url-safe base64 chars> (sandbox).
  • Issuing: mint your own in the partner consoleKeys. Sandbox keys are self-serve and instant; production keys unlock after approval.
  • Transport: the key is displayed once, at creation. LMN stores only a hash and cannot show it to you again — capture it then, into a secret manager. Never commit to source; never transmit in URLs.
  • Rotation: self-service from the console (Keys → Rotate). The old key is revoked immediately — it stops working the moment the new key is issued, with no overlap window. See Rotating without downtime for the safe procedure.
  • Errors:
    • 401 missing_api_keyx-api-key header absent.
    • 401 invalid_api_key — key not recognized, revoked, or wrong environment (e.g., lmn_stg_* against api.lmnauto.com).

Rotating without downtime

Keys → Rotate is create-then-revoke, and both halves complete server-side before the response reaches you. By the time you are looking at the new key, the old one is already revoked — there is no window in which both work. If your deployment takes ten minutes, that is ten minutes of 401 invalid_api_key. To rotate with no gap, use two keys instead of the Rotate button:
1

Create a second key

Keys → Create. Both keys are now valid.
2

Deploy the new key

Roll it out to every caller and confirm traffic is flowing on it.
3

Revoke the old key

Keys → Revoke on the original. Nothing is depending on it any more.
Trial accounts may hold 2 active sandbox keys, which is exactly enough to run this procedure from a single key. Production accounts are uncapped. If a trial account is already at the cap, Create returns 403 — but Rotate deliberately bypasses the cap so you are never locked out of replacing a key, at the cost of the gap described above.
Revocation propagates immediately in the normal case, and within ~60 seconds in the worst case (key state is cached for 60s, with cross-pod invalidation on revoke). Treat a revoked key as dead the instant you revoke it — never plan a cutover around the propagation lag.
Use Rotate when the key is compromised and killing it immediately is the point. Use the two-key procedure for routine, scheduled rotation.

X-User-Id (optional, attribution)

Send an X-User-Id header on any request to attribute it to the individual end-user/dealer within your org. Useful for per-dealer analytics and curation.
  • Optional — omitting it is never an error.
  • Not authenticated — LMN does not validate, resolve, or reject the value. Authentication is solely on x-api-key. This is opaque attribution metadata only.
  • Format — any stable opaque string; your namespace to define. Send the same value for the same user so attribution groups correctly (grouping is by exact, case-sensitive value). X_User_Id is accepted as an alternate header name.
  • Privacy — LMN’s request logs store a one-way SHA-256 hash of the value, not the raw string.
  • Where used — LMN’s logging/audit pipeline only; not stored on order resources.

IP Allowlist

Sandbox trial keys have no allowlist. Keys minted by a self-serve account accept requests from any source IP, so you can build from a laptop, a CI runner, or a serverless platform with rotating egress. Nothing below applies until you move to production.
Production keys are accepted only from pre-registered partner egress IPs.
  • Up to 16 addresses or CIDR ranges per environment — IPv4 and IPv6 both supported (e.g., 203.0.113.0/24, 2001:db8::/32).
  • Sandbox and production have independent allowlists.
  • Requests from unlisted IPs return 403 ip_not_allowed.
  • Matching is per-family: if your client egresses over both IPv4 and IPv6 (dual-stack), register ranges for both families — otherwise requests intermittently fail when the unlisted family is used.
Manage entries yourself in the partner console: Keys → the key → Allowlist. Changes take effect within a minute (keys are cached for up to 60 seconds). For emergency revocation outside the console, contact security@lmnauto.com.
Serverless backends and production keys. Platforms like Vercel, Supabase Edge Functions, Lovable Cloud, and Cloudflare Workers egress from large, rotating IP pools that cannot be meaningfully allowlisted. Certify your integration on a sandbox key, and raise the deployment target with us during production approval so we can plan a workable egress setup — a static-IP NAT or a dedicated proxy — rather than discovering it at cutover.

TLS Requirements

  • Minimum TLS 1.2 (TLS 1.3 preferred).
  • Forward-secret cipher suites required (ECDHE-*).
  • Public CA chain — no certificate pinning required.

Idempotency-Key (required on order creation)

POST /v1/orders must include an Idempotency-Key header with a UUID v4 value.
  • LMN enforces a permanent unique constraint on (api_key, idempotency_key). Replays return the cached response (same status, same body). Safe to retry on timeouts.
  • Missing on POST /v1/orders returns 400 missing_idempotency_key.
  • Reusing an Idempotency-Key with a different vehicle_id — or with a different secondary_inspection_required for the same vehicle — returns 422 idempotency_key_reused. Generate a fresh key per logical request, never reuse across different orders.

Safe vs unsafe key reuse

Rule of thumb: generate the Idempotency-Key once at the moment of order intent, then reuse it across all retries of the same logical request. Never reuse across different logical requests.

Rate Limits

Fair-use targets per API key (not currently enforced server-side, except the eagle-eye test-webhook limiter — 5 fires per minute per watch, which does return 429): Build your client as if these were enforced: stay under the targets and apply exponential backoff to transient failures. Server-side enforcement at these targets may be introduced later without a breaking-change notice — clients that already pace themselves won’t be affected. Sustained traffic far above the targets may be raised with your integration contact.
Do not map 429 rate_limited to a single behavior. On /v1 that code covers two conditions with opposite remedies, and neither sends Retry-After:
  • Test webhook throttle — 5 fires/min per watch on POST /v1/eagle-eye/watches/{watch_id}/test-webhook, the one throttle that is enforced. Transient; clears within 60s.
  • Trial budget exhausted — a sandbox trial key’s lifetime call budget is spent. Permanent; retrying never succeeds.
Branch on error.details.limit: present means budget, absent means throttle. See Telling the two 429s apart. If general burst throttling is introduced later it will be documented before it ships.

Webhook signing

All webhooks LMN sends to your endpoint are signed with HMAC-SHA256 (Stripe-compatible scheme). See Webhooks → Signing for verification details.