# Migrate from Skrapp

This guide maps the Skrapp API (the v2 finder, account, and list endpoints and the v3 verifier endpoints) to Tomba. Skrapp API behavior checked on 2026-09-30 against the [Skrapp API reference](https://skrapp.io/api).

## Before you begin

- Get your API key (`ta_…`) and secret (`ts_…`); see [Authentication](/authentication).
- Check what each endpoint costs in [Credit costs](/usage-and-quotas#credit-costs) and your plan's throttling in [Limits by plan](/rate-limits#limits-by-plan).
- Set your HTTP client timeout to at least 180 seconds. Tomba returns the finished result in the response.

## Endpoint mapping

Replace the host `api.skrapp.io` with `api.tomba.io`, and the `/api/v2` and `/v3` prefixes with `/v1`.

| Skrapp                           | Tomba                                                         | Notes                                                        |
| -------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------ |
| `GET /api/v2/find`               | [`GET /v1/email-finder`](/api/finder#email-finder)            |                                                              |
| `POST /api/v2/find_bulk`         | `POST /v1/bulk/finder`                                        | See [Bulk and async jobs](#bulk-and-async-jobs).             |
| `GET /v3/verify`                 | [`GET /v1/email-verifier`](/api/verifier#email-verifier)      |                                                              |
| `GET /v3/verify` with `enrich`   | [`GET /v1/enrich`](/api/finder#email-enrichment)              | Returns the person and company for an address.               |
| `GET /v3/verify_bulk`            | `POST /v1/bulk/verifier`                                      | See [Email verifier](/bulks#email-verifier).                 |
| `GET /api/v2/account`            | [`GET /v1/me`](/api/account#get-account)                      | See [Check usage](/usage-and-quotas#check-usage).            |
| `GET /api/v2/list`               | [`GET /v1/leads_lists`](/api/lead-lists#retrieve-leads-lists) |                                                              |
| `GET /api/v2/list/:listId/leads` | [`GET /v1/leads`](/api/leads#retrieve-leads) with `list`      | Pages with `page` and `limit` instead of `start` and `size`. |

## Authentication changes

Skrapp reads the key from the `X-Access-Key` header. Tomba needs two headers, `X-Tomba-Key` and `X-Tomba-Secret`:

```bash
# Skrapp
curl "https://api.skrapp.io/api/v2/find?firstName=Jane&lastName=Doe&domain=stripe.com" \
  -H "X-Access-Key: $SKRAPP_API_KEY"

# Tomba
curl "https://api.tomba.io/v1/email-finder?first_name=Jane&last_name=Doe&domain=stripe.com" \
  -H "X-Tomba-Key: $TOMBA_API_KEY" \
  -H "X-Tomba-Secret: $TOMBA_SECRET_KEY"
```

Tomba API keys expire; plan their rotation with [Key expiry](/authentication#key-expiry).

## Parameter mapping

| Skrapp                         | Tomba                     | Notes                                                                             |
| ------------------------------ | ------------------------- | --------------------------------------------------------------------------------- |
| Finder `firstName`, `lastName` | `first_name`, `last_name` | Tomba also accepts `full_name`.                                                   |
| Finder `domain`                | `domain`                  | Tomba returns `400 unknown_record` for a disposable or webmail domain.            |
| Finder `company`               | `company`                 | When you send both, Tomba uses `domain`.                                          |
| Verifier `email`               | `email`                   | A malformed address returns `422 params_invalid` instead of a result.             |
| Verifier `enrich`              | No equivalent             | Call [`GET /v1/enrich`](/api/finder#email-enrichment) for the person and company. |
| List leads `listId`            | `list`                    |                                                                                   |
| List leads `start`, `size`     | `page`, `limit`           | Tomba pages start at 1: `page` = `start` / `limit` + 1.                           |
| List leads `kw`                | No equivalent             |                                                                                   |

## Response field mapping

Tomba wraps every result in `data`.

| Skrapp                                                   | Tomba                                                                                                          | Notes                                                                                            |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Finder `email`                                           | `data.email`                                                                                                   | `null` when no address is found; the status is `200`, not `404`.                                 |
| Finder `accuracy`                                        | `data.score`                                                                                                   | Computed differently. Recalibrate any threshold you apply to it.                                 |
| Finder `firstName`, `lastName`                           | `data.first_name`, `data.last_name`                                                                            |                                                                                                  |
| Finder `companyName`                                     | `data.company`                                                                                                 |                                                                                                  |
| Finder `quality.status`                                  | `data.verification.status`                                                                                     | `null` when the address hasn't been verified. See [Status mapping](#status-mapping).             |
| Finder `quality.result`                                  | No equivalent                                                                                                  | Verify the address with [`GET /v1/email-verifier`](/api/verifier#email-verifier) for a `result`. |
| Verifier `email`                                         | `data.email.email`                                                                                             | An empty string when the domain is disposable.                                                   |
| Verifier `email_status`                                  | `data.email.status`                                                                                            | See [Status mapping](#status-mapping).                                                           |
| Verifier `result`                                        | `data.email.result`                                                                                            | See [Result values](/attributes/verifier#result-values).                                         |
| Verifier `firstName`, `lastName`, `companyName`, `title` | `data.first_name`, `.last_name`, `.company`, `.position` from [`GET /v1/enrich`](/api/finder#email-enrichment) |                                                                                                  |
| Account `credits.remaining`, `credits.total`             | `GET /v1/me`                                                                                                   | See [Check usage](/usage-and-quotas#check-usage).                                                |

Tomba's email finder also returns `full_name`, `position`, `linkedin`, `country`, and the `sources` where the address was found; see [Person](/attributes/person). The verifier fields are in [Email verifier response](/attributes/verifier).

## Status mapping

| Skrapp `email_status` | Tomba `status` | Tomba `result`  |
| --------------------- | -------------- | --------------- |
| `valid`               | `valid`        | `deliverable`   |
| `catch-all`           | `accept_all`   | `risky`         |
| `invalid`             | `invalid`      | `undeliverable` |
| `unknown`             | `unknown`      | `risky`         |

Tomba also returns `disposable`, with an empty `result`, for a disposable domain. The email finder uses the same status values in `data.verification.status`. Compare `status` case-insensitively. Each value is defined in [Status values](/attributes/verifier#status-values).

## Error mapping

Skrapp returns an `error` code, a `message`, and the `remaining` credits. Tomba returns an `errors` object with `type`, `message`, and `code`:

| Skrapp                                 | Tomba                                                                                                                        | What to do                                                                                          |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `400` missing or malformed parameter   | `422 params_invalid`                                                                                                         | Fix the parameter named in the message.                                                             |
| `401` invalid, missing, or revoked key | `400 authentication_failed` (missing or malformed), `400 api_key_expired`, `401 authentication_failed` (wrong key or secret) | Check both headers; [rotate](/authentication#rotate-keys) an expired key.                           |
| `402` `insufficient_credits`           | `402 quota_exceeded`                                                                                                         | Wait for your usage window to renew or add credits.                                                 |
| `404` no address found                 | `200` with `data.email` `null`                                                                                               | Check `data.email` instead of the status.                                                           |
| `429` rate limited                     | `429 rate_limit`                                                                                                             | Retry after the `Retry-After` delay; see [Handle 429 responses](/rate-limits#handle-429-responses). |
| `5xx`                                  | `500 api_error`                                                                                                              | Retry with backoff.                                                                                 |

Also handle `451 claimed_email` when the owner of an address asked Tomba to stop processing it. Error responses don't consume credits; every type is listed in [Errors](/error-handling#error-types).

## Bulk and async jobs

Skrapp's bulk finder takes up to 100 people in a JSON body and returns a job `id` to poll. Its bulk verifier takes up to 50 addresses per request and answers directly. Tomba runs both as bulk jobs:

| Skrapp endpoint          | Tomba bulk type                                                                                                            |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `POST /api/v2/find_bulk` | `finder`: a CSV file or JSON `data` rows with name and domain or company columns. See [Email finder](/bulks#email-finder). |
| `GET /v3/verify_bulk`    | `verifier`: a JSON `list` of addresses or a CSV file. See [Email verifier](/bulks#email-verifier).                         |

Each job is created, launched, polled, and downloaded as CSV; see [Lifecycle](/bulks#lifecycle). Row limits are in [Bulk types](/bulks#bulk-types). To be notified when a job ends, set `webhook_url`; see [Bulk job events](/webhook#bulk-job-events). A job is charged when you first download its results; see [Billing](/bulks#billing).

The `tId` you attach to each Skrapp row has no equivalent. Keep your own ID in an extra CSV column.

## Code example

This function replaces a call to Skrapp's `GET /api/v2/find` and returns Skrapp's field names, or `null` where Skrapp returned `404`. It needs Node.js 18 or later.

```js title="find.mjs"
const TOMBA_HEADERS = {
    "X-Tomba-Key": process.env.TOMBA_API_KEY,
    "X-Tomba-Secret": process.env.TOMBA_SECRET_KEY,
};

// Tomba status -> Skrapp email_status.
const SKRAPP_STATUS = {
    valid: "valid",
    accept_all: "catch-all",
    invalid: "invalid",
    unknown: "unknown",
};

// Accepts Skrapp's parameters: firstName, lastName, and domain or company.
async function find({ firstName, lastName, domain, company }) {
    const url = new URL("https://api.tomba.io/v1/email-finder");
    url.searchParams.set("first_name", firstName);
    url.searchParams.set("last_name", lastName);
    if (domain) url.searchParams.set("domain", domain);
    if (company) url.searchParams.set("company", company);

    const res = await fetch(url, { headers: TOMBA_HEADERS });
    const body = await res.json();
    if (body.errors) {
        throw new Error(
            `${res.status} ${body.errors.type}: ${body.errors.message}`,
        );
    }

    const found = body.data;
    if (!found.email) return null;
    const status = found.verification?.status?.toLowerCase();
    return {
        email: found.email,
        accuracy: found.score,
        firstName: found.first_name,
        lastName: found.last_name,
        companyName: found.company,
        quality: { status: SKRAPP_STATUS[status] ?? null },
    };
}

console.log(
    await find({ firstName: "Jane", lastName: "Doe", domain: "stripe.com" }),
);
```

## Cutover checklist

1. Store the Tomba key and secret as `TOMBA_API_KEY` and `TOMBA_SECRET_KEY`, and send them as `X-Tomba-Key` and `X-Tomba-Secret` instead of `X-Access-Key`.
2. Change the host and path prefixes, and rename `firstName` and `lastName` to `first_name` and `last_name`.
3. Treat `data.email` `null` as not found instead of a `404`.
4. Translate `email_status` with the [status mapping](#status-mapping), comparing `status` case-insensitively, and call `/v1/enrich` where you used `enrich=true`.
5. Handle `402` for exhausted credits, retry `429` after `Retry-After`, and drop addresses that return `451`.
6. Move `find_bulk` and `verify_bulk` batches to `finder` and `verifier` bulk jobs.
7. Run the same sample of people and addresses through both services and compare the results before you switch production traffic.
