---
title: "Check up to 100 numbers and e-mail addresses"
method: POST
path: "/lookup"
tags: ["lookup"]
---

# Check up to 100 numbers and e-mail addresses

`POST /lookup`

## Request

- Base URL: `https://api.mobilevalidate.com/v1`
- URL: `https://api.mobilevalidate.com/v1/lookup`
- Auth: HTTP bearer

Runs every requested check (see GET /v1/services) for every identifier of the check's input type: phone checks for `numbers`, e-mail checks for `emails`. Result rows come back in order: numbers first, then e-mails. The call waits up to `wait` seconds (default 10) for all answers; if some are still running it answers `202` with `status: pending` and a `next.poll_url` (or use a webhook). Checks without real-time support are refused with 403 service_disabled (param `checks[i]`) — send them in a bulk job. E-mail checks answer only whether an account or mailbox exists — never names, photos or profiles.

## Headers

- `Idempotency-Key` string

## Request body

- union: At least one of numbers / emails; together ≤ 100 identifiers (too_many_numbers above). Identifiers × applicable checks ≤ 2,000 (400 invalid_request, param checks).
  - object
    - `numbers` string[], required: Phone numbers for phone checks, ideally in international format (E.164, e.g. +447700900001). National numbers need `default_country`. 20 or more consecutive numbers → 403 suspected_enumeration.
    - `emails` string[]: E-mail addresses for e-mail checks. Normalized by trim + lowercase (no dot/plus rewriting); internationalised domains in punycode. ≥ 20 addresses on one domain whose local parts differ only by digits and/or separators (any run of non-letters is one class; googlemail.com = gmail.com), or (live keys) ≥ 50 such addresses of one pattern per account per UTC day → 403 suspected_enumeration.
    - `checks` string[]: Service codes or aliases (e.g. whatsapp, telegram, viber, carrier, spam; e-mail: email, gmail, outlook, yahoo; full list: GET /v1/services). Order is kept; duplicates are ignored; whatsapp.registered + whatsapp.business collapse to whatsapp.business. Phone checks apply to numbers, e-mail checks (input_type email) to emails: sending e-mails without an e-mail check (or numbers without a phone check) → 400 invalid_request, param checks; a check whose input type has no identifiers → 400 invalid_request, param checks[i]. At most 20 checks (400 invalid_request, param checks).
    - `default_country` string: ISO country for numbers without a country code.
    - `max_age` integer: Accept a cached answer up to this many seconds old (capped per check); 0 forces a fresh, billed check.
    - `wait` integer: Seconds to wait for all answers before returning 202 pending.
    - `max_cost` Money
      - `amount` string, required: Decimal USD amount.
      - `currency` 'USD', required
    - `webhook_endpoint_id` string: Endpoint to notify with lookup.completed if the lookup answers pending.
    - `metadata` object: Your own key/value pairs, echoed back.
  - object
    - `numbers` string[]: Phone numbers for phone checks, ideally in international format (E.164, e.g. +447700900001). National numbers need `default_country`. 20 or more consecutive numbers → 403 suspected_enumeration.
    - `emails` string[], required: E-mail addresses for e-mail checks. Normalized by trim + lowercase (no dot/plus rewriting); internationalised domains in punycode. ≥ 20 addresses on one domain whose local parts differ only by digits and/or separators (any run of non-letters is one class; googlemail.com = gmail.com), or (live keys) ≥ 50 such addresses of one pattern per account per UTC day → 403 suspected_enumeration.
    - `checks` string[]: Service codes or aliases (e.g. whatsapp, telegram, viber, carrier, spam; e-mail: email, gmail, outlook, yahoo; full list: GET /v1/services). Order is kept; duplicates are ignored; whatsapp.registered + whatsapp.business collapse to whatsapp.business. Phone checks apply to numbers, e-mail checks (input_type email) to emails: sending e-mails without an e-mail check (or numbers without a phone check) → 400 invalid_request, param checks; a check whose input type has no identifiers → 400 invalid_request, param checks[i]. At most 20 checks (400 invalid_request, param checks).
    - `default_country` string: ISO country for numbers without a country code.
    - `max_age` integer: Accept a cached answer up to this many seconds old (capped per check); 0 forces a fresh, billed check.
    - `wait` integer: Seconds to wait for all answers before returning 202 pending.
    - `max_cost` Money
      - `amount` string, required: Decimal USD amount.
      - `currency` 'USD', required
    - `webhook_endpoint_id` string: Endpoint to notify with lookup.completed if the lookup answers pending.
    - `metadata` object: Your own key/value pairs, echoed back.

## Response `200`

All checks completed.

- Lookup
  - `object` 'lookup', required
  - `id` string, required
  - `status` 'completed' | 'pending', required
  - `livemode` boolean, required
  - `created_at` string, date-time, required
  - `results` ResultItem[], required
    - union: One row. Phone rows (kind "phone"; older responses may omit kind) carry e164, country and number_status. E-mail rows (kind "email") carry email (normalized address, null if invalid) and email_status; their e164 and country are null.
      - object
        - `kind` 'phone': Input type of the row.
        - `input` string, required: As sent in the originating request; masked on later reads.
        - `e164` string, nullable
        - `country` string, nullable
        - `number_status` 'valid' | 'invalid_number' | 'duplicate' | 'suppressed', required: Phone rows only.
        - `email` string, nullable: E-mail rows only; normalized address (null when invalid).
        - `email_status` 'valid' | 'invalid_email' | 'duplicate' | 'suppressed': E-mail rows only.
        - `checks` object: One CheckResult per requested check of the row's input type, keyed by service code (absent for invalid/duplicate/suppressed rows).
        - `whatsapp` WhatsAppResult: Kept from the first API version; mirrors checks["whatsapp.business"] if requested, else checks["whatsapp.registered"].
          - `service` 'whatsapp.registered' | 'whatsapp.business', required
          - `status` 'completed' | 'pending' | 'unknown' | 'unsupported_country' | 'failed', required
          - `registered` boolean, nullable, required
          - `business` boolean, nullable
          - `confidence` 'high' | 'medium' | 'low' | 'null', nullable
          - `confidence_score` number, nullable
          - `checked_at` string, date-time, nullable
          - `cached` boolean, required
          - `age_seconds` integer, nullable
          - `billed` boolean, required
          - `reason` string, nullable
          - `poll_after_ms` integer, nullable
        - `suggestion` string: How to fix an invalid or likely mistyped identifier, e.g. "Missing country code: send the number in international format (E.164) …" or "Did you mean gmail.com?". Never repeats the input.
        - `test` boolean: true for test-mode rows.
      - object
        - `kind` 'email', required: Input type of the row.
        - `input` string, required: As sent in the originating request; masked on later reads.
        - `e164` string, nullable
        - `country` string, nullable
        - `number_status` 'valid' | 'invalid_number' | 'duplicate' | 'suppressed': Phone rows only.
        - `email` string, nullable, required: E-mail rows only; normalized address (null when invalid).
        - `email_status` 'valid' | 'invalid_email' | 'duplicate' | 'suppressed', required: E-mail rows only.
        - `checks` object: One CheckResult per requested check of the row's input type, keyed by service code (absent for invalid/duplicate/suppressed rows).
        - `whatsapp` WhatsAppResult: Kept from the first API version; mirrors checks["whatsapp.business"] if requested, else checks["whatsapp.registered"].
          - `service` 'whatsapp.registered' | 'whatsapp.business', required
          - `status` 'completed' | 'pending' | 'unknown' | 'unsupported_country' | 'failed', required
          - `registered` boolean, nullable, required
          - `business` boolean, nullable
          - `confidence` 'high' | 'medium' | 'low' | 'null', nullable
          - `confidence_score` number, nullable
          - `checked_at` string, date-time, nullable
          - `cached` boolean, required
          - `age_seconds` integer, nullable
          - `billed` boolean, required
          - `reason` string, nullable
          - `poll_after_ms` integer, nullable
        - `suggestion` string: How to fix an invalid or likely mistyped identifier, e.g. "Missing country code: send the number in international format (E.164) …" or "Did you mean gmail.com?". Never repeats the input.
        - `test` boolean: true for test-mode rows.
  - `summary` Summary, required: Top-level counts are per row (numbers and e-mails) for the row's primary check = the first requested check of the row's input type; invalid counts invalid numbers and invalid e-mails.
    - `total` integer
    - `registered` integer
    - `not_registered` integer
    - `unknown` integer
    - `pending` integer
    - `invalid` integer
    - `suppressed` integer
    - `by_service` object
  - `billing` object
    - `billed_units` integer
    - `cost` Money
      - `amount` string, required: Decimal USD amount.
      - `currency` 'USD', required
    - `balance_after` Money
      - `amount` string, required: Decimal USD amount.
      - `currency` 'USD', required
  - `next` object, nullable
    - `poll_url` string
    - `poll_after_ms` integer
  - `metadata` object
  - `request_id` string, required

## Other responses

- `202`: Some checks are still running; poll `next.poll_url` (the Location header) or wait for lookup.completed.
- `default`: Error. Branch on `error.code`; `suggestion` (optional) says how to fix the request. A known path called with the wrong method answers `404 not_found` with an `Allow` header listing the methods it accepts.

---

[API](https://skmtc.dev/mobilevalidate/apis/mobilevalidate-api.md) · [All operations](https://skmtc.dev/mobilevalidate/apis/mobilevalidate-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mobilevalidate/apis/mobilevalidate-api/revisions/f2e56c2454ef?raw)
