Skip to content

Micro-batch synchronous match

POST
/v1/match
curl --request POST \
--url https://api.infiniteaudience.ai/v1/match \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "records": [ { "row_id": "example", "email": "[email protected]", "phone": "example", "email_sha256": "example", "phone_sha256": "example", "full_name": "example", "first_name": "example", "middle_name": "example", "last_name": "example", "name_suffix": "example", "emails": [ "[email protected]" ], "emails_sha256": [ "example" ], "phones": [ "example" ], "phones_sha256": [ "example" ], "addresses": [ { "address_1": "example", "address_2": "example", "city": "example", "state": "example", "zip": "example", "zip5": "example", "postal_code": "example", "zip_code": "example" } ], "address_1": "example", "address_2": "example", "city": "example", "state": "example", "zip": "example", "dob": "example", "iag_person_id": "example" } ], "field_list": [ "example" ], "template_id": "example", "match_level": [ "I" ], "spatial_mode": "residential", "create_scratch_segment": false }'

Synchronous inline matching for small record sets (up to 100 records). Submit your records and the list of attributes you want appended, and receive matched results immediately.

Person IDs: A real match returns a tier 01 iag_person_id: a stable, non-reversible ID salted for your organization. The same real identity is consistent inside your organization and different in every other organization. An unmatched row may receive a derived tier 02–05 ID from its own submitted signals. That derived value is a continuity label—not a graph match, licensed identity, refresh key, or resolved audience member. Use the match metadata and match_count, not ID presence alone, to identify real matches.

Billing: Usage is emitted per matched record only (unmatched records are free). The platform reserves a conservative ceiling and durably queues finalized usage for billing rather than debiting a local balance field. amount_charged is the conservative USD estimate accepted for provider delivery; it is not a finalized invoice amount. Independent workflows for your organization can settle concurrently. License reuse is checked per distinct identity against confirmed canonical history before settlement. If two overlapping workflows settle before either confirmation is visible, both can be charged for that identity; the canonical ledger retains one license period.

Records array: one output record per input record — matched or not. Unmatched rows carry match_level/match_type/match_confidence: null and a best-effort iag_person_id derived from the row’s own identity signals (or null if none qualified) — only real matches are billed. Use match_count vs record_count to distinguish real matches from derived-only rows.

For datasets larger than 100 records, use POST /v1/match/file instead. Upload, analysis, and async matching are free until egress. The first successful delivery involving that file-match run emits its one aggregate match usage set together with normal delivery usage.

Retries: pass an Idempotency-Key header to make a retried call safe to repeat without a duplicate charge. The same key with an identical body returns the original response verbatim, at zero additional charge (honored for 24 hours); the same key with a different body is rejected with 409 IDEMPOTENCY_KEY_CONFLICT. Without this header, every call reserves and charges independently — recommended for any client that may retry on timeout. Requires ‘creator’ scope.

Idempotency-Key
string
>= 8 characters <= 160 characters /^[A-Za-z0-9][A-Za-z0-9._:-]{7,159}$/

Optional. Makes a retried call safe to repeat — see the endpoint description’s Retries section.

Media typeapplication/json
object
records
required

Records to match (max 100). Each object should include at least one identity signal: email (or email_sha256), phone (or phone_sha256), full_name (or first_name+last_name), or address attributes (address_1, city, state, zip). All attributes are optional — include only what you have. Any extra attributes you include are echoed back unchanged.

Array<object>
>= 1 items <= 100 items
object
row_id

Optional correlation ID, preserved exactly. Must contain at least one non-whitespace character. Omitted IDs default to the record’s 1-indexed string position (“1”, “2”, …). All effective IDs must be unique across this request, including custom/generated IDs. Duplicate IDs reject the whole request with 400 DUPLICATE_ROW_ID; invalid supplied IDs return 400 INVALID_ROW_ID.

string
>= 1 characters /\S/
email

Primary email address.

string format: email
phone

Phone number in any standard format.

string
email_sha256

Lowercase-hex SHA-256 hash of a normalized email address, for clients whose own systems never expose raw email addresses (e.g. data co-op / clean-room partners using the same hashing convention). The platform passes this through without re-hashing. Do not submit an already-hashed value in email — it would be hashed a second time and never match.

string
phone_sha256

Lowercase-hex SHA-256 hash of a normalized phone number. Same pre-hashed semantics as email_sha256.

string
full_name

Optional convenience field. When provided (and first_name / last_name are absent), the engine parses this into first_name, middle_name, last_name, and name_suffix automatically. The parsed components are used for matching; the original full_name value is echoed back unchanged.

string
first_name
string
middle_name
string
last_name
string
name_suffix

Generational suffix (e.g. JR, SR, III).

string
emails

Additional raw email addresses beyond email, tried as extra match permutations.

Array<string>
emails_sha256

Pre-hashed counterpart to emails.

Array<string>
phones

Additional raw phone numbers beyond phone, tried as extra match permutations.

Array<string>
phones_sha256

Pre-hashed counterpart to phones.

Array<string>
addresses

Additional addresses beyond address_1/city/state/zip, tried as extra match permutations.

Array<object>

One additional address, tried as an extra match permutation alongside the record’s primary address. Only the keys listed here are read. Any other key (for example street, line1, or postal) is ignored and contributes nothing to matching, so rename such fields before sending. Include address_1 in every entry. Send the ZIP code as zip. zip5, postal_code, and zip_code are accepted as aliases; when an entry carries more than one, the first non-empty value in the order zip, zip5, postal_code, zip_code is used.

object
address_1

Street address line 1.

string
address_2

Street address line 2 (apt, suite, etc.).

string
city
string
state
string
zip

ZIP code. Preferred key.

string
zip5

Alias for zip.

string
postal_code

Alias for zip.

string
zip_code

Alias for zip.

string
key
additional properties
any
address_1

Street address line 1.

string
address_2

Street address line 2 (apt, suite, etc.).

string
city
string
state

Two-letter US state code.

string
zip

5- or 9-digit ZIP code.

string
dob

Date of birth — any parseable date format (e.g. YYYY-MM-DD).

string
iag_person_id

A previously-issued tier 01 person ID from this organization (format CLIENTCODE_TIER_HASH, e.g. returned by a prior call to this endpoint, a matched delivery, or a licensed audience delivery). A valid ID can go directly to refresh without repeating identity matching. A foreign, malformed, or derived tier 02–05 ID cannot be used for direct refresh; the row falls back to its other identity signals, if any.

string
key
additional properties
any
field_list

Enrichment attribute names to append on match — every attribute must be a field allowed for this output (see GET /v1/catalog/fields). Mutually exclusive with template_id. If neither is provided, the Standard Enrichment set (fields tagged audience or feature_store) is used. Populated enrichment attributes are returned for every accepted match level.

Array<string>
template_id

Pre-built enrichment bundle ID. standard_iag and standard_enrichment are valid (see templates[] in GET /v1/catalog/fields). Mutually exclusive with field_list. If neither is provided, the Standard Enrichment set is used.

string
match_level

Filter results to specific match levels. I = individual, H = household, D = digital (email/phone only match), S = spatial (nearby-address proximity match), A = address-level. Defaults to all 5 levels (['I', 'H', 'D', 'S', 'A']) if omitted. A prior real match at one of the requested levels or a settled record license can authorize direct Refresh of a tier-01 ID. An identity without a prior real match at a requested level reports null match_level. Include I when requesting direct ID lookup because the engine classifies that path as I.

Array<string>
Allowed values: I H D S A
spatial_mode

Phase 3 spatial trade-area profile. residential is the default; use work for workplace-oriented spatial matching, or auto for dynamic commercial workplace routing.

string
default: residential
Allowed values: residential work auto
create_scratch_segment

When true, materialize the real matched identities from this completed response as a reusable 24-hour matched scratch segment. This reuses the already-paid result and does not run matching or billing again. The response’s scratch_segment is null when no identities matched.

boolean

Matched records.

Media typeapplication/json
object
data_release
One of:

Delivered IAG refresh version. Independent of license status. Null provenance means unknown; a newer refresh-major can prompt a refresh through existing workflows. Active licenses and existing identity IDs support free refresh; normal charges may apply otherwise.

object
major
required
integer
>= 1
minor
required
integer
records

One output record per input record — matched or not. Matched rows carry a resolved iag_person_id, match_level/match_type/match_confidence, and (when requested) enrichment attributes. Unmatched rows carry match_level/match_type/match_confidence: null and a best-effort derived iag_person_id (see iag_person_id below) computed from the row’s own identity signals, or null if none qualified. Use match_count vs record_count to distinguish real matches from derived-only rows — only real matches are billed. Input attributes are echoed back unchanged; resolved enrichment attributes are added alongside them.

Array<object>
object
row_id

Correlates a matched output row back to its position in the submitted records array (1-indexed as a string when the input didn’t supply one).

string
email
string format: email
phone
string
email_sha256

Present when the request included email_sha256, echoed back unchanged.

string
phone_sha256

Present when the request included phone_sha256, echoed back unchanged.

string
full_name

Present when the request included full_name; the original submitted value, echoed back unchanged. Null when the request did not include one.

string | null
first_name
string
middle_name

Echoed back when present on input, or populated from full_name parsing when the request supplied full_name without first_name/last_name.

string
last_name
string
name_suffix

Generational suffix (e.g. JR, SR, III). Echoed back when present on input, or populated from full_name/last_name parsing.

string
address_1
string
address_2
string
city
string
state
string
zip
string
dob
string
emails

Additional raw emails from the request, echoed back unchanged.

Array<string>
emails_sha256

Additional pre-hashed emails from the request, echoed back unchanged.

Array<string>
phones

Additional raw phones from the request, echoed back unchanged.

Array<string>
phones_sha256

Additional pre-hashed phones from the request, echoed back unchanged.

Array<string>
addresses

Additional addresses from the request, echoed back unchanged.

Array<object>
object
key
additional properties
any
iag_person_id

Org-scoped, non-reversible identifier — never a raw internal id. The same real identity receives a consistent tier-01 ID within one organization and a different ID in every other organization. Format: CLIENTCODE_TIER_HASH. TIER is 01 for a real graph match (see match_level/match_type/match_confidence) or 02–05 for a best-effort id deterministically derived from the row’s own identity signals when it did NOT match (name+address, email, name+phone, or name+zip, in that priority order). null when the row is unmatched and no identity signal qualified for derivation. A tier-01 id may be resubmitted as input (see iag_person_id on the request schema above) to re-resolve the same match; derived (tier 02–05) ids cannot be.

string | null
match_level

Granularity of the match. I = individual, H = household, A = address-level, S = spatial (nearby-address proximity match), D = digital (email/phone only match). Null on unmatched rows and on direct Refresh when no real observation exists at a requested level, including audience-only identities. Other direct Refresh rows report the most recent requested real level, not the ID lookup’s label.

string | null
Allowed values: I H A S D
match_type

Matching strategy that produced the result (e.g. graph_name_email_match, vector_name_address_match, spatial_match). Present only on matched records.

string
match_confidence

Confidence score for the match (0–1). Present only on matched records.

number
enrichment

Requested enrichment attributes keyed by column name (e.g. acs_housing_units, usda_median_hh_income_2023). Only present when field_list or template_id was provided and the record matched.

object
key
additional properties
any
resolution_action

Customer-facing resolution outcome for this row, orthogonal to license_action below. resolved = an organic PII match (no id submitted for this row). refreshed = the caller submitted a valid iag_person_id for this row (direct Refresh) and the platform cannot confirm this identity’s enrichment is unchanged since it was last delivered — whether or not this call was also billed (see license_action). current = same as refreshed, but the platform’s data-release registry (see GET /v1/data-release) confirms that the identity remains on the same refresh-major release as its last delivery. The response contains current-mart values for the fields requested in this call; the requested field set may differ from an earlier call. unmatched = no real match, never licensed. identity_unavailable = a previously valid seeded id no longer resolves to deliverable data (deletion, suppression, retirement, or a split graph identity — the underlying reason is deliberately never distinguished here); the record otherwise looks exactly like an ordinary unmatched row. The platform’s full vocabulary also defines invalid, reserved for a reject-the-row policy this API does not yet implement — it is not returned today, but a client should not treat its future appearance as a breaking change.

string
Allowed values: resolved refreshed current unmatched identity_unavailable
license_action

License effect of this row’s resolution, independent of resolution_action — a row can simultaneously be resolution_action: resolved and license_action: renewed. none = no license period was started or renewed this call (already active, unmatched, or identity_unavailable). started = this identity had no prior confirmed license claim and one was started. renewed = a prior confirmed claim existed (even if expired) and the period was renewed.

string
Allowed values: none started renewed
license_expires_at

ISO-8601 timestamp the identity’s current license period expires. Populated when reusing an existing active license (license_action: none) and for a row starting or renewing a period in this same call (license_action: started or renewed — a fixed 12 months from now). Null when no license period applies (e.g. an unmatched or identity_unavailable row).

string | null
key
additional properties
any
record_count

Total number of input records processed.

integer
match_count

Number of authorized records returned for a known identity.

integer
license_approval_required_count

Matched inputs withheld because the integration operation did not authorize a new licence or renewal. These inputs produce no enrichment output or licence charge and require explicit purchase approval. Ordinary manually requested matching returns zero.

integer
billable_identity_count

Number of unique real identities charged for this operation, deduplicated by internal identity rather than row count. Duplicate rows resolving to the same identity are counted once; a resubmitted iag_person_id for an identity with an active license contributes zero (free Refresh). May be less than or equal to match_count, and is the value actually billed — match_count describes matching, not billing.

integer
match_rate

Match_count / record_count.

number
amount_charged

Conservative platform estimate in USD for usage accepted for delivery (e.g. 0.30 means $0.30 estimated). This legacy-named field is not a local credit debit or finalized invoice amount; unmatched records emit no usage.

number
run_id

Unique identifier for this match run. Pass to GET /v1/match/runs/{runId} to retrieve full details or audit this call later. Requires ‘discovery’ scope to read.

string
scratch_segment
One of:
object
segment_id
required
string
name
required
string
record_count
required
integer
>= 1
ephemeral
required
boolean
expires_at
required
string format: date-time
scratch_segment_error

Present only when matching and billing succeeded but the optional, non-billable scratch-segment materialization failed.

object
code
required
string
Allowed value: SCRATCH_SEGMENT_CREATION_FAILED
message
required
string
Example
{
"records": [
{
"match_level": "I",
"resolution_action": "resolved",
"license_action": "none"
}
],
"scratch_segment": {
"ephemeral": true
},
"scratch_segment_error": {
"code": "SCRATCH_SEGMENT_CREATION_FAILED"
}
}

Invalid micro-batch request. DUPLICATE_ROW_ID means two records share an effective row_id, including collisions with automatically assigned positional IDs. INVALID_ROW_ID means a supplied ID is null, non-string, empty, or whitespace-only. Row-ID validation rejects the whole request before idempotency writes, billing reservations, or matching.

Media typeapplication/json
object
error
required

Stable machine-readable error code (e.g. INVALID_STATUS_TRANSITION, BILLING_INSUFFICIENT_BALANCE). Always present.

string
message

Human-readable explanation of the error.

string
code

Alternate machine-readable code — present on some endpoints as an alias for error for backward compatibility.

string
request_id

Opaque support/debug identifier when available.

string
next_step

Public action for correcting the request or retrying later.

string
issues
Array<object>
object
path
required

JSON path to the invalid filter field or value.

string
code
required
string
Allowed values: INVALID_FILTER_SHAPE UNKNOWN_FILTER_FIELD FIELD_NOT_FILTERABLE UNSUPPORTED_FILTER_OPERATOR UNSUPPORTED_TEXT_COMPARISON INVALID_FILTER_VALUE INVALID_ENUM_VALUE AMBIGUOUS_ENUM_VALUE
message
required
string
suggestions
Array<string>
key
additional properties
any
Examples
{
"error": "Bad Request",
"code": "DUPLICATE_ROW_ID",
"message": "Duplicate row_id \"2\" found in request; row_id values must be unique."
}

Missing or invalid Bearer token. Obtain one via POST /v1/auth/token. When a token was supplied but rejected, code distinguishes TOKEN_EXPIRED (the token’s lifetime has passed — request a new one via POST /v1/auth/token and retry) from TOKEN_INVALID (malformed or revoked — re-authenticate).

Media typeapplication/json
object
error
required

Stable machine-readable error code (e.g. INVALID_STATUS_TRANSITION, BILLING_INSUFFICIENT_BALANCE). Always present.

string
message

Human-readable explanation of the error.

string
code

Alternate machine-readable code — present on some endpoints as an alias for error for backward compatibility.

string
request_id

Opaque support/debug identifier when available.

string
next_step

Public action for correcting the request or retrying later.

string
issues
Array<object>
object
path
required

JSON path to the invalid filter field or value.

string
code
required
string
Allowed values: INVALID_FILTER_SHAPE UNKNOWN_FILTER_FIELD FIELD_NOT_FILTERABLE UNSUPPORTED_FILTER_OPERATOR UNSUPPORTED_TEXT_COMPARISON INVALID_FILTER_VALUE INVALID_ENUM_VALUE AMBIGUOUS_ENUM_VALUE
message
required
string
suggestions
Array<string>
key
additional properties
any
Examples
{
"error": "Unauthorized: Missing or invalid Authorization header"
}

The request cannot proceed on billing grounds. BILLING_INSUFFICIENT_BALANCE applies only to prepay accounts and includes required, available, and shortfall in USD. BILLING_POSTPAY_CEILING_EXCEEDED applies to an account ceiling; BILLING_CONSUMER_POSTPAY_CEILING_EXCEEDED applies to an agency child’s routed ceiling. Both ceiling responses include projected accrued and configured ceiling in USD.

Media typeapplication/json
object
error
required

Stable machine-readable error code (e.g. INVALID_STATUS_TRANSITION, BILLING_INSUFFICIENT_BALANCE). Always present.

string
message

Human-readable explanation of the error.

string
code

Alternate machine-readable code — present on some endpoints as an alias for error for backward compatibility.

string
request_id

Opaque support/debug identifier when available.

string
next_step

Public action for correcting the request or retrying later.

string
issues
Array<object>
object
path
required

JSON path to the invalid filter field or value.

string
code
required
string
Allowed values: INVALID_FILTER_SHAPE UNKNOWN_FILTER_FIELD FIELD_NOT_FILTERABLE UNSUPPORTED_FILTER_OPERATOR UNSUPPORTED_TEXT_COMPARISON INVALID_FILTER_VALUE INVALID_ENUM_VALUE AMBIGUOUS_ENUM_VALUE
message
required
string
suggestions
Array<string>
code
string
Allowed values: BILLING_INSUFFICIENT_BALANCE BILLING_POSTPAY_CEILING_EXCEEDED BILLING_CONSUMER_POSTPAY_CEILING_EXCEEDED
shortfall
number
required
number
available
number
accrued
number
ceiling
number
Examples
{
"error": "Insufficient balance",
"code": "BILLING_INSUFFICIENT_BALANCE",
"message": "Insufficient effective balance",
"required": 1,
"available": 0.75,
"shortfall": 0.25
}

Token is valid but lacks the required scope for this endpoint. Check the endpoint description for the required scope (discovery, purchase, or account).

Media typeapplication/json
object
error
required

Stable machine-readable error code (e.g. INVALID_STATUS_TRANSITION, BILLING_INSUFFICIENT_BALANCE). Always present.

string
message

Human-readable explanation of the error.

string
code

Alternate machine-readable code — present on some endpoints as an alias for error for backward compatibility.

string
request_id

Opaque support/debug identifier when available.

string
next_step

Public action for correcting the request or retrying later.

string
issues
Array<object>
object
path
required

JSON path to the invalid filter field or value.

string
code
required
string
Allowed values: INVALID_FILTER_SHAPE UNKNOWN_FILTER_FIELD FIELD_NOT_FILTERABLE UNSUPPORTED_FILTER_OPERATOR UNSUPPORTED_TEXT_COMPARISON INVALID_FILTER_VALUE INVALID_ENUM_VALUE AMBIGUOUS_ENUM_VALUE
message
required
string
suggestions
Array<string>
key
additional properties
any
Examples
Examplemissing_scope
{
"error": "SCOPE_REQUIRED",
"message": "This endpoint requires the creator scope."
}

BILLING_NOT_READY — the billing account/route isn’t active. IDEMPOTENCY_KEY_CONFLICT — the Idempotency-Key header was already used with a different request body. IDEMPOTENCY_REQUEST_IN_PROGRESS — another request with this key is in flight; retry after the seconds in Retry-After. LICENSE_ACQUISITION_BUSY — another attempt of this same billing operation is still settling; independent operations are unaffected.

Media typeapplication/json
object
error
required

Stable machine-readable error code (e.g. INVALID_STATUS_TRANSITION, BILLING_INSUFFICIENT_BALANCE). Always present.

string
message

Human-readable explanation of the error.

string
code

Alternate machine-readable code — present on some endpoints as an alias for error for backward compatibility.

string
request_id

Opaque support/debug identifier when available.

string
next_step

Public action for correcting the request or retrying later.

string
issues
Array<object>
object
path
required

JSON path to the invalid filter field or value.

string
code
required
string
Allowed values: INVALID_FILTER_SHAPE UNKNOWN_FILTER_FIELD FIELD_NOT_FILTERABLE UNSUPPORTED_FILTER_OPERATOR UNSUPPORTED_TEXT_COMPARISON INVALID_FILTER_VALUE INVALID_ENUM_VALUE AMBIGUOUS_ENUM_VALUE
message
required
string
suggestions
Array<string>
key
additional properties
any
Example
{
"issues": [
{
"code": "INVALID_FILTER_SHAPE"
}
]
}

A required billing provider partnership is temporarily unavailable.

Media typeapplication/json
object
error
required

Stable machine-readable error code (e.g. INVALID_STATUS_TRANSITION, BILLING_INSUFFICIENT_BALANCE). Always present.

string
message

Human-readable explanation of the error.

string
code

Alternate machine-readable code — present on some endpoints as an alias for error for backward compatibility.

string
request_id

Opaque support/debug identifier when available.

string
next_step

Public action for correcting the request or retrying later.

string
issues
Array<object>
object
path
required

JSON path to the invalid filter field or value.

string
code
required
string
Allowed values: INVALID_FILTER_SHAPE UNKNOWN_FILTER_FIELD FIELD_NOT_FILTERABLE UNSUPPORTED_FILTER_OPERATOR UNSUPPORTED_TEXT_COMPARISON INVALID_FILTER_VALUE INVALID_ENUM_VALUE AMBIGUOUS_ENUM_VALUE
message
required
string
suggestions
Array<string>
key
additional properties
any
Example
{
"issues": [
{
"code": "INVALID_FILTER_SHAPE"
}
]
}