APEXGuides

Consuming APEX directly

How to call the APEX API from your own systems — authenticate with an API key, request a single estimate or a batch, read the percentile/confidence response, and handle INSUFFICIENT_DATA and errors. Server-to-server patterns, not a shipped SDK.

APEX is a plain REST API, so you can call it directly from your own systems to get freight market prices — independently of the TOVR platform. This guide shows the practical client patterns; the exact contracts live in APEX › Reference.

This covers direct consumption from outside TOVR. If you're pricing freight inside TOVR (the cost engine, bid recommendation), that path is Using APEX from TOVR. There is no published client SDK yet — the patterns below are straight HTTP.

When to use this

Reach for direct APEX access when you want European freight market rates in your own application, pipeline, or analysis — a TMS, a pricing sheet, a data job — as a server-to-server integration. It is not intended for the browser: your API key is a secret.

1. Authenticate

Every request carries an X-API-Key header. Keys are issued by TOVR operators; see Authentication for the key model and security practices.

curl https://apex.tovr.eu/api/v1/analytics/overview \
  -H "X-API-Key: apex_your_key_here"

2. Request a single estimate

Post a lane to /estimate:

async function estimateLane() {
  const res = await fetch("https://apex.tovr.eu/api/v1/estimate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": process.env.APEX_API_KEY!,
    },
    body: JSON.stringify({
      loading_country: "PL",
      loading_postal_code: "50-148",
      unloading_country: "DE",
      unloading_postal_code: "60311",
      distance_km: 700,
    }),
  });

  if (!res.ok) throw new Error(`APEX ${res.status}`);
  return res.json();
}

3. Batch for volume

Pricing many lanes? Use /estimate/batch (up to 500 items per call) instead of many single requests — items are deduplicated and lookups are batched, so it's far cheaper and easier on your rate limit. Each item echoes its index, and items can fail independently (error instead of result), so iterate the results and check each one.

4. Read the response

An estimate is a distribution plus a trust signal, not a single number:

  • p25_/median_/p75_price_per_km and estimated_price_eur — the market band for the lane. The spread is the point: a wide band means room to negotiate.
  • confidence_score + quality_status (HIGH/MEDIUM/LOW) — how well-backed the estimate is (data volume + freshness). Weight your decision by it. See Confidence & quality.
  • match_level (exact → country_pair) — how specific the match was; broader matches carry lower confidence.

Handle INSUFFICIENT_DATA

When APEX has no usable data for a lane it returns 200 OK with zeroed prices, match_level: "none", and quality_status: "INSUFFICIENT_DATA". This is a coverage statement, not an error — check quality_status before trusting the numbers, and treat this case as "no price available" rather than retrying.

5. Errors and retries

Errors return a stable code (branch on it, not the message). Honour Retry-After on 429, back off on 5xx, and don't retry other 4xx — see the full catalog in Errors and the budget model in Rate limiting.

Configuration note (PIS → APEX)

APEX was previously called PIS ("Price Intelligence Service"). For backward compatibility, TOVR's own client reads APEX_API_URL / APEX_API_KEY and falls back to the legacy PIS_API_URL / PIS_API_KEY, and the old Pis* type and getPis* function names are @deprecated aliases (packages/core/src/services/apex.ts). New integrations should use the APEX_* names; the PIS_* names still work but will be removed.

Next

On this page