Node.js SDK
tomba is the official Node.js client for the Tomba API. Each API area is a service class, and each method returns a promise for one request.
Requirements
- Node.js.
package.jsondeclares no minimum version; the SDK is built and tested on Node.js 20. axios, installed as a dependency.
Install
Code
The package is CommonJS with TypeScript declarations. The examples on this page are ES modules: save them as .mjs files, or set "type": "module" in your package.json.
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 setKey() and setSecret(), 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 resolves to { data, rateLimit }, where data is the decoded JSON body. The API wraps its payload in its own data object (Response format), so the address is at result.data.data.email. The TypeScript declarations type result.data as the payload itself, so TypeScript code needs a cast to read result.data.data.
Errors
Methods reject with TombaException, a subclass of Error, when the API responds with status 400 or higher, and before sending a request when a required argument is missing.
| Property | Value |
|---|---|
message | The API's errors.message. |
code | The axios response object: code.status is the HTTP status and code.headers holds the response headers. undefined when no response was received. |
response | The decoded error body, { errors: { type, message, code } }. |
Code
Enrichment.person(), company(), and combined() don't reject when nothing is found: those endpoints answer with status 200 and an errors body, so check result.data.errors. Each errors.type is described in Errors.
Rate limits and retries
The SDK doesn't retry. result.rateLimit holds the response's rate limit headers as secondLimit, minuteLimit, dailyLimit, minuteRemaining, dailyRemaining, minuteReset, dailyReset, retryAfter, policy, and rateLimit. Numeric headers are parsed as integers, and a header that is absent or 0 becomes null.
A 429 rejects with TombaException; read the wait time from error.code.headers["retry-after"] and retry as described in Handle 429 responses.
Requests time out after 120 seconds. Change the timeout with client.setTimeout(milliseconds).
Method reference
Create each service with the client, for example new Finder(client). Every class is a named export of tomba.
| Method | Endpoint |
|---|---|
Account.getAccount() | GET /me |
Usage.getUsage() | GET /usage |
Logs.getLogs({ page, limit }) | GET /logs |
Domain.domainSearch({ domain, company, page, limit, country, department, enrich_mobile, webhook_url }) | GET /domain-search |
Finder.emailFinder({ domain, company, firstName, lastName, fullName, enrichMobile, webhook_url }) | GET /email-finder |
Finder.authorFinder(url, webhook_url) | GET /author-finder |
Finder.linkedinFinder(url, enrich_mobile, full, webhook_url) | GET /linkedin |
Finder.emailEnrichment(email, enrich_mobile, webhook_url) | GET /enrich |
Format.emailFormat(domain) | GET /email-format |
Location.getLocation(domain) | GET /location |
Count.emailCount(domain) | GET /email-count |
Verifier.emailVerifier(email, enrich_mobile, webhook_url) | GET /email-verifier |
Sources.emailSources(email) | GET /email-sources |
Enrichment.person(email) | GET /people/find |
Enrichment.company(domain) | GET /companies/find |
Enrichment.combined(email) | GET /combined/find |
Phone.finder({ email, domain, linkedin, full, webhook_url }) | GET /phone-finder |
Phone.validator(phone, country_code) | GET /phone-validator |
Status.domainStatus(domain) | GET /domain-status |
Status.autoComplete(query) | GET /domain-suggestions |
Similar.websites(domain) | GET /similar |
Technology.list(domain) | GET /technology |
Reveal.companiesSearch({ query, filters, page }) | POST /reveal/search |
Flag.listFlags({ page, limit }) | GET /flag |
Flag.createFlag({ flag_type, value, reason, comment }) | POST /flag |
Keys.getKeys() | GET /keys |
Keys.getKey(id) | GET /keys/{id} |
Keys.createKey() | POST /keys |
Keys.resetKey(id) | PUT /keys/{id} |
Keys.deleteKey(id) | DELETE /keys/{id} |
Leads.listLeads({ page, limit, domain }) | GET /leads |
Leads.getLead(id) | GET /leads/{id} |
Leads.createLead(data) | POST /leads |
Leads.updateLead(id, data) | PUT /leads/{id} |
Leads.deleteLead(id) | DELETE /leads/{id} |
LeadsLists.getLists() | GET /leads_lists |
LeadsLists.getList(id) | GET /leads_lists/{id} |
LeadsLists.createList({ name }) | POST /leads_lists |
LeadsLists.updateList(id, { name }) | PUT /leads_lists/{id} |
LeadsLists.deleteList(id) | DELETE /leads_lists/{id} |
LeadsAttributes.getLeadAttributes() | GET /attributes |
LeadsAttributes.getLeadAttribute(id) | GET /attributes/{id} |
LeadsAttributes.createLeadAttribute({ name, type }) | POST /attributes |
LeadsAttributes.updateLeadAttribute(id, { name, type }) | PUT /attributes/{id} |
LeadsAttributes.deleteLeadAttribute(id) | DELETE /attributes/{id} |
Bulk.list(type, { page, limit }) | GET /bulk/{type} |
Bulk.create(type, data) | POST /bulk/{type} |
Bulk.get(type, id) | GET /bulk/{type}/{id} |
Bulk.launch(type, id) | PUT /bulk/{type}/{id} |
Bulk.progress(type, id) | GET /bulk/{type}/{id}/progress |
Bulk.download(type, id) | GET /bulk/{type}/{id}/download |
Bulk.rename(type, id, name) | PUT /bulk/{type}/{id}/rename |
Bulk.archive(type, id) | DELETE /bulk/{type}/{id}/archive |
Bulk.delete(type, id) | DELETE /bulk/{type}/{id}/delete |
type is the {type} segment listed in Bulk types; the order of calls is described in Lifecycle. Bulk.create() sends a JSON body, so it can't create jobs that need a CSV upload, such as email finder jobs. Bulk.download() returns the results file, a CSV, as a string in result.data.
Source
github.com/tomba-io/node (Apache-2.0). Release notes are in CHANGELOG.md.