{
  "info": {
    "name": "Letztech — API para Parceiros",
    "description": "Collection oficial de integração da API Letztech para marketplaces parceiros.\n\nCobre os endpoints acessíveis via API key de marketplace (HTTP Basic Auth): criação de cobranças Pix e Boleto, consulta de status, devolução (refund) e as páginas públicas de pagamento (JSON e PDF do boleto).\n\n## Como usar\n1. Abra a aba **Variables** desta collection e preencha:\n   - `apiKey`: sua API key de marketplace (gerada no painel, em /dashboard/seller). Só é exibida uma vez.\n   - `marketplaceId`: para seller self-service, é o próprio id do seller.\n   - `sellerId`: id do seller dono da cobrança (`on_behalf_of`). Normalmente igual a `marketplaceId`.\n2. A autenticação HTTP Basic já está configurada no nível da collection: usuário = `{{apiKey}}`, senha vazia.\n3. Rode **Criar cobrança Pix** ou **Criar cobrança Boleto**. O `id` da resposta é salvo automaticamente em `{{transactionId}}` para reuso nas chamadas de consulta, refund e páginas públicas.\n\nBase URL padrão: https://api.letztech.com.br\n\nDocumentação completa: https://letztech.com.br/docs/partners\n\nNão há ambiente de sandbox — toda chamada é contra produção.\n\n## Migrando da Zoop\nA API Letztech foi desenhada para minimizar o esforço de migração de quem já integra a Zoop. O que se mantém igual e o que muda:\n\n| Item | Zoop | Letztech |\n|------|------|----------|\n| Host | payments.zoop.ws | api.letztech.com.br |\n| Path de transações | /v1/marketplaces/{marketplace_id}/transactions | /v1/marketplaces/{marketplaceId}/transactions (idêntico) |\n| Autenticação | HTTP Basic (API key como usuário, senha vazia) | HTTP Basic (API key como usuário, senha vazia) — igual |\n| mTLS (certificado cliente) | Exigido em vários endpoints | Não usado — só Basic Auth |\n| Campos do body | on_behalf_of, reference_id, amount (centavos), payment_type, customer | Iguais |\n| Devolução/estorno | Zoop pública: void de cartão (mesmo dia) e cancelamento de boleto, por tipo/prazo | Apenas devolução de PIX já liquidado: POST .../transactions/{id}/refund, amount em REAIS decimais (ex: 25.50), não centavos. Cartão e boleto NÃO têm devolução por enquanto |\n| Idempotência | não padronizada nesse header | header X-Idempotency-Key (opcional) + reference_id dedup por seller |\n| Páginas públicas de pagamento | n/d | GET /v1/pay/{id} (JSON) e /v1/pay/{id}/pdf |\n\nPontos de atenção na migração:\n- Troque só o host e a API key: o path e o formato do body de criação são compatíveis.\n- **Devolução só de PIX por enquanto**: a Letztech expõe devolução apenas para transações PIX já liquidadas. Não há equivalente ao void de cartão nem ao cancelamento de boleto da Zoop — não presuma que esse fluxo migra 1:1.\n- **Atenção ao refund**: na Letztech o `amount` vai em reais com 2 casas (25.50), diferente do `amount` de criação, que é em centavos (2550).\n- Remova a configuração de mTLS/certificado cliente — a Letztech não usa.\n- Não há sandbox: valide contra produção com valores baixos.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "basic",
    "basic": [
      { "key": "username", "value": "{{apiKey}}", "type": "string" },
      { "key": "password", "value": "", "type": "string" }
    ]
  },
  "variable": [
    { "key": "baseUrl", "value": "https://api.letztech.com.br", "type": "string" },
    { "key": "apiKey", "value": "", "type": "string" },
    { "key": "marketplaceId", "value": "", "type": "string" },
    { "key": "sellerId", "value": "", "type": "string" },
    { "key": "transactionId", "value": "", "type": "string" }
  ],
  "item": [
    {
      "name": "Criar cobrança Pix",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "// Salva o id da transação criada para reuso nas próximas chamadas.",
              "if (pm.response.code === 201) {",
              "  const body = pm.response.json();",
              "  if (body && body.id) {",
              "    pm.collectionVariables.set('transactionId', body.id);",
              "  }",
              "}"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          { "key": "Content-Type", "value": "application/json" },
          {
            "key": "X-Idempotency-Key",
            "value": "pix-{{$guid}}",
            "description": "Opcional, recomendado. Retentativas com a mesma chave retornam a resposta original em vez de duplicar a cobrança."
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"amount\": 15000,\n  \"currency\": \"BRL\",\n  \"payment_type\": \"pix\",\n  \"on_behalf_of\": \"{{sellerId}}\",\n  \"reference_id\": \"order-1234\",\n  \"customer\": \"customer-abc-123\",\n  \"description\": \"Pagamento do pedido #1234\",\n  \"postback_url\": \"https://parceiro.com.br/webhooks/letztech\",\n  \"payment_method\": {\n    \"pix_expiration_date_time\": \"2025-12-31T23:59:59Z\"\n  }\n}"
        },
        "url": {
          "raw": "{{baseUrl}}/v1/marketplaces/{{marketplaceId}}/transactions",
          "host": ["{{baseUrl}}"],
          "path": ["v1", "marketplaces", "{{marketplaceId}}", "transactions"]
        },
        "description": "Cria uma cobrança Pix. `amount` em centavos (inteiro positivo). `reference_id` é único por seller (reenvio do mesmo valor retorna 409). A resposta traz `payment_method.qr_code.emv` (Pix copia-e-cola) — gere a imagem do QR code a partir desse payload."
      }
    },
    {
      "name": "Criar cobrança Boleto",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "if (pm.response.code === 201) {",
              "  const body = pm.response.json();",
              "  if (body && body.id) {",
              "    pm.collectionVariables.set('transactionId', body.id);",
              "  }",
              "}"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          { "key": "Content-Type", "value": "application/json" },
          {
            "key": "X-Idempotency-Key",
            "value": "boleto-{{$guid}}",
            "description": "Opcional, recomendado."
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"amount\": 25000,\n  \"currency\": \"BRL\",\n  \"payment_type\": \"boleto\",\n  \"on_behalf_of\": \"{{sellerId}}\",\n  \"reference_id\": \"invoice-2026-001\",\n  \"customer\": \"customer-abc-123\",\n  \"description\": \"Mensalidade Janeiro/2026\",\n  \"postback_url\": \"https://parceiro.com.br/webhooks/letztech\",\n  \"logo\": \"https://minha-empresa.com/logo.png\",\n  \"payment_method\": {\n    \"expiration_date\": \"2025-12-31\",\n    \"payment_limit_date\": \"2026-01-15\",\n    \"buyer\": {\n      \"first_name\": \"João\",\n      \"last_name\": \"Silva\",\n      \"email\": \"joao@email.com\",\n      \"phone_number\": \"5199999999\",\n      \"taxpayer_id\": \"12345678901\",\n      \"birthdate\": \"1990-05-15\",\n      \"address\": {\n        \"line1\": \"Rua das Flores\",\n        \"line2\": \"123\",\n        \"line3\": \"Sala 4\",\n        \"neighborhood\": \"Centro\",\n        \"city\": \"Porto Alegre\",\n        \"state\": \"RS\",\n        \"postal_code\": \"90000000\"\n      }\n    },\n    \"body_instructions\": [\n      \"Não receber após vencimento\",\n      \"Juros de 1% ao mês\"\n    ],\n    \"billing_instructions\": {\n      \"late_fee\": { \"mode\": \"PERCENTAGE\", \"percentage\": 2.0, \"start_date\": \"2026-01-01\" },\n      \"interest\": { \"mode\": \"PERCENTAGE\", \"percentage\": 1.0, \"start_date\": \"2026-01-01\" },\n      \"discount\": [\n        { \"mode\": \"FIXED\", \"amount\": 500, \"limit_date\": \"2025-12-20\" }\n      ]\n    }\n  }\n}"
        },
        "url": {
          "raw": "{{baseUrl}}/v1/marketplaces/{{marketplaceId}}/transactions",
          "host": ["{{baseUrl}}"],
          "path": ["v1", "marketplaces", "{{marketplaceId}}", "transactions"]
        },
        "description": "Mesmo endpoint da criação de Pix — o tipo é definido por `payment_type: \"boleto\"`. `payment_method.buyer` é obrigatório. A resposta traz `payment_method.barcode` (linha digitável) e, se o BolePix foi emitido, `payment_method.pix.qr_code.emv`. Não há URL de PDF na resposta — monte a partir do `id`: GET /v1/pay/:id/pdf."
      }
    },
    {
      "name": "Consultar transação",
      "request": {
        "method": "GET",
        "header": [],
        "url": {
          "raw": "{{baseUrl}}/v1/marketplaces/{{marketplaceId}}/transactions/{{transactionId}}",
          "host": ["{{baseUrl}}"],
          "path": ["v1", "marketplaces", "{{marketplaceId}}", "transactions", "{{transactionId}}"]
        },
        "description": "Retorna a transação no mesmo formato da criação, com o `status` atualizado (pending | succeeded | failed | refunded). Escopada ao marketplace da API key — transação de outro marketplace retorna 404. Use como fallback de reconciliação caso um webhook não chegue."
      }
    },
    {
      "name": "Devolver transação (refund)",
      "request": {
        "method": "POST",
        "header": [
          { "key": "Content-Type", "value": "application/json" },
          {
            "key": "X-Idempotency-Key",
            "value": "refund-{{$guid}}",
            "description": "Opcional, recomendado."
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\n  \"amount\": 150.00,\n  \"reason\": \"Produto não entregue\"\n}"
        },
        "url": {
          "raw": "{{baseUrl}}/v1/marketplaces/{{marketplaceId}}/transactions/{{transactionId}}/refund",
          "host": ["{{baseUrl}}"],
          "path": ["v1", "marketplaces", "{{marketplaceId}}", "transactions", "{{transactionId}}", "refund"]
        },
        "description": "Devolve, parcial ou totalmente, uma transação PIX concluída.\n\nSó existe devolução de PIX por enquanto — cartão e boleto NÃO têm devolução/estorno via API.\n\nATENÇÃO: diferente da criação, `amount` aqui vai em REAIS com até 2 casas decimais (ex: 150.00), NÃO em centavos. Omita `amount` para devolver o valor restante integral. `reason` é opcional (máx 500 caracteres).\n\nAutenticada apenas pela API key do marketplace (server-to-server), sem MFA. Só se aplica a transações PIX já liquidadas."
      }
    },
    {
      "name": "Página pública de pagamento (JSON)",
      "request": {
        "auth": { "type": "noauth" },
        "method": "GET",
        "header": [],
        "url": {
          "raw": "{{baseUrl}}/v1/pay/{{transactionId}}",
          "host": ["{{baseUrl}}"],
          "path": ["v1", "pay", "{{transactionId}}"]
        },
        "description": "Endpoint público (sem autenticação) com os dados mínimos da cobrança e o Pix copia-e-cola / linha digitável. O id é um UUID não adivinhável — conhecer o link é o controle de acesso."
      }
    },
    {
      "name": "PDF do boleto (público)",
      "request": {
        "auth": { "type": "noauth" },
        "method": "GET",
        "header": [],
        "url": {
          "raw": "{{baseUrl}}/v1/pay/{{transactionId}}/pdf",
          "host": ["{{baseUrl}}"],
          "path": ["v1", "pay", "{{transactionId}}", "pdf"]
        },
        "description": "PDF do boleto (com QR Pix embutido quando existir), também público. Retorna 404 se a cobrança não tiver boleto. No Postman, use \"Send and Download\" para salvar o arquivo."
      }
    }
  ]
}
