# Upsert semantics (v1)

### Upsert semantics (v1)
`POST` **inserts or updates** each `(source, alternative)` pair; it never
removes links. Re-sending the same pair is idempotent. There is **no
delete endpoint yet** — omitting a previously sent alternative leaves it in
place. A row whose source or alternative `article_number` does not exist in
your catalogue is **skipped** (counted in the job's `skipped_count`), not
an error. If any row is structurally invalid (missing a required field, a
negative `order`) the whole batch is rejected and the per-row detail
appears in `GET /jobs/{job_id}`.

Version: 1.33.0
