# API de pagamentos

> Crie e gerencie sessões de pagamento em criptomoedas com a API de pagamentos da 2328.io.

A API de pagamentos permite criar sessões de pagamento, redirecionar clientes para um checkout hospedado e acompanhar o status do pagamento.

## Criar pagamento

Cria uma sessão de pagamento e retorna uma URL para o cliente realizar o pagamento.

### Parâmetros da requisição

| Campo | Tipo | Obrigatório | Descrição | Valores |
|-------|------|-------------|-----------|---------|
| `amount` | decimal | sim | Valor do pagamento na moeda informada, ex.: `100.00` |  |
| `currency` | string | sim | Moeda fiduciária (USD, EUR, RUB, …) ou criptomoeda (USDT, TRX, BTC, …) | `USD`, `EUR`, `RUB`, `KZT`, `UAH`, `UZS`, `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `order_id` | string | sim | Seu ID de pedido, ex.: `ORDER-12345` (até 128 caracteres) |  |
| `to_currency` | string | não | Criptomoeda pré-selecionada | `USDT`, `USDC`, `BTC`, `ETH`, `GRAM`, `SOL`, `TRX`, `BNB`, `POL`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `network` | string | não\* | Código da rede (obrigatório quando `to_currency` está definido ou `currency` é uma criptomoeda) | `TRX-TRC20`, `ETH-ERC20`, `BASE`, `BSC-BEP20`, `AVAX-C`, `POL-MATIC`, `TON`, `SOL`, `BTC`, `LTC`, `DASH`, `DOGE`, `ZEC`, `XRP`, `XMR` |
| `url_return` | string | não | URL de redirecionamento após o pagamento, ex.: `https://your-site.com/return` |  |
| `url_success` | string | não | Alternativa a `url_return` |  |
| `url_callback` | string | sim | URL para notificações de webhook, ex.: `https://your-site.com/webhook` |  |
| `invite_code` | string | não | Código do indicador |  |
| `fee_split` | decimal | não | Parcela da taxa do comerciante repassada ao pagador, 0–100 (%). 0 = comerciante paga integralmente, 100 = pagador paga integralmente. Sobrescreve a configuração do projeto. **Exemplo: `30`** (pagador cobre 30% da taxa). |  |
| `price_markup` | decimal | não | Acréscimo ou desconto sobre o valor da fatura, −99 a 100 (%). Sobrescreve a configuração do projeto. **Exemplo: `5`** (+5%) ou `-10` (10% de desconto). |  |
| `description` | string | não | Descrição opcional da fatura (máx. 200 caracteres). Exibida ao pagador na página de pagamento. **Exemplo: `Premium plan — Order #12345`**. |  |
| `ttl_seconds` | int | não | Tempo de vida da fatura em segundos, de `300` (5 minutos) a `86400` (24 horas). Após esse período a fatura expira e não pode mais ser paga. Padrão: `3600` (1 hora). **Exemplo: `3600`**. |  |

### Resposta

```json
{
  "state": 0,
  "result": {
    "uuid": "abc123-def456-...",
    "order_id": "ORDER-12345",
    "amount": "100.00",
    "currency": "USD",
    "amount_usd": "100.00",
    "exchange_rate": null,
    "url": "https://2328.io/pay/abc123-def456-...",
    "tg_deeplink": "https://t.me/my2328bot?start=pay_abc123-def456-...",
    "expires_at": "2026-01-11T21:00:00Z",
    "created_at": "2026-01-11T20:00:00Z",
    "payer_currency": "USDT",
    "payer_amount": "100.50",
    "network": "TRX-TRC20",
    "address": "TXYZabc123...",
    "payment_status": "check",
    "txid": null,
    "payment_amount": null,
    "qr": "data:image/png;base64,iVBORw0..."
  }
}
```

- Redirecione o cliente para `result.url` para concluir o pagamento.
- `tg_deeplink` — deeplink do bot do Telegram para pagamento via Telegram MiniApp.
- `qr` — QR code (data URI) do endereço de depósito codificado em base64. Presente quando um endereço já foi atribuído (quando `network` é informado junto com `to_currency`, ou quando `currency` é uma criptomoeda); caso contrário, `null`.
- `txid`, `payment_amount` — `null` até que o cliente pague. Preenchidos assim que a transação é detectada on-chain. Escute o webhook `payment_status: paid` para saber quando.
- `exchange_rate` — `null` se a conversão ainda não se aplica (por exemplo, a taxa fiat → cripto ainda não foi travada). Preenchido assim que a moeda do pagador é definida.

> Use your project UUID and the endpoint-appropriate API key from the merchant dashboard.

#### Interactive request: `POST /v1/payment`
  - `amount` (decimal, required)
  - `currency` (enum, required): USD,EUR,RUB,KZT,UAH,UZS,USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `order_id` (string, required)
  - `to_currency` (enum): USDT,USDC,BTC,ETH,GRAM,SOL,TRX,BNB,POL,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `network` (enum): TRX-TRC20,ETH-ERC20,BASE,BSC-BEP20,AVAX-C,POL-MATIC,TON,SOL,BTC,LTC,DASH,DOGE,ZEC,XRP,XMR
  - `url_return` (string)
  - `url_success` (string)
  - `url_callback` (string, required)
  - `invite_code` (string)
  - `fee_split` (decimal)
  - `price_markup` (decimal)
  - `description` (string)
  - `ttl_seconds` (integer)

## Checkout hospedado, H2H e valores exatos de criptomoeda

O mesmo endpoint suporta três formatos distintos de fatura. Escolha um deliberadamente; não misture a semântica de seus valores.

### Checkout hospedado com opção de pagador

Envie `amount`, `currency`, `order_id` e `url_callback`, mas omita `to_currency` e `network`. A resposta contém `result.url`; `address`, `qr` e às vezes campos do pagador permanecem `null` até que o pagador selecione uma direção na página hospedada.

```json
{
  "amount": "125.00",
  "currency": "EUR",
  "order_id": "ORDER-2026-1042",
  "url_callback": "https://merchant.example/webhooks/2328",
  "url_return": "https://merchant.example/orders/ORDER-2026-1042"
}
```

### Fatura H2H de endereço direto

Envie ambos `to_currency` e `network`. 2328.io cria a fatura blockchain durante a chamada da API, portanto, uma resposta bem-sucedida pode ser exibida dentro do seu checkout sem redirecionar o cliente.

```json
{
  "amount": "100.00",
  "currency": "USD",
  "to_currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1043",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

Exiba esses valores exatamente como retornados:

- `payer_amount` e `payer_currency` — a instrução de pagamento;
- `network` e `address` — o único destino para esta fatura;
- `qr` — um URI de dados para o mesmo endereço;
- `expires_at` — o prazo da fatura;
- `url` — um fallback hospedado útil quando o checkout personalizado não pode ser concluído.

> **DANGER:** Nunca gere ou substitua um endereço, reutilize um endereço de outra fatura ou calcule `payer_amount` a partir de um preço público. A resposta da API é autorizativa.

### Fatura por uma quantidade exata de criptomoeda

Coloque a criptomoeda em `currency` quando a própria fatura estiver denominada em criptomoeda:

```json
{
  "amount": "25.000000",
  "currency": "USDT",
  "network": "TRX-TRC20",
  "order_id": "ORDER-2026-1044",
  "url_callback": "https://merchant.example/webhooks/2328"
}
```

O valor solicitado da criptomoeda é preservado em `payer_currency` / `payer_amount`. O serviço também pode manter uma avaliação em USD internamente para campos contábeis e de taxa; não substitua a instrução exata de criptomoeda por essa avaliação. Preserve as strings decimais retornadas, incluindo a precisão final.

Para uma criptomoeda com apenas uma rede suportada, a rede pode ser selecionada automaticamente. Ainda é recomendado fornecer `network` explicitamente para uma integração determinística. Para ativos de múltiplas redes, como stablecoins, sempre envie.

## Idempotência e tentativas de nova tentativa

`order_id` está vinculado ao projeto do comerciante autenticado e funciona como a chave de idempotência de criação. Se um pagamento já existir, a API retorna essa sessão com `state: 0`.

> **WARNING:** Uma nova tentativa com o mesmo `order_id` faz com que **not** signifique “atualizar esta fatura.” Campos como valor, moeda, callback, markup, TTL ou direção podem ser ignorados porque a sessão existente é retornada. Armazene a primeira solicitação e rejeite tentativas conflitantes em sua própria aplicação.

Algoritmo de criação recomendado:

1. Insira sua tentativa de pagamento local e `order_id` único em uma transação de banco de dados.
2. Envie a requisição de API assinada.
3. Persista o `uuid` retornado e a resposta completa.
4. Se o resultado HTTP for perdido, tente novamente a mesma requisição ou consulte `/v1/payment/info` via `order_id`.
5. Nunca crie um segundo pedido local apenas porque a requisição upstream expirou.

## Casos extremos de pagamento

| Situação | Manuseio correto |
|-----------|------------------|
| `address` / `qr` é `null` | A direção do pagador não foi inicializada. Redirecione para `url` ou crie uma nova fatura H2H corretamente especificada com um novo `order_id`. |
| Erro de validação HTTP `400` | Leia o `errors` no nível do campo; não tente novamente com entrada inalterada. |
| HTTP `429` | Tente novamente com retardo exponencial com jitter e mantenha o mesmo `order_id`. |
| HTTP `503` / `direction_disabled` | Atualize `/v1/directions`; oculte a direção temporariamente ou tente novamente depois. |
| Tempo limite de solicitação do cliente | Trate o resultado como desconhecido. Consulte por `order_id` antes de criar qualquer outra coisa. |
| `underpaid_check` | Armazene o evento parcial e aguarde um complemento ou status posterior. Não credite duas vezes quando mais txids chegarem. |
| `underpaid` | Estado final de subpagamento. Aplique sua política configurada de cumprimento/revisão manual ao valor realmente creditado. |
| `overpaid` | Pagamento bem-sucedido com fundos excedentes. Cumpra de forma idempotente e mantenha os valores reais para políticas de reconciliação/reembolso. |
| `aml_lock` | Não cumpra nem libere fundos automaticamente; encaminhe para o fluxo de trabalho de conformidade/suporte. |
| `cancel` | Fatura expirada ou cancelada. Não presuma que uma transferência on-chain tardia seja impossível; reconcilie qualquer evento posterior com o suporte. |

A URL de retorno do navegador é apenas para navegação. Um cliente pode abri-la sem pagar, fechá-la após pagar ou reproduzi-la mais tarde. Apenas um estado de API/webhook verificado pode liquidar o pedido do comerciante.

## Informações do pagamento

Obtenha o status atual de um pagamento por `uuid` ou `order_id`.

### Parâmetros da requisição

| Campo | Tipo | Obrigatório | Descrição | Valores |
|-------|------|-------------|-----------|---------|
| `uuid` | string | sim\* | UUID do pagamento (de `result.uuid` na criação) |  |
| `order_id` | string | sim\* | Seu ID de pedido |  |

> **INFO:** Pelo menos um entre `uuid` e `order_id` é obrigatório.

#### Interactive request: `POST /v1/payment/info`
  - `uuid` (string)
  - `order_id` (string)

## Lista de pagamentos

Obtenha uma lista de todos os pagamentos com filtros e paginação.

### Parâmetros da requisição

| Campo | Tipo | Obrigatório | Descrição | Valores |
|-------|------|-------------|-----------|---------|
| `status` | string | não | Filtrar por status do pagamento (veja [References](/docs/references)) | `pending`, `check`, `paid`, `underpaid_check`, `underpaid`, `overpaid`, `cancel` |
| `date_from` | date | não | Data inicial (YYYY-MM-DD), ex.: `2026-01-01` |  |
| `date_to` | date | não | Data final (YYYY-MM-DD), ex.: `2026-01-31` |  |
| `page` | int | não | Número da página, padrão `1` |  |
| `per_page` | int | não | Itens por página, padrão `15`, máximo `5000` |  |

#### Interactive request: `POST /v1/payment/list`
  - `status` (enum): pending,check,paid,underpaid_check,underpaid,overpaid,cancel
  - `date_from` (string)
  - `date_to` (string)
  - `page` (integer)
  - `per_page` (integer)