# CheckThatPhone — Full API Reference

> Real-time phone number validation API for US & Canada numbers.

CheckThatPhone provides instant phone number verification including carrier lookup (a live carrier dip at lookup time), line type detection, number portability status, deliverability checks, and geolocation — all in a single API call. Sign up at https://checkthatphone.com/sign-up to get an API key. Free tier: 500 credits per month, hard-capped; signing up requires a card on file, verified with a $0 check and never charged.

Two delivery channels: a live REST API (POST /v1/lookup) for real-time per-number checks, and a dashboard CSV uploader for bulk lists — up to 1M rows per file, same fields, same per-unique-number pricing. The CSV path is dashboard-only (signed-URL uploads, no public /v1/bulk endpoint).

## API Endpoint

```
POST https://api.checkthatphone.com/v1/lookup
```

### Authentication

Use the API key from your dashboard as a bearer token:

```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

### Request Body

| Parameter         | Type    | Required | Description |
|-------------------|---------|----------|-------------|
| phone             | string  | Yes      | US or Canada phone number (10 digits, e.g. 8182925409) |
| ip                | string  | No       | IPv4 or IPv6 address of the subscriber for enhanced geolocation |
| litigatorFilter   | boolean | No       | Set to true to check against the TCPA litigator database (+1 credit). Adds `litigator`, `litigator_type`, `litigator_name` to the response. |
| landlineSmsLookup | boolean | No       | Set to true to perform a landline SMS eligibility lookup (+1 credit when applied). Adds `dipMessaging*` fields. Mobile numbers are not affected. |
| dncState          | boolean | No       | Set to true to run the state do-not-call check (free — no extra credit). Adds `dncStateChecked` and `dncStateResult`. Covers 38 states plus DC; not run for CO, FL, IN, LA, MA, MS, MO, OK, PA, TN, TX and WY. |
| dncComplainer     | boolean | No       | Set to true to check the national complainer list (free — no extra credit). Adds `dncComplainerChecked` and `dncComplainerResult`. |
| dncOther          | boolean | No       | Deprecated alias that turns on both DNC checks. Use `dncState` and `dncComplainer`. |

### Example Request (cURL)

```bash
curl --request POST \
  --url 'https://api.checkthatphone.com/v1/lookup' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"phone":"8182925409","ip":"136.38.145.14"}'
```

### Example Request (JavaScript)

```javascript
const response = await fetch('https://api.checkthatphone.com/v1/lookup', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ phone: '8182925409', ip: '136.38.145.14' }),
});
const result = await response.json();
```

### Example Request (Python)

```python
import requests

response = requests.post(
    'https://api.checkthatphone.com/v1/lookup',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
    },
    json={'phone': '8182925409', 'ip': '136.38.145.14'},
)
result = response.json()
```

## Response Envelope

Every successful response is wrapped in this envelope:

```json
{
  "success": true,
  "credits_used": 1,
  "data": { ... per-field result ... }
}
```

| Field            | Type    | Description |
|------------------|---------|-------------|
| success          | boolean | true if the lookup completed |
| credits_used     | number  | credits this call consumed (1 base + 1 per paid add-on; the DNC checks are free). Also returned in the `X-Credits-Used` response header. |
| data.error       | string\|false | error indicator when applicable |
| data.*           | object  | per-field result described below |

## Response Fields (data.*)

### Subscriber Info

| Field      | Type   | Description |
|------------|--------|-------------|
| subscriber | string | The phone number queried |
| optDate    | string | ISO 8601 timestamp of when the query was processed |

### Deliverability

| Field             | Type             | Description |
|-------------------|------------------|-------------|
| action            | string           | Recommended action: `send`, `unsubscribe`, `error` (a blacklist hit returns `unsubscribe`; see `reason`) |
| deliverable       | string\|boolean | Whether the number can receive calls/SMS |
| error             | string\|boolean | `true` if an error occurred in the request |
| reason            | string           | Explanation for the action (one of "Associated with TCPA Litigator DO NOT CONTACT", "Not a valid mobile number", "Blacklisted Subscriber", "Number deactivated by carrier id <N> on <date>") |
| deactivationDate  | string           | Date of most recent deactivation, when known |
| age               | number           | Days the subscriber has had this active number |
| blackList         | string\|boolean | `true` if the number is in our internal blacklist |

### NANP

| Field       | Type   | Description |
|-------------|--------|-------------|
| nanpType    | string | Line type per NANP: `mobile`, `landline`, `not-mobile` |
| nanpCarrier | string | Carrier per NANP. Not authoritative due to porting — prefer `dipCarrier`. |

### Carrier DIP

| Field             | Type             | Description |
|-------------------|------------------|-------------|
| dip               | string           | DIP lookup status: `success`, `error`, `invalid` |
| dipLrn            | string           | Local Routing Number |
| dipPorted         | string           | `"true"` if the number has been ported |
| dipOcn            | string           | Operating Carrier Numeric ID |
| dipCarrier        | string           | Carrier name (authoritative) |
| dipCarrierType    | string           | `mobile`, `landline`, `invalid`, `undefined` |
| dipCarrierSubType | string           | Sub-type: `WIRELESS`, `PCS`, `PCSR`, `WRSL`, `PAGING`, `ILEC`, `CLEC`, `ULEC`, `RBOC`, `ICO`, `CAP`, `IXC`, `LRSL`, `IPES`, `ETHX`, `INTL`, `GENERAL` (full names in the field reference at /docs) |

### Landline SMS Lookup (only when `landlineSmsLookup: true`)

| Field                   | Type             | Description |
|-------------------------|------------------|-------------|
| dipMessagingLookup      | string\|boolean | `true` if a landline messaging lookup was performed |
| dipMessagingEnabled     | string\|boolean | `true` if landline messaging is enabled |
| dipMessagingProvider    | string           | Messaging provider name |
| dipMessagingRefId       | string           | Provider's reference ID |
| dipMessagingCountryCode | string           | Country code of the messaging provider |

### Litigator Filter (only when `litigatorFilter: true`)

| Field          | Type             | Description |
|----------------|------------------|-------------|
| litigator      | string\|boolean | `true` if the subscriber is a suspected litigator — do not contact |
| litigator_type | string           | Classification: `litigator`, `plaintiff`, `agitator` |
| litigator_name | string           | Name on record |

### State DNC & Complainers (free; each field present only when its check ran)

| Field               | Type   | Description |
|---------------------|--------|-------------|
| dncStateChecked     | string | `true` when the state check ran; `error` when it could not complete (treat the result as unavailable, not clear). Absent when not requested, and for the 12 uncovered states: CO, FL, IN, LA, MA, MS, MO, OK, PA, TN, TX, WY |
| dncStateResult      | string | `STATE DNC` on a state do-not-call match; empty otherwise. Present only when `dncStateChecked` is `true` |
| dncComplainerChecked | string | `true` when the complainer check ran; `error` when it could not complete |
| dncComplainerResult | string | `DNC COMPLAINER` on a national complainer-list match; empty otherwise. Present only when `dncComplainerChecked` is `true` |
| dncOtherChecked     | string | Legacy: `true` when either check ran |
| dncStateCovered     | string | Deprecated: same answer as `dncStateChecked` (`true`/`false`), returned whenever the state check is requested |

### IP & Geolocation

| Field      | Type   | Description |
|------------|--------|-------------|
| ipResult   | string | IP validation result (e.g. `valid-v4`, `valid-v6`) |
| geoCountry | string | Two-letter country code |
| geoState   | string | Two-letter US state code |
| geoCity    | string | City from area code or IP |
| geoMetro   | number | Metro / DMA code |
| geoSource  | string | Data source: `ip` or `area-code` |
| timezone   | string | IANA timezone identifier |
| tzOffset   | number | UTC offset in hours |

### Example Response

```json
{
  "success": true,
  "credits_used": 1,
  "data": {
    "subscriber": "8182925409",
    "optDate": "2026-05-21T18:55:56.532Z",
    "action": "send",
    "deliverable": "true",
    "nanpType": "mobile",
    "blackList": "false",
    "ipResult": "valid-v4",
    "dip": "success",
    "dipLrn": "8182925409",
    "dipPorted": "false",
    "dipOcn": "6010",
    "dipCarrier": "AT&T",
    "dipCarrierSubType": "WIRELESS",
    "dipCarrierType": "mobile",
    "geoCountry": "US",
    "geoState": "CA",
    "geoCity": "Riverside",
    "geoMetro": 803,
    "geoSource": "ip",
    "timezone": "America/Los_Angeles",
    "tzOffset": 8
  }
}
```

## Errors

Standard HTTP status codes. Failed lookups are never charged.

| Status | Meaning |
|--------|---------|
| 400 | Invalid request: missing or malformed `phone` (10 digits, or 11 starting with 1) or an unparseable body. Retrying the same request returns the same error. |
| 401 | Missing or invalid API key. |
| 402 | Account safety limit reached for this billing period (paid plans). Contact us to raise it; requests resume when the limit rises or the next period starts. |
| 429 | Rate limit exceeded, or the Free tier's monthly quota is used up. Back off and retry, or upgrade. Rate limits aren't a fixed published number: each account's limit grows with its billing history. |
| 502 | Upstream validation service errored. Safe to retry. |
| 503 | Service briefly busy. Honor the `Retry-After` header and retry. |

## Use Cases

- **Fraud Prevention**: detect disposable VoIP numbers and recently ported numbers
- **KYC/Compliance**: verify phone numbers during customer onboarding
- **CRM Cleanup**: validate and enrich existing contact databases
- **SMS Campaigns**: check deliverability before sending messages
- **Lead Validation**: score leads based on phone number quality
- **2FA Verification**: confirm phone numbers can receive authentication codes
- **TCPA Compliance**: enable `litigatorFilter` to scrub TCPA-known litigators before outbound contact
- **DNC Compliance**: enable `dncState` and `dncComplainer` (free) to flag state do-not-call matches (38 states plus DC) and telemarketing complainers — the 12 uncovered states come back without `dncStateChecked`, meaning not checked

## Pricing

- **Free** — $0/month, 500 credits/month (hard-capped)
- **1K** — $5/month, 1,000 credits included, then $0.005/credit
- **10K** — $30/month, 10,000 credits included, then $0.003/credit
- **100K** — $100/month, 100,000 credits included, then $0.001/credit
- **500K** — $450/month, 500,000 credits included, then $0.0009/credit

Paid tiers have no hard limit — overage is billed at the per-credit rate. Paid add-ons (litigator filter, landline SMS lookup) cost 1 additional credit per lookup; the state-DNC and complainer checks (`dncState`, `dncComplainer`) are free.

See pricing details: https://checkthatphone.com/pricing

## Links

- Website: https://checkthatphone.com
- Documentation: https://checkthatphone.com/docs
- Pricing: https://checkthatphone.com/pricing
- Sign up: https://checkthatphone.com/sign-up
- Blog: https://checkthatphone.com/blog
- Use cases: https://checkthatphone.com/use-cases
- Contact: hello@checkthatphone.com
