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

# Pagamentos

> Criação, consulta e detalhe de transações com cartão e PIX.

## Criar pagamento — cartão

`POST /api/v1/payments/card` — requer `X-Client-ID` + `X-API-Key`.
Nenhum dado sensível de cartão fica salvo, somente os 4 últimos dígitos e as datas de expiração para controle do cliente.

Todos os dados sensíveis de clientes, como CPF, são criptografados com o algoritmo AES-256-CBC com chave de 32 bytes, que não fica exposta em nenhum lugar, apenas nos cofres da AWS.

```http theme={null}
POST /api/v1/payments/card
Content-Type: application/json
X-Client-ID: client_...
X-API-Key: sk_...
Idempotency-Key: ORD-2026-12345  (opcional, mas recomendado)
```

```json theme={null}
{
  "merchant_order_id": "ORD-2026-12345",
  "amount": 15000,
  "currency": "BRL",
  "payment_method": "card",
  "customer": {
    "token": "cus_7556...", // OU
    "name": "João Silva",
    "email": "joao@example.com",
    "document": "12345678909",
    "phone": "11987654321"       // opcional
  },
  "card": {
    "number": "4111111111111111",
    "cvv": "123",
    "expiration_month": "12",
    "expiration_year": "2028",
    "installments": 1,
    "holder": "Fulano da Silva",
    "holder_birthdate": "1990-05-25",
    "holder_document": "12345678909",
    "holder_phone": "11987542563",
    "save_card": true
  },
  "billing_address": {
    "street": "Rua dos advogados",
    "number": "321",
    "neighborhood": "Jardim",
    "zip_code": "35900000",
    "city": "Belo Horizonte",
    "state": "MG",
    "country": "Brasil"
  }
  // "splits": [...] — em breve
}
```

Para reutilizar um cartão tokenizado, substitua os campos do cartão pelo `token`:

```json theme={null}
{
  "card": {
    "token": "tok_a1b2c3d4e5f6",
    "installments": 1
  }
}
```

Para forçar um gateway específico, inclua gateway\_first\_try; ele será a prioridade 1 e, caso falhe, seguirá a regra definida na página de Orquestração:

```json theme={null}
{
  "gateway_first_try": "GATEWAY_SLUG"
}
```

Em ambiente sandbox é possível enviar a chave simulate\_payment\_fail para simular e testar a retentativa de pagamentos:

```json theme={null}
{
  "simulate_payment_fail": {
      "pagbank": "Motivo da falha",
      "asaas": ""
  }
}
```

### Códigos de resposta

| HTTP           | Significado                                                   |
| -------------- | ------------------------------------------------------------- |
| `201 Created`  | Aprovado dentro do `time_to_wait_sync` configurado            |
| `202 Accepted` | Processamento em andamento — acompanhe via webhook ou polling |
| `500`          | Falhou em todas as tentativas configuradas                    |

<Info>
  O backend usa coroutines para processar o pagamento em paralelo à requisição. Se o gateway não responder dentro do `time_to_wait_sync` (padrão 5s), o status `202` é retornado imediatamente e o resultado final chega via webhook assim que o pagamento for finalizado.
</Info>

### Resposta (201 ou 202)

```json theme={null}
{
  "status": "approved",
  "transaction_id": "019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73",
  "amount": 15000,
  "message": "Payment approved",
  "attempts": 1,
  "payment_method": "card",
  "merchant_order_id": "ORD-2026-12345",
  "idempotency_key": "ORD-2026-12345",
  "plugtopay_request_time": "0.45s",
  "total_request_time": "1.23s",
  "gateways_request_time": "0.78s",
  "created_at": "2026-04-30T01:23:45+00:00",
  "updated_at": "2026-04-30T01:23:46+00:00",
  "transactions": [
    {
      "attempt": 1,
      "gateway": "pagarme",
      "status": "approved",
      "holder_name": "JOAO SILVA",
      "brand": "visa",
      "last_4_digits": "1111",
      "installments": 1,
      "response_code": "00",
      "gateway_message": "Transação aprovada",
      "soft_descriptor": null,
      "request_time": "0.78s"
    }
  ],
  "card": {
    "holder_name": "JOAO SILVA",
    "token": "card_86123...",
    "brand": "visa",
    "first_6_digits": "411111",
    "last_4_digits": "1111",
    "expire_month": "12",
    "expire_year": "2028",
    "status": "active",
    "response_code": "00",
    "soft_descriptor": null,
    "authorization_nsu": "123456",
    "gateway_message": "Transação aprovada",
    "created_at": "2026-04-30T01:23:45+00:00",
    "updated_at": "2026-04-30T01:23:46+00:00"
  },
  "customer": {
    "name": "João Silva",
    "email": "joao@example.com",
    "token": "cus_7556...",
    "document_type": "cpf",
    "type": "individual",
    "phone": "11987654321",
    "phone_country_code": "55",
    "birthdate": "1990-05-25",
    "created_at": "2026-04-30T01:23:44+00:00",
    "updated_at": "2026-04-30T01:23:44+00:00"
  },
  "webhook": {
    "id": "wh_...",
    "status": "delivered",
    "url": "https://seu-servidor.com/webhooks",
    "retry_count": 0,
    "next_retry_at": null,
    "created_at": "2026-04-30T01:23:47+00:00",
    "attempts": []
  }
}
```

***

## Pré-autorização, captura e cancelamento

Por padrão a cobrança é autorizada e capturada na mesma requisição. Enviando `capture: false` no corpo do pagamento com cartão, a PlugToPay apenas **reserva** o valor no cartão do cliente: a transação volta com status `authorized` e o dinheiro só sai quando você capturar.

É o fluxo usado quando a cobrança final só se confirma depois — reserva de hospedagem, pedido que ainda vai ser separado no estoque, aluguel com caução.

```json theme={null}
{
  "merchant_order_id": "ORD-2026-12345",
  "amount": 15000,
  "currency": "BRL",
  "payment_method": "card",
  "capture": false,
  "customer": { "...": "..." },
  "card": { "...": "..." }
}
```

<Info>
  A pré-autorização depende do gateway que processar a transação. Hoje é suportada por **Pagar.me**, **PagBank**, **Stripe** e **e-Rede**. Nos demais, `capture: false` é ignorado e a cobrança sai capturada.
</Info>

### Capturar

`POST /api/v1/payments/{id}/capture` — confirma a cobrança de uma transação `authorized`.

```http theme={null}
POST /api/v1/payments/019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73/capture
Content-Type: application/json
X-Client-ID: client_...
X-API-Key: sk_...
```

O corpo é opcional. Omitir captura o valor total; informar `amount` faz uma captura parcial.

```json theme={null}
{
  "amount": 5000
}
```

**Resposta `200`:**

```json theme={null}
{
  "status": "approved",
  "transaction_id": "019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73",
  "amount": 15000,
  "captured_amount": 5000,
  "message": "Capture processed successfully."
}
```

| Campo    | Tipo                      | Obrigatório | Descrição                                                                         |
| -------- | ------------------------- | ----------- | --------------------------------------------------------------------------------- |
| `amount` | inteiro (centavos, min 1) | não         | Valor a capturar. Omitir captura o total. Não pode ultrapassar o valor autorizado |

### Cancelar a pré-autorização

`POST /api/v1/payments/{id}/cancel` — libera o valor reservado. Não tem corpo.

```http theme={null}
POST /api/v1/payments/019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73/cancel
X-Client-ID: client_...
X-API-Key: sk_...
```

**Resposta `200`:**

```json theme={null}
{
  "status": "cancelled",
  "transaction_id": "019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73",
  "amount": 15000,
  "message": "Authorization cancelled successfully."
}
```

### Regras

| Situação                                  | Resultado |
| ----------------------------------------- | --------- |
| Transação não está em `authorized`        | `422`     |
| Transação não é de cartão                 | `422`     |
| Valor da captura maior que o autorizado   | `422`     |
| Transação inexistente ou de outra empresa | `404`     |

<Warning>
  **Um `200` não garante que deu certo.** Se o gateway recusar a captura ou o cancelamento, a resposta ainda é `200` — o que muda é o `status` do corpo, que vem como `failed` em vez de `approved`/`cancelled`. O `422` cobre só os casos da tabela acima. Sempre confira o `status` da resposta antes de considerar a operação concluída. O mesmo vale para o [estorno](#estornar-pagamento).
</Warning>

<Warning>
  Capturar e cancelar são operações finais e opostas: depois de capturar, use o [estorno](#estornar-pagamento) para devolver o valor; depois de cancelar, a transação não pode mais ser capturada.
</Warning>

<Info>
  Ainda não é possível **assinar** um webhook para as transições `authorized` e `cancelled` — a lista de eventos aceitos no cadastro de webhooks não inclui esses dois. Até que isso mude, acompanhe o resultado da captura e do cancelamento pela própria resposta da requisição ou consultando `GET /payments/{id}`.
</Info>

Ambas as rotas também existem sob `/api/v1/user/payments/{id}/capture` e `/cancel` para uso do painel, autenticadas com `Authorization: Bearer <jwt>`.

***

## Estornar pagamento

`POST /api/v1/payments/{id}/refund` — devolve ao cliente o valor de uma transação já **aprovada** (capturada). Para desfazer uma pré-autorização que ainda não foi capturada, use o cancelamento acima.

```http theme={null}
POST /api/v1/payments/019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73/refund
Content-Type: application/json
X-Client-ID: client_...
X-API-Key: sk_...
```

O corpo é opcional. Omitir estorna o valor total; informar `amount` faz um estorno parcial.

```json theme={null}
{
  "amount": 5000
}
```

**Resposta `200`:**

```json theme={null}
{
  "status": "refunded",
  "transaction_id": "019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73",
  "amount": 15000,
  "refunded_amount": 5000,
  "message": "Refund processed successfully."
}
```

| Situação                                  | Resultado |
| ----------------------------------------- | --------- |
| Transação não está em `approved`          | `422`     |
| Transação não é de cartão                 | `422`     |
| Valor do estorno maior que o da transação | `422`     |
| Transação inexistente ou de outra empresa | `404`     |

Também disponível em `/api/v1/user/payments/{id}/refund` para o painel.

***

## Criar pagamento — PIX

`POST /api/v1/payments/pix` — requer `X-Client-ID` + `X-API-Key`. O campo `payment_method` é injetado automaticamente pelo backend.

```http theme={null}
POST /api/v1/payments/pix
Content-Type: application/json
X-Client-ID: client_...
X-API-Key: sk_...
Idempotency-Key: ORD-PIX-2026-999  (opcional)
```

```json theme={null}
{
  "merchant_order_id": "ORD-PIX-2026-999",
  "amount": 5000,
  "currency": "BRL",
  "expires_in": 3600,                  // opcional — segundos até o QR expirar (mín. 60)
  "gateway_first_try": "GATEWAY_SLUG", // opcional
  "customer": {
    "name": "Maria Santos",
    "email": "maria@example.com",
    "document": "98765432100"
  }
  // "splits": [...] — em breve
}
```

### Resposta PIX

O objeto `pix` contém tudo que é necessário para renderizar o QR ao cliente:

```json theme={null}
{
  "status": "pending",
  "transaction_id": "019ddb60-6f6e-72ee-99ff-a75b60ce6d87",
  "amount": 5000,
  "message": null,
  "attempts": 1,
  "payment_method": "pix",
  "merchant_order_id": "ORD-PIX-2026-999",
  "idempotency_key": null,
  "plugtopay_request_time": "0.12s",
  "total_request_time": "0.95s",
  "gateways_request_time": "0.83s",
  "created_at": "2026-04-30T01:23:45+00:00",
  "updated_at": "2026-04-30T01:23:45+00:00",
  "transactions": [
    {
      "gateway": "pagarme",
      "qr_code": "00020126580014br.gov.bcb.pix...",
      "qr_code_url": "data:image/png;base64,...",
      "expiration_at": "2026-04-30T02:23:45+00:00",
      "request_time": "0.83s"
    }
  ],
  "pix": {
    "qr_code": "00020126580014br.gov.bcb.pix...",
    "qr_code_url": "data:image/png;base64,...",
    "expiration_at": "2026-04-30T02:23:45+00:00"
  },
  "customer": {
    "name": "Maria Santos",
    "email": "maria@example.com",
    "token": "cus_9988...",
    "document_type": "cpf",
    "type": "individual",
    "phone": null,
    "phone_country_code": null,
    "birthdate": null,
    "created_at": "2026-04-30T01:23:44+00:00",
    "updated_at": "2026-04-30T01:23:44+00:00"
  },
  "webhook": null
}
```

| Campo           | Uso                                               |
| --------------- | ------------------------------------------------- |
| `qr_code`       | String EMV — copiar e colar                       |
| `qr_code_url`   | Data URL da imagem do QR — renderizar com `<img>` |
| `expiration_at` | Quando o QR expira — exiba countdown ao usuário   |

<Info>
  Recomendamos aguardar o webhook de `approved` em vez de fazer polling. Se o usuário fechar a tela, armazene o `transaction_id` e consulte o status sob demanda via `GET /api/v1/user/payments/{id}`.
</Info>

***

## Listar pagamentos

Disponível em dois contextos com autenticação diferente:

| Rota                        | Auth         | Contexto                       |
| --------------------------- | ------------ | ------------------------------ |
| `GET /api/v1/payments`      | `X-API-Key`  | Integração servidor-a-servidor |
| `GET /api/v1/user/payments` | `Bearer JWT` | Painel administrativo          |

Ambas retornam o mesmo shape paginado e aceitam os mesmos filtros:

| Parâmetro           | Tipo                                  | Descrição                                                                                       |
| ------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `start_date`        | `YYYY-MM-DD`                          | Data inicial (criação)                                                                          |
| `end_date`          | `YYYY-MM-DD`                          | Data final (criação)                                                                            |
| `status`            | `pending\|approved\|failed\|refunded` | Status da transação. `authorized` e `cancelled` ainda **não** são aceitos aqui e devolvem `422` |
| `payment_method`    | `pix\|card\|billet`                   | Método de pagamento                                                                             |
| `gateway`           | `pagarme\|safe2pay\|asaas\|pagbank`   | Gateway processador                                                                             |
| `amount_from`       | inteiro (centavos)                    | Valor mínimo                                                                                    |
| `amount_to`         | inteiro (centavos)                    | Valor máximo                                                                                    |
| `transaction_id`    | string (UUID)                         | ID exato da transação                                                                           |
| `customer_email`    | string (e-mail)                       | E-mail do cliente                                                                               |
| `customer_document` | string                                | CPF ou CNPJ do cliente                                                                          |
| `card_brand`        | string                                | Bandeira do cartão (ex: `visa`)                                                                 |
| `card_last_4`       | string                                | Últimos 4 dígitos do cartão                                                                     |
| `transaction_type`  | `payment\|withdraw`                   | Tipo de transação                                                                               |
| `per_page`          | inteiro                               | Itens por página (padrão 15)                                                                    |
| `page`              | inteiro                               | Página atual                                                                                    |

Resposta:

```json theme={null}
{
  "data": [ /* array de PaymentResource */ ],
  "meta": {
    "current_page": 1,
    "per_page": 15,
    "total": 142,
    "last_page": 10
  }
}
```

***

## Buscar pagamento por ID

Disponível em dois contextos com autenticação diferente:

| Rota                             | Auth         | Contexto                       |
| -------------------------------- | ------------ | ------------------------------ |
| `GET /api/v1/payments/{id}`      | `X-API-Key`  | Integração servidor-a-servidor |
| `GET /api/v1/user/payments/{id}` | `Bearer JWT` | Painel administrativo          |

```bash theme={null}
curl https://sandbox-api.plugtopay.com/api/v1/user/payments/019ddb56-fbe3-72e1-9f3c-8d0b2faf8f73 \
  -H "Authorization: Bearer eyJ..."
```

Retorna um único `PaymentResource` com o mesmo shape da listagem, incluindo o objeto `webhook` com as tentativas de entrega associadas à transação.
