Integração previsível
JSON, valores em centavos, erros estruturados e idempotência obrigatória.
Um guia direto e completo para criar cobranças Pix, acompanhar pagamentos e processar webhooks com segurança.
https://trust7.dev/v1JSON, valores em centavos, erros estruturados e idempotência obrigatória.
Webhooks assinados, entrega at-least-once e regras claras de retentativa.
llms.txt e OpenAPI públicos para dar contexto exato a qualquer agente.
Antes de escrever código, confirme estes quatro pontos. Eles evitam a maioria das falhas de primeira integração.
A conta do seller precisa estar aprovada para emitir uma chave de API e operar pagamentos.
Abra Integração → Chaves de API. Copie a chave completa na criação; o segredo não pode ser consultado depois.
Nunca exponha a chave em navegador, aplicativo distribuído, repositório ou ferramenta de analytics.
Consulte GET /payment-methods. Só crie Pix quando method=pix e enabled=true.
O fluxo mínimo seguro é: validar disponibilidade, criar uma cobrança, exibir o código Pix e aguardar a confirmação por webhook.
curl --request GET \
--url https://trust7.dev/v1/payment-methods \
--header 'Authorization: Bearer SUA_CHAVE_SECRETA' \
--header 'Accept: application/json'curl --request POST \
--url https://trust7.dev/v1/payments \
--header 'Authorization: Bearer SUA_CHAVE_SECRETA' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: pedido-789-pix-1' \
--data '{
"amount": 2590,
"currency": "BRL",
"payment_method": {
"type": "pix",
"expires_in_seconds": 1800
},
"customer": {
"reference": "cliente-123",
"name": "Ana Silva",
"email": "cliente@example.com",
"phone": "+5511999999999"
},
"metadata": {
"order_id": "pedido-789"
}
}'A criação Pix responde 202 Accepted. Salve id e sequence; mostre next_action.qr_code como Pix Copia e Cola ou gere a imagem do QR Code no frontend.
{
"id": "pay_01J8ZQ5MB2",
"status": "pending_action",
"amount": 2590,
"amount_captured": 0,
"amount_refunded": 0,
"currency": "BRL",
"capture_method": "automatic",
"payment_method": { "type": "pix" },
"next_action": {
"type": "pix_qr_code",
"qr_code": "000201...",
"expires_at": "2026-08-13T00:30:00Z"
},
"metadata": { "order_id": "pedido-789" },
"sequence": 1,
"created_at": "2026-08-13T00:00:00Z",
"updated_at": "2026-08-13T00:00:00Z"
}Marque o pedido como pago somente ao receber payment.captured com assinatura válida, ou após confirmar o mesmo estado em GET /payments/{id}.
Todas as chamadas técnicas usam uma chave secreta no header Authorization.
Authorization: Bearer key_xxxxx.sk_xxxxxNo dashboard do seller, abra Integração, informe um nome que identifique o sistema e clique em Criar chave.
Guarde em secret manager ou variável de ambiente do servidor. O valor completo aparece uma única vez.
Ao rotacionar, a chave anterior permanece válida por 24 horas. Migre o sistema e depois remova o segredo antigo.
Revogar é imediato. Faça isso quando uma integração for desativada ou houver suspeita de vazamento.
https://trust7.dev/v12590 = R$ 25,90BRL2026-08-13T00:00:00Z| Header | Quando | Valor |
|---|---|---|
Authorization | Todas as chamadas | Bearer SUA_CHAVE |
Content-Type | Corpo JSON | application/json |
Accept | Recomendado | application/json |
Idempotency-Key | POST financeiro | ID único da operação lógica |
Todo POST que cria ou move dinheiro exige Idempotency-Key, com 8 a 255 caracteres. A chave representa uma operação lógica — por exemplo, “criar o Pix do pedido 789”.
Crie o pagamento no seu backend. O exemplo abaixo está pronto para uso e trata erros antes de devolver os dados necessários ao frontend.
import crypto from "node:crypto";
export async function criarPix({ orderId, amount, customer }) {
const response = await fetch("https://trust7.dev/v1/payments", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRUST7_API_KEY}`,
"Content-Type": "application/json",
"Accept": "application/json",
"Idempotency-Key": `order-${orderId}-pix-v1`
},
body: JSON.stringify({
amount,
currency: "BRL",
payment_method: { type: "pix", expires_in_seconds: 1800 },
customer,
metadata: { order_id: String(orderId) }
}),
signal: AbortSignal.timeout(10_000)
});
const payload = await response.json();
if (!response.ok) {
const error = new Error(payload.error?.message ?? "Trust7 request failed");
error.status = response.status;
error.code = payload.error?.code;
throw error;
}
return {
paymentId: payload.id,
status: payload.status,
copyPaste: payload.next_action?.qr_code,
expiresAt: payload.next_action?.expires_at
};
}import os
import requests
def criar_pix(order_id: str, amount: int, customer: dict) -> dict:
response = requests.post(
"https://trust7.dev/v1/payments",
headers={
"Authorization": f"Bearer {os.environ['TRUST7_API_KEY']}",
"Idempotency-Key": f"order-{order_id}-pix-v1",
"Accept": "application/json",
},
json={
"amount": amount,
"currency": "BRL",
"payment_method": {"type": "pix", "expires_in_seconds": 1800},
"customer": customer,
"metadata": {"order_id": order_id},
},
timeout=10,
)
payload = response.json()
response.raise_for_status()
return {
"payment_id": payload["id"],
"status": payload["status"],
"copy_paste": payload["next_action"]["qr_code"],
"expires_at": payload["next_action"]["expires_at"],
}<?php
function criarPix(string $orderId, int $amount, array $customer): array {
$curl = curl_init('https://trust7.dev/v1/payments');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('TRUST7_API_KEY'),
'Content-Type: application/json',
'Accept: application/json',
'Idempotency-Key: order-' . $orderId . '-pix-v1',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => $amount,
'currency' => 'BRL',
'payment_method' => ['type' => 'pix', 'expires_in_seconds' => 1800],
'customer' => $customer,
'metadata' => ['order_id' => $orderId],
], JSON_THROW_ON_ERROR),
]);
$raw = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
$payload = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);
if ($status < 200 || $status >= 300) {
throw new RuntimeException($payload['error']['message'] ?? 'Trust7 request failed');
}
return $payload;
}| Campo | Obrigatório | Descrição |
|---|---|---|
amount | Sim | Valor inteiro em centavos, maior que zero. |
currency | Sim | BRL. |
payment_method.type | Sim | Use exatamente pix. |
expires_in_seconds | Não | De 60 a 86.400; padrão de 3.600 segundos. |
customer.reference | Não | ID estável do cliente no seu sistema. |
customer.name | Não | Nome do pagador; aparece na lista e na exportação de clientes. |
customer.email | Não | E-mail válido do pagador. |
customer.phone | Não | Telefone com DDI e DDD; aparece na exportação de clientes. |
metadata | Não | Chaves e valores string para conciliação; não armazene segredos. |
curl https://trust7.dev/v1/payments/pay_01J8ZQ5MB2 \
--header 'Authorization: Bearer SUA_CHAVE_SECRETA'| Status | É final? | Ação recomendada |
|---|---|---|
pending_action | Não | Exiba o Pix e aguarde webhook. |
captured | Sim | Confirme o pedido como pago. |
expired | Sim | Ofereça a criação de uma nova cobrança. |
canceled | Sim | Não entregue o pedido. |
failed | Sim | Informe falha sem expor detalhes internos. |
refunded | Sim | Registre o reembolso integral. |
partially_refunded | Não | Concilie amount_refunded. |
blocked_med | Não | Bloqueie disponibilidade do valor e acompanhe os eventos MED. |
A Trust7 envia um POST quando o estado de um pagamento muda. A entrega é at-least-once: o mesmo evento pode chegar mais de uma vez, e eventos diferentes podem chegar fora de ordem.
curl --request POST \
--url https://trust7.dev/v1/webhook-endpoints \
--header 'Authorization: Bearer SUA_CHAVE_SECRETA' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://api.sualoja.com/webhooks/trust7",
"events": [
"payment.captured",
"payment.expired",
"payment.canceled",
"payment.failed"
]
}'A resposta 201 contém secret. Armazene-o imediatamente: nas listagens posteriores o segredo é omitido. Uma lista vazia de eventos ou ["*"] assina todos os eventos.
{
"id": "evt_01J8ZQ7",
"type": "payment.captured",
"sequence": 2,
"created_at": "2026-08-13T00:02:10Z",
"data": {
"object": {
"id": "pay_01J8ZQ5MB2",
"status": "captured",
"amount": 2590,
"amount_captured": 2590,
"currency": "BRL",
"metadata": { "order_id": "pedido-789" },
"sequence": 2
}
}
}Cada entrega inclui Trust7-Signature no formato t=TIMESTAMP,v1=HEX. O digest é HMAC-SHA256(secret, timestamp + "." + corpo_cru).
import crypto from "node:crypto";
import express from "express";
const app = express();
app.post("/webhooks/trust7", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.get("Trust7-Signature") ?? "";
const parts = Object.fromEntries(signature.split(",").map(part => part.split("=", 2)));
const timestamp = Number(parts.t);
if (!Number.isFinite(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300) {
return res.sendStatus(400);
}
const expected = crypto.createHmac("sha256", process.env.TRUST7_WEBHOOK_SECRET)
.update(`${timestamp}.`)
.update(req.body)
.digest("hex");
const received = Buffer.from(parts.v1 ?? "", "hex");
const valid = received.length === expected.length / 2 &&
crypto.timingSafeEqual(received, Buffer.from(expected, "hex"));
if (!valid) return res.sendStatus(401);
const event = JSON.parse(req.body.toString("utf8"));
// 1) insira event.id com UNIQUE; duplicado significa que já foi processado
// 2) aplique somente sequence maior que a última do mesmo pagamento
// 3) confirme o pedido apenas em payment.captured
res.sendStatus(204);
});import hashlib
import hmac
import json
import os
import time
from flask import Flask, request
app = Flask(__name__)
@app.post("/webhooks/trust7")
def trust7_webhook():
raw = request.get_data(cache=False)
parts = dict(item.split("=", 1) for item in request.headers.get("Trust7-Signature", "").split(",") if "=" in item)
timestamp = int(parts.get("t", "0"))
if abs(int(time.time()) - timestamp) > 300:
return "stale", 400
signed = str(timestamp).encode() + b"." + raw
expected = hmac.new(os.environ["TRUST7_WEBHOOK_SECRET"].encode(), signed, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, parts.get("v1", "")):
return "invalid signature", 401
event = json.loads(raw)
# deduplicar event["id"] e respeitar event["sequence"]
return "", 204event.id em armazenamento persistente.| Evento | Quando acontece |
|---|---|
payment.pending_action | A cobrança aguarda ação do pagador. |
payment.authorized | Pagamento autorizado, ainda não capturado. |
payment.captured | Pagamento confirmado; libere o pedido. |
payment.canceled | Pagamento cancelado antes da conclusão. |
payment.expired | Pix ou boleto expirou sem pagamento. |
payment.failed | Falha definitiva. |
payment.blocked_med | Valor Pix capturado foi bloqueado pelo MED. |
payment.med_released | Bloqueio MED liberado. |
payment.med_debited | Devolução MED debitada em definitivo. |
Também existem refund.created, refund.failed, dispute.opened, dispute.won, dispute.lost, payout.paid, payout.failed, payout.returned e seller.status_changed.
A Trust7 repete em falha de rede, timeout, HTTP 408, 429 e 5xx. Outros 4xx encerram a entrega, pois indicam rejeição permanente do payload. Responda 2xx somente depois de validar e persistir o evento; execute trabalho pesado de forma assíncrona.
Erros sempre usam um envelope previsível. Registre request_id para suporte, mas não mostre detalhes internos ao comprador.
{
"error": {
"type": "payment_method_error",
"code": "payment_method_unavailable",
"message": "payment method is not available",
"param": "payment_method.type",
"request_id": "req_01J8ZR0"
}
}| HTTP | Significado | Retry? |
|---|---|---|
400 | Corpo ou parâmetro inválido. | Não; corrija a requisição. |
401 | Chave ausente, inválida ou revogada. | Não; corrija a credencial. |
403 | Credencial sem escopo ou conta bloqueada. | Não automaticamente. |
404 | Recurso não encontrado para esta conta. | Não. |
409 | Estado inválido ou conflito de idempotência. | Leia error.code. |
424 | Método/adquirente indisponível. | Não em loop; consulte disponibilidade. |
429 | Limite de requisições excedido. | Sim, respeite Retry-After. |
500+ | Falha temporária da Trust7. | Sim, com backoff e mesma idempotência. |
Uma IA integra melhor quando recebe fontes estruturadas. Forneça os dois links abaixo e o prompt recomendado.
Integre pagamentos Pix da Trust7 neste projeto.
Fontes canônicas:
- https://docs.trust7.dev/llms.txt
- https://docs.trust7.dev/openapi.yaml
Antes de editar:
1. Leia as duas fontes por completo e identifique a arquitetura atual do projeto.
2. Mantenha TRUST7_API_KEY apenas no backend e em variável de ambiente.
3. Consulte GET /payment-methods e trate Pix desabilitado.
4. Use valores inteiros em centavos e Idempotency-Key persistida por pedido.
5. Crie o Pix no backend e devolva ao frontend somente payment_id, qr_code e expires_at.
6. Implemente webhook com corpo cru, HMAC-SHA256, tolerância de 300 s, deduplicação por event.id e fencing por sequence.
7. Confirme pedidos somente em payment.captured.
8. Trate 400, 401, 409, 424, 429 e 5xx conforme a documentação.
9. Adicione testes para sucesso, replay idempotente, assinatura inválida, evento duplicado e evento fora de ordem.
10. Não invente endpoints, campos, status ou capacidades ausentes do OpenAPI.
Ao final, liste arquivos alterados, variáveis de ambiente, testes executados e um roteiro de validação.| Método | Endpoint | Uso |
|---|---|---|
| GET | /payment-methods | Capacidades ativas da conta. |
| POST | /payments | Criar pagamento; exige idempotência. |
| GET | /payments/{id} | Consultar um pagamento. |
| GET | /payments | Listar e filtrar pagamentos. |
| POST | /payments/{id}/refunds | Reembolso total ou parcial. |
| POST | /webhook-endpoints | Cadastrar destino e obter secret. |
| GET | /webhook-endpoints | Listar destinos sem segredos. |
| DELETE | /webhook-endpoints/{id} | Remover destino. |
| GET | /webhook-deliveries?limit=50 | Histórico de entregas. |