Matching rules and previews
Create and maintain custom matching rules, and preview their matches.
The APIs on this page require alpha access for your organization. App availability and API access are separate. Check access and permissions.
Matching rules
GET /v1/deduplication/rules
Lists the matching rules used to find duplicates. A standard rule also shows whether Attio checks new and changed records with it, its number for ignoring very common values, and how many values it ignores.
Requires dedupe:read. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: list_dedupe_rules. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
object_type |
query | No | "companies", "people" |
|
enabled |
query | No | boolean | Use true or false in the query string. |
sort |
query | No | "name", "-name", "id", "-id" |
|
limit |
query | No | integer | |
cursor |
query | No | string |
Response
| HTTP status | Result |
|---|---|
200 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
array of object | Yes | |
data[].object |
"deduplication_rule" |
Yes | |
data[].id |
string | Yes | |
data[].name |
string | Yes | |
data[].object_type |
"companies", "people" |
Yes | |
data[].origin |
"standard", "custom" |
Yes | |
data[].enabled |
boolean | Yes | |
data[].automatic_check |
boolean | No | |
data[].ignore_common_values |
integer or null | No | |
data[].ignored_values |
object | No | |
data[].ignored_values.mode |
"standard", "custom" |
Yes | |
data[].ignored_values.count |
integer | Yes | |
data[].checks |
array of object | Yes | |
data[].checks[].conditions |
array of object | Yes | |
data[].checks[].conditions[].field_id |
string | Yes | |
data[].checks[].conditions[].match |
"exact", "similar" |
Yes | |
pagination |
object | Yes | |
pagination.next_cursor |
string or null | Yes |
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter, invalid_request, invalid_cursor. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
Create matching rule
POST /v1/deduplication/rules
Creates a custom matching rule for an object. Send the configuration's version as expected_version. Each condition names an Attio attribute by its slug and how its values are compared; a similar comparison takes a similarity. A value shared by many records can be ignored, at a number you choose or your organization's default, on a rule whose conditions all compare exact values. A short sets_label is what the rule shows as on Sets. The id is permanent and can't be used again for this object, even after the rule is archived. Scans started after this use the rule. The answer is the rule's id and the configuration's new version.
Requires dedupe:config:write. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: create_dedupe_rule. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
expected_version |
JSON body | Yes | string | |
object_type |
JSON body | Yes | "companies", "people" |
|
id |
JSON body | Yes | string | |
name |
JSON body | Yes | string | |
description |
JSON body | No | string or null | |
conditions |
JSON body | Yes | array of object | |
conditions[].field_id |
Within the JSON value | Within this object | string | |
conditions[].match |
Within the JSON value | Within this object | "exact", "exact_or_both_blank", "similar", "normalized_domain", "normalized_email", "normalized_email_domain", "normalized_phone", "normalized_linkedin", "normalized_twitter", "normalized_facebook", "same_linked_record" |
|
conditions[].similarity |
Within the JSON value | No | "low", "medium", "high", "very_high", "extreme" |
|
ignore_common_values |
JSON body | No | "organization_default" or integer |
|
sets_label |
JSON body | No | string or null | |
request_key |
Header: Idempotency-Key |
Yes | string |
Response
| HTTP status | Result |
|---|---|
201 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
object | Yes | |
data.object |
"deduplication_rule_change" |
Yes | |
data.rule_id |
string | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.version |
string | Yes |
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter, invalid_request. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
Change matching rule
PATCH /v1/deduplication/rules/{rule_id}
Changes a custom matching rule: its name, description, Sets label, conditions and how it treats very common values. Name the rule's object as object_type, send the configuration's version as expected_version, and send the whole rule; a Sets label you leave out stays as it is. Its object and id never change. A standard rule is changed with the settings change instead. Scans started after this use the change. What this replaces is not kept, so it can't be undone.
Requires dedupe:config:write. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: update_dedupe_rule. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
rule_id |
path | Yes | string | |
expected_version |
JSON body | Yes | string | |
object_type |
JSON body | Yes | "companies", "people" |
|
name |
JSON body | Yes | string | |
description |
JSON body | No | string or null | |
conditions |
JSON body | Yes | array of object | |
conditions[].field_id |
Within the JSON value | Within this object | string | |
conditions[].match |
Within the JSON value | Within this object | "exact", "exact_or_both_blank", "similar", "normalized_domain", "normalized_email", "normalized_email_domain", "normalized_phone", "normalized_linkedin", "normalized_twitter", "normalized_facebook", "same_linked_record" |
|
conditions[].similarity |
Within the JSON value | No | "low", "medium", "high", "very_high", "extreme" |
|
ignore_common_values |
JSON body | No | "organization_default" or integer |
|
sets_label |
JSON body | No | string or null | |
request_key |
Header: Idempotency-Key |
Yes | string |
Response
| HTTP status | Result |
|---|---|
200 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
object | Yes | |
data.object |
"deduplication_rule_change" |
Yes | |
data.rule_id |
string | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.version |
string | Yes |
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter, invalid_request. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
Archive matching rule
POST /v1/deduplication/rules/{rule_id}/archive
Archives a custom matching rule, so scans started after this no longer use it. Name the rule's object as object_type, and send the configuration's version as expected_version. Its id stays reserved, and sets it already found keep it. The last rule an object has can't be archived. An archived rule can be restored.
Requires dedupe:config:write. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: archive_dedupe_rule. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
rule_id |
path | Yes | string | |
expected_version |
JSON body | Yes | string | |
object_type |
JSON body | Yes | "companies", "people" |
|
request_key |
Header: Idempotency-Key |
Yes | string |
Response
| HTTP status | Result |
|---|---|
200 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
object | Yes | |
data.object |
"deduplication_rule_change" |
Yes | |
data.rule_id |
string | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.version |
string | Yes |
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter, invalid_request. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
Restore matching rule
POST /v1/deduplication/rules/{rule_id}/restore
Restores an archived custom matching rule, with its id and conditions, so scans started after this use it again. Name the rule's object as object_type, and send the configuration's version as expected_version. It is refused when your plan's custom rules are all in use, or when scans couldn't run with it added.
Requires dedupe:config:write. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: restore_dedupe_rule. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
rule_id |
path | Yes | string | |
expected_version |
JSON body | Yes | string | |
object_type |
JSON body | Yes | "companies", "people" |
|
request_key |
Header: Idempotency-Key |
Yes | string |
Response
| HTTP status | Result |
|---|---|
200 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
object | Yes | |
data.object |
"deduplication_rule_change" |
Yes | |
data.rule_id |
string | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.version |
string | Yes |
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter, invalid_request. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
Preview matching rule
POST /v1/deduplication/rule-previews
Checks what a matching rule would find before you create it: how many pairs of the object's records it matches, how many new duplicate sets it adds beyond what your other rules find, the size of the largest set, and how many very common values it ignores. A preview changes no setting and no record. It uses the latest read of the object's records when that read has every attribute the rule names, and reads the records first when it doesn't; send fresh: true to read them again. Read the preview with its id for the answer.
Requires dedupe:scan. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: preview_dedupe_rule. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
object_type |
JSON body | Yes | "companies", "people" |
|
conditions |
JSON body | Yes | array of object | |
conditions[].field_id |
Within the JSON value | Within this object | string | |
conditions[].match |
Within the JSON value | Within this object | "exact", "exact_or_both_blank", "similar", "normalized_domain", "normalized_email", "normalized_email_domain", "normalized_phone", "normalized_linkedin", "normalized_twitter", "normalized_facebook", "same_linked_record" |
|
conditions[].similarity |
Within the JSON value | No | "low", "medium", "high", "very_high", "extreme" |
|
ignore_common_values |
JSON body | No | "organization_default" or integer |
|
fresh |
JSON body | No | boolean | |
request_key |
Header: Idempotency-Key |
Yes | string |
Response
| HTTP status | Result |
|---|---|
202 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
object | Yes | |
data.object |
"deduplication_rule_preview" |
Yes | |
data.id |
string (uuid) | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.status |
"queued", "running", "complete", "refused" |
Yes | |
data.matches_found |
integer or null | Yes | |
data.sets_found |
integer or null | Yes | |
data.largest_set |
integer or null | Yes | |
data.common_values_ignored |
integer or null | Yes |
Accepted work can continue after the request returns. Follow its returned status or operation until it finishes; accepting work does not mean every item succeeded. See operation status.
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter, invalid_request. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
Get matching rule preview
GET /v1/deduplication/rule-previews/{preview_id}
Gets a matching rule preview: queued, running, complete, or refused when it couldn't finish. A complete preview gives how many pairs of records the rule matches, how many new duplicate sets it adds, the size of the largest set, and how many very common values it ignored. A count the preview couldn't measure for this rule is null.
Requires dedupe:read. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: get_dedupe_rule_preview. Its argument names match the fields below; an HTTP header is passed using its argument name in MCP.
Parameters
| Name | Send in | Required | Type or allowed values | Notes |
|---|---|---|---|---|
preview_id |
path | Yes | string |
Response
| HTTP status | Result |
|---|---|
200 |
The requested result. Asynchronous work returns an operation to poll. |
Required fields are required within their containing object. Notes identify fields that apply only to a particular response alternative.
| Response field | Type | Required in object | Notes |
|---|---|---|---|
data |
object | Yes | |
data.object |
"deduplication_rule_preview" |
Yes | |
data.id |
string (uuid) | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.status |
"queued", "running", "complete", "refused" |
Yes | |
data.matches_found |
integer or null | Yes | |
data.sets_found |
integer or null | Yes | |
data.largest_set |
integer or null | Yes | |
data.common_values_ignored |
integer or null | Yes |
Errors
| HTTP status | Meaning |
|---|---|
400 |
One of: credential_in_url, invalid_parameter, unknown_parameter. |
401 |
One of: missing_credential, invalid_credential, credential_expired, credential_revoked. |
402 |
One of: payment_overdue. |
403 |
The current permissions, plan or policy do not allow this request. |
404 |
One of: not_found. |
409 |
The request conflicts with current resource state, authorization or an earlier request. Read the error code and current resource before retrying. |
410 |
The requested resource or retained recovery data has expired. |
412 |
One of: version_conflict. |
413 |
One of: request_too_large. |
422 |
A field, filter or selection cannot be used for this request. |
423 |
One of: organization_reopening. |
428 |
One of: customer_agreement_required. |
429 |
One of: rate_limited. |
503 |
One of: service_unavailable. |
See errors and recovery and safe retries before repeating a write.
The public OpenAPI document lists generally available API families. Alpha operations may not appear in that document; their request and response fields are listed on this page. Use the API Playground to inspect a real response with your connection's access.