Skip to content

Merge two custom object records

POST/v1/objects/{entitySlug}/merge

Merges two records of the specified custom object type into one. The primary record retains its ID; the duplicate is soft-deleted. Both records must belong to the custom object type named in the path.

Required scopes: custom_objects:update + custom_objects:delete

Rate limit category: Write

Path ParametersExpand Collapse
entitySlug: string

The slug of the custom object type.

Body ParametersJSONExpand Collapse
duplicateId: string

ID of the duplicate record to merge into the primary and then discard.

primaryId: string

ID of the record to keep.

fieldResolutions: optional map["primary" or "duplicate" or object { value } ]

Per-field resolution overrides keyed by attribute slug.

One of the following:
"primary" or "duplicate"
One of the following:
"primary"
"duplicate"
Value object { value }
value: string or number or boolean or 3 more
One of the following:
string
number
boolean
array of string
Address object { city, country, latitude, 5 more }
city: optional string

City name.

country: optional string

2-letter ISO 3166-1 alpha-2 country code.

latitude: optional number

Latitude coordinate.

longitude: optional number

Longitude coordinate.

postalCode: optional string

Postal or ZIP code.

state: optional string

State or province.

street: optional string

Street address line 1.

street2: optional string

Street address line 2.

FullName object { firstName, lastName }
firstName: optional string

The contact’s first name.

lastName: optional string

The contact’s last name.

options: optional object { multiSelectUnion }
multiSelectUnion: optional boolean

When true, multi-select fields are merged by union rather than primary-takes-all.

ReturnsExpand Collapse
MergeMergeObjectValuesResponse object { merge, primary, summary }
merge: object { id, status }
id: string

Unique identifier for the merge operation.

status: string

Current status of the merge: cleanup_pending, done, or failed.

primary: object { id, createdAt, fields, 4 more }
id: string

Unique identifier for the entity.

createdAt: string

ISO 8601 timestamp of when the entity was created.

fields: map[object { value, valueType } ]

Map of field names to their typed values. System fields are prefixed with $ (e.g. $name, $email); custom attributes use their bare slug.

value: string or number or boolean or 3 more

The field value, or null if unset.

One of the following:
string
number
boolean
array of string
Address object { city, country, latitude, 5 more }
city: optional string

City name.

country: optional string

2-letter ISO 3166-1 alpha-2 country code.

latitude: optional number

Latitude coordinate.

longitude: optional number

Longitude coordinate.

postalCode: optional string

Postal or ZIP code.

state: optional string

State or province.

street: optional string

Street address line 1.

street2: optional string

Street address line 2.

FullName object { firstName, lastName }
firstName: optional string

The contact’s first name.

lastName: optional string

The contact’s last name.

valueType: "ADDRESS" or "CHECKBOX" or "CURRENCY" or 12 more

The data type of the field.

One of the following:
"ADDRESS"
"CHECKBOX"
"CURRENCY"
"DATETIME"
"EMAIL"
"FULL_NAME"
"MARKDOWN"
"MULTI_SELECT"
"NUMBER"
"SINGLE_SELECT"
"SOCIAL_HANDLE"
"TELEPHONE"
"TEXT"
"URL"
"HTML"
relationships: map[object { cardinality, objectType, values } ]

Map of relationship names to their associated entities. System relationships are prefixed with $ (e.g. $owner, $contact).

cardinality: string

Whether the relationship is has_one or has_many.

objectType: string

The type of the related object (e.g. account, contact).

values: array of string

IDs of the related entities.

updatedAt: string

ISO 8601 timestamp of when the entity was last updated, or null.

externalId: optional string

External identifier for the entity, or null if unset.

summary: object { fieldWriteCount, syncRepointedCount, warnings }
fieldWriteCount: number

Number of attribute fields written onto the primary record.

minimum-9007199254740991
maximum9007199254740991
syncRepointedCount: number

Number of related records re-pointed from the duplicate to the primary.

minimum-9007199254740991
maximum9007199254740991
warnings: array of string

Non-fatal warnings from the merge (e.g. skipped transfers).

Merge two custom object records

curl https://api.lightfield.app/v1/objects/$ENTITY_SLUG/merge \
    -H 'Content-Type: application/json' \
    -H 'Lightfield-Version: 2026-03-01' \
    -H "Authorization: Bearer $API_KEY" \
    -d '{
          "duplicateId": "duplicateId",
          "primaryId": "primaryId"
        }'
{
  "merge": {
    "id": "id",
    "status": "status"
  },
  "primary": {
    "id": "id",
    "createdAt": "createdAt",
    "fields": {
      "foo": {
        "value": "string",
        "valueType": "ADDRESS"
      }
    },
    "httpLink": "httpLink",
    "relationships": {
      "foo": {
        "cardinality": "cardinality",
        "objectType": "objectType",
        "values": [
          "string"
        ]
      }
    },
    "updatedAt": "updatedAt",
    "externalId": "externalId"
  },
  "summary": {
    "fieldWriteCount": -9007199254740991,
    "syncRepointedCount": -9007199254740991,
    "warnings": [
      "string"
    ]
  }
}
Returns Examples
{
  "merge": {
    "id": "id",
    "status": "status"
  },
  "primary": {
    "id": "id",
    "createdAt": "createdAt",
    "fields": {
      "foo": {
        "value": "string",
        "valueType": "ADDRESS"
      }
    },
    "httpLink": "httpLink",
    "relationships": {
      "foo": {
        "cardinality": "cardinality",
        "objectType": "objectType",
        "values": [
          "string"
        ]
      }
    },
    "updatedAt": "updatedAt",
    "externalId": "externalId"
  },
  "summary": {
    "fieldWriteCount": -9007199254740991,
    "syncRepointedCount": -9007199254740991,
    "warnings": [
      "string"
    ]
  }
}