---
title: "Rebind By Remote"
method: PUT
path: "/datamate-project-bindings/by-remote"
tags: ["DatamateProjectBindings"]
---

# Rebind By Remote

`PUT /datamate-project-bindings/by-remote`

Atomically move an active binding from its current workspace to a new one.

Holds a row-level ``FOR UPDATE`` lock on the existing binding for the
duration of the transaction so two concurrent PUTs against the same
remote serialize cleanly. When ``expected_current_datamate_id`` is
provided, it must equal the currently-bound workspace's id or the swap
is rejected with 412 (optimistic concurrency); when absent, the swap is
unconditional — the caller is explicitly opting into last-writer-wins.

Authorization: BOTH the source and the target workspace must be owned by
the caller. Without the source-side check, any tenant user could re-point
another user's project binding at their own workspace. The row is mutated
in place rather than delete+insert; ``created_at`` keeps reflecting the
original binding.

## Request body

- RebindByRemoteRequest — Body for PUT /datamate-project-bindings/by-remote (atomic re-link). Mutates the existing active binding for ``repo_remote`` **in place**, re-pointing its ``datamate_id`` at ``target_datamate_id``. Runs in a single transaction under a ``SELECT ... FOR UPDATE`` row lock so two concurrent PUTs against the same remote serialize cleanly. When ``expected_current_datamate_id`` is provided, it must equal the currently -bound workspace's id or the swap is rejected with 412 (optimistic concurrency). When absent, the swap is unconditional — the caller explicitly opts into last-writer-wins. Note: the binding row is mutated in place rather than delete-then-insert (consensus review m5). ``created_at`` therefore reflects the original binding's creation, not the rebind moment.
  - `repo_remote` string, required
  - `target_datamate_id` integer, required
  - `expected_current_datamate_id` integer, nullable

## Response `200`

Successful Response

- BindingResponse — Response for the bind-existing and rebind endpoints.
  - `binding` BindingModel, required — Wire shape returned to the CLI for a single binding row. Either ``repo_remote`` or ``project_path`` is present (at least one; the row's CHECK constraint enforces this). Projects with a git remote use ``repo_remote``; projects without one (materialized sample scaffolds, fresh scratch dirs) use ``project_path`` as the fallback identifier.
    - `id` integer, required
    - `datamate_id` integer, required
    - `datamate_name` string, required
    - `repo_remote` string, nullable
    - `project_path` string, nullable
    - `created_at` string, date-time, nullable

## Other responses

- `400` — Invalid request
- `403` — Not the current or target owner
- `404` — No existing binding for this remote
- `412` — Current binding does not match expected_current_datamate_id
- `422` — Validation Error

---

[API](https://skmtc.net/myaltimate/apis/fastapi.md) · [All operations](https://skmtc.net/myaltimate/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/myaltimate/fastapi/revisions/b9cc757ca795/schema)
