Skip to content

Start an async file-based identity resolution job

POST
/v1/match/file
curl --request POST \
--url https://dev-api.infiniteaudience.ai/v1/match/file \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'

Creates a matched segment by uploading a customer list for identity resolution. Equivalent to POST /v1/segments with subtype: matched.

Upload csv, newline-delimited json/jsonl, or Avro records to the Infinite Audience identity graph and receive an enriched file back. Each format may be raw or gzip. Useful for CRM onboarding, suppression list resolution, contact data hygiene, and data co-op workflows.

File structure: there is no fixed column schema — column names are inferred via AI (POST /v1/match/{segment_id}/analyze reports the mapping, a confidence score per column, and any warnings). For the best match quality, name your columns (or use names that closely resemble) the standard identity attributes: email, phone, full_name (or separately, first_name, middle_name, last_name, name_suffix), address_1, address_2, city, state, zip, dob, iag_person_id (a re-upload of an id previously returned by this platform — format CLIENTCODE_TIER_HASH — resolved server-side before matching). Only map a column to full_name when the file has a single combined-name column — if separate first/last name columns exist, map those instead. A column that can’t be confidently mapped is excluded from identity resolution — if a critical attribute (email, phone, last_name) ends up unmapped, match accuracy drops or the segment may fail to resolve at all.

Pre-hashed identity columns: for clients whose own systems never expose raw email/phone values, map a column to email_sha256 or phone_sha256 (lowercase-hex SHA-256 digests) instead of the raw email/phone target — the platform passes these through without re-hashing. Do not map an already-hashed column to the raw email/phone target (it would be hashed a second time and never match), and do not map a raw email/phone column to email_sha256/phone_sha256 just because of its name — the mapper trusts sample-value shape over column name. avro/json/ jsonl uploads (which support array columns) may also supply emails, phones, addresses, emails_sha256, and phones_sha256 as extra match permutations beyond the primary identity fields. If your upload includes row_id, every value must be unique across all shards. When it is absent, the platform assigns stable row_0, row_1, … values. Duplicate ids or collisions with generated values fail the match before its result can be delivered.

Billing: Upload, analysis, and matching completion emit no billable usage. The first successful POST /v1/audiences/{id}/deliveries or POST /v1/match/{id}/deliveries involving the current run emits its one aggregate platform_match usage set together with audience, destination, and enrichment usage. Retries, duplicates, and later deliveries do not emit that file-match usage again.

Workflow (hitl unset/false — default, upload resolves automatically):

  1. POST /v1/match/file — receive a segment_id and a 30-minute presigned upload_url. Pass file_format to specify your file type (default csv). When create_audience: true (default), also receives an audience_id.

  2. Upload your filePUT to upload_url with the underlying format’s Content-Type. For gzip, send raw gzip bytes and do not set Content-Encoding. No Authorization header is needed.

  3. (Optional) POST /v1/match/{segment_id}/analyze — preview column mapping. Note that by the time this can return real data, the upload has already triggered automatic resolution — this step does not pause anything.

  4. Automatic column analysis — the platform always runs column analysis as part of the match workflow. If no usable identity attributes can be resolved, the segment transitions to failed and error_message describes the issue.

    Standard column names for best results: email, phone, full_name, first_name, middle_name, last_name, name_suffix, address_1, address_2, city, state, zip, dob, iag_person_id. Pre-hashed email_sha256/phone_sha256 are also supported — see below.

  5. Poll GET /v1/match/{match_id} until matching_status: completed (or use a segment.ready webhook).

  6. POST /v1/match/{match_id}/deliveries — export the already resolved result. Poll GET /v1/match/{match_id}/deliveries for status; it takes the match id directly and needs no audience id — if you only want matching/enrichment and don’t need audience-building concepts, this and step 1’s segment_id/match_id are the only ids you need to track end to end. (The audience-scoped POST /v1/audiences/{audience_id}/deliveries also works and is what this endpoint forwards to internally, but requires the audience id from step 1.)

Workflow (hitl: true — requires an explicit confirm before resolution runs):

  1. POST /v1/match/file {"hitl": true} — receive a segment_id and upload_url.

  2. Upload your file — lands at a staging location, NOT the path that triggers automatic resolution.

  3. POST /v1/match/{segment_id}/analyze — reads the staged file; safe to call any time after upload, since nothing has started yet.

  4. POST /v1/segments/{segment_id}/mappings to confirm (moves the file into place and starts resolution) or POST /v1/segments/{segment_id}/mappings/cancel to abort (nothing ever ran).

  5. Poll GET /v1/match/{match_id} until matching_status: completed, then POST /v1/match/{match_id}/deliveries — same match-namespaced export and polling as the default flow above (see step 6 there).

Sharded uploads: set shard_count > 1 for same-format files. The response returns index-ordered upload_urls; upload every declared shard. Every CSV shard must include the same header row, and all shards must share schema and compression. Analysis samples shard 0; a later mismatch fails the job explicitly.

Retries: pass an Idempotency-Key header to make a retried create call safe to repeat: the same key with an identical body returns the original segment/audience (and freshly re-signed upload URL(s), if the originals already expired) instead of creating a duplicate. Unlike POST /v1/match, this endpoint isn’t billed at creation, so a duplicate without this header is an orphan Library entry, not a double charge — recommended for any integration that may retry. Requires ‘purchase’ scope.

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

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

All attributes are optional. You may omit the request body entirely or send {} — both are equivalent and will create a CSV match job with an auto-generated name.

Media typeapplication/json
object
name

Optional label for this match job. Defaults to "File Match — {ISO date}" if omitted.

string
>= 1 characters <= 120 characters
file_format

Input file format. csv (default) treats every column as a single scalar value — multi-value/array attributes (email, phone, address_1, etc.) are not supported in csv. avro supports native array columns — use it when your file already encodes multi-value attributes as proper arrays. json and jsonl also support native array columns and are parsed identically — newline-delimited JSON, one record object per line (not a single top-level JSON array).

string
default: csv
Allowed values: csv avro json jsonl
compression

Gzip means the complete underlying file is a gzip stream. Upload raw gzip bytes with the underlying format’s Content-Type and no Content-Encoding. gzip is not supported with file_format=avro (avro is already internally compressed) — rejected with 400 UNSUPPORTED_INPUT_COMPRESSION.

string
default: none
Allowed values: none gzip
create_audience

When true (default), automatically creates a thin audience wrapper referencing the new matched segment. The audience_id is returned in the response and can be used for delivery immediately once the segment is active.

boolean
default: true
campaign_id

Optional. If provided and create_audience is true, the created audience is automatically linked to this campaign on creation. Omit if you are not using campaign workspaces.

string
webhook_url

Optional HTTPS URL to receive segment.ready or segment.failed events when the identity matching job completes. Overrides the org-level webhook URL for this request only.

string format: uri
hitl

Requires an explicit confirmation step before identity resolution runs — see the two workflow sequences above. Defaults to false (upload alone resolves automatically, the existing behavior).

boolean
match_level

Filter which match levels are accepted for this job. 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. This only affects which rows match and at what level — field selection (field_list/template_id) happens separately, per delivery (POST /v1/audiences/{id}/deliveries or POST /v1/match/{id}/deliveries), where individual-level attributes are nulled out per row for rows that didn’t match at a level that qualifies for individual-level data.

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

Set > 1 for same-format shards. Every CSV shard must include the same header row, and all shards must share schema and compression. Returns upload_urls instead of upload_url.

integer
default: 1 >= 1 <= 50
Examples

Minimal request — omit the body entirely or send `{}` (CSV, auto-named)

{}

File match job created — upload your file to the returned upload_url to proceed.

Media typeapplication/json
object
match_id
required

Backward-compatible alias of segment_id.

string
segment_id
required

Unique ID for this matched segment. Poll GET /v1/segments/{segment_id} until status is active.

string
audience_id

ID of the auto-created audience wrapper. Present when create_audience is true. Use for deliveries once the segment is active.

string
name
required

Label assigned to the job (supplied or auto-generated).

string
status
required

Always pending on creation — the segment is awaiting file upload. Poll GET /v1/segments/{segment_id} — it will show status: pending until identity resolution completes, then status: active.

string
Allowed values: pending
upload_url

30-minute presigned GCS PUT URL. Upload your file to this URL with the Content-Type matching your file_format. No Authorization header required. Present when shard_count is 1 (the default) — absent when sharded, use upload_urls instead.

string
upload_urls

30-minute presigned GCS PUT URLs, one per shard, index-ordered. Present only when shard_count > 1 was requested — upload_url is absent. Every CSV shard must include the same header row.

Array<string>
upload_expires_at
required

ISO timestamp when upload_url/upload_urls expires (30 minutes from creation).

string format: date-time
expires_at
required

ISO date — 90-day hard expiry for this segment. After this date the segment and associated files are permanently deleted.

string
file_format
required

Confirmed file format for this job.

string
Allowed values: csv avro json jsonl
compression
required

Confirmed input artifact compression.

string
Allowed values: none gzip
Examples
Examplecsv_job

CSV job with audience (default)

{
"match_id": "seg_csv123",
"segment_id": "seg_csv123",
"audience_id": "aud_csv123",
"name": "Q2 2026 CRM Refresh",
"status": "pending",
"upload_url": "https://storage.googleapis.com/cf-uploads/enrichment-uploads/org_x/seg_csv123/input.csv?X-Goog-Signature=...",
"upload_expires_at": "2026-06-22T19:30:00.000Z",
"expires_at": "2026-09-27",
"file_format": "csv",
"compression": "none"
}

Invalid request — malformed body, missing required attribute, or failed validation. See error and message for details.

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
key
additional properties
any
Examples
Examplevalidation_error
{
"error": "Bad Request",
"code": "MISSING_SEGMENTS",
"message": "segment_ids is required for filter audiences."
}

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
key
additional properties
any
Examples
{
"error": "Unauthorized: Missing or invalid Authorization header"
}

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
key
additional properties
any
Examples
Examplemissing_scope
{
"error": "SCOPE_REQUIRED",
"message": "This endpoint requires the purchase scope."
}

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.

Media typeapplication/json
object
error
required
string
code
required
string
Allowed values: IDEMPOTENCY_KEY_CONFLICT IDEMPOTENCY_REQUEST_IN_PROGRESS
message
required
string
Example
{
"code": "IDEMPOTENCY_KEY_CONFLICT"
}