Query Transaction by External ID
Queries a transaction by external_id, the identifier defined by your system at creation time (cash-in or cash-out).
Endpoint
GET /api/external/transactions/ref/:external_idHeaders
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | String | Yes | ApiKey {client_id}:{client_secret} |
X-Key-Case | String | No | Set to camelCase to receive response fields in camelCase (default is snake_case) |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
external_id | String | Yes | External identifier defined at transaction creation |
When to use
This endpoint is useful for reconciliation between your system and Owem Pay. Instead of storing Owem's transaction_id, query directly by your order ID, invoice, or internal reference.
Example
curl -X GET https://api.owem.com.br/api/external/transactions/ref/order-9876 \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"Response Shapes
The response varies by transaction state. Below are the 4 possible shapes.
Shape 1 -- Settled transaction (status: "settled")
Returned when the transaction has settled and is persisted in the transactions table.
{
"worked": true,
"data": {
"id": "c7f3a8b1-2d4e-4f6a-9c1b-3e5f7a9b1d3e",
"transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
"end_to_end_id": "E37839059202603091530abcdef01",
"external_id": "order-9876",
"type": "pix",
"direction": "outbound",
"status": "settled",
"amount": 300000,
"fee_amount": 350,
"net_amount": 300350,
"description": "Pagamento fornecedor",
"counterparty_name": "Joao Silva",
"recipient_key": "12345678901",
"payer_document": null,
"recipient_document": "12345678901",
"payer_ispb": null,
"payer_bank_name": null,
"created_at": "2026-03-09T15:30:00Z",
"completed_at": "2026-03-09T15:30:02Z"
}
}| Field (top-level) | Type | Description |
|---|---|---|
id | String | Internal transaction UUID |
transaction_id | String | Public transaction identifier |
end_to_end_id | String | BACEN E2E ID |
external_id | String | Your system identifier |
type | String | pix, ted, internal |
direction | String | inbound or outbound |
status | String | Transaction status (see pix-lifecycle) |
amount | Integer | Value in base units (÷ 10,000 for BRL) |
fee_amount | Integer | Fee charged in base units |
net_amount | Integer | Net value in base units |
description | String | Transaction description |
counterparty_name | String | Counterparty name |
recipient_key | String | Recipient PIX key (outbound only) |
payer_document | String | Payer's CPF/CNPJ (inbound). null for outbound |
recipient_document | String | Recipient's CPF/CNPJ (outbound). null for inbound |
payer_ispb | String | Payer institution ISPB (inbound). null for outbound |
payer_bank_name | String | Payer's bank name (inbound). null for outbound |
created_at | String | Creation date (ISO 8601) |
completed_at | String | Completion date (ISO 8601) |
Shape 2 -- Transaction in processing (status: "processing")
Returned when the transaction is in outbound_requests awaiting BACEN response (not settled or failed yet).
{
"worked": true,
"data": {
"transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
"end_to_end_id": "E37839059202603091530abcdef01",
"external_id": "order-9876",
"amount": 300000,
"fee_amount": 350,
"net_amount": 300350,
"status": "processing",
"payment_status": "processing",
"type": "pix",
"direction": "outbound",
"pix_key": "12345678901",
"description": "Pagamento fornecedor",
"started_at": "2026-03-09T15:30:00Z"
}
}| Field | Type | Description |
|---|---|---|
transaction_id | String | Public identifier (prefix PIXOUT) |
end_to_end_id | String | BACEN E2E ID |
external_id | String | Your system identifier |
amount | Integer | Value in base units (÷ 10,000 for BRL) |
fee_amount | Integer | Fee in base units |
net_amount | Integer | amount + fee_amount in base units |
status | String | Always "processing" in this shape |
payment_status | String | Mirror of status for compatibility |
type | String | pix, ted, internal |
direction | String | outbound (shape exclusive to PIX OUT in flight) |
pix_key | String | Recipient PIX key |
description | String | Description sent in the request |
started_at | String | Moment when the request was queued (ISO 8601) |
Intermediate shape
Transactions in processing are in flight at BACEN. Do not trust this state as final — wait for the pix.payout.confirmed or pix.payout.failed webhook. Quarantine operations (stage=5, no BACEN response >30min) also return "processing" — see pix-lifecycle.
Shape 3 -- Failed transaction
Returned when the transaction is in failed_transactions (rejected by BACEN or internal failure).
{
"worked": true,
"data": {
"transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
"end_to_end_id": "E37839059202603091530abcdef01",
"external_id": "order-9876",
"amount": 300000,
"status": "failed",
"type": "pix",
"direction": "outbound",
"reason_code": "AC03",
"reason_description": "Invalid creditor account number",
"recipient": {
"name": "Joao Silva",
"key": "12345678901"
},
"failed_at": "2026-03-09T15:30:02Z"
}
}| Extra field | Type | Description |
|---|---|---|
reason_code | String | BACEN/provider code (e.g., AC03, ED05, AM02) |
reason_description | String | English description |
recipient | Object | {name, key} of the recipient |
failed_at | String | Failure date (ISO 8601) |
Shape 4 -- QR code (cash-in)
Returned when the external_id was registered on a charge QR code (paid or unpaid). Used as a fallback when there is no row in transactions or in outbound_requests.
{
"worked": true,
"data": {
"id": "e9f3df72-031f-49bf-abc3-a9ce1d540726",
"tx_id": "smyoka2zd5xowvqq2hea",
"pix_key": "evp-xxxx-xxxx-xxxx",
"amount": 100000,
"fee_amount": 0,
"status": "paid",
"external_id": "order-9876",
"description": "Pedido #1234",
"end_to_end_id": "E37839059202604101607b2fc9d8b4c6b",
"direction": "inbound",
"type": "pix_qrcode",
"created_at": "2026-04-10T16:00:00Z",
"paid_at": "2026-04-10T16:07:08Z"
}
}| Field | Type | Description |
|---|---|---|
id | String | QR code UUID |
tx_id | String | BACEN txId (QR identifier in SPI) |
pix_key | String | PIX key of the QR receiver |
amount | Integer | QR amount in base units (0 if QR has no defined value) |
fee_amount | Integer | Always 0 on the QR code (fee is charged on settlement) |
status | String | paid, pending, expired, cancelled |
external_id | String | Your system identifier |
description | String | Description provided at QR creation |
end_to_end_id | String | E2E of the PIX that paid the QR (only if status=paid). null otherwise. |
direction | String | Always "inbound" for QR code |
type | String | Always "pix_qrcode" |
created_at | String | QR creation moment (ISO 8601) |
paid_at | String | Payment moment (ISO 8601). null if not yet paid. |
All monetary values are in base units (÷ 10,000 for BRL).
Search priority
The backend looks up external_id in this order: (1) transactions → shape 1, (2) in-flight outbound_requests → shape 2, (3) failed_transactions → shape 3, (4) qrcodes → shape 4. The first table containing the ID wins.
Differences between shapes (important for client parser)
The 4 shapes share some fields (e.g., transaction_id, end_to_end_id, external_id, amount, status, type, direction) but do not have the same set of fields:
- Shape 1 (
settled): 18 fields includingfee_amount,net_amount,payer_document,payer_ispb,payer_bank_name,recipient_document,recipient_key,counterparty_name - Shape 2 (
processing): 13 fields — does not include counterparty data (payer_document,payer_ispb,recipient_documentabsent), only what is inoutbound_requests - Shape 3 (
failed): includesreason_code+reason_description+ nestedrecipient.{name, key}object (note: notrecipient_documentflat) - Shape 4 (QR code): different schema — has
tx_id,paid_at,pix_key, alwaysdirection="inbound"andtype="pix_qrcode"
Recommendation: inspect data.status first; use switch/case to dispatch to 4 distinct parsers. Do not assume cross-shape field presence.
Official receipt
To generate a formatted receipt (PDF-ready, with institution data and BRL-formatted values), use GET /api/external/transactions/:id/receipt after settlement — the /transactions/ref/:external_id endpoint provides raw data for programmatic reconciliation, not visual formatting.
Error Response -- 404
{
"worked": false,
"errors": {
"not_found": "Transação não encontrada para o external_id informado"
}
}Error Response -- 401
{
"worked": false,
"errors": {
"unauthorized": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
}
}Uniqueness
external_id is not unique per account. If multiple transactions share the same external_id, the endpoint returns the most recent. We recommend using unique values to simplify reconciliation.