---
title: "Attach a durable key"
method: POST
path: "/api/v1/ackdb/persons/{personId}/links"
tags: ["ackDB"]
---

# Attach a durable key

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

## Request

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

Scope-validated (person-scope types only), normalized (lowercased email / canonical LinkedIn), and **first-writer-wins**: a value owned by another human is **409** — the response names the owning person AND the `merge_candidates` row it just recorded, and nothing is written. Adding a SECOND `linkedin_url` to one person is also 409 + candidate (a slug change and two different humans look identical from here — a person decides). Re-adding a key the person already holds is an idempotent 200.

**Email is a fallback anchor (#575).** An `email_address` is added only when the person has NO `linkedin_url` anchor. A clean email on a linkedin-anchored person is DECLINED with **200** `{ data: null, suppressed: true, stored: false, reason }` — this door has no contact edge, so the value is not stored anywhere (set it on a contact to keep it as `contacts.email` context). A conflict still wins first: an email owned by another human is 409 + candidate even on a linkedin-anchored person.

## Path parameters

- `personId` string, required

## Request body

- AckdbPersonLinkCreateRequest: Attach one durable key to a person.
  - `externalIdType` string, required
  - `externalIdValue` string, required
  - `source` string: Source stamp on the key row. Defaults to "manual".

## Response `200`

The person already held this key — nothing changed.

- object
  - `data` unknown, required

## Other responses

- `201`: The stored key (`PersonIdentityLink`).
- `400`: Missing externalIdType/externalIdValue.
- `404`: Person not found.
- `409`: Owned by another person, or a second linkedin_url — merge candidate recorded.
- `422`: Not a person-scope key type, or a blank/garbage/role-inbox value.

---

[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)
