Matches and review
Check a record for duplicates, inspect duplicate sets, and update review decisions.
The APIs on this page require alpha access for your organization. App availability and API access are separate. Check access and permissions.
Check for duplicates
POST /v1/deduplication/match-queries
Checks whether one existing record, or the details of a record you have not created yet, has duplicates in your CRM. It starts no scan and changes no records. A complete check that returns none means no duplicates were found among the records checked at that time; a check that could not finish returns uncertain or unavailable instead, which does not mean there are no duplicates.
Requires dedupe:read. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: check_for_duplicates. 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 |
|---|---|---|---|---|
connection_id |
JSON body | Yes | string | |
object_type |
JSON body | Yes | "companies", "people" |
|
subject |
JSON body | Yes | object | |
subject.type |
Within the JSON value | Within this object | "record" |
When subject.type is "record". |
subject.record_id |
Within the JSON value | Within this object | string | When subject.type is "record". |
subject.values |
Within the JSON value | No | object | When subject.type is "record". |
subject.type |
Within the JSON value | Within this object | "values" |
When subject.type is "values". |
subject.values |
Within the JSON value | Within this object | object | When subject.type is "values". |
limit |
JSON body | No | integer |
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_match_result" |
Yes | |
data.outcome |
"match", "none", "uncertain", "unavailable" |
Yes | |
data.reason_code |
"no_completed_scan", "values_expired", "probe_unavailable", "record_not_scanned", "stored_evidence_only", "configuration_changed", "scan_partial", "rules_incomplete", "corpus_not_current" or null |
Yes | |
data.candidates |
array of object | Yes | |
data.candidates[].record_id |
string | Yes | |
data.candidates[].set_id |
string or null | Yes | |
data.candidates[].rule_ids |
array of string | Yes | |
data.candidates[].match_kinds |
array of "exact", "similar" |
Yes | |
data.truncated |
boolean | Yes | |
data.coverage |
object | Yes | |
data.coverage.source |
"current_values", "stored_evidence" |
Yes | |
data.coverage.complete |
boolean | Yes | |
data.coverage.run_id |
string or null | Yes | |
data.coverage.as_of |
string (date-time) or null | Yes | |
data.coverage.rules_evaluated |
array of string | Yes | |
data.coverage.rules_unavailable |
array of object | Yes | |
data.coverage.rules_unavailable[].rule_id |
string | Yes | |
data.coverage.rules_unavailable[].reason |
"related_unavailable", "redirects_unchecked", "incomplete", "not_supplied" |
Yes | |
references |
array of object | Yes | |
references[].provider |
"attio" |
Yes | |
references[].workspace_id |
string or null | Yes | |
references[].object_id |
string or null | Yes | |
references[].object_slug |
string or null | Yes | |
references[].records |
array of object | Yes | |
references[].records[].record_id |
string | Yes | |
references[].records[].web_url |
string (uri) or null | Yes | |
references[].records[].attributes |
array of object | Yes | |
references[].records[].attributes[].attribute_id |
string or null | Yes | |
references[].records[].attributes[].attribute_slug |
string or null | Yes | |
references[].records[].via |
array of object | Yes | |
references[].records[].via[].source_object_id |
string or null | Yes | |
references[].records[].via[].source_object_slug |
string or null | Yes | |
references[].records[].via[].source_record_id |
string | Yes | |
references[].records[].via[].attribute_id |
string or null | Yes | |
references[].records[].via[].attribute_slug |
string or null | Yes | |
references[].records[].via[].target_object_id |
string or null | Yes | |
references[].records[].via[].target_object_slug |
string or null | Yes | |
references[].records[].via[].target_record_id |
string | Yes | |
references[].lookup_hint |
object | Yes | |
references[].lookup_hint.resource |
"records" |
Yes | |
references[].lookup_hint.object |
string | Yes | |
references[].lookup_hint.record_ids |
array of string | 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.
List sets
GET /v1/deduplication/sets
Lists current duplicate sets, one page at a time. Filter by state, review flags, record, the scan that found them or a structured filter, and add AI results with include. Read the capabilities for the fields and operators you can filter on; a filter this key cannot use is refused, never ignored.
Requires dedupe:read. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: list_duplicate_sets. 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" |
|
run_id |
query | No | string | |
state |
query | No | array of "open", "ready_to_merge", "needs_review" |
Repeat this query parameter for multiple values. |
ready_to_merge |
query | No | boolean | Use true or false in the query string. |
needs_review |
query | No | boolean | Use true or false in the query string. |
record_id |
query | No | string | |
filter |
query | No | object | Send URL-encoded JSON in REST; pass the JSON value directly in MCP. |
filter.field |
Within the JSON value | Within this object | "matched_rule_count" |
Alternative 1. Alternative 1. |
filter.eq |
Within the JSON value | Within this object | integer or null | Alternative 1. Alternative 1. Alternative 1. |
filter.ne |
Within the JSON value | Within this object | integer | Alternative 1. Alternative 1. Alternative 2. |
filter.lt |
Within the JSON value | Within this object | integer | Alternative 1. Alternative 1. Alternative 3. |
filter.lte |
Within the JSON value | Within this object | integer | Alternative 1. Alternative 1. Alternative 4. |
filter.gt |
Within the JSON value | Within this object | integer | Alternative 1. Alternative 1. Alternative 5. |
filter.gte |
Within the JSON value | Within this object | integer | Alternative 1. Alternative 1. Alternative 6. |
filter.empty |
Within the JSON value | Within this object | true |
Alternative 1. Alternative 1. Alternative 2. Alternative 7. |
filter.not_empty |
Within the JSON value | Within this object | true |
Alternative 1. Alternative 1. Alternative 2. Alternative 8. |
filter.field |
Within the JSON value | Within this object | "ai_score" |
Alternative 1. Alternative 2. |
filter.eq |
Within the JSON value | Within this object | number or null | Alternative 1. Alternative 2. Alternative 1. |
filter.ne |
Within the JSON value | Within this object | number | Alternative 1. Alternative 2. Alternative 2. |
filter.lt |
Within the JSON value | Within this object | number | Alternative 1. Alternative 2. Alternative 3. |
filter.lte |
Within the JSON value | Within this object | number | Alternative 1. Alternative 2. Alternative 4. |
filter.gt |
Within the JSON value | Within this object | number | Alternative 1. Alternative 2. Alternative 5. |
filter.gte |
Within the JSON value | Within this object | number | Alternative 1. Alternative 2. Alternative 6. |
filter.field |
Within the JSON value | Within this object | "rule_id" |
Alternative 1. Alternative 3. |
filter.in |
Within the JSON value | Within this object | array of string | Alternative 1. Alternative 3. Alternative 1. |
filter.not_in |
Within the JSON value | Within this object | array of string | Alternative 1. Alternative 3. Alternative 2. |
filter.and |
Within the JSON value | Within this object | array of object | Alternative 2. |
filter.and[].field |
Within the JSON value | Within this object | "matched_rule_count" |
Alternative 2. Alternative 1. |
filter.and[].eq |
Within the JSON value | Within this object | integer or null | Alternative 2. Alternative 1. Alternative 1. |
filter.and[].ne |
Within the JSON value | Within this object | integer | Alternative 2. Alternative 1. Alternative 2. |
filter.and[].lt |
Within the JSON value | Within this object | integer | Alternative 2. Alternative 1. Alternative 3. |
filter.and[].lte |
Within the JSON value | Within this object | integer | Alternative 2. Alternative 1. Alternative 4. |
filter.and[].gt |
Within the JSON value | Within this object | integer | Alternative 2. Alternative 1. Alternative 5. |
filter.and[].gte |
Within the JSON value | Within this object | integer | Alternative 2. Alternative 1. Alternative 6. |
filter.and[].empty |
Within the JSON value | Within this object | true |
Alternative 2. Alternative 1. Alternative 2. Alternative 7. |
filter.and[].not_empty |
Within the JSON value | Within this object | true |
Alternative 2. Alternative 1. Alternative 2. Alternative 8. |
filter.and[].field |
Within the JSON value | Within this object | "ai_score" |
Alternative 2. Alternative 2. |
filter.and[].eq |
Within the JSON value | Within this object | number or null | Alternative 2. Alternative 2. Alternative 1. |
filter.and[].ne |
Within the JSON value | Within this object | number | Alternative 2. Alternative 2. Alternative 2. |
filter.and[].lt |
Within the JSON value | Within this object | number | Alternative 2. Alternative 2. Alternative 3. |
filter.and[].lte |
Within the JSON value | Within this object | number | Alternative 2. Alternative 2. Alternative 4. |
filter.and[].gt |
Within the JSON value | Within this object | number | Alternative 2. Alternative 2. Alternative 5. |
filter.and[].gte |
Within the JSON value | Within this object | number | Alternative 2. Alternative 2. Alternative 6. |
filter.and[].field |
Within the JSON value | Within this object | "rule_id" |
Alternative 2. Alternative 3. |
filter.and[].in |
Within the JSON value | Within this object | array of string | Alternative 2. Alternative 3. Alternative 1. |
filter.and[].not_in |
Within the JSON value | Within this object | array of string | Alternative 2. Alternative 3. Alternative 2. |
filter.or |
Within the JSON value | Within this object | array of object | Alternative 3. |
filter.or[].field |
Within the JSON value | Within this object | "matched_rule_count" |
Alternative 3. Alternative 1. |
filter.or[].eq |
Within the JSON value | Within this object | integer or null | Alternative 3. Alternative 1. Alternative 1. |
filter.or[].ne |
Within the JSON value | Within this object | integer | Alternative 3. Alternative 1. Alternative 2. |
filter.or[].lt |
Within the JSON value | Within this object | integer | Alternative 3. Alternative 1. Alternative 3. |
filter.or[].lte |
Within the JSON value | Within this object | integer | Alternative 3. Alternative 1. Alternative 4. |
filter.or[].gt |
Within the JSON value | Within this object | integer | Alternative 3. Alternative 1. Alternative 5. |
filter.or[].gte |
Within the JSON value | Within this object | integer | Alternative 3. Alternative 1. Alternative 6. |
filter.or[].empty |
Within the JSON value | Within this object | true |
Alternative 3. Alternative 1. Alternative 2. Alternative 7. |
filter.or[].not_empty |
Within the JSON value | Within this object | true |
Alternative 3. Alternative 1. Alternative 2. Alternative 8. |
filter.or[].field |
Within the JSON value | Within this object | "ai_score" |
Alternative 3. Alternative 2. |
filter.or[].eq |
Within the JSON value | Within this object | number or null | Alternative 3. Alternative 2. Alternative 1. |
filter.or[].ne |
Within the JSON value | Within this object | number | Alternative 3. Alternative 2. Alternative 2. |
filter.or[].lt |
Within the JSON value | Within this object | number | Alternative 3. Alternative 2. Alternative 3. |
filter.or[].lte |
Within the JSON value | Within this object | number | Alternative 3. Alternative 2. Alternative 4. |
filter.or[].gt |
Within the JSON value | Within this object | number | Alternative 3. Alternative 2. Alternative 5. |
filter.or[].gte |
Within the JSON value | Within this object | number | Alternative 3. Alternative 2. Alternative 6. |
filter.or[].field |
Within the JSON value | Within this object | "rule_id" |
Alternative 3. Alternative 3. |
filter.or[].in |
Within the JSON value | Within this object | array of string | Alternative 3. Alternative 3. Alternative 1. |
filter.or[].not_in |
Within the JSON value | Within this object | array of string | Alternative 3. Alternative 3. Alternative 2. |
include |
query | No | "ai_score" |
|
sort |
query | No | "-updated_at", "updated_at", "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_set" |
Yes | |
data[].id |
string | Yes | |
data[].version |
string | Yes | |
data[].object_type |
"companies", "people" |
Yes | |
data[].records |
array of object | Yes | |
data[].records[].id |
string | Yes | |
data[].records[].ai_score |
integer or null | No | |
data[].keeper_record_id |
string or null | Yes | |
data[].matched_rule_ids |
array of string | Yes | |
data[].rules_incomplete |
boolean | Yes | |
data[].first_found_at |
string (date-time) | Yes | |
data[].updated_at |
string (date-time) | Yes | |
data[].first_found_run_id |
string or null | Yes | |
data[].review |
object | Yes | |
data[].review.version |
string | Yes | |
data[].review.ready_to_merge |
boolean | Yes | |
data[].review.needs_review |
boolean | Yes | |
data[].review.bucket |
"open", "ready_to_merge", "needs_review" |
Yes | |
data[].review.attention_reasons |
array of "large_group", "keeper_undecided" |
Yes | |
pagination |
object | Yes | |
pagination.next_cursor |
string or null | Yes | |
references |
array of object | Yes | |
references[].provider |
"attio" |
Yes | |
references[].workspace_id |
string or null | Yes | |
references[].object_id |
string or null | Yes | |
references[].object_slug |
string or null | Yes | |
references[].records |
array of object | Yes | |
references[].records[].record_id |
string | Yes | |
references[].records[].web_url |
string (uri) or null | Yes | |
references[].records[].attributes |
array of object | Yes | |
references[].records[].attributes[].attribute_id |
string or null | Yes | |
references[].records[].attributes[].attribute_slug |
string or null | Yes | |
references[].records[].via |
array of object | Yes | |
references[].records[].via[].source_object_id |
string or null | Yes | |
references[].records[].via[].source_object_slug |
string or null | Yes | |
references[].records[].via[].source_record_id |
string | Yes | |
references[].records[].via[].attribute_id |
string or null | Yes | |
references[].records[].via[].attribute_slug |
string or null | Yes | |
references[].records[].via[].target_object_id |
string or null | Yes | |
references[].records[].via[].target_object_slug |
string or null | Yes | |
references[].records[].via[].target_record_id |
string | Yes | |
references[].lookup_hint |
object | Yes | |
references[].lookup_hint.resource |
"records" |
Yes | |
references[].lookup_hint.object |
string | Yes | |
references[].lookup_hint.record_ids |
array of string | 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.
Get set
GET /v1/deduplication/sets/{set_id}
Gets one duplicate set, with the version to send when you assess it or add it to a merge plan.
Requires dedupe:read. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: get_duplicate_set. 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 |
|---|---|---|---|---|
set_id |
path | Yes | string | |
include |
query | No | "ai_score" |
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_set" |
Yes | |
data.id |
string | Yes | |
data.version |
string | Yes | |
data.object_type |
"companies", "people" |
Yes | |
data.records |
array of object | Yes | |
data.records[].id |
string | Yes | |
data.records[].ai_score |
integer or null | No | |
data.keeper_record_id |
string or null | Yes | |
data.matched_rule_ids |
array of string | Yes | |
data.rules_incomplete |
boolean | Yes | |
data.first_found_at |
string (date-time) | Yes | |
data.updated_at |
string (date-time) | Yes | |
data.first_found_run_id |
string or null | Yes | |
data.review |
object | Yes | |
data.review.version |
string | Yes | |
data.review.ready_to_merge |
boolean | Yes | |
data.review.needs_review |
boolean | Yes | |
data.review.bucket |
"open", "ready_to_merge", "needs_review" |
Yes | |
data.review.attention_reasons |
array of "large_group", "keeper_undecided" |
Yes | |
references |
array of object | Yes | |
references[].provider |
"attio" |
Yes | |
references[].workspace_id |
string or null | Yes | |
references[].object_id |
string or null | Yes | |
references[].object_slug |
string or null | Yes | |
references[].records |
array of object | Yes | |
references[].records[].record_id |
string | Yes | |
references[].records[].web_url |
string (uri) or null | Yes | |
references[].records[].attributes |
array of object | Yes | |
references[].records[].attributes[].attribute_id |
string or null | Yes | |
references[].records[].attributes[].attribute_slug |
string or null | Yes | |
references[].records[].via |
array of object | Yes | |
references[].records[].via[].source_object_id |
string or null | Yes | |
references[].records[].via[].source_object_slug |
string or null | Yes | |
references[].records[].via[].source_record_id |
string | Yes | |
references[].records[].via[].attribute_id |
string or null | Yes | |
references[].records[].via[].attribute_slug |
string or null | Yes | |
references[].records[].via[].target_object_id |
string or null | Yes | |
references[].records[].via[].target_object_slug |
string or null | Yes | |
references[].records[].via[].target_record_id |
string | Yes | |
references[].lookup_hint |
object | Yes | |
references[].lookup_hint.resource |
"records" |
Yes | |
references[].lookup_hint.object |
string | Yes | |
references[].lookup_hint.record_ids |
array of string | 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.
Get review
GET /v1/deduplication/sets/{set_id}/review
Gets a duplicate set's review: whether it is ready to merge or needs review, and the version to send when you update it.
Requires dedupe:read. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: get_duplicate_set_review. 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 |
|---|---|---|---|---|
set_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_set_review" |
Yes | |
data.set_id |
string | Yes | |
data.version |
string | Yes | |
data.ready_to_merge |
boolean | Yes | |
data.needs_review |
boolean | Yes | |
data.bucket |
"open", "ready_to_merge", "needs_review" |
Yes | |
data.attention_reasons |
array of "large_group", "keeper_undecided" |
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.
Update review
PATCH /v1/deduplication/sets/{set_id}/review
Marks a duplicate set ready to merge or needing review, or changes its note. Send the review's version as expected_version. Values you leave out stay as they are, and null clears the note. Marking a set ready does not start or allow a merge. What this replaces is not kept, so it can't be undone.
Requires dedupe:review:write. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: update_duplicate_set_review. 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 |
|---|---|---|---|---|
set_id |
path | Yes | string | |
expected_version |
JSON body | Yes | string | |
ready_to_merge |
JSON body | No | boolean | |
needs_review |
JSON body | No | boolean | |
note |
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.id |
string | Yes | |
data.object |
"operation" |
Yes | |
data.version |
string | Yes | |
data.resource_id |
string | Yes | |
data.resource_type |
string | Yes | |
data.status |
"pending", "succeeded", "failed", "canceled", "needs_attention" |
Yes | |
data.terminal |
boolean | Yes | |
data.created_at |
string (date-time) | Yes | |
data.ended_at |
string (date-time) or null | Yes | |
data.reason_code |
string or null | Yes | |
data.replayed |
true |
No | |
data.operation_type |
"scan_cancel", "ai_assessment", "ai_assessment_cancel", "review_update", "exclusion_create", "exclusion_update", "scheduled_batch_create", "scheduled_batch_update", "scheduled_batch_cancel", "scheduled_run_cancel", "scheduled_record_cancel", "schedule_create", "schedule_update", "webhook_endpoint_create", "webhook_endpoint_update", "webhook_secret_rotate", "endpoint_verification", "webhook_replay", "merge_rebuild", "scheduled_batch_transfer", "webhook_endpoint_transfer" |
Yes | When data.operation_type is "scan_cancel", "ai_assessment", "ai_assessment_cancel", "review_update", "exclusion_create", "exclusion_update", "scheduled_batch_create", "scheduled_batch_update", "scheduled_batch_cancel", "scheduled_run_cancel", "scheduled_record_cancel", "schedule_create", "schedule_update", "webhook_endpoint_create", "webhook_endpoint_update", "webhook_secret_rotate", "endpoint_verification", "webhook_replay", "merge_rebuild", "scheduled_batch_transfer", "webhook_endpoint_transfer". |
data.action_metadata |
object | Yes | |
data.action_metadata.resource_version |
string | Yes | |
data.action_metadata.allowed_actions |
array of string | Yes | |
data.operation_type |
"merge_execute", "merge_cancel" |
Yes | When data.operation_type is "merge_execute", "merge_cancel". |
data.action_metadata.execute_not_before |
string (date-time) | Yes | When data.operation_type is "merge_execute", "merge_cancel". |
data.action_metadata.authorization_expires_at |
string (date-time) | Yes | When data.operation_type is "merge_execute", "merge_cancel". |
data.operation_type |
"plan_prepare", "plan_revision_prepare", "retry_plan_prepare" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.plan_revision |
string | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.effects_digest |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.preview_digest |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.recovery_coverage_digest |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement |
object | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.scope |
"organization_baseline" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.mode |
"api_key_allowed", "not_allowed" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.policy_version |
string | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.grant_evaluation |
"at_execution" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.reason_code |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_state |
"unauthorized", "authorized", "rejected", "invalidated", "expired" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.operation_type |
"review_bulk_update", "exclusion_bulk_create" |
Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results |
array of object | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].index |
integer | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].outcome |
"succeeded", "failed" |
Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].resource_ref |
object | No | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].resource_ref.id |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].resource_ref.version |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error |
object | No | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error.code |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error.message |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error.param |
string | No | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.operation_type |
"scan", "scan_continue" |
Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child |
object | Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.state |
"not_requested", "pending_admission", "admitted", "skipped", "failed" |
Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.reason_code |
string or null | Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.ai_run_id |
string | No | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.ai_operation_id |
string | No | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.operation_url |
string (uri) | No | When data.operation_type is "scan", "scan_continue". |
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.
Update reviews
POST /v1/deduplication/sets/review-updates
Updates the reviews of several duplicate sets at once. Send each set's review version. Each item succeeds or fails on its own unless all_or_nothing is true, so read every item's outcome. Marking a set ready does not start or allow a merge. What this replaces is not kept, so it can't be undone.
Requires dedupe:review:write. The connection also needs access to the relevant tables, objects, or workflows.
MCP action: update_duplicate_set_reviews. 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 |
|---|---|---|---|---|
items |
JSON body | Yes | array of object | |
items[].set_id |
Within the JSON value | Within this object | string | |
items[].expected_version |
Within the JSON value | Within this object | string | |
items[].ready_to_merge |
Within the JSON value | No | boolean | |
items[].needs_review |
Within the JSON value | No | boolean | |
items[].note |
Within the JSON value | No | string or null | |
all_or_nothing |
JSON body | No | boolean | |
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.id |
string | Yes | |
data.object |
"operation" |
Yes | |
data.version |
string | Yes | |
data.resource_id |
string | Yes | |
data.resource_type |
string | Yes | |
data.status |
"pending", "succeeded", "failed", "canceled", "needs_attention" |
Yes | |
data.terminal |
boolean | Yes | |
data.created_at |
string (date-time) | Yes | |
data.ended_at |
string (date-time) or null | Yes | |
data.reason_code |
string or null | Yes | |
data.replayed |
true |
No | |
data.operation_type |
"scan_cancel", "ai_assessment", "ai_assessment_cancel", "review_update", "exclusion_create", "exclusion_update", "scheduled_batch_create", "scheduled_batch_update", "scheduled_batch_cancel", "scheduled_run_cancel", "scheduled_record_cancel", "schedule_create", "schedule_update", "webhook_endpoint_create", "webhook_endpoint_update", "webhook_secret_rotate", "endpoint_verification", "webhook_replay", "merge_rebuild", "scheduled_batch_transfer", "webhook_endpoint_transfer" |
Yes | When data.operation_type is "scan_cancel", "ai_assessment", "ai_assessment_cancel", "review_update", "exclusion_create", "exclusion_update", "scheduled_batch_create", "scheduled_batch_update", "scheduled_batch_cancel", "scheduled_run_cancel", "scheduled_record_cancel", "schedule_create", "schedule_update", "webhook_endpoint_create", "webhook_endpoint_update", "webhook_secret_rotate", "endpoint_verification", "webhook_replay", "merge_rebuild", "scheduled_batch_transfer", "webhook_endpoint_transfer". |
data.action_metadata |
object | Yes | |
data.action_metadata.resource_version |
string | Yes | |
data.action_metadata.allowed_actions |
array of string | Yes | |
data.operation_type |
"merge_execute", "merge_cancel" |
Yes | When data.operation_type is "merge_execute", "merge_cancel". |
data.action_metadata.execute_not_before |
string (date-time) | Yes | When data.operation_type is "merge_execute", "merge_cancel". |
data.action_metadata.authorization_expires_at |
string (date-time) | Yes | When data.operation_type is "merge_execute", "merge_cancel". |
data.operation_type |
"plan_prepare", "plan_revision_prepare", "retry_plan_prepare" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.plan_revision |
string | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.effects_digest |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.preview_digest |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.recovery_coverage_digest |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement |
object | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.scope |
"organization_baseline" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.mode |
"api_key_allowed", "not_allowed" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.policy_version |
string | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.grant_evaluation |
"at_execution" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_requirement.reason_code |
string or null | Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.action_metadata.authorization_state |
"unauthorized", "authorized", "rejected", "invalidated", "expired" |
Yes | When data.operation_type is "plan_prepare", "plan_revision_prepare", "retry_plan_prepare". |
data.operation_type |
"review_bulk_update", "exclusion_bulk_create" |
Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results |
array of object | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].index |
integer | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].outcome |
"succeeded", "failed" |
Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].resource_ref |
object | No | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].resource_ref.id |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].resource_ref.version |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error |
object | No | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error.code |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error.message |
string | Yes | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.action_metadata.results[].error.param |
string | No | When data.operation_type is "review_bulk_update", "exclusion_bulk_create". |
data.operation_type |
"scan", "scan_continue" |
Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child |
object | Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.state |
"not_requested", "pending_admission", "admitted", "skipped", "failed" |
Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.reason_code |
string or null | Yes | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.ai_run_id |
string | No | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.ai_operation_id |
string | No | When data.operation_type is "scan", "scan_continue". |
data.action_metadata.ai_child.operation_url |
string (uri) | No | When data.operation_type is "scan", "scan_continue". |
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.
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.