API Reference
Everything you need to integrate with the Ambect API.
Authentication
All requests require an API key sent as a Bearer token in the Authorization header.
API keys are prefixed with en_. Get a free key →
Endpoints
Base URL: https://api.ambect.com
/v1/normalize/companyNormalize a company name through the full normalization pipeline.
/v1/normalize/addressParse and normalize a postal address. Optional geocoding on Growth and Business plans.
/v1/normalize/phoneParse and normalize a phone number to E.164, national, and international formats.
/v1/normalize/emailNormalize an email address or URL. Detects disposable email domains.
/v1/normalize/identifierNormalize and validate a business identifier: SSN, EIN, EU VAT, SIC code, or stock ticker.
/v1/normalize/batchNormalize up to 100 entities of a single type in one request, with per-item results.
Company endpoint
Request
Send JSON with Content-Type: application/json.
{
"name": "Berkshire Hathaway Inc.", // required, 1–512 chars
"country": "us" // optional, ISO 3166-1 alpha-2
}| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | The company name to normalize. Max 512 characters. |
| country | string | No | ISO 3166-1 alpha-2 country code. Enables country-specific pipeline rules. |
Response
{
"data": {
"canonical": "berkshire hathaway",
"tokens": ["berkshire", "hathaway"],
"match_key": "berkshire hathaway",
"legal_type": "inc"
},
"meta": {
"pipeline": ["lowercase", "punctuation", "legal_suffix"],
"country": "us",
"confidence": 1.0,
"ms": 1.3
},
"error": null
}canonical and tokens are in processing order. match_key is the same tokens sorted alphabetically — use it to match records whose words appear in a different order (e.g. "Global Acme" and "Acme Global" share a match_key).
Pipeline stages
Runs up to 11 discrete stages. Only stages relevant to the input fire. The meta.pipeline array tells you exactly what ran.
decodeStrip control characters and HTML tags, and repair common encoding artifacts (mojibake).
unicode_normApply Unicode NFC normalization.
transliterateConvert non-Latin scripts to Latin equivalents by country.
lowercaseNormalize all characters to lowercase.
punctuationStrip punctuation and special characters.
whitespaceCollapse and trim whitespace.
legal_suffixStrip and record the legal entity suffix (LLC, Inc., Ltd., etc.) separately from the canonical name.
acronym_expandExpand known acronyms to canonical long forms.
stop_wordsRemove noise tokens by entity type and country.
synonym_mapMap synonyms to canonical tokens (3,000+ mappings).
dedupRemove consecutive duplicate tokens.
Address endpoint
Request
{
"address": "10 Downing Street, London, SW1A 2AA", // required, 1–1024 chars
"country": "gb", // optional, ISO 3166-1 alpha-2
"geocode": false // optional, Growth+ only
}| Field | Type | Required | Description |
|---|---|---|---|
| address | string | Yes | Raw address string. Max 1,024 characters. |
| country | string | No | ISO 3166-1 alpha-2 hint. Improves parse accuracy for ambiguous addresses. |
| geocode | boolean | No | Request lat/lng geocoding. Defaults to false. Requires Growth or Business plan. |
Response
{
"data": {
"components": {
"building": null,
"house_number": "10",
"street": "Downing Street",
"unit": null,
"level": null,
"staircase": null,
"entrance": null,
"cross_street": null,
"suburb": "Westminster",
"city_district": null,
"city": "London",
"county": null,
"region": null,
"country_region": null,
"postal_code": "SW1A 2AA",
"country": "GB"
},
"normalized": "10 Downing Street Westminster London SW1A 2AA GB",
"match_key": "downing street 10 westminster london sw1a 2aa gb",
"geocode": null
},
"meta": {
"pipeline": ["validate_input", "parse", "normalize_components",
"country_context", "build_normalized"],
"country": "GB",
"confidence": 0.97,
"ms": 2.1
},
"error": null
}When geocode: true, the data.geocode object contains lat, lng, place_id, and formatted. Passing geocode: true on a Free or Starter plan returns a 403 with error.code: "geocode_tier_required".
Pipeline stages
validate_inputCheck for non-empty input and validate the country hint against ISO 3166-1.
parseStatistical address parsing via libpostal — trained on 1B+ addresses across 100+ countries and all scripts.
normalize_componentsExpand street and region abbreviations, title-case all free-text fields (street, city, suburb, city district, county), and resolve country to ISO 3166-1 alpha-2.
country_contextApply country-specific postal code formatting and validation (67 countries).
build_normalizedAssemble a canonical single-line address string and compute a match_key — stopword-stripped street tokens + house number after street + remaining components, lowercased — suitable for deduplication and fuzzy matching.
geocodeLook up lat/lng via Google Maps API. Results are cached for 30 days. Growth and Business plans only.
Phone endpoint
Request
{
"phone": "+1 (415) 555-0123", // required, 1–30 chars
"country": "US" // optional, ISO 3166-1 alpha-2 region hint
}| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Yes | Raw phone number in any format. Max 30 characters. |
| country | string | No | ISO 3166-1 alpha-2 default region (e.g. US, GB). Required for local numbers without a country code prefix. |
Response
{
"data": {
"e164": "+14155550123",
"national": "(415) 555-0123",
"international": "+1 415-555-0123",
"country_code": 1,
"region": "US",
"type": "FIXED_LINE_OR_MOBILE"
},
"meta": {
"pipeline": ["validate_input", "parse", "validate_format", "format"],
"ms": 0.8
},
"error": null
}The type field reflects the ITU-T line classification: MOBILE, FIXED_LINE, FIXED_LINE_OR_MOBILE, TOLL_FREE, VOIP, PREMIUM_RATE, and others.
Pipeline stages
validate_inputReject empty or oversized input.
parseParse the raw string into a structured phone number, using the country hint as the default region when no international dialling prefix is present.
validate_formatConfirm the parsed number is structurally valid for its region.
formatProduce E.164, national, and international representations; classify line type (mobile, fixed, toll-free, VoIP, etc.).
Email endpoint
Accepts an email address or URL — the type is auto-detected. Returns a normalized form plus metadata.
Request
{
"value": "User+Tag@GMAIL.COM" // required, 1–512 chars — email or URL
}| Field | Type | Required | Description |
|---|---|---|---|
| value | string | Yes | Email address or URL to normalize. Max 512 characters. |
Response — email
{
"data": {
"normalized": "user+tag@gmail.com",
"type": "email",
"local": "user+tag",
"domain": "gmail.com",
"tld": "com",
"disposable": false
},
"meta": {
"pipeline": ["validate_input", "detect_type", "normalize", "enrich"],
"ms": 0.5
},
"error": null
}Response — URL
{
"data": {
"normalized": "https://example.com/path",
"type": "url",
"scheme": "https",
"host": "example.com",
"path": "/path",
"disposable": null
},
"meta": {
"pipeline": ["validate_input", "detect_type", "normalize", "enrich"],
"ms": 0.3
},
"error": null
}Pipeline stages
validate_inputReject empty or oversized input.
detect_typeClassify input as email or URL based on structure.
normalizeLowercase local part and domain; strip default ports and trailing slashes from URLs.
enrichExtract local part, domain, TLD, and flag disposable domains for emails. Runs for URLs too, but adds no fields.
Identifier endpoint
Normalizes and validates business identifiers. Supported types: us_ssn us_ein eu_vat us_sic ticker
Request
{
"value": "045-85-7321", // required, 1–64 chars
"type": "us_ssn" // optional — auto-detected if omitted
}| Field | Type | Required | Description |
|---|---|---|---|
| value | string | Yes | Raw identifier value. Max 64 characters. |
| type | string | No | Type hint. One of us_ssn, us_ein, eu_vat, us_sic, ticker. Auto-detected if omitted. |
Response
{
"data": {
"normalized": "045-85-7321",
"type": "us_ssn",
"valid": true,
"country": null,
"description": null
},
"meta": {
"pipeline": ["validate_input", "detect_type", "validate_format", "format"],
"ms": 0.4
},
"error": null
}{
"data": {
"normalized": "DE129273398",
"type": "eu_vat",
"valid": true,
"country": "Germany",
"description": null
},
"meta": {
"pipeline": ["validate_input", "detect_type", "validate_format", "format"],
"ms": 0.4
},
"error": null
}{
"data": {
"normalized": "7372",
"type": "us_sic",
"valid": true,
"country": null,
"description": "Prepackaged Software"
},
"meta": {
"pipeline": ["validate_input", "detect_type", "validate_format", "format"],
"ms": 0.4
},
"error": null
}Pipeline stages
validate_inputReject empty or oversized input.
detect_typeAuto-detect identifier type (SSN, EIN, EU VAT, SIC, ticker) from structure, or accept an explicit type hint.
validate_formatApply domain-specific validity rules (e.g. SSN area 000 invalid, EU VAT checksum must be valid for its country prefix).
formatProduce a canonical representation (e.g. dashed SSN, padded SIC, uppercase ticker) and attach contextual metadata: SIC industry description, EU VAT country name.
Batch endpoint
Normalize many entities in a single request. A batch is homogeneous — every item is the same type, and each item uses that type's request schema. Items are processed independently, so one bad item never fails the whole batch.
Request
{
"type": "company", // required — company | address | phone | email | identifier
"items": [ // required, 1–100 items
{ "name": "Microsoft Corporation", "country": "us" },
{ "name": "Berkshire Hathaway Inc." }
]
}| Field | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | Entity type for every item. One of company, address, phone, email, identifier. |
| items | array | Yes | 1 to 100 objects, each matching the request schema of the chosen type (e.g. { "name", "country" } for company). |
Response
Returns 200 OK with one entry per input item, in order. Each entry carries the same data, meta, and error fields the single-entity endpoint returns, plus its index.
{
"results": [
{
"index": 0,
"data": { "canonical": "microsoft", "tokens": ["microsoft"], "match_key": "microsoft", "legal_type": "corp" },
"meta": { "pipeline": ["lowercase", "legal_suffix"], "country": "us", "confidence": 1.0, "ms": 1.4 },
"error": null
},
{
"index": 1,
"data": { "canonical": "berkshire hathaway", "tokens": ["berkshire", "hathaway"], "match_key": "berkshire hathaway", "legal_type": "inc" },
"meta": { "pipeline": ["lowercase", "punctuation", "legal_suffix"], "country": null, "confidence": 1.0, "ms": 1.3 },
"error": null
}
],
"meta": { "type": "company", "count": 2, "succeeded": 2, "failed": 0, "ms": 3.1 }
}Partial success & validation
per-itemIf an item can't be normalized, its entry has data: null and a message in error — the request still returns 200. Use meta.succeeded and meta.failed for a quick summary.
422An empty list, more than 100 items, an unknown type, or an item missing a required field fails the whole request with 422 Validation error.
quotaEach item counts as one request against your monthly limit — a 50-item batch consumes 50. The call uses a single token against your per-second rate limit.
Rate limits
Two limits apply per API key across all endpoints. When either is exceeded, the request returns 429 Too Many Requests.
QPS (queries per second) — enforced via a token bucket with 5× burst capacity. Exceeding the sustained rate returns a Retry-After: 1 header.
Monthly cap — total requests per calendar month across all endpoints. Each item in a batch request counts as one request. See the Pricing page for overage options.
| Plan | QPS | Monthly limit | Geocoding |
|---|---|---|---|
| Free | 1 req/s | 100 req / month | — |
| Starter | 5 req/s | 2,000 req / month | — |
| Growth | 25 req/s | 15,000 req / month | ✓ |
| Business | 100 req/s | 75,000 req / month | ✓ |
Errors
Two kinds of failure
Every normalization response has the same shape: data, meta, and error. A request that is well-formed but cannot be normalized — an unparseable phone number, an address the parser can't break down, an identifier of unknown type — is a normalization outcome, not a transport error. It returns 200 OK with data and meta set to null and a message in error:
{
"data": null,
"meta": null,
"error": "could not parse phone number: (1) The string supplied did not seem to be a phone number."
}Always check the error field, not just the HTTP status. A 200 with a non-null error is a handled failure, not a success. In a batch response the same rule applies per item. The company endpoint never returns an error — it always produces a best-effort result.
The status codes below are reserved for problems with the request itself — authentication, plan limits, malformed JSON, or fields that fail schema validation:
400Bad request — invalid or missing fields
401Unauthorized — missing or invalid API key
403Forbidden — feature not available on your plan
404Not found — unknown endpoint path
422Validation error — input failed schema checks
429Rate limit exceeded
500Internal server error
503Service starting — the model is still warming up; retry shortly