---
title: "Merge two persons"
method: POST
path: "/api/v1/ackdb/persons/{personId}/merge"
tags: ["ackDB"]
---

# Merge two persons

`POST /api/v1/ackdb/persons/{personId}/merge`

## Request

- Base URL: `http://localhost:3009`
- URL: `http://localhost:3009/api/v1/ackdb/persons/{personId}/merge`
- Auth: HTTP bearer

Fuses two humans. The path person wins by default; `winnerOverride` (which must be one of the two ids) flips that. One transaction: keys move (exact dups dropped), the loser's edges re-point to the winner — a (person, company) collision folds the two edges via the contact-merge sub-cascade (events re-pointed, links/traits/ownership merged) — `entity_events.person_id` is restamped, the loser is tombstoned (`merged_into`), open candidates between the pair are closed, and `person.identity.merged` lands on the winner's person timeline with no company/contact, including when the winner has no affiliations. Historical company-associated `person.merged` rows remain readable.

Both ids are resolved through merge chains first, so a duplicate or concurrent merge is a **no-op** (`merged: false`), never an error. This endpoint and the batch one are the ONLY ways persons merge in ackDB — ingest never does.

## Path parameters

- `personId` string, required

## Request body

- AckdbPersonMergeRequest: Merge `loserId` into the path person (or into `winnerOverride`, which must be one of the two).
  - `loserId` string, required
  - `winnerOverride` string, nullable

## Response `200`

`{ data: PersonMergeResult }`.

- object
  - `data` unknown, required

## Other responses

- `400`: Missing loserId, or winnerOverride is not one of the two persons.
- `404`: Person not found.

---

[API](https://skmtc.dev/floqer/apis/floqer-public-api.md) - [All operations](https://skmtc.dev/floqer/apis/floqer-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/floqer/apis/floqer-public-api/revisions/fce50dc07b20?raw)
