---
title: "Accept a pending project transfer (the recipient, whatever its address)"
method: POST
path: "/agent/v1/transfers/{transfer_id}/accept"
tags: ["Project Transfers"]
---

# Accept a pending project transfer (the recipient, whatever its address)

`POST /agent/v1/transfers/{transfer_id}/accept`

## Request

- Base URL: `https://api.run402.com`
- URL: `https://api.run402.com/agent/v1/transfers/{transfer_id}/accept`
- Auth: one of:
  - API key in header `SIGN-IN-WITH-X`
  - HTTP bearer

The ONE completion route. The row's recipient kind picks the credential: a wallet-addressed transfer is accepted by the to_wallet's SIWX signature; an email-addressed transfer is accepted by a sign-in session (or SIWX principal) whose verified email matches, into an org it owns (org_id) or, with org_id omitted, a newly created wallet-less org. Both paths run the same atomic transaction: ownership flip + grant/CI revoke + notification enqueue (one per recipient) + secrets-rotation advisory stamp + audit row, all in one COMMIT, and both return the project's anon_key + service_key. Routes scope by transfer_id (NOT project_id) — stale-offer safe. If the preview carries retain_member, accept_retained_member: true keeps the sender on as a developer of the receiving org; default false severs access. Pre-condition codes: CONTACT_EMAIL_NOT_VERIFIED (412), RECIPIENT_ORGANIZATION_NOT_ACTIVE (409), PROJECT_NOT_TRANSFERABLE (409), PROJECT_OWNER_CHANGED (409), TRANSFER_EXPIRED (410). Uses clock_timestamp() for the expiry check (NOT NOW() — would be stale under lock waits).

## Path parameters

- `transfer_id` string, uuid, required

## Headers

- `SIGN-IN-WITH-X` string, required

## Request body

- object
  - `org_id` string, uuid: Email-addressed transfers only. An org the recipient owns to receive the project; omit to create a new wallet-less org.
  - `accept_retained_member` boolean: Email-addressed transfers only. Opt-in. When the preview carries retain_member, true keeps the sender on as a developer of the receiving org; default false severs access.

## Response `200`

Accept succeeded (ownership flipped). A wallet-addressed row returns AcceptTransferResponse; an email-addressed row returns {status: 'accepted', project_id, to_org_id, created_new_org, retained_member_principal_id, credentials_revoked, credentials_issued}. Both carry anon_key + service_key.

- AcceptTransferResponse: v1.59 — response from POST /agent/v1/transfers/:transfer_id/accept after the atomic accept transaction commits.
  - `project_id` string
  - `from_wallet` string
  - `to_wallet` string
  - `new_org_id` string, uuid, nullable
  - `completed_at` string, date-time
  - `secrets_rotation_advised` true
  - `secret_names_inherited` string[]: Names of every secret currently on the project. Names ONLY — values transferred with the project but are not returned here. The persistent secrets_rotation_advised_at advisory on the project prompts B to re-write each one.
  - `secrets_count_inherited` integer
  - `github_repo_note` string
  - `ci_bindings_suspended` integer: Count of the prior owner's CI/OIDC (ci_oidc) bindings revoked by this accept. When > 0, push-to-deploy is suspended until the new owner re-links CI.
  - `ci_bindings_note` string: Present only when ci_bindings_suspended > 0: explains that CI/OIDC bindings were revoked and how to re-link (run402 ci link github / POST /ci/v1/bindings).
  - `next_actions` object[]: Present only when ci_bindings_suspended > 0: a single re-link-CI action.
    - `type` string
    - `method` string
    - `path` string
    - `auth` string
    - `why` string

## Other responses

- `401`: INVALID_AUTH — an email-addressed transfer needs an authenticated principal
- `403`: FORBIDDEN — a wallet-addressed transfer needs the to_wallet's SIWX signature (signer is not the to_wallet, or no wallet was presented); NOT_ORG_OWNER — the recipient does not own org_id
- `404`: TRANSFER_NOT_FOUND
- `409`: TRANSFER_VAULT_HANDOVER_PENDING (the project's vault has not been handed over: details.vault_handover.state, and one next action for the party that must act, nominate_vault_recipient or complete_vault_handover) / TRANSFER_VAULT_HANDOVER_PRINCIPAL_MISMATCH / TRANSFER_VAULT_BUSY (vault maintenance holds a short lease; retry) / TRANSFER_ALREADY_PROCESSED / RECIPIENT_ORGANIZATION_NOT_ACTIVE / PROJECT_NOT_TRANSFERABLE / PROJECT_OWNER_CHANGED / PAYMENT_DESTINATION_DRAINING / PAYMENT_DESTINATION_CHANGED / WRONG_COMPLETION_FOR_TRANSFER_KIND (the row's kind needs the other credential; next_actions names it). A draining response carries Retry-After and must be repeated with the same transfer id; it never advances the ownership epoch early.
- `410`: TRANSFER_EXPIRED
- `412`: CONTACT_EMAIL_NOT_VERIFIED — the recipient must verify the addressed email first

---

[API](https://skmtc.dev/run402/apis/run402-api.md) · [All operations](https://skmtc.dev/run402/apis/run402-api/llms.txt) · [OpenAPI document](https://skmtc.dev/run402/apis/run402-api/revisions/893607557f50?raw)
