Before you map endpoints
A few things work differently on Generect — knowing them up front makes the mapping obvious:- Authentication uses an
Authorization: Token <your_token>header (theTokenprefix is required). See Authentication. - Pricing is pay-as-you-go credits, not seats or monthly contact caps. You are billed per returned result, and no data is never charged.
- Every search and enrich endpoint has two modes —
database(cached, sub-second, cheaper) andrealtime(live lookup, freshest, costs more). You choose per call by swappingdatabase↔realtimein the path. See Database vs Real-time. - Counts are free in database mode and billable in real-time mode — size an audience with a free count before paying for results.
From Apollo
From Hunter
From ZoomInfo
Migrating from our legacy endpoints
This section maps all legacyapi endpoints to their api/v1 replacements.
- Base URL — unchanged:
https://api.generect.com(only the path structure changed) - Auth — unchanged: header
Authorization: Token <your_api_token>
- Old paths were under
/api/.... New paths are versioned under/api/v1/...and grouped by resource (email,enrich,search,accounts). - Every new response is wrapped in a top-level object:
Previously the payload was returned flat (no
data/metawrapper). Update your response parsing to read fromresponse.dataandresponse.meta. - Billing/pricing behavior is unchanged: you’re only charged when a valid result is found (
meta.amount_charged = 0otherwise). - New endpoints accept multiple identifier types in one endpoint (send only ONE per request) instead of separate endpoints per identifier type.
Auth & Account
1. Token login — retired, no v1 equivalent
1. Token login — retired, no v1 equivalent
v1 has no login flow — every request authenticates with a static API key from account settings, sent as
Authorization: Token <key>. Drop the login call and store the key directly.2. Get account profile
2. Get account profile
3. List transactions
3. List transactions
4. Spent credits → Usage
4. Spent credits → Usage
Search (ICP)
5. Search leads by ICP
5. Search leads by ICP
Request — most filters keep their name:
locations, personas, company_locations, company_headcounts, company_types, limit_by, offset_by, exclude_names, exclude_ids, filter_empty_vars, company_link, company_id.New: job_titles, seniorities, exclude_locations, exclude_company_locations, exclude_company_industries, exclude_company_headcounts, strict, company_name (any mode) and keywords, functions (realtime mode only) — not required for a straight migration, but available if useful.Request field mapping:Response: item field names largely match Enrich lead (
title, nested company object, etc.), but each item’s identifier is returned as lead_id, not id. amount → meta.amount_charged (positive now); status removed.Full reference: Search leads · Realtime6. Count leads by ICP
6. Count leads by ICP
Same request filters as Search leads.
results_count/status → data.results_count. Database-mode counts are always free; realtime counts are billable.Full reference: Count leads · Realtime7. Search companies by ICP
7. Search companies by ICP
Request — most filters keep their name:
company_types, headcounts, industries, keywords, locations, num_of_followers, limit_by, offset_by. New: exclude_industries, exclude_locations, exclude_ids, exclude_domains, technologies, company_names, strict (any mode) and revenues_range, department_headcount, headcount_growth, hiring_on_linkedin, linkedins_links (realtime mode only).Request field mapping:Response: item field names largely match Enrich company, but each item’s identifier is returned as
linkedin_id, not id. amount → meta.amount_charged (positive now); time_cached removed.Full reference: Search companies · Realtime8. Count companies by ICP
8. Count companies by ICP
Same request filters as Search companies.
results_count → data.results_count. Database-mode counts are always free; realtime counts are billable.Full reference: Count companies · RealtimeEnrich
9. Enrich company by URL
9. Enrich company by URL
Request — send exactly ONE identifier field (was: LinkedIn company URL / company website):
The new endpoint also accepts
id (Generect internal company ID) or name (fuzzy match) — extra options, not required for migration.Response: the v1 payload is much slimmer than the legacy one — only name, domain, industry carry over unchanged, plus two renames and one new field. Everything else legacy returned (website, description, headcount_range, founded_year, company_type, hq_city, hq_state, hq_country, and internal fields like hashtags, groups, tagline) is dropped.Example — before / after:
data — unlike the lead endpoint below, nothing here moves into a sub-object.Note: there’s also a /enrich/database/company/ variant (same request shape) that returns cached data instead of a fresh live lookup — cheaper/faster if slightly-stale data is acceptable. realtime is the direct successor to the old behavior.Full reference: Enrich company (realtime)10. Enrich lead by LinkedIn URL
10. Enrich lead by LinkedIn URL
Request:
id (Generect lead ID) or email (reverse lookup) as alternative identifiers.Response: the v1 payload is slimmer than the legacy one — headline and location are dropped entirely, and only id/name/domain carry over into the new company object (company_industry is dropped, not nested).Example — before / after:
/enrich/database/lead/ variant (cached data, cheaper) — realtime is the direct successor to the old behavior.Full reference: Enrich lead (realtime)11. Find email by name and domain
11. Find email by name and domain
Request — same 3 fields, unchanged:
lead_id or linkedin_url instead of name + domain — not required for a straight migration, but available if useful.Response field mapping:Example — before / after:
12. Validate emails
12. Validate emails
Request — legacy took a bare array of email strings; v1 requires an object wrapper:
Example — before / after:
Quick reference
Error handling
Every v1 endpoint uses the same error envelope:Migration checklist
1
Get a static API key
If you’re still calling
/api/auth/token/login/, stop — grab a key from account settings and send it as Authorization: Token <key> on every request.2
Swap paths
Replace each legacy path with its
/api/v1/... equivalent from the Quick reference table above.3
Update response parsing
Read results from
data and cost from meta.amount_charged instead of a flat payload or a negative root-level amount.4
Update nested field reads
Change flattened reads like
lead.company_name to data.company.name — see each endpoint’s field mapping table above.5
Prioritize the deprecated search endpoints
Migrate the four
by_icp endpoints first — they’re already flagged deprecated in the API spec.Renamed search controls
Several search controls were renamed to say what they do. The old spellings keep working — the API accepts both and treats them identically, so nothing breaks if you do nothing. New integrations should use the names on the right, and existing ones can switch whenever convenient.
If you send both spellings of the same control in one request, the old one wins and
the new one is ignored, so migrate a control in a single step rather than leaving
both in place.
A typical migration path
- Swap your auth to the
Authorization: Tokenheader. - Replace your search call with
databasemode first — it’s the cheapest, fastest equivalent — and only move specific calls torealtimewhen you need live freshness or advanced filters. - Replace enrichment and email/phone lookups with the endpoints above, and remove any “charged on no-match” handling — Generect doesn’t bill empty results.
- Read Limits and Errors before going to production.