Loqate CLI
Verify addresses, emails, and phone numbers against Loqate's APIs.
Get confidence scores, policy-aware recommendations, and full auditability β in one command.
Real-time verification decisioning for agents that need to know whether contact data is good enough for the job.
Part of GBG Reach.
lqt verify Β Β·Β lqt parse Β Β·Β lqt mcp
Install
macOS
curl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_darwin_arm64.tar.gz | tar xz
sudo mv lqt /usr/local/bin/
curl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_darwin_amd64.tar.gz | tar xz
sudo mv lqt /usr/local/bin/
Linux
curl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_linux_amd64.tar.gz | tar xz
sudo mv lqt /usr/local/bin/
curl -sL https://github.com/gbgplc/lqt/releases/latest/download/lqt_linux_arm64.tar.gz | tar xz
sudo mv lqt /usr/local/bin/
Windows
- Download
lqt_windows_amd64.zip from the latest release
- Extract
lqt.exe
- Move it to a directory on your
PATH, or run it directly
Verify Installation
All Downloads
See Releases for all versions and platforms. Each release includes SHA-256 checksums.
| Platform | Archive |
|---|
| macOS (Apple Silicon) | lqt_*_darwin_arm64.tar.gz |
| macOS (Intel) | lqt_*_darwin_amd64.tar.gz |
| Linux (x86_64) | lqt_*_linux_amd64.tar.gz |
| Linux (ARM64) | lqt_*_linux_arm64.tar.gz |
| Windows (x86_64) | lqt_*_windows_amd64.zip |
Quick Start
API Keys
You need a Loqate API key for verification. Optionally, an Anthropic API key for the parse command.
macOS / Linux:
export LOQATE_API_KEY=your-key-here
export ANTHROPIC_API_KEY=your-key-here
Windows (PowerShell):
$env:LOQATE_API_KEY="your-key-here"
# Optional β for lqt parse
$env:ANTHROPIC_API_KEY="your-key-here"
Your First Verification
macOS / Linux:
lqt verify --address "125 Summer Street, Boston, MA 02110, US"
lqt verify -a "10 Downing St, London, GB" \
-e "pm@gov.uk" \
-p "+442071234567" \
--policy shipping
lqt parse --address "125 summer street boston ma 02110 us"
Windows (PowerShell):
# Verify an address
.\lqt.exe verify --address "125 Summer Street, Boston, MA 02110, US"
# Verify address + email + phone with a policy
.\lqt.exe verify -a "10 Downing St, London, GB" -e "pm@gov.uk" -p "+442071234567" --policy shipping
# Parse and standardize without calling Loqate (uses Claude)
.\lqt.exe parse --address "125 summer street boston ma 02110 us"
Commands
verify
Verify addresses, emails, and/or phone numbers against Loqate's APIs. Returns a confidence score and a policy-driven recommendation (accept, review, or reject).
Flags:
| Flag | Short | Description |
|---|
--address | -a | Full address to verify |
--locality | | City/town |
--admin-area | | State/province |
--postcode | | Postal/ZIP code |
--country | -c | ISO 2-letter country code |
--detect-country | | When no country is supplied, guess it from the address and flag the guess in the result. Address-only; off by default. |
--suggest | | When the address does not clear the policy (review or reject), look up alternative addresses suggested by Loqate and return them under address.suggestions. Not called for an accepted address. Requires a separately licensed Loqate feature enabled on your account. Address-only; off by default; not available with --batch. |
--suggest-limit | | Maximum suggestions to return, 1β10 (default 5). Requires --suggest. |
--suggest-below | | Confidence floor for suggestions: an accepted address scoring below it still gets suggestions. Defaults to the active policy's value (standard 0.85). 0 disables the floor. Requires --suggest. |
--suggestion-id | | Verify a suggestion the user chose, by its id from address.suggestions. Resolves the id to its cleansed components and verifies those. Use instead of --address. Consumes a Loqate credit. Not available with --batch or --dry-run. |
--email | -e | Email address to verify |
--phone | -p | Phone number (E.164 format) |
--key | -k | Loqate API key (overrides env) |
--policy | | Policy name: strict, shipping, standard, permissive |
--policy-file | | Path to custom policy JSON file |
--batch | -b | CSV/TSV/pipe-delimited file path (or - for stdin) |
--delimiter | -d | Batch delimiter: comma, tab, pipe (auto-detected if omitted) |
--output | -o | Output format: json, jsonl, table |
--summary | -s | Show batch summary statistics |
--field | | Extra Loqate input field Key=Value (repeatable) |
--option | | Loqate API option Key=Value (repeatable, dot notation for nesting) |
--jsonl | | JSON Lines output (one object per line) |
--no-color | | Disable color output |
--verify-url | | Custom address verification endpoint URL (overrides LOQATE_VERIFY_URL env var) |
--verify-key | | Custom address verification API key (overrides LOQATE_VERIFY_KEY env var). When set, --key is not required for address-only verification. |
--verbose | -v | Show reasoning log |
Examples:
lqt verify -a "1600 Amphitheatre Parkway, Mountain View, CA 94043, US"
lqt verify -a "221B Baker St, London, GB" \
-e "sherlock@example.com" \
-p "+442071234567" \
--policy strict
lqt verify -e "sherlock@example.com"
lqt verify -p "+442071234567"
lqt verify -a "10 Downing St, London SW1A 2AA" --detect-country
lqt verify -a "10 downin st london" -c GB --suggest
lqt verify -a "10 downin st london" -c GB --suggest --suggest-limit 3
lqt verify -a "marsh wall, E14 9TN" -c GB --suggest
lqt verify -a "marsh wall, E14 9TN" -c GB --suggest --suggest-below 0.95
lqt verify -a "marsh wall, E14 9TN" -c GB --suggest --suggest-below 0
lqt verify -a "10 Downing St, London, GB" -o json | jq '.address.confidence'
lqt verify -a "125 Summer St" --field Organization="Acme Corp" --field Building="Suite 200"
lqt verify -a "125 Summer St, Boston, MA 02110, US" --option GeoCode=true
lqt verify -a "125 Summer St, Boston, MA 02110, US" --option ServerOptions.OutputCasing=Upper
Full list of input fields and API options: Loqate International Batch Cleanse API
Address suggestions (--suggest)
Licensing. Suggestions use a Loqate feature that is licensed separately from address
verification and must be enabled on your account. If it isn't, nothing breaks: the
verification still returns its normal result and exit code, and the reason appears in
suggestions.error (typically an unknown-key or licence message from Loqate). Talk to your
Loqate account contact to have it enabled.
Verification tells you an address is wrong. Suggestions tell you what the right one probably
is. Add --suggest and lqt asks Loqate for real addresses matching what was typed, returning
them with the decision.
The lookup runs when either:
- the address was not accepted (
review or reject), or
- the address was accepted but scored below the policy's suggestion floor (0.85 on
standard β see the Policies table).
The second case is the one that catches near-misses. A policy accepts anything at or above its
minimum confidence, so accepted is not the same as confident: on standard the input
marsh wall, E14 9TN matches a street and scores exactly 0.55, which is accepted β yet the
house number is missing and better addresses exist. Use --suggest-below to move that line
(--suggest-below 0 turns the confidence check off and only suggests on review/reject).
{
"address": {
"verified_address": "Downing Street, London",
"confidence": 0.5,
"recommendation": "review",
"suggestions": {
"requested": true,
"triggered": true,
"reason": "accepted but confidence 0.55 is below the 0.85 floor",
"floor": 0.85,
"source": "loqate",
"count": 2,
"items": [
{
"id": "GB|RM|A|52509479",
"type": "Address",
"text": "10 Downing Street",
"description": "London, SW1A 2AA",
"address": "10 Downing Street, London, SW1A 2AA"
},
{
"id": "GB|RM|A|52509480",
"type": "Address",
"text": "11 Downing Street",
"description": "London, SW1A 2AB",
"address": "11 Downing Street, London, SW1A 2AB"
}
]
}
}
}
Things worth knowing:
- Off by default, so existing output is unchanged unless you ask for suggestions.
- No lookup for a confidently accepted address β you pay the extra latency only where it
helps. The
suggestions block is still returned with "triggered": false and a reason, so
you can tell "no alternatives needed" from "suggestions were never requested".
floor reports the threshold that was applied, so you can see why a lookup ran (or
didn't) without knowing the policy's configuration.
- Suggestions never change the decision. If the lookup fails, the reason appears in
suggestions.error and the verification result stands.
- Address-only. With
verify --email / --phone, or verify_contact, only the address
block is decorated.
- An entry with
"expandable": true is a street, postcode, or building holding several
addresses rather than one deliverable address. Search within it for a specific premise.
- Suggestion lookups do not consume Loqate verification credits, but the feature must be licensed on your account (see the note above).
- Suggestions need a standard Loqate key (
--key / LOQATE_API_KEY); --verify-key alone
covers address verification only.
- Not available with
--batch. A large file would fan out into an unbounded number of
lookups, so the combination is rejected. Verify the file, then re-run the flagged rows
individually with --suggest.
Available on the MCP verify_address / verify_contact tools and the REST
/v1/verify/address / /v1/verify/contact endpoints as suggest: true, with optional
suggest_limit (1β10, default 5) and suggest_below (0β1).
Closing the loop: offer, choose, re-verify
A suggestion is a candidate, not a verdict. Items carry no confidence score, no match
level, and no AVC β they are what the reference data thinks the address might have been. Don't
write one into your system of record on faith. Close the loop in three steps:
- Verify with
--suggest. A non-empty suggestions.items means alternatives exist.
- Offer
items[].address to whoever can decide β the customer in a checkout or support
flow, the agent in an automated one. That field is the ready-to-display line.
- Confirm the choice by its
id (--suggestion-id). That result β its confidence,
match level, and standardized fields β is the one you keep. Full flow below.
lqt verify -a "marsh wall, E14 9TN" -c GB --suggest -o json > result.json
jq -r '.address.suggestions.items[] | .address' result.json
lqt verify -a "1 Marsh Wall, London, E14 9TN" -c GB -o json
Over REST it's the same shape β one call with suggest, then a plain call with the choice:
curl -s -X POST https://your-host/v1/verify/address \
-H "Authorization: Bearer $LOQATE_API_KEY" -H 'Content-Type: application/json' \
-d '{"address":"marsh wall, E14 9TN","country":"GB","suggest":true}'
curl -s -X POST https://your-host/v1/verify/address \
-H "Authorization: Bearer $LOQATE_API_KEY" -H 'Content-Type: application/json' \
-d '{"address":"1 Marsh Wall, London, E14 9TN","country":"GB"}'
The full flow, end to end
- Verify with
--suggest β get candidates for an address that didn't come back clean.
- Offer
items[].address to whoever decides.
- Confirm with
--suggestion-id, using the chosen item's id. That result is the one you keep.
lqt verify -a "marsh wall london" -c GB --suggest -o json > r.json
jq -r '.address.suggestions.items[] | "\(.id)\t\(.address)"' r.json
lqt verify --suggestion-id "GB|RM|B|55782678" -o json
Passing the id rather than the text is what makes step 3 accurate: lqt fetches that
address's cleansed components (company, sub-building, number, street, city, postcode, country)
and verifies those, so nothing is re-parsed. It matters for suggestions carrying a company name
β London Lash, 56 Marsh Wall, London β where re-reading the text can misplace the company as
part of the street.
The result records what it resolved from, so you can audit it without resolving again:
{
"verified_address": "56 Marsh Wall, London, E14 9TP",
"confidence": 0.95,
"recommendation": "accept",
"resolved_from": {
"suggestion_id": "GB|RM|B|55782678",
"address": "London Lash, Unit 7, Hampton Tower, 56 Marsh Wall, LONDON, E14 9TP"
}
}
Over REST, the same two steps:
curl -s -X POST https://your-host/v1/verify/address \
-H "Authorization: Bearer $LOQATE_API_KEY" -H 'Content-Type: application/json' \
-d '{"address":"marsh wall london","country":"GB","suggest":true}'
curl -s -X POST https://your-host/v1/verify/address \
-H "Authorization: Bearer $LOQATE_API_KEY" -H 'Content-Type: application/json' \
-d '{"suggestion_id":"GB|RM|B|55782678"}'
What to know:
- Step 3 consumes a Loqate credit to resolve the id (the search in step 1 does not). Resolve
the one address that was chosen β not the whole list to compare.
suggestion_id replaces address; sending both is a 400.
- Not available with
--batch, and not with --dry-run (resolving needs a live billable call).
- A stale id returns
SUGGESTION_NOT_FOUND / 404. Ids change over time β search again rather
than retrying the same id.
Just want the address, not a decision? Resolve it on its own:
lqt retrieve --id "GB|RM|B|55782678"
lqt retrieve --id "GB|RM|B|55782678" -o table
GET /v1/address/{id} over REST, or the retrieve_address MCP tool. This returns reference
data, not a verification β no confidence, no recommendation β so don't treat it as checked.
Four rules that keep the loop safe:
- Omit
suggest on the confirmation call. If the chosen address still doesn't clear the
policy you'd get a fresh set of suggestions, and an automated flow could bounce between them.
One round of suggestions, then a plain verify.
- Let the re-verify decide β not the fact that a suggestion existed. If the confirmation
returns
review or reject, the record still needs a human. You've narrowed it, not fixed it.
- Don't re-verify an
expandable item as-is. It's a street, postcode, or building, so
verifying it lands at street level at best. Use it to ask for the missing piece ("which
number on Marsh Wall?") and verify the completed address.
- Never store
id. It's a Loqate-assigned identifier that changes over time. Key off the
verified address returned in step 3.
Keep the country from the original request on the confirmation call β dropping it can change
the match.
Suggestion ranking comes from Loqate
lqt returns suggestions in the order Loqate provides them β no re-ranking or filtering is
applied. Loqate matches across the whole address record, including organisation names, so a
query like marsh wall london ranks businesses with "London" in their name above plain
residential addresses on that street:
London Lash, 56 Marsh Wall, London, E14 9TP
London Metropolis Ltd, 77 Marsh Wall, London, E14 9SH
That's standard address-autocomplete behaviour, but it means suggestion quality tracks input
quality. Where you know the country, pass it as --country rather than leaving it in the
address text β that moves the token out of the fuzzy match and into a filter:
lqt verify -a "marsh wall london" --suggest
lqt verify -a "marsh wall" -c GB --suggest
parse
Parse and standardize contact data using Claude (Haiku). Extracts address components, validates email syntax, and normalizes phone numbers with awareness of 250+ country-specific postal formats. No Loqate API calls β no credits spent.
Flags:
| Flag | Short | Description |
|---|
--address | -a | Full address to parse |
--email | -e | Email address to validate |
--phone | -p | Phone number to normalize |
--country | -c | ISO 2-letter country code hint |
--batch | -b | CSV/TSV/pipe-delimited file path (or - for stdin) |
--delimiter | -d | Batch delimiter: comma, tab, pipe (auto-detected if omitted) |
--output | -o | Output format: json, jsonl, table |
--jsonl | | JSON Lines output |
--no-color | | Disable color output |
--anthropic-key | | Anthropic API key (overrides env) |
Examples:
lqt parse -a "125 summer street boston ma 02110 us"
lqt parse -a "10 downing st london" -e "test@mailinator.com" -p "02071234567"
lqt parse --batch messy-data.csv --output json
policy
List, inspect, and validate verification policies.
lqt policy list
lqt policy show <name>
lqt policy validate <file>
mcp
Start an MCP (Model Context Protocol) server. Exposes LQT as tools for AI agents.
lqt mcp
lqt mcp --http :8080
lqt mcp --smoke-test
Flags:
| Flag | Default | Description |
|---|
--http | | Listen address (e.g. :8080, 127.0.0.1:8080) |
--rate-limit | 10 | Max requests/sec per IP (0 to disable) |
--rate-burst | 20 | Max burst size for rate limiter |
--smoke-test | | Self-test the MCP server (checks tools and prompts register) and exit |
--disable-custom-endpoint | | Block per-request custom verify endpoint fields |
--rest | | Also serve the REST API at /v1 (HTTP mode only) |
REST API
For clients that don't speak MCP, the HTTP server can also expose a plain REST API β opt-in with --rest, mounted at /v1 on the same port. Same result data as the CLI and MCP.
lqt mcp --http :8080 --rest
Authentication: your Loqate API key as a bearer token β Authorization: Bearer <LOQATE_API_KEY> (or key in the request body).
| Method | Path | Description |
|---|
POST | /v1/verify/address | Verify an address (supports detect_country, suggest, suggestion_id) |
POST | /v1/verify/email | Verify an email |
POST | /v1/verify/phone | Verify a phone number |
POST | /v1/verify/contact | Verify any combination + overall recommendation (supports detect_country, suggest) |
GET | /v1/address/{id} | Resolve a suggestion id to a cleansed address (consumes a credit) |
GET | /v1/policies | List decisioning policies |
GET | /v1/policies/{name} | Show one policy |
GET | /v1/openapi.json | OpenAPI 3.1 specification |
GET | /v1/docs | Interactive API reference |
A recommendation (accept / review / reject) is always returned as HTTP 200 with the decision in the body. Errors use standard status codes: 400 invalid input, 401 missing/invalid key, 429 rate limited, 502 upstream error.
curl -s -X POST https://your-host/v1/verify/address \
-H "Authorization: Bearer $LOQATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"125 Summer St, Boston, MA 02110, US","policy":"standard"}'
curl -s -X POST https://your-host/v1/verify/address \
-H "Authorization: Bearer $LOQATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"10 downin st london","country":"GB","suggest":true,"suggest_limit":5}'
Full request/response schemas are documented in the OpenAPI spec at /v1/openapi.json (browse it at /v1/docs).
Explaining a result
Every address verification also returns detail that explains the score without changing it:
| Field | What it tells you |
|---|
matchscore | 0-100, how closely the returned address resembles what you sent. Surfaced so you need not parse it out of avc. |
coverage_level + coverage_level_label | The country's maximum Loqate verification level, as a number and a name: 5 delivery_point, 4 premise, 3 street, 2 locality. The label uses the same vocabulary as match_level, so when the two are equal the address matched as precisely as that country's data allows. |
coverage_boost | The level shift applied because that country's data tops out below premise. This is the number that explains why a street-level match in a low-coverage country still scores highly. |
changes | What Loqate altered, in words. Opt-in β see below. |
To get changes, ask Loqate for its per-field status codes:
lqt verify -a "125 Summer St, Boston, MA 02110, US" \
--option ServerOptions.FieldStatus=true -o json
"changes": [
{ "field": "country_name", "change": "added", "value": "United States", "code": "5" },
{ "field": "postal_code", "change": "reformatted", "value": "02110-1634", "code": "2" },
{ "field": "postal_code_secondary", "change": "added", "value": "1634", "code": "5" },
{ "field": "sub_administrative_area", "change": "added", "value": "Suffolk", "code": "5" }
]
Nothing was wrong with that address; three things were added (ZIP+4, county, country name) and the
postcode was reformatted. Fields Loqate verified without touching are not listed, so a short list means
a clean address.
change is one of added, corrected, reformatted or unrecognised. code is Loqate's original
status code, kept so the categorisation is not lossy β the codes are Loqate's own, documented at
docs.loqate.com/report-codes/fieldstatus.
Absent changes means you did not ask for the codes. An empty array means you asked and nothing changed.
The option also adds a <field>_status key per component to fields, since that passthrough returns
everything Loqate sends.
This detail appears on every address verification β single, batch (per row), MCP and REST β because
all four go through the same result builder.
Policies
Policies control what gets accepted, reviewed, or rejected. Every verification runs through a policy β there are no hardcoded thresholds.
| Policy | Addr Confidence | Match Level | Email Confidence | Phone Required | Suggest Below | Use Case |
|---|
| strict | 0.90 | premise | 0.85 | yes | 0.90 | KYC, fraud prevention, regulated |
| shipping | 0.85 | street | 0.50 | no | 0.85 | Physical delivery, ecommerce |
| standard | 0.55 | street | 0.45 | no | 0.85 | General verification (default) |
| permissive | 0.30 | locality | 0.30 | no | 0.70 | Lead capture, early funnel |
Suggest Below is not an acceptance threshold β it never changes accept/review/reject. It is
the confidence below which --suggest looks up alternatives even for an accepted address.
See Address suggestions. Custom policies can set their own
value, and the recommend_policy MCP tool proposes one for the use case you describe.
Custom Policies
Create a JSON file:
{
"name": "my-custom-policy",
"description": "Tuned for my use case",
"address": {
"min_confidence": 0.65,
"min_match_level": "street",
"reject_verification_status": ["U", "R"]
},
"email": {
"min_confidence": 0.50,
"allow_catch_all": true,
"reject_disposable": true
},
"phone": {
"min_confidence": 0.40,
"required": false
}
}
lqt policy validate my-policy.json
lqt verify -a "..." --policy-file my-policy.json
Batch Processing
Batch endpoints (up to 100 records per call)
lqt batch verifies up to 100 records in a single call β the same thing the
verify_*_batch MCP tools and the /v1/verify/*/batch REST endpoints do.
One record per input line, from a file or stdin:
lqt batch address --file addresses.txt --country GB
lqt batch email --file emails.txt --policy strict
lqt batch phone --file phones.txt --country GB -o table
lqt batch contact --file contacts.json
cat emails.txt | lqt batch email
contact is the exception to one-record-per-line: a contact has several fields,
so it reads a JSON array β the same shape the MCP tool and REST endpoint take.
Each contact may carry any combination of address, email and phone and gets an
overall recommendation drawn from whichever fields were verified. The three
types run concurrently, so a full batch is paced by email.
Results come back in submission order and each carries its input index, so
they can be zipped back onto rows without relying on order. One bad record
fails only itself β it carries an error while the rest are verified β and
the summary reports count, succeeded and failed.
Exit codes reflect the batch, not any one record: 0 all verified, 1 some
failed, 2 none succeeded, 3 the request never ran.
A batch record takes the same fields as a single verification. All 38
structured inputs β premise, thoroughfare, organization, sub_building,
the address2βaddress8 and delivery_address lines, and the recipient fields
(contact, function, department, forename, surname, middle_name,
full_name, id) β are accepted per record by verify_address_batch,
verify_contact_batch and their REST equivalents, and are listed once as
AddressComponents in the OpenAPI document. The recipient fields name who a
delivery is for rather than where it goes; they are passed to Loqate unchanged
and do not affect the decision. The only fields left out are the ones that mean nothing in bulk: the
suggestion fields, and the request-level settings (key, policy, options,
detect_country) that apply to the whole batch. lqt batch address reads one
free-form address per line; to send structured columns from a file, use
lqt verify --batch.
Three things worth knowing:
- Addresses are grouped by country before being sent, which is what Loqate
recommends. The cost is therefore one upstream call per distinct country in
the batch, not one per call.
- Email batch returns less detail than single verification:
risk,
is_complainer_or_fraud_risk and reason are absent. The accept/review/reject
recommendation and the disposable-mailbox flag are identical.
- Phone has no bulk endpoint upstream, so numbers are checked concurrently
against a process-wide limit. Measured over 100 records: address ~3s,
phone ~2.6s, email ~7s. Email is the slowest of the three, because it probes
mail servers β phone is quicker than its lack of a bulk endpoint suggests.
Records without a country. An address with no country verifies poorly β the
same Boston address scores 0.03 without one and 0.95 with it β so lqt batch address warns when neither --country nor --detect-country is given. With
--detect-country, the country is guessed per record from its address text and
the guess is flagged in that record's result. Detection runs before grouping,
so a batch spanning several countries still sends each group with its own
default rather than one wrong default for everything.
Suggestions are not available in batch, for the same reason they are not
available with --batch.
Rate limiting on the hosted server. Batch endpoints are charged by record,
not by request β a 100-record batch costs 100 against a per-caller budget, because
that is what it costs upstream. The default is 100 records/second with a burst of
600, so two full contact batches run back to back and further ones are paced. A batch that
would wait more than --record-max-wait (2s) is refused with 429 and a retry
hint rather than holding the connection open. Tune with --record-rate,
--record-burst and --record-max-wait, or set --record-rate 0 to disable. The
burst must be at least 300 or the server refuses to start: a contact is charged
per field verified, so a full contact batch costs 300, and a smaller burst could
never accept one. The CLI is not rate limited.
For files larger than 100 records, or delimited files with named columns, use
lqt verify --batch <file>, which walks a file of any size in chunks of 100.
Large files with verify --batch
Process files with address, email, and phone columns. Supports comma, tab, and pipe delimited input.
verify --batch reads a file of any size and sends it through the same batch
endpoints as lqt batch β up to 100 records per call, grouped by country,
streamed in chunks so memory does not grow with the file. It used to verify one
row per request; a 10,000-row file was 10,000 sequential round trips.
Three things follow from that, none of them visible in a result:
- Rows travel together. The upstream cost is one call per distinct country
per chunk of 100, not one per row.
- A chunk is one transaction. The
pca-source session id is shared by the
rows sent together, as it is for every other batch surface. Per-row
correlation was a property of sending one request per row, and no batch
endpoint can offer it.
- Email carries less detail, exactly as it does for
lqt batch email:
risk, is_complainer_or_fraud_risk and reason are absent, because the
bulk email endpoint does not return them. The accept/review/reject
recommendation is computed the same way.
A file needs at least one address column, or an email or phone column. One bad
row fails only itself; a whole chunk that fails upstream leaves the rest of the
file running.
lqt verify --batch addresses.csv --policy shipping -o json > results.json
lqt verify --batch addresses.tsv -o json
lqt verify --batch addresses.txt --delimiter pipe -o json
cat addresses.csv | lqt verify --batch - --policy standard
lqt verify --batch addresses.csv --summary
Windows (PowerShell):
.\lqt.exe verify --batch addresses.csv --policy shipping -o json > results.json
Get-Content addresses.csv | .\lqt.exe verify --batch - --policy standard
Delimiters
Auto-detected from the first line. Override explicitly with --delimiter:
| Value | Aliases | Description |
|---|
comma | csv | Comma-separated (default) |
tab | tsv | Tab-separated |
pipe | | Pipe-separated |
Supported Columns
Use a single address column or structured fields β or both. All column names are case-insensitive. Every field from the Loqate International Batch Cleanse API is supported.
Address lines:
| Field | Accepted column names |
|---|
| Address (line 1) | address, address1, street, address_line_1 |
| Address lines 2-8 | address2-address8, address_line_2-address_line_8 |
| Delivery address | deliveryaddress, delivery_address |
| Delivery lines 1-8 | deliveryaddress1-deliveryaddress8, delivery_address_1-delivery_address_8 |
Geography:
| Field | Accepted column names |
|---|
| City | city, locality, town |
| State/Province | state, admin_area, province, region, administrative_area |
| County | county, sub_admin_area, sub_administrative_area |
| Postal code | postcode, postal_code, zip, zipcode |
| Country | country, country_code |
Street / building / premise:
| Field | Accepted column names |
|---|
| Street name | thoroughfare, street_name |
| Building | building, building_name |
| House number | premise, house_number, building_number |
| Apartment/Suite | sub_building, apartment, suite, unit, flat |
Organization / postal:
| Field | Accepted column names |
|---|
| Organization | organization, organisation, company, company_name |
| PO Box | post_box, postbox, po_box, pobox |
Contact / person:
| Field | Accepted column names |
|---|
| First name | forename, first_name |
| Last name | surname, last_name |
| Full name | full_name, name |
Non-address fields:
| Field | Accepted column names |
|---|
| Email | email, email_address |
| Phone | phone, telephone, phone_number, mobile |
Example CSV
address,email,phone,country
"125 Summer St, Boston, MA 02110",user@example.com,+16175551234,US
"10 Downing St, London",pm@gov.uk,+442071234567,GB
MCP Integration
The lqt mcp command exposes LQT as tools for AI agents via the Model Context Protocol. Connecting the MCP server also provides a built-in usage guide prompt that teaches the AI how to use the tools effectively.
Claude Code / Cursor
Add to your project's .mcp.json:
{
"mcpServers": {
"loqate": {
"command": "lqt",
"args": ["mcp"],
"env": {
"LOQATE_API_KEY": "your-key-here",
"ANTHROPIC_API_KEY": "your-key-here"
}
}
}
}
Claude Desktop
Add to Claude Desktop's MCP settings:
{
"mcpServers": {
"lqt": {
"command": "/usr/local/bin/lqt",
"args": ["mcp"],
"env": {
"LOQATE_API_KEY": "your-key-here",
"ANTHROPIC_API_KEY": "your-key-here"
}
}
}
}
GBG-hosted endpoint (recommended)
The fastest way to use Loqate over MCP is the GBG-hosted endpoint β no install, no infrastructure. Point any MCP client at:
https://reach.prod.fabric.gbgplatforms.com/mcp
Claude Code / Cursor / any MCP client β .mcp.json:
{
"mcpServers": {
"loqate": {
"url": "https://reach.prod.fabric.gbgplatforms.com/mcp"
}
}
}
Restart your client, then ask it to "verify 125 Summer St, Boston, MA 02110, US". It will discover the tools, call them, and explain the result.
Authenticate with your Loqate API key β pick one:
- Per-call β pass
key in the tool arguments ({"key": "YOUR-KEY", "address": "..."}).
- Connection-wide β set
Authorization: Bearer <YOUR-LOQATE-KEY> on the HTTP connection. Applies to every tool call.
- Out of band (Claude only) β put
<loqate_api_key>YOUR-KEY</loqate_api_key> in org / project / user instructions; the model injects it as key automatically.
If you supply none of the three, the server returns a NO_API_KEY error. The Bearer header only supplies the standard Loqate key; verify_key for a custom address-verify endpoint is separate.
Sanity check from your terminal (no client needed):
curl -s -X POST https://reach.prod.fabric.gbgplatforms.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
curl -s -X POST https://reach.prod.fabric.gbgplatforms.com/mcp \
-H 'Authorization: Bearer YOUR-LOQATE-KEY' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"verify_address","arguments":{"address":"125 Summer St, Boston, MA 02110, US"}}}'
Hosted deployments disable custom verify endpoints for security. If you receive a CUSTOM_ENDPOINT_DISABLED error, remove verify_url and verify_key from your tool arguments.
GBG-hosted REST endpoint
Prefer plain REST? The same hosted service also exposes the REST API β no MCP client required. Authenticate with your Loqate API key as a bearer token.
curl -s -X POST https://reach.prod.fabric.gbgplatforms.com/v1/verify/address \
-H 'Authorization: Bearer YOUR-LOQATE-KEY' \
-H 'Content-Type: application/json' \
-d '{"address":"125 Summer St, Boston, MA 02110, US","policy":"standard"}'
open https://reach.prod.fabric.gbgplatforms.com/v1/docs
The OpenAPI spec (/v1/openapi.json) and reference page (/v1/docs) are unauthenticated, so you can explore the full API before you have a key.
Remote HTTP (self-hosted)
If you'd rather run the server yourself, deploy lqt mcp --http as a service:
{
"mcpServers": {
"loqate": {
"url": "https://lqt.your-company.com/mcp"
}
}
}
Same three-tier key resolution applies (body key β Authorization: Bearer β server env LOQATE_API_KEY).
10 tools in stdio mode, 7 in HTTP mode (tools marked stdio mode only are not available over HTTP).
| Tool | Description |
|---|
verify_address | Verify an address with confidence score and recommendation (supports detect_country, suggest, suggestion_id) |
verify_email | Verify an email with risk level and recommendation |
verify_phone | Verify a phone number with type/carrier and recommendation |
verify_contact | Verify all fields together with overall recommendation (supports detect_country, suggest, suggestion_id) |
retrieve_address | Resolve a suggestion id to a cleansed address (consumes a credit; not a verification) |
parse_address | Parse and standardize an address via Claude (stdio mode only) |
list_policies | List available decisioning policies |
show_policy | Show details for a specific policy |
set_policy | Register a custom policy (stdio mode only) |
recommend_policy | Get a recommended policy for your use case, including its suggestion confidence floor (stdio mode only) |
Exit Codes
Designed for scripting and CI/CD:
| Code | Meaning |
|---|
| 0 | ACCEPT β all fields passed verification |
| 1 | REVIEW β manual review recommended |
| 2 | REJECT β verification failed |
| 3 | ERROR β missing key, invalid input, API failure |
macOS / Linux:
lqt verify -a "125 Summer St, Boston, MA 02110, US" --policy shipping -o json
case $? in
0) echo "Ship it" ;;
1) echo "Queue for review" ;;
2) echo "Bad address" ;;
3) echo "Something broke" ;;
esac
Windows (PowerShell):
.\lqt.exe verify -a "125 Summer St, Boston, MA 02110, US" --policy shipping -o json
switch ($LASTEXITCODE) {
0 { Write-Host "Ship it" }
1 { Write-Host "Queue for review" }
2 { Write-Host "Bad address" }
3 { Write-Host "Something broke" }
}
API Keys
Loqate API Key (for verify)
macOS / Linux:
export LOQATE_API_KEY=your-key-here
echo "your-key-here" > .loqate-key
lqt verify -a "..." --key your-key-here
Windows (PowerShell):
# Current session
$env:LOQATE_API_KEY="your-key-here"
# Persistent (survives restarts)
[System.Environment]::SetEnvironmentVariable("LOQATE_API_KEY", "your-key-here", "User")
# Per-command flag
.\lqt.exe verify -a "..." --key your-key-here
Anthropic API Key (for parse)
macOS / Linux:
export ANTHROPIC_API_KEY=your-key-here
Windows (PowerShell):
$env:ANTHROPIC_API_KEY="your-key-here"
Resolution order: flag > environment variable > key file
Custom Verify Endpoint (optional)
If you need to route address verification through a different endpoint (e.g., an on-premises or partner-hosted Loqate instance):
macOS / Linux:
export LOQATE_VERIFY_URL=https://custom-verify.example.com/v1/batch
export LOQATE_VERIFY_KEY=your-custom-key
lqt verify -a "..." --verify-url https://custom-verify.example.com/v1/batch --verify-key your-custom-key
Windows (PowerShell):
$env:LOQATE_VERIFY_URL="https://custom-verify.example.com/v1/batch"
$env:LOQATE_VERIFY_KEY="your-custom-key"
Resolution order: flag > environment variable > default Loqate endpoint
When --verify-key is set, the standard --key / LOQATE_API_KEY is not required for address-only verification. If you also verify email (-e) or phone (-p), the standard key is still needed for those.
These flags only affect address verification. Email and phone always use the standard Loqate endpoints.
In MCP mode, clients can pass verify_url and verify_key per-request in verify_address and verify_contact tool inputs.
Support
When reporting a bug, please include:
lqt version (lqt --version)
- OS and architecture (e.g., macOS ARM64, Linux x86_64)
- The command you ran (redact any API keys)
- Expected vs actual behavior
License
Proprietary β see LICENSE. Use requires an active Loqate subscription.
Built by GBG.