R13
Sign inGet started
API reference

Route13 API

Two REST endpoints — search the index for free, unlock full records. Bearer auth, JSON responses. Same credit balance as the web dashboard.

Base URLhttps://route13.io/api/v1

Overview


The Route13 API is read-only and returns company records normalised across European registries. Two endpoints:

  • GET /companies — paginated search. Returns identifiers + sector + employees + address. FREE — same model as Apollo / Hunter / Crunchbase basic search. Rate limits apply (see below).
  • GET /companies/:identifier — full record. Returns financials, directors (names + roles, NO emails), Egapro, IDCC, BODACC events, PSC register (UK), establishments. Costs 1 credit the first time. Once paid, every future request for that company is free forever (on web or API).

Credits are the same balance you see on the web dashboard — unlock via API and the company appears unlocked on the web, and vice versa.

All endpoints require a valid API key. Generate yours at dashboard/keys.

Authentication


Pass your API key as a Bearer token in the Authorization header, or as a api_key query parameter (less secure, use only for testing):

# Recommended
curl https://route13.io/api/v1/companies \
  -H "Authorization: Bearer r13_live_..."

# Quick test
curl "https://route13.io/api/v1/companies?api_key=r13_live_..."
⚠️Never expose API keys in client-side code or public repos. Use environment variables.

Pricing


Pay only for value delivered: search is free, full records cost 1 credit (permanent unlock). Same balance as the web.

OperationCostNotes
GET /companiesFREESearch is unmetered; rate limits prevent abuse. Same model as Apollo / Hunter.
GET /companies/:id1 credit, then free foreverFirst unlock charges 1 cr and adds it to your unlocks. Re-fetches are free, on either web or API.

Every response includes a meta object with cost (credits charged on this call) and the relevant remaining balance so you can track usage in real time.

If the operation costs more than your remaining balance, the request fails with a 402 Payment Required and nothing is charged.

Plan gates


Each endpoint is gated by subscription plan. Your plan is checked live against subscriptions.plan on every request (not the snapshot stored on the API key) — upgrades and downgrades take effect immediately.

EndpointFreePro
GET /companies
GET /companies/:id

Free tier users have no API access at all (they get HTTP 403 on every API call).

Rate limits


Rate limits are infrastructure protection, not paywalls — they apply to every plan including Business.

ScopeLimitWindow
Per API key 100 requests 1 minute
Per IP 1,000 requests 1 hour

When you hit a limit you get 429 Too Many Requests with a Retry-After header. If your integration legitimately needs higher throughput contact [email protected] and we'll raise the cap.

Try it


Already have a key? Test it right here. The request goes directly from your browser to the Route13 API — your key never hits Route13 servers (other than the API endpoint itself).

Try it now

Paste a key and run a real call against /api/v1/companies. Your key never leaves the browser.

GET /companies/:identifier


Returns the full record for one company. First call charges 1 credit and permanently unlocks the company for your account. Subsequent calls (on web or API) are free.

Path parameter

ParameterDescription
identifierNational identifier (SIREN for France, BCE for Belgium, KvK for Netherlands, etc.). Alphanumeric.

Optional query parameter

ParameterDescription
countryISO-2 country code. Required only when the same identifier exists in multiple countries.

Example

curl "https://route13.io/api/v1/companies/652014051" \
  -H "Authorization: Bearer r13_live_..."

Response

{
  "data": {
    "id": "5f3a4b7c-...",
    "identifier": "652014051",
    "country": "FR",
    "name": "Carrefour SA",
    "address": "...",
    "sector_code": "4711F",
    "sector_name": "Hypermarchés",
    "employees": 320000,
    "vat_number": "FR48652014051",
    "financials": [
      {
        "fiscal_year": "2024",
        "revenue_eur": 84860000000,
        "ebitda_eur":  4023000000,
        "ebitda_is_estimated": false,
        "net_result_eur": 1670000000
      }
    ],
    "directors": [
      {
        "type": "person",
        "last_name": "BOMPARD",
        "first_names": "Alexandre",
        "birth_year": 1972,
        "role": "Président-directeur général"
      }
    ],
    "esg": {
      "egapro": [
        { "year": 2024, "total_score": 88, "structure": "Entreprise" }
      ],
      "idcc": ["1486", "2216"]
    }
  },
  "meta": {
    "cost": 1,
    "credits_remaining": 997.75,
    "already_unlocked": false,
    "plan": "pro"
  }
}

already_unlocked: true means this call was free because you'd unlocked the company before (via API or web).

Errors


StatusMeaning
400Malformed parameter, or identifier is ambiguous across countries (pass ?country=XX)
401Missing or invalid API key
402Insufficient credits — top up at /pricing. Body includes the exact shortfall.
403Plan not eligible (e.g. Free trying an API call that needs a paid plan). Body explains the required tier.
404Company not found
429Rate limit (100/min per key, 1000/h per IP). Check Retry-After.
500Server error — please retry

SDKs & recipes


Node.js / fetch

const KEY = process.env.ROUTE13_API_KEY;
const headers = { Authorization: `Bearer ${KEY}` };

// Search
const search = await fetch(
  "https://route13.io/api/v1/companies?country=FR&min_revenue=10000000",
  { headers },
);
const { data: results, meta } = await search.json();

// Fetch full record for the first hit
const full = await fetch(
  `https://route13.io/api/v1/companies/${results[0].identifier}`,
  { headers },
);
const { data: company } = await full.json();

Python / requests

import os, requests
H = {"Authorization": f"Bearer {os.environ['ROUTE13_API_KEY']}"}

# Search
r = requests.get(
    "https://route13.io/api/v1/companies",
    params={"country": "FR", "min_revenue": 1_000_000},
    headers=H,
)
r.raise_for_status()
results = r.json()["data"]

# Full record
r = requests.get(
    f"https://route13.io/api/v1/companies/{results[0]['identifier']}",
    headers=H,
)
r.raise_for_status()
company = r.json()["data"]

Pagination loop (search only, no detail charge)

async function* allSearchHits(filters) {
  let page = 1;
  while (true) {
    const url = new URL("https://route13.io/api/v1/companies");
    Object.entries({ ...filters, page, per_page: 100 }).forEach(([k, v]) => url.searchParams.set(k, v));
    const res = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } });
    if (res.status === 402) throw new Error("Out of credits");
    if (res.status === 429) {
      const wait = parseInt(res.headers.get("Retry-After") ?? "60", 10);
      await new Promise(r => setTimeout(r, wait * 1000));
      continue;
    }
    const { data, meta } = await res.json();
    yield* data;
    if (data.length < meta.per_page) break;
    page++;
  }
}

Changelog


  • v2.32026-07-14 — director-emails endpoint withdrawn. The GET /companies/:id/director-emails endpoint now returns 410 Gone; the director-email dataset is suspended product-wide.
  • v2.22026-05-15 — search is FREE. Search no longer charges credits — aligned with Apollo / Crunchbase basic. Plan gates checked live on subscriptions.plan (not the cached key snapshot).
  • v2.02026-05-11 — credit-based pricing. Two endpoints (search + detail). The legacy meta.calls_remaining field is gone; use meta.credits_remaining instead.
  • v1.0Initial release. France live with 42K companies.
Need help integrating?

Email [email protected] — we usually respond within a day.

Get an API key