> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cbpayapp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Transferencias internas

> Mueve USDT, USDC, BTC, GOLD, SILVER o PLATINUM entre cuentas CBPay, gratis y al instante

export const EnvUrls = ({lang = "en"}) => {
  const T = {
    en: {
      test: "Test",
      live: "Live",
      hint: "Same API on both environments — build against test first, then go live by swapping the base URL and the key.",
      guide: "Environments and testing",
      href: "/en/environment-testing"
    },
    es: {
      test: "Test",
      live: "Live",
      hint: "La misma API en ambos ambientes — construye primero contra test y pasa a live cambiando la URL base y la key.",
      guide: "Entorno y pruebas",
      href: "/es/environment-testing"
    },
    zh: {
      test: "Test",
      live: "Live",
      hint: "两个环境的 API 完全一致——先在 test 环境构建，再通过切换基础 URL 和密钥上线。",
      guide: "环境与测试",
      href: "/zh/environment-testing"
    }
  };
  const t = T[lang] || T.en;
  const row = (label, url, keyPattern, badgeCls) => <div className="flex flex-wrap items-center gap-2 px-3 py-2">
      <span className={"rounded px-1.5 py-0.5 text-xs font-semibold uppercase tracking-wide " + badgeCls}>
        {label}
      </span>
      <code className="text-xs">{url}</code>
      <span className="text-xs text-gray-400 dark:text-zinc-500">·</span>
      <code className="text-xs">{keyPattern}</code>
    </div>;
  return <div className="my-4 rounded-xl border border-gray-200 dark:border-zinc-700 divide-y divide-gray-200 dark:divide-zinc-700 text-sm not-prose">
      {row(t.test, "https://cryptobank.qbank.cl/platform", "pk_test_...", "bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300")}
      {row(t.live, "https://api.qbank.cl/platform", "pk_...", "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300")}
      <p className="px-3 py-2 text-xs text-gray-500 dark:text-zinc-400 m-0">
        {t.hint} <a href={t.href}>{t.guide} →</a>
      </p>
    </div>;
};

<EnvUrls lang="es" />

Las transferencias internas mueven saldo entre dos cuentas **CBPay**, de
forma atómica en el ledger y **siempre sin comisión** — el dinero nunca sale
del ecosistema. Funcionan con las seis monedas (`USDT`, `USDC`, `BTC`,
`GOLD`) y siempre **entre saldos de la misma moneda**: el `asset` que envías
es el `asset` que recibe el destino, sin conversión.

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
sequenceDiagram
    participant A as Cuenta origen
    participant CB as CBPay (ledger)
    participant B as Cuenta destino
    A->>CB: POST /v1/transfers (idempotency_key)
    CB->>CB: Movimiento atómico:<br/>transfer_out (A) + transfer_in (B)
    CB-->>A: 201 completed (síncrono)
    CB-->>B: Webhook transfer_received
```

Funcionan entre **cualquier combinación de cuentas**:

| Origen | Destino | Comisión |
| - | - | - |
| Persona | Persona | 0 |
| Persona | Empresa | 0 |
| Empresa | Persona | 0 |
| Empresa | Empresa | 0 |

## Crear una transferencia

El destino se identifica por `to_account_id`, `to_email`, **`to_phone`**
(teléfono verificado) o **`to_contact_id`** (un
[contacto](/es/guides/contacts) de tu libreta):

<CodeGroup>
  ```bash Por teléfono (verificado) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.qbank.cl/platform/v1/transfers \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "to_phone": "+56987654321",
      "amount": "25.000000",
      "description": "Almuerzo",
      "idempotency_key": "alm-2026-07-10-a"
    }'
  ```

  ```bash Por contacto theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.qbank.cl/platform/v1/transfers \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "to_contact_id": "3f8a1b2c-…",
      "amount": "10.000000",
      "idempotency_key": "t-991"
    }'
  ```

  ```bash Por email (persona → persona) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.qbank.cl/platform/v1/transfers \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "to_email": "carlos@ejemplo.com",
      "amount": "25.000000",
      "description": "Split de gastos",
      "idempotency_key": "split-2026-07-06-a"
    }'
  ```

  ```bash Por account_id (persona → empresa) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.qbank.cl/platform/v1/transfers \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "to_account_id": "ae8cf540-22a9-414d-82cc-8ac04732be4f",
      "amount": "120.500000",
      "description": "Pago servicio mensual",
      "idempotency_key": "serv-2026-07-a"
    }'
  ```

  ```bash Empresa → persona (nómina) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.qbank.cl/platform/v1/transfers \
    -H "Authorization: Bearer <token de la empresa>" \
    -H "Content-Type: application/json" \
    -d '{
      "to_email": "empleado@ejemplo.com",
      "amount": "850.000000",
      "description": "Sueldo julio",
      "idempotency_key": "nomina-2026-07-emp01"
    }'
  ```

  ```bash En otra moneda (GOLD, gramos de oro) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.qbank.cl/platform/v1/transfers \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "to_email": "carlos@ejemplo.com",
      "asset": "GOLD",
      "amount": "2.500000",
      "description": "Regalo en oro",
      "idempotency_key": "oro-2026-07-09-a"
    }'
  ```
</CodeGroup>

La forma del request es idéntica en todas las combinaciones (persona o
empresa, en cualquier dirección) — cambia solo la credencial que llama.
`asset` es opcional y por defecto usa el **settlement asset del emisor**
(`USD` es el saldo principal); acepta cualquiera de los diez
assets del ledger (`USD`, `USDT`, `USDC`, `BTC`, `GOLD`, `SILVER`,
`PLATINUM`, `BOB`, `MXN`, `ARS`) y el destino recibe **en esa misma moneda**.

Respuesta `201` — la transferencia es **síncrona e inmediata**:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "transfer_id": "77b1…",
  "from_account_id": "…",
  "to_account_id": "…",
  "asset": "USDT",
  "amount": "25.000000",
  "description": "Split de gastos",
  "status": "completed",
  "created_at": "2026-07-06T20:10:00Z"
}
```

Replay con la misma `idempotency_key` — `200` con la transferencia
original:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "transfer_id": "77b1…",
  "amount": "25.000000",
  "status": "completed",
  "idempotency_hit": true
}
```

El receptor puede enterarse por el webhook `transfer_received` y ambos ven
el movimiento en su historial (`transfer_out` / `transfer_in`).

<Note>
  Cada transferencia guarda al destinatario como [contacto](/es/guides/contacts)
  automáticamente (envía `"save_contact": false` para no guardarlo). Por
  seguridad, `to_phone` solo resuelve cuentas con el teléfono **verificado
  por OTP**; si más de una cuenta comparte el número responde
  `422 recipient_ambiguous`.
</Note>

## Consultar transferencias

Lista las transferencias de tu cuenta (enviadas y recibidas), con
paginación y filtros de fecha:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl "https://api.qbank.cl/platform/v1/transfers?from=2026-07-01&to=2026-07-07&page_size=50" \
  -H "Authorization: Bearer <token>"
```

O una en particular por su ID (solo visible para las dos partes):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl https://api.qbank.cl/platform/v1/transfers/77b1… \
  -H "Authorization: Bearer <token>"
```

Cada fila trae `direction` (`sent` o `received`) desde tu perspectiva.

## Reglas

* Solo entre cuentas CBPay **activas**; las cuentas internas del sistema no
  pueden recibir.
* Siempre **misma moneda en origen y destino**: no hay conversión entre
  saldos (`USDT`→`USDT`, `GOLD`→`GOLD`, …).
* No puedes transferirte a ti mismo (`400 self_transfer`).
* Requiere `idempotency_key` (body o header `Idempotency-Key`); el replay
  devuelve `200` con `idempotency_hit: true`.
* `amount` acepta hasta los decimales de la moneda: 2 para `USD`/`BOB`/`MXN`/
  `ARS`, 6 para `USDT`/`USDC`/`GOLD`/`SILVER`/`PLATINUM`, 8 para `BTC`.

## Errores

| HTTP | `error` | Causa |
| - | - | - |
| 400 | `recipient_required` | Falta `to_account_id`, `to_email`, `to_phone` y `to_contact_id` |
| 400 | `invalid_amount` | Monto inválido, demasiados decimales o `asset` no soportado |
| 400 | `invalid_phone` | `to_phone` no se pudo normalizar a E.164 |
| 400 | `self_transfer` | Origen y destino son la misma cuenta |
| 402 | `insufficient_funds` | Saldo disponible insuficiente en esa moneda |
| 404 | `recipient_not_found` | El email/ID no corresponde a una cuenta CBPay, o ningún teléfono verificado coincide |
| 422 | `recipient_ambiguous` | Más de una cuenta comparte ese teléfono (usa `to_account_id` o `to_email`) |
| 422 | `contact_not_linked` | El contacto no tiene cuenta CBPay asociada |
| 422 | `recipient_unavailable` | La cuenta destino está bloqueada/cerrada |

## FAQ

<AccordionGroup>
  <Accordion title="¿Las transferencias internas tienen costo?">
    No — las transferencias entre cuentas de tu organización son gratis e
    instantáneas.
  </Accordion>

  <Accordion title="¿Puedo transferir entre assets distintos?">
    No — ambos lados mueven el **mismo** asset (USDT a USDT, USDC a USDC…).
    Para cambiar de asset, convierte primero con [Swaps](/es/guides/swaps).
  </Accordion>

  <Accordion title="¿Una transferencia se puede reversar?">
    No — las transferencias son instantáneas e irreversibles. Si enviaste a la
    cuenta equivocada, coordina la devolución con la contraparte.
  </Accordion>

  <Accordion title="¿Cómo funciona el envío por teléfono?">
    `to_phone` solo resuelve números **verificados** de tu organización. Un
    número sin verificar o desconocido responde 404; si más de una cuenta calza
    recibes `recipient_ambiguous` (422) — usa `to_alias` o el ID de cuenta.
  </Accordion>

  <Accordion title="¿Qué son to_alias y to_qr_token?">
    Destinatarios alternativos: el alias inmutable de la cuenta y el token de
    su QR de perfil (`GET /v1/me/qr`). Todos resuelven solo dentro de tu
    organización.
  </Accordion>

  <Accordion title="¿Para qué sirve checkout_token?">
    Liquida un [link de cobro](/es/guides/checkout) por transferencia interna:
    el destino se fuerza a la cuenta del link y el monto debe cubrir el due
    cotizado (si no, `checkout_amount_mismatch`, 422).
  </Accordion>
</AccordionGroup>

Los errores de límites money-out están en la referencia pública de errores.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.