Match people, normalize addresses, and enrich records.
Use Linksync to compare person records with Splink, parse messy US addresses, match to OpenStreetMap features, and return locality-aware place details.
Quick start
curl -X POST https://your-domain.example/api/normalize \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"address":"47 Glen Avenue, Newton, MA 02459"}'
The public demo uses /api/normalize/demo. Production API requests should use a bearer token from /oauth/token with client credentials.
Overview
Match people
Compare CRM records, imports, or caller-supplied candidate blocks using Splink.
Parse
Convert free-text or structured inputs into consistent address components.
Match
Optionally resolve addresses to OSM features with coordinates and IDs.
Enrich
Return main city, locality, state, and administrative area details where available.
Authentication
Request an OAuth-style bearer token, then send it as Authorization: Bearer <access_token> on API calls. Legacy ?key=... access still works for now but bearer auth is preferred.
Client credentials grant
grant_type=client_credentials&client_id=YOUR_API_KEY&client_secret=YOUR_OAUTH_CLIENT_SECRET
Response
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600
}
Normalize a free-text address
Send a single address string. Linksync parses it into address components. Add match=true to also attempt an OSM building or place match.
- address
- Required. Full address string for POST body or GET query string.
- match
- Optional query parameter. Boolean, defaults to
false. - locality_output_mode
- Optional request field. One of
main_city,replace_city, orseparate_field.
POST request
{
"address": "47 Glen Avenue, Newton, MA 02459",
"locality_output_mode": "separate_field"
}
Example response
{
"street": "Glen Avenue",
"housenumber": "47",
"postcode": "02459",
"city": "Newton",
"locality": "Newton Centre",
"admin_area": "Middlesex County",
"admin_area_type": "county",
"state": "MA",
"country_code": "US",
"lat": 42.298,
"lon": -71.203
}
Normalize a structured address
Use this endpoint when your source system already separates street, city, state, and postcode fields.
- housenumber
- Required with
street. Street number, including unit suffix if present. - street
- Required with
housenumber. Street name. - city/state/postcode
- At least one of these should be supplied. Postcode lookup can fill missing city/state details.
- countrycode
- Optional. Defaults to the configured country, currently US.
POST request
{
"housenumber": "47",
"street": "Glen Avenue",
"city": "Newton",
"county": "Middlesex",
"state": "MA",
"postcode": "02459",
"countrycode": "US"
}
Person matching
Person matching requires Match People to be enabled on your account. Use bearer auth from /oauth/token.
Match an uploaded person file
After uploading and processing a person-matching CSV in the UI or upload API, call Splink match with the upload id. Linksync automatically uses your primary person parquet/model.
{
"upload_id": 456,
"matching_scheme": "person_balanced_v1",
"use_trained_model": true
}
Match direct JSON records
Use this endpoint when you want to send people directly instead of uploading a CSV. Linksync builds temporary Splink input parquet and returns an upload_id that can be used with progress and download endpoints.
{
"blocking_mode": "splink",
"matching_scheme": "person_default_v1",
"use_trained_model": true,
"parse_address": true,
"match_address": true,
"records": [
{
"row_id": "import-55",
"full_name": "Simon French",
"email": "simon@example.com",
"address": "47 Glen Avenue, Newton, MA 02459"
}
]
}
- matching_scheme
- Optional. One of
person_default_v1,person_conservative_v1,person_balanced_v1,person_import_v1,household_v1, ororganization_v1. - use_trained_model
- Optional, defaults to
true. Set tofalseto ignore the stored trained model and use the selected scheme settings. - blocking_mode
- Optional for direct records.
splinkuses Linksync/Splink blocking.crmuses caller-supplied block ids. - parse_address
- Optional. Parse single-line addresses with libpostal before creating Splink input.
- match_address
- Optional. Match parsed or structured addresses to Photon/OSM and use verified OSM-derived address fields.
Accepted person and address fields
Records may include full_name or first_name plus last_name, and optional fields such as middle_name, dob, gender, email, phone, organization_name, and person_id.
Address input may be a single string in address, address_line, or full_address; an address object; or top-level components such as street, housenumber, city, state, and postcode. Request-level parse_address and match_address can also be overridden per record.
CRM-supplied blocking
When your CRM has already selected candidate blocks, send blocking_mode: "crm". Linksync only compares records where primary_records[].crm_block_id equals records[].crm_block_id.
{
"blocking_mode": "crm",
"matching_scheme": "person_default_v1",
"use_trained_model": true,
"parse_address": true,
"match_address": true,
"primary_records": [
{
"row_id": "crm-1001",
"crm_block_id": "block-a",
"full_name": "Simon French",
"address_line": "47 Glen Avenue, Newton, MA 02459"
}
],
"records": [
{
"row_id": "import-55",
"crm_block_id": "block-a",
"first_name": "Simon",
"last_name": "French",
"address": {
"street": "Glen Avenue",
"housenumber": "47",
"postcode": "02459"
}
}
]
}
primary_records and records. Direct JSON matching is intended for small/interactive jobs; use the CSV upload workflow for larger files.
Remove PII but keep training analysis
Use this endpoint when a user wants uploaded person/address data removed while keeping the Splink trained model summary and training analysis charts.
Linksync deletes source files, result files, Splink input CSV/parquet files, and Splink match outputs. It keeps the trained model JSON and training chart HTML files, so training analysis remains available.
Locality output modes
Locality output lets clients choose whether ZIP-level neighborhoods and villages should appear as the returned city or as separate fields.
| Mode | Behavior |
|---|---|
main_city | Return the canonical main city only. |
replace_city | Replace city with a nearby locality when Linksync can do so safely. |
separate_field | Keep city as the main city and add locality, admin_area, and admin_area_type when available. |
Errors and geographic limits
- 400: missing or invalid request input.
- 401: missing, expired, or invalid bearer token.
- 500: unexpected server error, returned as
{"error":"message"}.
Results are filtered to the configured country, currently US. Some deployments may also be restricted to a test state such as Massachusetts.