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

# Receber por cartão

> Checkout hospedado: você redireciona, a gente cobra e devolve o resultado.

No cartão você não recebe o número do cartão em momento nenhum. A API devolve uma URL de
checkout hospedado, o cliente paga lá, e você recebe o resultado por webhook e por
consulta.

Isso mantém dado de cartão fora do seu servidor, que é exatamente onde ele deve ficar.

> [!WARNING]
>
> Cartão não funciona em sandbox. Com chave `ps_test_` a resposta é erro. Para testar,
> use produção com um valor baixo.

## Criando a cobrança

```bash theme={null}
curl -X POST https://api.purin.cash/v1/card-payments \
  -H "Authorization: Bearer $PURINCASH_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "valueCents": 4990,
    "description": "Plano Premium",
    "callbackUrl": "https://minhaloja.com/webhooks/purincash",
    "customer": { "name": "João Silva", "email": "joao@exemplo.com", "externalId": "user_42" },
    "successUrl": "https://minhaloja.com/obrigado",
    "cancelUrl": "https://minhaloja.com/carrinho",
    "metadata": "{\"pedido\":\"1042\"}"
  }'
```

```json Resposta 201 theme={null}
{
  "orderCode": "JUE7Y9MPSX",
  "status": "pending",
  "amountCents": 4990,
  "currency": "BRL",
  "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_live_...",
  "expiresAt": "2026-03-18T12:30:00.000Z"
}
```

Redirecione o cliente para `checkoutUrl`. A sessão vale 30 minutos.

> [!NOTE]
>
> Cartão é o único recurso identificado por `orderCode` em vez de `paymentId`. É esse
> código que você usa para consultar e é ele que volta no webhook.

## Para onde o cliente volta

| Campo | Quando é usado |
| - | - |
| `successUrl` | O cliente terminou o pagamento |
| `cancelUrl` | O cliente desistiu e voltou |

> [!WARNING]
>
> Cair na `successUrl` não significa pagamento aprovado. É só o navegador voltando, e
> qualquer pessoa consegue abrir essa URL na mão. Libere o produto pelo webhook
> `card_payment.paid` ou pela consulta, nunca pelo redirecionamento.

## Consultando

```bash theme={null}
curl https://api.purin.cash/v1/card-payments/JUE7Y9MPSX \
  -H "Authorization: Bearer $PURINCASH_KEY"
```

```json theme={null}
{
  "orderCode": "JUE7Y9MPSX",
  "status": "paid",
  "amount": 49.90,
  "amountCents": 4990,
  "currency": "BRL",
  "description": "Plano Premium",
  "checkoutUrl": null,
  "paidAt": "2026-03-18T12:05:00.000Z",
  "createdAt": "2026-03-18T12:00:00.000Z"
}
```

Status possíveis: `pending`, `paid`, `expired`, `refunded` e `failed`.

Para listar, use `GET /v1/card-payments` com `limit`, `offset` e `status`.

## Cartão tem prazo de liberação

> [!NOTE]
>
> Diferente do PIX, o valor do cartão entra como **a liberar** antes de virar saldo
> sacável. Em `GET /v1/wallet` esse montante aparece em `pendingRelease`, e ele não entra
> no `withdrawable`.

Vale considerar isso no seu fluxo de caixa: vendeu no cartão hoje não quer dizer que dá
pra sacar hoje. O detalhe de cada campo está em [Carteira](https://docs.purin.cash/guias/carteira.md).

## Diferenças no webhook

O evento é `card_payment.paid` e a forma muda um pouco em relação ao PIX:

```json theme={null}
{
  "event": "card_payment.paid",
  "orderCode": "JUE7Y9MPSX",
  "amount": 49.90,
  "status": "paid",
  "paidAt": "2026-03-18T12:05:00.000Z",
  "customer": { "name": "João Silva", "email": "joao@exemplo.com" },
  "metadata": "{\"pedido\":\"1042\"}"
}
```

> [!WARNING]
>
> Repare em duas coisas: o identificador é `orderCode` e não `paymentId`, e o valor vem
> em `amount` (reais, decimal) e não em `amountCents`. Se o seu handler for genérico,
> trate os dois formatos.

Detalhes completos em [Webhook de cartão](https://docs.purin.cash/webhooks/cartao.md).


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