# API reference

> Common response structure, shared types, and error codes for all endpoints.

Every endpoint returns a consistent JSON structure. This page documents the shared envelope, types, and error codes that apply across all endpoints.

## Response envelope

Every response uses a consistent JSON envelope with five top-level fields:

**Response**

| Field      | Type            | Description                                      |
| ---------- | --------------- | ------------------------------------------------ |
| `success`  | boolean         | `true` if the request was processed successfully |
| `data`     | object \| null  | The endpoint-specific result payload (`null` on error or when no data is returned) |

**error**

| Field      | Type              | Description                                  |
| ---------- | ----------------- | -------------------------------------------- |
| `code`     | string            | Machine-readable error code (e.g. `API_KEY_MISSING`, `API_KEY_MALFORMED`, `VALIDATION_ERROR`, `PAGINATION_LIMIT_EXCEEDED`) |
| `message`  | string            | Human-readable error description             |
| `details`  | object            | Additional context (only present on some errors) |

`null` when `success` is `true`.

> [!TIP]
> Include `metadata.requestId` from error responses when contacting support -- it speeds up troubleshooting.

**quotas**

| Field              | Type   | Description                                  |
| ------------------ | ------ | -------------------------------------------- |
| `creditsConsumed`  | number | Credits used for this request after pricing resolution |

**workspace**

| Field                 | Type           | Description                                             |
| --------------------- | -------------- | ------------------------------------------------------- |
| `id`                  | string         | Your workspace identifier                               |
| `hasUnlimitedCredits` | boolean        | Whether workspace credits are unlimited                 |
| `allowDailyOvercost`  | boolean        | Whether the workspace may exceed its daily cap (Enterprise only) |

**credits**

| Field   | Type   | Description              |
| ------- | ------ | ------------------------ |
| `total` | number | Total credits in your plan |
| `used`  | number | Credits consumed so far  |
| `left`  | number | Remaining credits        |

**dailyLimit**

| Field       | Type           | Description                              |
| ----------- | -------------- | ---------------------------------------- |
| `limit`     | number         | Maximum requests per day                 |
| `used`      | number         | Requests made today                      |
| `left`      | number         | Remaining requests today                 |
| `nextReset` | string \| null | When the daily window resets (ISO 8601)  |

`null` when no daily limit is configured.

**minuteRateLimit**

| Field       | Type           | Description                              |
| ----------- | -------------- | ---------------------------------------- |
| `limit`     | number         | Maximum requests per minute              |
| `used`      | number         | Requests made in the current minute      |
| `left`      | number         | Remaining requests in the current minute |
| `nextReset` | string \| null | When the minute window resets (ISO 8601) |

**key**

| Field             | Type           | Description                                             |
| ----------------- | -------------- | ------------------------------------------------------- |
| `id`              | string         | API key identifier                                      |

**dailyLimit**

| Field       | Type           | Description                              |
| ----------- | -------------- | ---------------------------------------- |
| `limit`     | number         | Maximum requests per day                 |
| `used`      | number         | Requests made today                      |
| `left`      | number         | Remaining requests today                 |
| `nextReset` | string \| null | When the daily window resets (ISO 8601)  |

`null` when no daily limit is configured.

**minuteRateLimit**

| Field       | Type           | Description                                |
| ----------- | -------------- | ------------------------------------------ |
| `limit`     | number         | Maximum requests per minute                |
| `used`      | number         | Requests made in the current minute        |
| `left`      | number         | Remaining requests in the current minute   |
| `nextReset` | string \| null | When the minute window resets (ISO 8601)   |

The `key` field is `null` when the request is made from the dashboard (no API key).

When authentication or quota context is unavailable (e.g. invalid API key), `quotas` may be omitted.

**metadata**

| Field             | Type            | Description                                                                 |
| ----------------- | --------------- | --------------------------------------------------------------------------- |
| `requestId`       | string          | Unique identifier for this request (useful for support inquiries)           |
| `executionTimeMs` | number          | Total execution time in milliseconds                                        |
| `updatedAt`       | string          | Last upstream update timestamp (ISO 8601). Present only when available.     |

## Shared types

Some types are reused across multiple endpoints. They are documented here once to avoid repetition -- individual endpoint pages reference them by name.

**DateRange**

| Field   | Type           | Description                  |
| ------- | -------------- | ---------------------------- |
| `start` | string \| null | Start date (ISO 8601)        |
| `end`   | string \| null | End date (ISO 8601, null if current) |

## Error codes

| Status  | Description                                                      |
| ------- | ---------------------------------------------------------------- |
| `400`   | Invalid JSON body                                                |
| `401`   | Missing, malformed, invalid, or expired API key                  |
| `402`   | No credits left, purchase more to continue. The free /check endpoints return `NO_CREDITS` |
| `403`   | Workspace disabled (`WORKSPACE_DISABLED`) or API key lacks permission |
| `404`   | Data not found                                                   |
| `422`   | V2 schema/validation error, `INVALID_LINKEDIN_URL`, disposable email domain, or missing webhook URL on async endpoints |
| `422`   | `PAGINATION_LIMIT_EXCEEDED` on search endpoints when company-search `page` exceeds `50`, or `perPage` exceeds `100` on people or company search. Details: `{ "field": "page", "max": 50 }` or `{ "field": "perPage", "max": 100 }` |
| `429`   | Rate limit exceeded , wait and retry after `nextReset`           |
| `451`   | Data Subject Blocked , the profile has been removed per GDPR/CCPA data subject request |
| `5xx`   | Temporary upstream or platform issue , retry with backoff        |

> [!TIP]
> For `429` errors, read the `quotas.workspace.minuteRateLimit.nextReset` field and retry after that timestamp.

> [!TIP]
> For `5xx` errors, use exponential backoff starting at 1 second.

`WORKSPACE_DISABLED` is `403` for both dashboard and API-key authentication. `INVALID_LINKEDIN_URL` and `VALIDATION_ERROR` return `422`.

> [!NOTE]
> For async endpoints, the initial response is a standard V2 acknowledgement containing a `webhookId`. Most async endpoints support polling or a [webhook callback](https://docs.reversecontact.com/guides/webhooks); the [Contact Email Finder](https://docs.reversecontact.com/endpoints/contact-email) uses the webhook flow and delivers an email array or an error code in its callback. Webhook callback payloads do not use the full V2 envelope.
