# Blimx Gateway — Documentação de Integração (para LLMs)

Este documento descreve **tudo** o que uma LLM precisa para integrar um projeto com o **Blimx Gateway**: criar cobranças PIX (cash-in), fazer pagamentos PIX (cash-out), consultar saldo/extrato e receber webhooks assinados. Cole este arquivo no contexto da sua LLM para gerar código de integração correto.

/ Base URL de produção: `https://gateway.rhuar.com`

---

## Visão Geral

O **Blimx Gateway** é um gateway de pagamentos **PIX** (somente PIX). Cada conta tem uma **carteira** com saldo calculado a partir de um livro de `transactions` (entradas e saídas). Você pode:

1. **Receber dinheiro** (depósito / cash-in): cria uma cobrança PIX, o pagador paga, o saldo é creditado.
2. **Pagar / sacar** (saque / cash-out): envia PIX para uma chave; o valor é reservado do saldo e debitado.
3. **Consultar** saldo e extrato.
4. **Receber webhooks** assinados (HMAC-SHA256) quando um evento ocorre.

Integração é **server-to-server**, autenticada por **Bearer Token** (Laravel Sanctum).

---

## Autenticação

Toda requisição protegida deve incluir o header:

```
Authorization: Bearer {access_token}
```

- Obtenha o primeiro token via `POST /api/register` (cadastro) ou `POST /api/login`.
- Crie tokens adicionais (nomeados) via `POST /api/keys`. O token plain é mostrado **uma única vez**.
- Tokens **não expiram**; revogue manualmente via `DELETE /api/keys/{id}` se comprometidos.
- Requisições à API são **JSON-only**: sempre envie `Accept: application/json`. Sem token válido → `401` (JSON, nunca redireciona).

---

# Parte 1 — Conta e Chaves

### `POST /api/register` — cadastro (rate limit 3/min)

```json
// Body
{ "name": "Minha Loja", "email": "loja@exemplo.com", "password": "segredo123" }
```

```json
// Resposta 201 — webhook_secret mostrado UMA ÚNICA VEZ
{
  "success": true,
  "token": "1|xxxxxxxx",
  "user": { "id": 1, "name": "Minha Loja", "email": "loja@exemplo.com", "webhook_secret": "abc123..." },
  "warning": "O webhook_secret será mostrado apenas UMA VEZ. Guarde-o em local seguro."
}
```

### `POST /api/login` — autentica (rate limit 5/min)

```json
// Body — name é opcional (nomeia o token); NÃO apaga tokens existentes
{ "email": "loja@exemplo.com", "password": "segredo123", "name": "servidor-prod" }
```

```json
// Resposta 200
{ "success": true, "data": { "token_type": "Bearer", "access_token": "2|yyyy", "name": "servidor-prod" } }
```

### `GET /api/keys` — lista chaves (não retorna o token plain)
### `POST /api/keys` — cria chave nomeada `{ "name": "string(3-50)" }` → retorna `access_token` 1x
### `DELETE /api/keys/{id}` — revoga chave (404 se não for sua)

---

# Parte 2 — Depósitos (cash-in)

### `POST /api/deposito` — cria cobrança PIX

```json
// Body
{
  "amount": 100.00,                      // obrigatório, 0.01 .. max_deposito
  "callback_url": "https://seu.site/webhook", // opcional; rejeita IP privado/reservado (SSRF)
  "expires_in": 5                        // opcional, minutos (default 5)
}
```

```json
// Resposta 201
{
  "success": true,
  "data": {
    "txid": "abc123...",
    "brcode": "00020126...",            // PIX copia-e-cola; gere o QR a partir dele
    "amount": 100.00,
    "expira_em": "13-06-2026 18:00:00",
    "status": "criado"
  }
}
```

Quando o pagador paga, a Sicoob notifica o Blimx, que **confirma a cobrança consultando a Sicoob** (não confia no payload bruto), credita o líquido (bruto − taxa de depósito, se houver) e dispara o webhook `deposito.concluido`.

### `GET /api/deposito/{txid}` — consulta (rate limit 10/min)
### `GET /api/depositos?limit=100` — lista, cap 500 (rate limit 10/min)

---

# Parte 3 — Saques (cash-out)

### `POST /api/saque` — cria saque PIX

```json
// Body
{
  "amount": 50.00,                        // obrigatório, 0.01 .. max_saque
  "pix_key": "12345678901",               // obrigatório, 11-77 chars (CPF/CNPJ/email/telefone/aleatória)
  "callback_url": "https://seu.site/webhook" // opcional; SSRF-protected
}
```

```json
// Resposta 201
{ "success": true, "data": { "e2e": "E12345678...", "amount": 50.00, "status": "processando" } }
```

```json
// Resposta 422 — saldo insuficiente
{ "success": false, "data": { "message": "Saldo insuficiente" } }
```

Fluxo: o saldo (saque + taxa) é **reservado atomicamente** (lock por usuário + débito provisório commitado) **antes** de enviar à Sicoob. O envio à Sicoob ocorre **fora da transação**. Se o envio falhar, o saque e a taxa são **estornados** automaticamente. A confirmação final (`REALIZADO`/`NAO_REALIZADO`) chega pelo webhook da Sicoob e é reconciliada de forma idempotente.

### `GET /api/saque/{e2e}` — consulta por endToEndId (rate limit 10/min)
### `GET /api/saques?limit=100` — lista, cap 500 (rate limit 10/min)

---

# Parte 4 — Conta

### `GET /api/saldo` → `{ "success": true, "data": { "saldo": "150.00" } }`
### `GET /api/extrato?limit=100` — extrato de transactions (cap 500)
### `GET /api/webhook-secret` — ROTACIONA o `webhook_secret`: invalida o anterior e retorna um novo (consultar = "perdi o secret"; nunca re-exibe). Reconfigure a verificação HMAC dos webhooks após chamar.

---

# Parte 5 — Webhooks enviados ao seu sistema

Quando um evento ocorre, o Blimx faz um `POST` assinado para a `callback_url` informada.

### Headers

| Header | Descrição |
|---|---|
| `X-Blimx-Event` | `deposito.concluido` \| `saque.concluido` \| `saque.falhou` |
| `X-Blimx-Timestamp` | Unix timestamp do envio |
| `X-Blimx-Signature` | `sha256=<HMAC-SHA256(timestamp . "." . body, webhook_secret)>` |

### Eventos / payload

```json
// deposito.concluido
{ "event": "deposito.concluido", "txid": "...", "e2e": "...", "valor": 100.0, "status": "concluido" }

// saque.concluido / saque.falhou
{ "event": "saque.concluido", "e2e": "...", "valor": 50.0, "origem": {...}, "destino": {...}, "status": "concluido" }
```

### Verificação da assinatura (OBRIGATÓRIO)

1. Leia `X-Blimx-Signature` e `X-Blimx-Timestamp`.
2. Calcule `sha256=` + `hash_hmac('sha256', timestamp . "." . rawBody, webhook_secret)`.
3. Compare com `hash_equals` (tempo constante).
4. Rejeite se `abs(time() - timestamp) > 300` (anti-replay).

**PHP:**
```php
$ts = $request->header('X-Blimx-Timestamp');
$sig = $request->header('X-Blimx-Signature');
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $request->getContent(), $webhookSecret);
abort_unless(hash_equals($expected, $sig) && abs(time() - (int) $ts) <= 300, 403);
```

**Node.js:**
```js
const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig)) && Math.abs(Date.now()/1000 - ts) <= 300;
```

**Python:**
```python
import hmac, hashlib, time
expected = 'sha256=' + hmac.new(secret.encode(), f'{ts}.{raw_body}'.encode(), hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, sig) and abs(time.time() - int(ts)) <= 300
```

---

## Códigos de Resposta HTTP

| Código | Significado |
|---|---|
| `200` | Sucesso |
| `201` | Recurso criado |
| `401` | Não autenticado ou credenciais inválidas |
| `404` | Recurso não encontrado |
| `422` | Erro de validação (inclui bloqueio SSRF em `callback_url` e valor acima do máximo) |
| `429` | Rate limit excedido |
| `500` | Erro interno |

---

## Checklist de Integração (para LLM)

- [ ] Guardar `access_token` e `webhook_secret` no `.env` do projeto.
- [ ] Criar cobrança: `POST /api/deposito` → mostrar `brcode` (QR) ao pagador.
- [ ] Fazer pagamento: `POST /api/saque` com `pix_key`.
- [ ] Expor `callback_url` pública (HTTPS) e **verificar HMAC** em todo webhook.
- [ ] Deduplicar por `txid` (depósito) e `e2e` (saque) — retries podem reenviar.
- [ ] Rejeitar webhooks com timestamp fora de ±300s.
- [ ] Tratar `422` saldo insuficiente / valor acima do máximo.
