{
  "info": {
    "_postman_id": "a1b2c3d4-e5f6-4a7b-8c9d-owem20260412",
    "name": "Owem Pay -- External API",
    "description": "Official Postman collection for the Owem Pay External API (https://api.owem.com.br).\n\n## Setup\n\n1. Import this collection into Postman\n2. Open the collection -> Variables tab\n3. Fill in `client_id`, `client_secret`, and `base_url`\n4. The pre-request script computes HMAC-SHA512 automatically on POST requests\n\n## Authentication\n\nThe External API uses three security layers:\n- **Authorization header**: `ApiKey <client_id>:<client_secret>`\n- **HMAC-SHA512 header**: `hmac: <hex>` (for POST requests only)\n- **IP Whitelist**: configure allowed IPs in the Merchant Portal\n\n## Status Vocabulary\n\nSee the full [PIX Lifecycle page](https://docs.owem.com.br/pix-lifecycle) for authoritative status reference.\n\n- `active` — QR Code freshly generated (cash-in POST)\n- `accepted` — PIX OUT/refund accepted for async processing (HTTP 202)\n- `processing` — PIX OUT in flight, awaiting BACEN\n- `settled` — Terminal success (GET + webhook bodies)\n- `rejected` — Terminal failure (webhook body)\n- `failed` — Terminal failure (GET body)\n\nGenerated 2026-04-12 by Owem Pay engineering team.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      { "key": "key", "value": "Authorization", "type": "string" },
      { "key": "value", "value": "ApiKey {{client_id}}:{{client_secret}}", "type": "string" },
      { "key": "in", "value": "header", "type": "string" }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// HMAC-SHA512 pre-request script for Owem Pay External API",
          "// Runs on every request. On POST requests it computes the HMAC of the body",
          "// and sets the 'hmac' header. On GET/DELETE requests it does nothing.",
          "",
          "if (pm.request.method === 'POST') {",
          "  const secret = pm.variables.get('client_secret');",
          "  if (!secret) {",
          "    console.warn('client_secret not set — HMAC header will not be computed.');",
          "    return;",
          "  }",
          "  const body = pm.request.body && pm.request.body.raw ? pm.request.body.raw : '';",
          "  // Normalize: parse and re-stringify without spaces to match backend normalization",
          "  let normalized = body;",
          "  try {",
          "    normalized = JSON.stringify(JSON.parse(body));",
          "  } catch (e) {",
          "    // body is not valid JSON — sign as-is",
          "  }",
          "  const hmac = CryptoJS.HmacSHA512(normalized, secret).toString(CryptoJS.enc.Hex);",
          "  pm.request.headers.upsert({ key: 'hmac', value: hmac });",
          "  // Replace the raw body with the normalized version so the request sends exactly",
          "  // the same bytes that were signed",
          "  if (normalized !== body && pm.request.body) {",
          "    pm.request.body.raw = normalized;",
          "  }",
          "}"
        ]
      }
    }
  ],
  "variable": [
    { "key": "base_url", "value": "https://api.owem.com.br", "type": "string" },
    { "key": "client_id", "value": "cli_your_client_id_here", "type": "string" },
    { "key": "client_secret", "value": "sk_your_client_secret_here", "type": "string" }
  ],
  "item": [
    {
      "name": "PIX Cash Out",
      "item": [
        {
          "name": "Cash Out by PIX Key",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "order-{{$timestamp}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\"amount\":3000,\"pix_key\":\"12345678901\",\"pix_key_type\":\"cpf\",\"description\":\"Test cash-out\",\"external_id\":\"order-9876\"}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/pix/cash-out",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "pix", "cash-out"]
            },
            "description": "Send a PIX transfer by PIX key. Amount is in **cents** on the request (R$ 30,00 = 3000). Response is in **base units** (subcentavos, R$ 30,00 = 300000). Returns HTTP 202 with `status: accepted` when queued for async processing, or HTTP 200 with `status: settled` on fast-track settlement. Terminal states arrive via webhook `pix.payout.confirmed` (status settled) or `pix.payout.failed` (status rejected)."
          }
        },
        {
          "name": "Cash Out by EMV (copy-paste)",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "order-{{$timestamp}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\"amount\":3000,\"emv\":\"00020126580014br.gov.bcb.pix0136...\",\"description\":\"Payment via QR\",\"external_id\":\"order-emv-123\"}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/pix/cash-out",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "pix", "cash-out"]
            },
            "description": "Send PIX using an EMV copy-paste string extracted from a QR code. Same endpoint as cash-out by key. The API extracts key, recipient and original amount from the EMV payload."
          }
        }
      ]
    },
    {
      "name": "PIX Cash In",
      "item": [
        {
          "name": "Generate QR Code",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "charge-{{$timestamp}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\"amount\":3000,\"description\":\"Order #1234\",\"external_id\":\"order-9876\"}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/pix/cash-in",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "pix", "cash-in"]
            },
            "description": "Generate a PIX QR code for receiving payments. Amount is in cents on the request. Returns `status: active`, the EMV `qr_code` string, a `qr_code_image` base64 PNG, and `expires_at`. Payment notification arrives via webhook `pix.charge.paid` (status paid)."
          }
        }
      ]
    },
    {
      "name": "PIX Refund",
      "item": [
        {
          "name": "Refund PIX",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "Idempotency-Key", "value": "refund-{{$timestamp}}" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\"original_transaction_id\":\"PIXINE37839059202603171234abcdef12345\",\"amount\":3000,\"reason\":\"MD06\",\"description\":\"Customer requested refund\"}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/pix/refund",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "pix", "refund"]
            },
            "description": "Initiate a PIX refund (partial or full). `original_transaction_id` is the ID of the PIX IN you want to refund. `reason` is a BACEN code (MD06, BE08, AM09, SL02, RR04). Returns `status: accepted` (HTTP 202) or `status: settled` (HTTP 200 fast-track)."
          }
        }
      ]
    },
    {
      "name": "Queries",
      "item": [
        {
          "name": "Get Transaction by ID",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/transactions/:id",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "transactions", ":id"],
              "variable": [
                { "key": "id", "value": "PIXOUT20260309a1b2c3d4e5f6", "description": "transaction_id" }
              ]
            },
            "description": "Query a transaction by `transaction_id`. Returns the full transaction data with `status` (settled/processing/failed/pending/expired/cancelled)."
          }
        },
        {
          "name": "Get Transaction by E2E ID",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/transactions/e2e/:e2e_id",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "transactions", "e2e", ":e2e_id"],
              "variable": [
                { "key": "e2e_id", "value": "E37839059202603091530abcdef01" }
              ]
            },
            "description": "Query a transaction by the BACEN End-to-End ID (format `E<ISPB><YYYYMMDDHHMM><seq>`)."
          }
        },
        {
          "name": "Get Transaction by External ID",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/transactions/ref/:external_id",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "transactions", "ref", ":external_id"],
              "variable": [
                { "key": "external_id", "value": "order-9876" }
              ]
            },
            "description": "Query a transaction by the external_id you provided at creation time. Useful for reconciliation."
          }
        },
        {
          "name": "Get Transaction by Tag (prefix)",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/transactions/tag/:tag",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "transactions", "tag", ":tag"],
              "variable": [
                { "key": "tag", "value": "PIXIN20260309", "description": "transaction_id prefix" }
              ]
            },
            "description": "Query transactions matching a transaction_id prefix. Useful for fetching all PIX IN or OUT from a given date. Returns max 50 transactions."
          }
        },
        {
          "name": "List Transactions",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/transactions?page=1&per_page=20",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "transactions"],
              "query": [
                { "key": "page", "value": "1" },
                { "key": "per_page", "value": "20" },
                { "key": "status", "value": "settled", "disabled": true },
                { "key": "type", "value": "pix", "disabled": true },
                { "key": "date_from", "value": "2026-03-01", "disabled": true },
                { "key": "date_to", "value": "2026-03-31", "disabled": true }
              ]
            },
            "description": "List transactions with pagination and filters. Status filter accepts: `processing`, `settled`, `failed`."
          }
        },
        {
          "name": "Get Transaction Receipt",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/transactions/:id/receipt",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "transactions", ":id", "receipt"],
              "variable": [
                { "key": "id", "value": "PIXOUT20260309a1b2c3d4e5f6" }
              ]
            },
            "description": "Get a structured receipt for a settled transaction. Only available for transactions with status `settled` — in-flight or failed transactions return 422."
          }
        }
      ]
    },
    {
      "name": "Account",
      "item": [
        {
          "name": "Get Balance",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/balance",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "balance"]
            },
            "description": "Get the current account balance. Returns `balance`, `available`, `pending` (all in subcentavos — divide by 10000 for BRL), and `currency: BRL`. This endpoint has NO rate limit — safe for high-frequency polling."
          }
        },
        {
          "name": "Get Statement",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/statement?page=1&per_page=20",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "statement"],
              "query": [
                { "key": "page", "value": "1" },
                { "key": "per_page", "value": "20" },
                { "key": "status", "value": "settled", "disabled": true },
                { "key": "date_from", "value": "2026-03-01", "disabled": true },
                { "key": "date_to", "value": "2026-03-31", "disabled": true }
              ]
            },
            "description": "Get account statement with pagination. Same endpoint as /transactions."
          }
        }
      ]
    },
    {
      "name": "PIX Keys",
      "item": [
        {
          "name": "List PIX Keys",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/pix/keys",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "pix", "keys"]
            },
            "description": "List all PIX keys registered for the account associated with this API key."
          }
        }
      ]
    },
    {
      "name": "MED (Refund Requests)",
      "item": [
        {
          "name": "List MEDs",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/med",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "med"]
            },
            "description": "List MED (Mecanismo Especial de Devolucao) refund requests for the account. Status is returned in UPPERCASE from OnZ/BACEN: OPEN, ACKNOWLEDGED, CLOSED, CANCELLED."
          }
        },
        {
          "name": "Get MED Details",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/med/:id",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "med", ":id"],
              "variable": [
                { "key": "id", "value": "MED20260307001" }
              ]
            },
            "description": "Get details of a specific MED by ID."
          }
        }
      ]
    },
    {
      "name": "Webhooks",
      "item": [
        {
          "name": "Create Webhook",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\"url\":\"https://your-site.com/webhook\",\"events\":[\"pix.charge.paid\",\"pix.payout.confirmed\",\"pix.payout.failed\"],\"description\":\"Production webhook\"}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/webhooks",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "webhooks"]
            },
            "description": "Register a webhook URL to receive event notifications. The response includes a `secret` field used to sign delivery payloads (HMAC-SHA256 via X-Owem-Signature header). Store this secret securely — it is NOT the same as client_secret."
          }
        },
        {
          "name": "List Webhooks",
          "request": {
            "method": "GET",
            "url": {
              "raw": "{{base_url}}/api/external/webhooks",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "webhooks"]
            },
            "description": "List all webhooks registered for the account."
          }
        },
        {
          "name": "Delete Webhook",
          "request": {
            "method": "DELETE",
            "url": {
              "raw": "{{base_url}}/api/external/webhooks/:id",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "webhooks", ":id"],
              "variable": [
                { "key": "id", "value": "wh_a1b2c3d4e5f6" }
              ]
            },
            "description": "Remove a webhook by ID."
          }
        }
      ]
    },
    {
      "name": "Validation",
      "item": [
        {
          "name": "Validate CPF",
          "request": {
            "method": "POST",
            "header": [
              { "key": "Content-Type", "value": "application/json" }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\"cpf\":\"12345678909\"}"
            },
            "url": {
              "raw": "{{base_url}}/api/external/cpf/validate",
              "host": ["{{base_url}}"],
              "path": ["api", "external", "cpf", "validate"]
            },
            "description": "Validate a Brazilian CPF (Modulo 11 algorithm). Does NOT query Receita Federal — only mathematical validation."
          }
        }
      ]
    }
  ]
}
