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

# Subcontas

> Um saldo separado para cada cliente seu, sem você manter essa contabilidade na mão.

Se você roda uma plataforma (marketplace, SaaS que cobra pelos clientes, rede de
revendedores), uma pergunta aparece rápido: *do dinheiro que entrou, quanto é de quem?*

Subconta é a resposta da API pra isso. Você cria uma subconta por cliente, aponta as
cobranças pra ela, e o saldo de cada um passa a ser mantido pelo gateway: creditado
quando o pagamento confirma, debitado quando você transfere, consultável a qualquer
momento com extrato completo.

## O que uma subconta é (e o que não é)

<Columns cols={2}>
  <Card title="É" icon="circle-check">
    Um ledger com saldo próprio dentro da **sua** conta.

    Criada por API, na hora, sem documento nem aprovação.

    Extrato permanente de tudo que entrou e saiu.
  </Card>

  <Card title="Não é" icon="circle-xmark">
    Uma conta PurinCash: não tem login, painel nem chave de API própria.

    Um destino de dinheiro real: o valor continua na carteira da **sua** conta.

    Um cadastro com KYC: a relação com o cliente final é sua.
  </Card>
</Columns>

<Info>
  O dinheiro real fica sempre na sua carteira, e o saldo da subconta diz que fatia dele
  pertence a cada cliente. É por isso que criar subconta é instantâneo. E é também por
  isso que um bug seu de atribuição nunca move dinheiro de verdade: a camada é contábil.
</Info>

## Criando uma subconta

```bash theme={null}
curl -X POST https://api.purincash.com/v1/subaccounts \
  -H "Authorization: Bearer $PURINCASH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Loja do João",
    "email": "joao@exemplo.com",
    "externalId": "cliente_42",
    "metadata": "{\"plano\":\"pro\"}"
  }'
```

```json Resposta 201 theme={null}
{
  "subaccountId": "sacc_a1b2c3d4e5f60718293a4b5c6d7e8f90",
  "name": "Loja do João",
  "email": "joao@exemplo.com",
  "externalId": "cliente_42",
  "active": true,
  "balanceCents": 0,
  "totalReceivedCents": 0,
  "metadata": "{\"plano\":\"pro\"}",
  "createdAt": "2026-08-04T12:00:00.000Z",
  "updatedAt": "2026-08-04T12:00:00.000Z"
}
```

<ParamField body="name" type="string" required>
  Nome do cliente. Até 100 caracteres.
</ParamField>

<ParamField body="externalId" type="string">
  O ID do cliente **no seu sistema**. Vale usar sempre: ele é único por ambiente, e criar
  de novo com o mesmo `externalId` devolve `409` com o `subaccountId` da existente. Ou
  seja: a criação vira idempotente, e o retry do seu código nunca duplica cliente.
</ParamField>

<ParamField body="email" type="string">
  Contato do cliente. Informativo, não autentica nada.
</ParamField>

<ParamField body="metadata" type="string">
  String JSON de até 2 KB, devolvida sem alteração.
</ParamField>

Limite de 1000 subcontas por conta e por ambiente. Guarde o `sacc_...` junto do cadastro
do seu cliente: é ele que você vai usar em todas as outras chamadas.

## Cobrando para uma subconta

Adicione `subaccountId` na criação da cobrança. Funciona em `POST /v1/charges` e em
`POST /v1/payments`, com PIX:

```bash theme={null}
curl -X POST https://api.purincash.com/v1/charges \
  -H "Authorization: Bearer $PURINCASH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "valueCents": 19900,
    "description": "Pedido #1042 da Loja do João",
    "subaccountId": "sacc_a1b2c3d4e5f60718293a4b5c6d7e8f90",
    "callbackUrl": "https://plataforma.com/webhooks/purincash"
  }'
```

O resto do fluxo é o de [sempre](/guias/pix): o cliente final paga o PIX, o webhook
chega. O passo novo é o seguinte: **o líquido da venda é creditado no ledger da
subconta** no mesmo instante em que entra na sua carteira. O crédito é idempotente:
reenvio de webhook não credita duas vezes.

O webhook `charge.paid` / `payment.paid` vem com o campo `subaccountId` quando a
cobrança tem subconta, então o seu handler sabe de quem é a venda sem consultar nada:

```json theme={null}
{
  "event": "charge.paid",
  "paymentId": "psc_9f8e7d6c5b4a",
  "amountCents": 19900,
  "status": "paid",
  "subaccountId": "sacc_a1b2c3d4e5f60718293a4b5c6d7e8f90",
  "paidAt": "2026-08-04T12:05:00.000Z"
}
```

<Note>
  O valor creditado no ledger é o **líquido**, o mesmo que entrou na sua carteira, já
  sem a taxa do gateway. Assim a soma dos saldos das subcontas nunca promete mais
  dinheiro do que existe.
</Note>

### Onde `subaccountId` não entra

| Situação                     | Comportamento                                                                                                           |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Cobrança com `splits`        | `400`. Split divide entre contas reais; subconta atribui num ledger. Os dois juntos deixariam ambíguo quem possui o quê |
| `paymentMethod: "ltc"`       | `400`. A confirmação de LTC segue um caminho próprio que não alimenta o ledger                                          |
| Cartão (`/v1/card-payments`) | Campo não existe. Subconta é PIX por enquanto                                                                           |
| Subconta desativada          | `400` na criação da cobrança                                                                                            |

## Consultando saldo e extrato

```bash theme={null}
curl https://api.purincash.com/v1/subaccounts/sacc_a1b2c3d4.../transactions \
  -H "Authorization: Bearer $PURINCASH_KEY"
```

```json theme={null}
{
  "subaccountId": "sacc_a1b2c3d4e5f60718293a4b5c6d7e8f90",
  "balanceCents": 45900,
  "transactions": [
    { "type": "sale", "amountCents": 19400, "refId": "psc_9f8e7d6c5b4a", "description": "Venda confirmada", "createdAt": "2026-08-04T12:05:00.000Z" },
    { "type": "transfer_out", "amountCents": -30000, "refId": "tr_1a2b3c4d5e6f", "description": "Comissão da plataforma", "createdAt": "2026-08-03T09:00:00.000Z" }
  ],
  "total": 2,
  "limit": 50,
  "offset": 0
}
```

Os `amountCents` vêm com sinal: crédito positivo, débito negativo. Somar a coluna
reproduz o saldo. O `refId` amarra cada lançamento à origem: `psc_`/`psa_` é uma
venda (dá pra consultar a cobrança), `tr_` é uma transferência.

`GET /v1/subaccounts` lista todas com saldo, e aceita `?externalId=` pra achar um
cliente pelo **seu** ID sem guardar o `sacc_` do lado de lá.

## Transferindo saldo

`POST /v1/subaccounts/{id}/transfer` move valor entre a subconta e a sua conta, nos
dois sentidos. É uma operação contábil, nenhum PIX é disparado:

<CodeGroup>
  ```bash Cobrar sua comissão theme={null}
  curl -X POST https://api.purincash.com/v1/subaccounts/sacc_a1b2c3d4.../transfer \
    -H "Authorization: Bearer $PURINCASH_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "direction": "to_master",
      "amountCents": 30000,
      "description": "Comissão da plataforma de julho"
    }'
  ```

  ```bash Dar bônus ou estorno theme={null}
  curl -X POST https://api.purincash.com/v1/subaccounts/sacc_a1b2c3d4.../transfer \
    -H "Authorization: Bearer $PURINCASH_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "direction": "to_subaccount",
      "amountCents": 5000,
      "description": "Crédito de boas-vindas"
    }'
  ```
</CodeGroup>

`to_master` exige saldo suficiente na subconta, e a checagem é atômica: duas
transferências concorrentes nunca deixam o saldo negativo. A `description` aparece no
extrato. Capriche nela: é o que o seu financeiro vai ler depois.

## Pagando o cliente de verdade

Quando chega a hora de repassar o saldo pro seu cliente, são dois passos, e o segundo
você já conhece:

<Steps>
  <Step title="Traga o saldo pra conta principal">
    `POST /v1/subaccounts/{id}/transfer` com `direction: "to_master"` e o valor do
    repasse. Isso debita o ledger do cliente e documenta o repasse no extrato dele.
  </Step>

  <Step title="Saque com a chave PIX do cliente">
    [`POST /v1/payouts`](/guias/saques) com `method: "pix"` e o `walletAddress` sendo a
    chave PIX **do cliente**. O dinheiro real sai da sua carteira, que é onde ele sempre
    esteve.
  </Step>
</Steps>

<Warning>
  Não existe atalho que salte o passo 1 de propósito. Repasse mexe em dinheiro real, e
  dinheiro real sai por um lugar só: o fluxo de saque, com as regras de sempre (chave
  verificada, limites e aprovação). A transferência antes do saque é o que mantém o
  extrato da subconta batendo com o que foi pago.
</Warning>

## Desativando

`PUT /v1/subaccounts/{id}` com `active: false`. A subconta some das novas cobranças e
não aceita mais entradas, mas o saldo continua consultável e o `to_master` continua
funcionando. Desativar não prende dinheiro. Excluir não existe: o extrato é histórico
financeiro, e histórico financeiro não se apaga.

## Em sandbox

Tudo funciona com chave `ps_test_`, com o mesmo isolamento do resto da API: subcontas
de teste são separadas das reais. No `simulate-paid` o ledger é creditado com o valor
cheio (sandbox não tem taxa), então dá pra testar o ciclo inteiro sem mover um centavo:
criar subconta, cobrar, simular pagamento, ver o saldo mudar, transferir.

<Card title="Referência completa" icon="code" href="/api-reference/introducao" horizontal>
  Os 6 endpoints de subcontas com playground, na seção Subcontas da Referência.
</Card>
