---
title: "Safe review preview document for a pending transfer"
method: GET
path: "/agent/v1/transfers/{transfer_id}"
tags: ["Project Transfers"]
---

# Safe review preview document for a pending transfer

`GET /agent/v1/transfers/{transfer_id}`

## Request

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

Kind-agnostic preview. Wallet-addressed transfers are visible to from_wallet or to_wallet; email-addressed transfers are visible to the addressed-email principal or offering-org members. Returns the full transfer footprint, including payment_drain with its cutoff generation, blockers, active leases, and outgoing-generation settled-intent count. Secret NAMES are returned; values never are. Third-party viewers receive 403; non-existent transfer ids receive 404.

## Path parameters

- `transfer_id` string, uuid, required

## Response `200`

Preview document

- ProjectTransferPreview: v1.59 — safe review document. secret_names are present; secret VALUES are never returned. signers is [] in Phase 1A.
  - `transfer_id` string, uuid
  - `project_id` string
  - `project_name_snapshot` string, nullable
  - `status` 'pending' | 'accepted' | 'cancelled' | 'expired'
  - `recipient_kind` 'wallet' | 'email' | 'org'
  - `from_wallet` string
  - `from_wallet_display` string: Truncated form, e.g. 0xaaaa…1234
  - `to_wallet` string
  - `to_wallet_display` string
  - `to_email` string, email, nullable
  - `billing_policy` 'migrate'
  - `message` string, nullable
  - `initiated_at` string, date-time
  - `expires_at` string, date-time
  - `kysigned_record_id` string, nullable
  - `terms_sha256` string
  - `custom_domains` object[]
    - `hostname` string
    - `status` string, nullable
  - `subdomains` object[]
    - `name` string
    - `status` string, nullable
  - `functions` object[]
    - `name` string
    - `runtime` string, nullable
    - `timeout_ms` integer, nullable
    - `memory_mb` integer, nullable
    - `scheduled` boolean
  - `secret_names` string[]: Names ONLY. Secret values are never returned anywhere in this response.
  - `mailbox_summary` object
    - `count` integer
    - `slugs_truncated` string[]
  - `ci_bindings_to_be_revoked` object[]
    - `id` string
    - `github_repository` string, nullable
    - `github_subject_pattern` string
    - `created_at` string, date-time
  - `signers` object[]: Empty in Phase 1A. signers are currently wallet-scoped; this field is reserved for the future case where they become project-scoped.
    - `address` string
    - `chain` string
  - `github_repo_note` string: Verbatim clarifier: 'GitHub repository ownership is not transferred by Run402. B must receive repo/admin access separately.'
  - `billing_implications` object
    - `from_org_id` string, uuid, nullable
    - `target_org_id` string, uuid, nullable
    - `tier` string, nullable
    - `secrets_count` integer
    - `functions_count` integer
    - `custom_domains_count` integer
  - `retain_member` object, nullable: Present only when an email-addressed transfer includes a sender proposal to stay on as a developer of the receiving org.
    - `principal_id` string, uuid
    - `role` 'developer'
    - `sender_label` string, nullable
    - `scope` 'organization'
    - `note` string
    - `accept_field` 'accept_retained_member'
  - `payment_drain` object: Payment-generation drain state for this transfer. Existing pre-cutoff payments remain discoverable/reconcilable; no post-cutoff identity, settlement, lease, or delivery is admitted.
    - `active` boolean, required
    - `mutation_id` string, nullable, required
    - `cutoff_epoch` integer, nullable, required
    - `expected_by` string, date-time, nullable, required
    - `blocker_count` integer, required
    - `active_lease_count` integer, required
    - `outgoing_generation_settled_intent_count` integer, required
  - `source_organization` OrganizationReference
    - `org_id` string, uuid, required
  - `destination_organization` OrganizationReference
    - `org_id` string, uuid, required
  - `initiated_by` OperationActorSnapshot
    - `schema_version` 1, required
    - `principal` PrincipalSnapshot, required
      - `principal_id` string, required
      - `principal_type` string, required
      - `display_name_at_capture` string, nullable, required
      - `linked_identities_at_capture` LinkedIdentitySnapshot[], required
        - `identity_link_id` string, required
        - `kind` string, required
        - `public_subject` string, required
        - `display_subject` string, required
        - `verified_at` string, date-time, required
        - `status_at_capture` 'active', required
    - `authenticator` AuthenticatorSnapshot, required
      - `authenticator_id` string, required
      - `kind` string, required
      - `public_subject` string, required
    - `authority` AuthoritySnapshot, required: Discriminated immutable action-time authority: organization_membership, project_grant, grant_key, ci, system, legacy, or a preserved future kind. A link is never an authority kind.
      - `kind` string, required
      - `org_id` string, nullable
      - `project_id` string, nullable
      - `membership_id` string, nullable
      - `grant_id` string, nullable
      - `grant_key_id` string, nullable
      - `credential_id` string, nullable
      - `role` string, nullable
      - `scope` string[]
      - `reason_code` string, nullable
    - `captured_at` string, date-time, required
  - `recipient_principal` PrincipalRepresentation
    - `principal_id` string, required
    - `principal_type` string, required
    - `display_name` string, nullable, required
    - `linked_identities` LinkedIdentityRepresentation[], required
      - `identity_link_id` string, required
      - `proof_protocol` 'run402.identity-link.nostr.v1' | 'run402.identity-link.nostr.human.v1', required
      - `kind` string, required: Current v1 value is nostr_nip01; clients must preserve unknown future kinds.
      - `public_subject` string, required
      - `display_subject` string, required
      - `verified_at` string, date-time, required
      - `status` 'active' | 'revoked', required
      - `effective_status` 'active' | 'revoked' | 'principal_inactive', required
      - `revoked_at` string, date-time, nullable, required
  - `vault` object, nullable: The project's vault and its footprint in the recipient's pool; null when the project has no admitted vault. Billed bytes (the per-vault minimum applies) beside decimal labels. Informational: being over the limit never refuses accept.
    - `repo_id` string
    - `storage_profile` 'managed' | 'byo'
    - `source_bytes` integer
    - `source` string
    - `recipient_vault_usage_after_accept` object
      - `source_bytes` integer
      - `source` string
      - `source_bytes_limit` integer, nullable
      - `source_limit` string, nullable
    - `over_limit` boolean
  - `vault_handover` object, nullable: The vault handover this transfer requires; null when the project has no admitted vault. A transfer moves the project's KyGit vault, and the gateway never holds its key, so the recipient names the principal that receives the source (POST /agent/v1/transfers/{transfer_id}/vault-handover), the sender's writer admits that principal's key and wraps the source key for it (`run402 transfer handover <transfer_id>`), and only then can accept succeed. `state` is derived from the vault's writer set and envelopes at read time.
    - `repo_id` string
    - `state` 'awaiting_recipient' | 'awaiting_sender' | 'complete'
    - `recipient_principal_id` string, uuid, nullable
    - `recipient` object, nullable: The nominee's published keystore identity (public keys only) the sender's writer admits and wraps to.
      - `principal_id` string, uuid
      - `writer_key_id` string
      - `signing_pubkey` string
      - `ek_fingerprint` string
      - `public_key` string
    - `current_epoch` string: 16 lowercase hex: the vault's current epoch.
    - `writer_admitted` boolean
    - `envelope_current_epoch` boolean

## Other responses

- `403`: FORBIDDEN — signer is not party to this transfer
- `404`: TRANSFER_NOT_FOUND

---

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