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.
https://route13.io/api/v1Overview
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=truemode 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_..."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.
| Operation | Cost | Notes |
|---|---|---|
GET /companies | FREE | Search is unmetered; rate limits prevent abuse. Same model as Apollo / Hunter. |
GET /companies/:id | 1 credit, then free forever | First unlock charges 1 cr and adds it to your unlocks. Re-fetches are free, on either web or API. |
GET /companies/:id/director-emails | 1 email-credit per NEW reveal | Re-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.
| Endpoint | Free | Starter | Professional |
|---|---|---|---|
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.
| Scope | Limit | Window |
|---|---|---|
| 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).
GET /companies
Paginated search. Returns metadata only — no financials. Use this to discover companies, then call /companies/:id for full records.
Query parameters
| Parameter | Type | Description |
|---|---|---|
q | string | Substring search on company name |
country | string (ISO-2) | Filter by country code (e.g. FR) |
sector | string | Sector code prefix (NAF, SBI, …) |
min_revenue | number | Minimum revenue in EUR (matches any fiscal year on file) |
max_revenue | number | Maximum revenue in EUR |
min_ebitda | number | Minimum EBITDA in EUR |
page | integer | 1-indexed page number (default 1) |
per_page | integer | Results per page (default 25, max 100) |
Example
curl "https://route13.io/api/v1/companies?country=FR&min_revenue=10000000&per_page=50" \
-H "Authorization: Bearer r13_live_..."Response
{
"data": [
{
"id": "5f3a4b7c-...",
"identifier": "652014051",
"country": "FR",
"name": "Carrefour SA",
"address": "93 avenue de Paris, 91300 Massy",
"sector_code": "4711F",
"sector_name": "Hypermarchés",
"employees": 320000,
"vat_number": "FR48652014051"
}
// ... up to per_page results
],
"meta": {
"total": 8421,
"page": 1,
"per_page": 25,
"cost": 1.25, // 0.05 × 25 rows
"credits_remaining": 998.75,
"next_page_cost_estimate": 1.25,
"plan": "pro"
}
}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
| Parameter | Description |
|---|---|
identifier | National identifier (SIREN for France, BCE for Belgium, KvK for Netherlands, etc.). Alphanumeric. |
Optional query parameter
| Parameter | Description |
|---|---|
country | ISO-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
| Parameter | Description |
|---|---|
identifier | National identifier (same shape as the detail endpoint) |
Query parameters
| Parameter | Type | Description |
|---|---|---|
country | string (ISO-2) | Required only when identifier is ambiguous across countries |
preview | boolean | FREE 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
| Status | Meaning |
|---|---|
400 | Malformed parameter, or identifier is ambiguous across countries (pass ?country=XX) |
401 | Missing or invalid API key |
402 | Insufficient credits or email-credits — top up at /pricing. Body includes the exact shortfall. |
403 | Plan not eligible (e.g. Free trying any API call, or Starter trying director-emails endpoint). Body explains the required tier. |
404 | Company not found |
429 | Rate limit (100/min per key, 1000/h per IP). Check Retry-After. |
500 | Server 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 onsubscriptions.plan(not the cached key snapshot). - v2.02026-05-11 — credit-based pricing. Two endpoints (search + detail). The legacy
meta.calls_remainingfield is gone; usemeta.credits_remaininginstead. - v1.0Initial release. France live with 42K companies.
Email [email protected] — we usually respond within a day.