# Query Cash-In by ID

Queries the status and details of a PIX transaction by its transaction ID.

## Endpoint

```
GET /api/external/transactions/:id
```

## Headers

| 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 |
|-----------|------|----------|-------------|
| `id` | String | Yes | Transaction ID (`transaction_id`) |

## Example

```bash
curl -X GET https://api.monetarie.com/api/external/transactions/7popu57v6us7p6pcicgq12345 \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"
```

## Success Response (200)

```json
{
  "worked": true,
  "data": {
    "id": "a1b2c3d4e5f64a7b8c9d0e1f2a3b4c5d",
    "transaction_id": "7popu57v6us7p6pcicgq12345",
    "end_to_end_id": "E46026562202603071530000001",
    "external_id": "order-9876",
    "type": "pix",
    "status": "settled",
    "amount": 300000,
    "fee_amount": 0,
    "net_amount": 300000,
    "description": "Pedido #1234",
    "direction": "inbound",
    "counterparty_name": "Maria Santos",
    "payer_document": "12345678901",
    "recipient_document": "46026562000165",
    "recipient_key": "contato@empresa.com.br",
    "payer_ispb": "60701190",
    "payer_bank_name": "ITAU UNIBANCO S.A.",
    "created_at": "2026-03-07T15:30:00Z",
    "completed_at": "2026-03-07T15:30:02Z"
  }
}
```

| Field | Type | Description |
|-------|------|-------------|
| `worked` | Boolean | `true` indicates operation success |
| `data.id` | String | Internal transaction ID. For **settled** transactions (default shape above), the format is **32-character lowercase hex without hyphens** (e.g., `a1b2c3d4e5f64a7b8c9d0e1f2a3b4c5d`). In other shapes (QR not yet linked, failures), the field may not be present or may have another format (UUID with hyphens when derived directly from `qrcodes.id`) |
| `data.transaction_id` | String | Public transaction identifier. For PIX IN via this pipeline, takes the form `PIXIN` + E2E (e.g., `PIXINE46026562202603071530000001`) -- **the prefix is always `PIXIN` followed by the E2E itself** (which starts with `E`). Use it as an opaque identifier; **do not** try to extract the E2E via careless string-split, as the concatenation has no separator |
| `data.end_to_end_id` | String | BACEN end-to-end ID (E2E, format `^E\d{8}[a-zA-Z0-9]{22,26}$`) |
| `data.external_id` | String \| null | Your system identifier. `null` if not provided at creation |
| `data.type` | String | `pix` for transactions settled via the normal pipeline. `pix_qrcode` when the `id` queried resolves only in `qrcodes` (QR still `pending`/`expired`/`cancelled`, OR QR already paid but not yet linked to the final row in `transactions` -- short window post-settlement). `pix_return` on received refunds (see [PIX Refunds](/en/pix-refund)) |
| `data.status` | String | Current status (see table below) |
| `data.amount` | Integer | Amount in **base units** (÷ 10,000 for BRL). `300000` = R$ 30.00 |
| `data.fee_amount` | Integer | Fee amount in base units |
| `data.net_amount` | Integer | Net amount in base units (for PIX IN, normally `amount - fee_amount`) |
| `data.description` | String \| null | Transaction description |
| `data.direction` | String | `inbound` for incoming, `outbound` for outgoing |
| `data.counterparty_name` | String \| null | For `inbound`, name of the **payer**; for `outbound`, name of the **recipient** |
| `data.payer_document` | String \| null | Payer's CPF/CNPJ. Present in received payments when the issuing bank sends it |
| `data.recipient_document` | String \| null | Recipient's CPF/CNPJ |
| `data.recipient_key` | String \| null | PIX key used in the incoming payment (evp/email/phone/cpf/cnpj) |
| `data.payer_ispb` | String \| null | 8-digit ISPB of the payer's bank |
| `data.payer_bank_name` | String \| null | Payer's bank name (resolved from the ISPB) |
| `data.created_at` | String | Creation date (ISO 8601 in UTC) |
| `data.completed_at` | String \| null | Completion date (ISO 8601 in UTC), `null` if still pending |

::: info Endpoint also answers for outbound
Despite this document's focus on receivables, `GET /api/external/transactions/:id` is **the same endpoint for PIX IN and PIX OUT**. When the `id` resolves to an outgoing in processing or a failure, the response has the format described in [Query Cash-Out by ID](/en/pix-cashout-status) (`status: processing` / `status: failed` with `reason_code`/`reason_description`).
:::

## Possible Statuses

Possible values returned in the `status` field:

| Status | Origin | Description |
|--------|--------|-------------|
| `settled` | `transactions` | **Final success state.** Payment received and credited to the account. Same value as the `pix.charge.paid` webhook with `status: "paid"`. |
| `settled` | `qrcodes` (fallback) | Also emitted when the QR has `paid_at` but the final row in `transactions` has not yet been persisted -- short window between BACEN Phase 2 ACCC and local persistence. In this case `type: "pix_qrcode"` and some fields (`end_to_end_id`, `counterparty_name`, `payer_*`) may be only partially populated |
| `pending` | `qrcodes` | QR Code generated, awaiting payment |
| `expired` | `qrcodes` | QR Code expired (TTL configurable per account, default 1h). Also applied automatically on QRs whose `expires_at` has passed but that have not yet been processed by the worker |
| `cancelled` | `qrcodes` | QR Code cancelled manually by the merchant (via portal) or in administrative operations (e.g., static→dynamic bulk migration of April 2026) |
| `failed` | `failed_transactions` | Credit attempt **rejected** (e.g., limit exceeded, account blocked, duplicate, BACEN rejection). The `reason_code` field indicates the structured reason. |

::: info Opt-in receiving controls - no default impact
If the receiving account has enabled an **opt-in** receiving control ("expected-payer verification" or "block receiving from CNPJ"), an incoming PIX that does not meet the criterion is **rejected and returned to the payer** (BACEN return) instead of credited - visible via the transaction status and webhooks. These controls are **OFF by default**; without activation, all receipts are processed normally. See [Account Controls](/en/account-controls).
:::

::: info When `failed` is emitted
Although less frequent than in cash-out, receipts **may** fail in specific scenarios: BACEN rejection post-ACSP (e.g., `AC03`, `AM02`, `DUPL`), operational limit exceeded, destination account blocked or nonexistent. In these cases, the record appears in `failed_transactions` with `direction = "inbound"` and the endpoint returns the following additional format (fields exclusive to the `failed` path):

```json
{
  "worked": true,
  "data": {
    "status": "failed",
    "transaction_id": "PIXINE46026562202603071530000001",
    "end_to_end_id": "E46026562202603071530000001",
    "amount": 300000,
    "fee_amount": 0,
    "external_id": "order-9876",
    "type": "pix",
    "direction": "inbound",
    "payment_status": "failed",
    "failure_reason": "rejected: AC03",
    "reason_code": "AC03",
    "reason_description": "Invalid creditor account number",
    "started_at": "2026-03-07T15:30:00Z",
    "failed_at": "2026-03-07T15:30:02Z",
    "recipient": {
      "name": "Empresa Exemplo LTDA",
      "key": "contato@empresa.com.br"
    }
  }
}
```

When you query by the `tx_id` of the QR and the QR has not yet been paid, the endpoint returns `pending`/`expired`/`cancelled` (derived from `qrcodes`, without a row in `transactions`). In this case the payload is reduced: `id`, `transaction_id` (= `tx_id`), `amount`, `status`, `description`, `recipient_key` (PIX key of the QR), `type: "pix_qrcode"`, `direction: "credit"`, `created_at` (when the QR was generated) and `completed_at` (when paid, or `null`). The `counterparty_name` field is `null` in this shape (it is only filled when there is a real row in `transactions`).

**Note on bulk cancellation**: during the April 2026 migration from static to dynamic QRs, a batch of active static QRs with fixed value was administratively cancelled (status `cancelled`). Queries return this status normally; no special handling is needed.
:::

## Error Response (404)

```json
{
  "worked": false,
  "detail": "Transação não encontrada"
}
```

## Error Response (401)

```json
{
  "error": {
    "status": 401,
    "message": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
  }
}
```

::: tip Polling vs Webhook
To track the status of a charge, prefer using [Webhooks](/en/webhooks) over polling. If you need to query, use intervals of at least 5 seconds.
:::
