Python SDK
tomba-io is the official Python client for the Tomba API. Each API area is a service class, and each method sends one request.
Requirements
- Python 3.8 or later. The package declares no minimum version; its CI tests Python 3.8 to 3.12.
requests, installed as a dependency.
Install
Code
The import name is tomba.
Authenticate
Create an API key and copy your secret on the API keys page, then export both:
Code
The SDK doesn't read environment variables. Pass the values to set_key() and set_secret(), and the client sends them as the X-Tomba-Key and X-Tomba-Secret headers. Key expiry and rotation are covered in Authentication.
First request
Find the email address of a person at a company:
Code
Every method returns a dict with two keys: data, the decoded JSON body, and rate_limit. The API wraps its payload in its own data object (Response format), so the address is at result["data"]["data"]["email"].
Errors
The SDK raises TombaException when the API responds with status 400 or higher, when the request fails, and before sending a request when a required argument is None.
| Attribute | Value |
|---|---|
code | The HTTP status. 0 when no response was received, for example a missing argument or a network error. |
message | The API's errors.message, or the underlying error. |
response | The decoded error body, {"errors": {"type": …, "message": …, "code": …}}, or None. |
Code
Enrichment.person(), company(), and combined() don't raise when nothing is found: those endpoints answer with status 200 and an errors body, so check result["data"].get("errors"). Each errors.type is described in Errors.
Rate limits and retries
The SDK doesn't retry. result["rate_limit"] holds the response's rate limit headers as second_limit, minute_limit, daily_limit, minute_remaining, daily_remaining, minute_reset, daily_reset, retry_after, policy, and rate_limit. Numbers are integers, and a header that is absent or 0 becomes None.
A 429 raises TombaException with code 429, without the Retry-After header. Wait before retrying as described in Handle 429 responses.
Requests time out after 120 seconds. Change the timeout with client.set_timeout(seconds).
Method reference
Create each service with the client, for example Finder(client). Every class is importable from tomba. IDs are strings.
| Method | Endpoint |
|---|---|
Account.get_account() | GET /me |
Usage.get_usage() | GET /usage |
Logs.get_logs(page=None, limit=None) | GET /logs |
Domain.domain_search(domain, page=None, limit=None, department=None, country=None, enrich_mobile=None, webhook_url=None) | GET /domain-search |
Finder.email_finder(domain, first_name, last_name, webhook_url=None) | GET /email-finder |
Finder.author_finder(url, webhook_url=None) | GET /author-finder |
Finder.linkedin_finder(url) | GET /linkedin |
Finder.enrichment(email, webhook_url=None) | GET /enrich |
Finder.format(domain), Format.email_format(domain) | GET /email-format |
Finder.location(domain), Location.get_location(domain) | GET /location |
Count.email_count(domain) | GET /email-count |
Verifier.email_verifier(email, enrich_mobile=None, webhook_url=None) | GET /email-verifier |
Sources.email_sources(email) | GET /email-sources |
Enrichment.person(email, webhook_url=None) | GET /people/find |
Enrichment.company(domain) | GET /companies/find |
Enrichment.combined(email) | GET /combined/find |
Phone.finder(email=None, domain=None, linkedin=None, full=None, webhook_url=None) | GET /phone-finder |
Phone.validator(phone) | GET /phone-validator |
Status.domain_status(domain) | GET /domain-status |
Status.auto_complete(query) | GET /domain-suggestions |
Similar.websites(domain) | GET /similar |
Technology.list(domain) | GET /technology |
Reveal.search_companies(**params) | POST /reveal/search |
Flag.list_flags(page=None, limit=None) | GET /flag |
Keys.get_keys() | GET /keys |
Keys.get_key(id) | GET /keys/{id} |
Keys.create_key(**params) | POST /keys |
Keys.reset_key(id) | PUT /keys/{id} |
Keys.delete_key(id) | DELETE /keys/{id} |
Leads.list_leads(page=None, limit=None, domain=None) | GET /leads |
Leads.get_lead(lead_id) | GET /leads/{id} |
Leads.create_lead(**params) | POST /leads |
Leads.update_lead(lead_id, **params) | PUT /leads/{id} |
Leads.delete_lead(lead_id) | DELETE /leads/{id} |
LeadsLists.get_lists() | GET /leads_lists |
LeadsLists.create_list(**params) | POST /leads_lists |
LeadsLists.update_list_id(id, **params) | PUT /leads_lists/{id} |
LeadsLists.delete_list_id(id) | DELETE /leads_lists/{id} |
LeadsAttributes.get_lead_attributes() | GET /attributes |
LeadsAttributes.create_lead_attribute(**params) | POST /attributes |
LeadsAttributes.update_lead_attribute(id, **params) | PUT /attributes/{id} |
LeadsAttributes.delete_lead_attribute(id) | DELETE /attributes/{id} |
Bulk.list_bulks(bulk_type, page=None, limit=None) | GET /bulk/{type} |
Bulk.create_bulk(bulk_type, **params) | POST /bulk/{type} |
Bulk.get_bulk(bulk_type, bulk_id) | GET /bulk/{type}/{id} |
Bulk.launch_bulk(bulk_type, bulk_id) | PUT /bulk/{type}/{id} |
Bulk.bulk_progress(bulk_type, bulk_id) | GET /bulk/{type}/{id}/progress |
Bulk.download_bulk(bulk_type, bulk_id) | GET /bulk/{type}/{id}/download |
Bulk.rename_bulk(bulk_type, bulk_id, name) | PUT /bulk/{type}/{id}/rename |
Bulk.archive_bulk(bulk_type, bulk_id) | DELETE /bulk/{type}/{id}/archive |
Bulk.delete_bulk(bulk_type, bulk_id) | DELETE /bulk/{type}/{id}/delete |
bulk_type is the {type} segment listed in Bulk types; the order of calls is described in Lifecycle. create_bulk sends a JSON body, so it can't create jobs that need a CSV upload, such as email finder jobs. download_bulk returns the results file, a CSV, as bytes in result["data"].
Source
github.com/tomba-io/python (Apache-2.0). Release notes are in CHANGELOG.md.