R13
Sign inGet started
API reference

Route13 API

Three REST endpoints — search the index for free, unlock full records, reveal verified director emails. 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. Three 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), sanctions, 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).
  • GET /companies/:identifier/director-emails — verified director email reveals (SMTP-verified). Professional plan only. Costs 1 email-credit per newly-revealed email; re-fetching emails you've already revealed is free forever (idempotent). Includes a free ?preview=true mode that returns the cost without charging.

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. Same for director email reveals (audit-logged per GDPR Art. 30(2)).

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), director email reveals cost 1 email-credit each (Professional only). 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.
GET /companies/:id/director-emails1 email-credit per NEW revealRe-fetching already-revealed emails is free. Use ?preview=true to count without charging.

Every response includes a meta object with cost (credits/email-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. Director email reveals will additionally fail with 402 if you have insufficient email-credits.

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.

EndpointFreeStarterProfessional
GET /companies
GET /companies/:id
GET /companies/:id/director-emails

Free tier users have no API access at all (they get HTTP 403 on every API call). Starter callers requesting director-emails get HTTP 403 with an upgrade pointer.

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"
      }
    ],
    "compliance": {
      "sanctions": [],
      "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).

GET /companies/:identifier/director-emails


Reveal verified business emails for the directors of a company. Professional plan only. Each newly-revealed email costs 1 email-credit from your monthly quota (25 / 200 / 1,000 depending on volume tier). Re-fetching emails you've already revealed before is free forever (idempotent via audit log).

Path parameter

ParameterDescription
identifierNational identifier (same shape as the detail endpoint)

Query parameters

ParameterTypeDescription
countrystring (ISO-2)Required only when identifier is ambiguous across countries
previewbooleanFREE preview. Returns the cost (number of new reveals) without charging. Recommended before a real reveal.

Example — preview first (free)

curl "https://route13.io/api/v1/companies/652014051/director-emails?preview=true" \
  -H "Authorization: Bearer r13_live_..."

# Response
{
  "company": { "id": "...", "identifier": "652014051", "country": "FR", "name": "Carrefour SA" },
  "preview": true,
  "directors_with_email_total": 12,
  "already_revealed": 3,        // free re-fetches
  "new_reveals_available": 9,   // would cost 9 email-credits
  "cost_if_proceed": 9,
  "email_credits_remaining": 200
}

Example — real reveal (charges)

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

# Response
{
  "company": { "id": "...", "identifier": "652014051", "country": "FR", "name": "Carrefour SA" },
  "directors": [
    {
      "id": "97125aa6-...",
      "last_name": "BOMPARD",
      "first_names": "Alexandre",
      "role": "Président-directeur général",
      "email": "[email protected]",
      "email_verified": "valid",          // 'valid' | 'catch_all' | null
      "email_confidence": 85,             // 0-100
      "newly_revealed": true              // false = previously revealed, free
    }
    // ... up to 12 directors with email
  ],
  "meta": {
    "cost_charged": 9,                    // email-credits deducted
    "email_credits_remaining": 191,
    "total_directors_with_email": 12
  }
}

Insufficient email-credits

If revealing N new emails costs more than your remaining email-credits, the request fails with HTTP 402 and nothing is charged — use ?preview=true first to avoid this.

# When the cost exceeds your quota
{
  "error": "Insufficient email credits: this reveal needs 12 but you have 7. Upgrade to a larger volume tier at https://route13.io/pricing or wait for monthly reset.",
  "cost_needed": 12,
  "email_credits_remaining": 7
}

GDPR posture

Each reveal is logged to customer_unlock_audit with action_type='reveal_director_email' for GDPR Art. 30(2) compliance. The audit log is what makes re-fetches free (we know you already paid). It's also what we use to satisfy Art. 15 access-by-subject requests.

Errors


StatusMeaning
400Malformed parameter, or identifier is ambiguous across countries (pass ?country=XX)
401Missing or invalid API key
402Insufficient credits or email-credits — top up at /pricing. Body includes the exact shortfall.
403Plan not eligible (e.g. Free trying any API call, or Starter trying director-emails endpoint). 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.22026-05-15 — director-emails endpoint + plan gating + search is FREE. New GET /companies/:id/director-emails (Professional only). Search no longer charges credits — aligned with Apollo / Hunter / 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