> ## Documentation index
> Fetch the complete documentation index at: https://docs.leadity.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview validation

> Quote a list for free: how many items survive parsing and what they cost.

Parses a list of phone numbers or email addresses without buying anything and takes no credits. It answers how many items survive parsing and de-duplication, which is what a run holds credits for, and what that costs. rejectedSample shows a few refused lines, so a wrong column is easy to spot. A list holding UK or Australian numbers answers numbering_unavailable while that country's register is not loaded. Call it before create_validation and set maxCredits from credits.

`POST https://api.leadity.io/v1/validations/preview`

- Scope: `read`
- Spends credits: no
- MCP tool: `preview_validation`

## Headers

- `Authorization`, string, required. Bearer, a space, then an API key: Bearer lk_api_... An MCP key is refused here with wrong_key_kind.
- `Content-Type`, string, required. application/json

## Body parameters

- `kind`, string, required. phone to classify line types, email to check deliverability. One of: `phone`, `email`.
- `items`, string[], optional. The list as an array, one phone number or address per item: 1 to 50,000 items of at most 254 characters, and at most 8 MB joined one per line, as raw. Send items or raw, not both. 1 to 50,000 items, each 1 to 254 characters.
- `raw`, string, optional. The list as pasted text, one item per line or separated by commas, at most 8 MB (8,388,608 bytes of UTF-8). Send items or raw, not both. 1 to 8,388,608 characters.
- `region`, string, optional. For a phone list, the country a number written without its country code is read under: US (also Canada), GB or AU. Default US. Ignored for addresses. One of: `US`, `GB`, `AU`.

## Example request

```bash cURL
curl -X POST "https://api.leadity.io/v1/validations/preview" \
  -H "Authorization: Bearer $LEADITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "phone",
    "items": [
      "+1 512 555 0123",
      "(415) 555-0199",
      "not a number"
    ],
    "region": "US"
  }'
```

```javascript Node.js
const response = await fetch("https://api.leadity.io/v1/validations/preview", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.LEADITY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "kind": "phone",
    "items": [
      "+1 512 555 0123",
      "(415) 555-0199",
      "not a number"
    ],
    "region": "US"
  }),
});

const data = await response.json();
console.log(data);
```

```python Python
import os

import requests

response = requests.post(
    "https://api.leadity.io/v1/validations/preview",
    headers={
        "Authorization": f"Bearer {os.environ['LEADITY_API_KEY']}",
    },
    json={
        "kind": "phone",
        "items": ["+1 512 555 0123", "(415) 555-0199", "not a number"],
        "region": "US",
    },
)

print(response.json())
```

## Response

- `kind`, string, required. phone to classify line types, email to check deliverability. One of: `phone`, `email`.
- `region`, string, required. The region the list was read under. One of: `US`, `GB`, `AU`.
- `submitted`, integer, required. Lines or items submitted.
- `total`, integer, required. Items that would be checked.
- `rejected`, integer, required. Items refused as not a phone number or address.
- `duplicates`, integer, required. Repeats collapsed to one.
- `truncated`, boolean, required. True when the list held more than the most one run takes, and only that many would be checked.
- `credits`, integer, required. What a run of this list holds, in credits. Answers that tell nothing are refunded when it settles.
- `rejectedSample`, string[], required. Up to eight refused lines.

## Example response

```json 200
{
  "kind": "phone",
  "region": "US",
  "submitted": 3,
  "total": 2,
  "rejected": 1,
  "duplicates": 0,
  "truncated": false,
  "credits": 1,
  "rejectedSample": [
    "not a number"
  ]
}
```

## Errors

Every refusal answers `{ error, message }` with the status below. The full list is on the [Errors](https://docs.leadity.io/errors) page.

| Code | Status | Meaning | Extra fields |
| --- | --- | --- | --- |
| `unauthorized` | 401 | The API key is missing, malformed, revoked or expired. | - |
| `wrong_key_kind` | 401 | This key opens the other surface: an API key works on the HTTP API, an MCP key on the MCP server. | - |
| `account_suspended` | 403 | The account is suspended. | - |
| `email_not_verified` | 403 | The account's email address is not verified yet. | - |
| `invalid_body` | 400 | The request does not match the operation's schema. | `issues`: The problems found, each with path (the field as a dotted path, led by the part of the request it travels in: path, query or body, such as body.items.1) and message (what is wrong there). |
| `numbering_unavailable` | 409 | The list holds numbers whose country register is not loaded yet. The body names the plan. | `region`: The region the list was read under. `plan`: The register not loaded yet: gb or au. |
| `rate_limited` | 429 | Too many requests. Wait for the Retry-After seconds and try again. | `retryAfterSeconds`: The seconds to wait, the same number as the Retry-After header. |
| `try_again` | 503 | Leadity could not answer just now. Retry in a moment, with the same Idempotency-Key on a spending call. | `retryAfterSeconds`: When a request with this Idempotency-Key is still being processed: the seconds to wait before retrying with the same key, as the Retry-After header says. |
| `internal_error` | 500 | Something failed on our side. Nothing was charged twice. | `body`: On the MCP server, when Leadity answered in a shape the tool does not publish: that answer as it came. |
