Sequencer, Unibox and CRM are live:send, reply and close from the same login, included on every plan
Use case · AI agents

Clean a lead list from an AI agent with verify_list

Verify a lead list from Claude or Cursor with the verify_list MCP tool: one credit per address, 500 to 4,500 a day, refused up front with 429 if the list does not fit.

The short answer

An AI agent cleans a lead list by calling the emailpal_verify_list MCP tool with the file contents, then polling emailpal_get_list for the verdict. It costs one verification credit per address, taken in full when the list is accepted from a daily allowance of 500 (Starter), 1,500 (Growth) or 4,500 (Scale) checks. If the list needs more credits than are left today, the call is refused up front with 429 verification_limit_reached and nothing is queued or charged.

verify_list needs a write key and an active subscription. The agent pastes the CSV text or one address per line, gets an upload id back, and polls get_list for counts and a whole-list verdict (passed, flagged, blocked or failed). The MCP tools return counts and the verdict, not the per-address rows: to pull the cleaned addresses, call GET /lists/{id}/results on the REST API. Large lists take minutes to hours, so split files to fit the daily allowance and keep the content inside what your model can carry in one tool call.

How it works, step by step

  1. Step 1

    Connect the MCP server with a write key

    POST /lists/verify needs the write scope, and verify_list is flagged as a mutating tool, so it is hidden in read-only mode. Use the same config as any EmailPal MCP setup, with a write key and without EMAILPAL_MCP_READ_ONLY.

    .cursor/mcp.json or claude_desktop_config.jsonjson
    {
      "mcpServers": {
        "emailpal": {
          "command": "npx",
          "args": ["-y", "@emailpal/mcp"],
          "env": { "EMAILPAL_API_KEY": "ep_live_..." }
        }
      }
    }
  2. Step 2

    Size the list against today’s allowance

    The allowance is one daily pool shared by the dashboard, POST /verify and MCP, and it resets at midnight UTC. Starter has 500 checks a day, Growth 1,500, Scale 4,500, and extra blocks of 500 a day cost $9.95/mo each. Dedupe the file first: extraction counts every address it finds before deduplication.

  3. Step 3

    Submit the list with verify_list

    Pass content as the CSV text or one address per line, with an optional filename. Any column can hold the emails and extra columns are ignored. The tool queues the check and returns immediately.

    emailpal_verify_list argumentsjson
    {
      "filename": "q3-prospects.csv",
      "content": "email\npriya@acme.example\nsam@example.org"
    }
  4. Step 4

    Read the acceptance response

    The response has upload_id, the number of extracted addresses, a job_id and credits used and limit for today. Keep the upload_id: both get_list and the REST results endpoint use it.

    Response (202)json
    {
      "upload_id": "lst_7c31ee",
      "addresses": 2,
      "job_id": "job_6j40wl",
      "poll": "/api/public/v1/lists/lst_7c31ee",
      "results": "/api/public/v1/lists/lst_7c31ee/results",
      "credits": { "used": 216, "limit": 1500 }
    }
  5. Step 5

    Poll get_list until the status leaves pending and verifying

    get_list returns counts per status, the whole-list status and a sendable flag. Counts fill in while the list runs, so read progress.remaining before trusting them. Branch on sendable: true for passed and flagged, false for blocked and failed.

    emailpal_get_list resultjson
    {
      "id": "lst_7c31ee",
      "filename": "q3-prospects.csv",
      "status": "flagged",
      "sendable": true,
      "depth": "probed",
      "progress": { "answered": 2116, "remaining": 0 },
      "counts": {
        "total": 2140, "safe": 1502, "catch_all": 218, "role_account": 61,
        "disposable": 9, "inbox_full": 14, "disabled": 37, "invalid": 214,
        "unknown": 49, "suppressed": 12, "duplicate": 24, "risky": 288
      },
      "blocked_reason": null
    }
  6. Step 6

    Fetch the cleaned addresses over REST

    There is no MCP tool for per-address results. GET /lists/{id}/results returns one row per address with status and sub_status, readable while the list is still running, and filterable with ?status=. Results are kept for 90 days.

    GET /api/public/v1/lists/{id}/resultsbash
    curl "https://www.emailpal.io/api/public/v1/lists/lst_7c31ee/results?status=safe&limit=200" \
      -H "Authorization: Bearer $EMAILPAL_API_KEY"

01

Credit math: one per address, all or nothing

A list costs one credit per address extracted, the same rate as a single POST /verify. The whole amount is reserved atomically when the list is accepted. There is no partial acceptance: a 1,200-address list on a 500-a-day allowance is not half-checked, it is refused. The refusal is a 429 with code verification_limit_reached, and the body carries addresses, used and limit, so the agent can compute what is left and split the file.

Through MCP the error text is relayed to the model with the code appended, for example: This list needs 1,200 credits and 500 of today’s 500 are left. The allowance resets at midnight UTC, or buy another block of 500 a day from Billing. Splitting the file also works. (verification_limit_reached). Nothing was queued and no credits were taken.

Extraction does not deduplicate before charging, so a file that lists the same address three times is charged for three. The per-address results are one row per distinct address, and the repeats show up as duplicate in the counts. Dedupe before you submit.

Credits are refunded for every address that finishes unknown, which is where greylisted and unreachable mailboxes end up. They are never refunded for addresses that are merely still queued. The charge is for an answer.

02

What 1,200 and 4,000 addresses cost across plans

On Starter (500 a day) a 1,200-address list does not fit in one day. You can submit 500, 500 and 200 on three UTC days, or buy two extra blocks, which makes 1,500 a day for $19.90/mo more. On Growth (1,500 a day) it fits in one submission. A 4,000-address list fits in one day only on Scale (4,500 a day), or on a smaller plan with enough extra blocks.

A block of 500 a day is $9.95/mo, which is about 15,000 checks a month and roughly $0.0007 per check at full utilisation. That figure assumes you use the whole allowance every day. Unused allowance does not carry over to the next day.

03

What the agent gets back, and what it does not

The MCP get_list tool returns the counts, the whole-list status, sendable, blocked_reason and progress. It does not return the addresses. For the per-address answers you need GET /lists/{id}/results on the REST API, which an agent with shell or HTTP access can call with the same key, or which your own script can call.

The list status is one of pending, verifying, passed, flagged, blocked or failed. flagged means send it but know what is in it. blocked means the list exceeds the bounce threshold and sending it would hurt deliverability for the whole account, and blocked_reason says which measure crossed the line. A list with depth classified ran only the free syntax and MX gate, so catch_all, inbox_full and disabled read zero because nothing asked, which is different from none being found. A probed list ran the mailbox-level check.

04

Verdict handling

The per-address statuses are safe, invalid, disposable, role_account, catch_all, disabled, inbox_full and unknown, plus suppressed and duplicate, which only a list can produce. sub_status narrows unknown and invalid, for example no_mx_record, unable_to_connect and antispam_system (greylisted).

A sensible default policy: send safe; drop disabled, inbox_full, invalid and disposable; skip role_account for cold email unless the function is the buyer; decide catch_all as a policy (many teams drop them, some mail a subset at lower volume); never round unknown up to safe, because unknown means the server would not say, usually greylisting. Re-verify after a few months or whenever you buy a new file.

The check is a mailbox-level probe: EmailPal asks the receiving server about a mailbox that cannot exist, then about the real one, and sends no message. A catch-all domain accepts the impossible mailbox, so a yes on your contact carries no information.

05

Limits to plan around

File size. The REST endpoint accepts up to 12,000,000 characters of content, but through MCP the agent has to put the whole file into a tool call, so the practical limit is what the model can read and write in one message. Split large files into chunks that fit both the model and the day’s allowance.

Speed. Large lists take minutes to hours, not seconds, because probing a receiving domain faster than a real sender would gets a verifier blocked there. Results stream as they are decided. A list that is slow because egress capacity is busy waits and finishes; the only bound is a 24-hour deadline, after which anything still unchecked comes back unknown and is refunded.

Retention. Per-address results are kept for 90 days and then deleted, and the counts and the verdict stay for as long as the upload. Pull what you need before then.

Eligibility. verify_list returns subscription_required (402) on an account with no active subscription, and verification_capacity_required (402) if the plan includes no daily allowance and no blocks have been bought. No credits are taken in either case.

06

Reselling verification through an agent

Section 9 of the Terms (effective 6 October 2026) allows you to embed list verification in your own product or service and supply it to your own end customers through the REST API or MCP server, under your own account and name. Allowances are daily and capped at what you purchased, capacity beyond that is not guaranteed, and you are responsible for end users’ compliance with the acceptable use policy.

The numbers

Limits, prices and names, in one table

The figures this page relies on, so you do not have to hunt for them.

Cost per address1 creditSame rate as POST /verify; refunded for every address that finishes unknown
Starter allowance500 checks a day$69/mo plan
Growth allowance1,500 checks a day$189/mo plan
Scale allowance4,500 checks a day$499/mo plan
Extra capacity$9.95/mo per 500 a dayAbout 15,000 checks a month, roughly $0.0007 each at full use
Allowance resetMidnight UTCShared by dashboard, POST /verify and MCP; no carry-over
Over-allowance list429 verification_limit_reachedRefused up front; nothing queued, nothing charged; body has addresses, used, limit
Max content per REST call12,000,000 characters
List status valuespending, verifying, passed, flagged, blocked, failedsendable is true for passed and flagged
Per-address statusessafe, invalid, disposable, role_account, catch_all, disabled, inbox_full, unknownLists also return suppressed and duplicate
Unchecked deadline24 hoursThen unknown and refunded
Per-address result retention90 days
Required key scopewriteverify_list is hidden in read-only mode

Checked against the product and the API on . Plans and limits change, so confirm in the docs before you build on them.

This is not for you if

  • You need the cleaned addresses returned inside the MCP conversation. get_list returns counts and a verdict only; per-address rows come from GET /lists/{id}/results on the REST API.
  • You have a file too large to paste into one tool call. The agent must pass the contents as a string, so split it, or call the REST API from a script instead.
  • You need to check more addresses in a day than your allowance covers and cannot split the file. The list is refused whole, not partly processed.
  • You need an answer in seconds for one address inside a signup flow. Use the synchronous POST /verify endpoint, which is instant and metered from the same allowance.
  • You need lead data. There is no built-in lead database; verification checks addresses you already have.
FAQ

Common questions

How many credits does verify_list use?

One per extracted address, taken in full when the list is accepted. Extraction does not deduplicate first, so repeated addresses are charged. Addresses that finish as unknown are refunded.

What happens if my list is bigger than the credits I have left?

It is refused with HTTP 429 and code verification_limit_reached before anything is queued. No credits are taken. The error body names the address count, today’s used credits and the limit, so you can split the file or wait for the midnight UTC reset or buy another block of 500 a day.

Can the agent get the verified addresses back through MCP?

No. The MCP get_list tool returns counts per status, the whole-list status and sendable. The per-address results come from the REST endpoint GET /lists/{id}/results, which can be filtered with ?status= and read while the list is still running. Results are kept for 90 days.

How long does verification take?

Large lists take minutes to hours. The pace is deliberate, because probing a receiving domain faster than a real sender would gets a verifier blocked. Results arrive as they are decided, and anything still unchecked after 24 hours comes back unknown and is refunded.

Which verdicts should I send to?

Send safe. Drop disabled, inbox_full, invalid and disposable. Skip most role_account addresses for cold email. Treat catch_all as a policy decision, not as valid. Treat unknown as unverified and re-try later rather than rounding it up. The list-level sendable flag is true for passed and flagged and false for blocked and failed.

Do I need a paid plan?

Yes. verify_list needs an active subscription and a write key. Without a subscription it returns 402 subscription_required, and with a plan that has no daily allowance and no purchased blocks it returns 402 verification_capacity_required. Starter includes 500 checks a day.

Build it on infrastructure that holds up

Domains, mailboxes, warming and verification over one REST API and MCP server, with the sequencer, Unibox and CRM on every plan.

No card to start — cancel any time.