---
title: "Get a cross-border transaction by external id"
method: GET
path: "/irt/v1/transactions/external-id/{externalId}"
tags: ["IRT"]
---

# Get a cross-border transaction by external id

`GET /irt/v1/transactions/external-id/{externalId}`

## Request

- The document declares no server URL.
- Auth: none declared. Required headers: `ApiKey`, `MerchantId`, `Environment`

Returns the transaction you funded under this externalId — the same object the by-id lookup returns. Resolved against your own externalId namespace: a group owner looking up an externalId one of its sub-merchants registered must use the transaction id instead, because the same externalId is a valid key for the owner and for each sub-merchant at once.

## Path parameters

- `externalId` string, required

## Headers

- `ApiKey` string, required
- `MerchantId` string, required
- `Environment` 'live' | 'sandbox', required

## Response `200`

- CrossBorderTransactionDto
  - `id` string, required: Hub2 transaction identifier
  - `externalId` string, required: Merchant-owned idempotency key echoed back
  - `status` 'created' | 'pending' | 'compliance_review' | 'pending_manual' | 'successful' | 'failed' | 'cancelled', required: Current state. A successful create-and-fund returns `pending`: the float is reserved and the payout is on its way.
  - `senderId` string, required: Registered sender the payout was initiated for
  - `corridor` string, required: Corridor the payout was priced on
  - `rail` 'mobile_wallet' | 'bank_transfer', required: Last-mile rail
  - `inputCurrency` string, required: Input currency, ISO 4217
  - `inputAmount` string, required: Amount sent, exact decimal string. This is the amount converted and paid out — the Hub2 fee is charged on top of it, so the float is debited `inputAmount` plus `hub2Fee`.
  - `outputCurrency` string, required: Output currency, ISO 4217
  - `outputAmount` string, required: Amount the recipient receives, frozen at funding. Priced on the full `inputAmount` — the Hub2 fee is additive and never reduces it.
  - `hub2Fee` string, required: Total Hub2 fee applied, frozen at funding. The sum of the `fees` lines. Charged in addition to `inputAmount`, not deducted from it.
  - `fees` CrossBorderFeeDto[], required: Itemisation behind `hub2Fee`, frozen at funding and never recomputed. Each line carries the taxes reported against it.
    - `id` string, required: Unique identifier of the applied fee
    - `rate` string, required: The configured rate, as an exact two-decimal string: a percentage for `percent`, the flat amount for `flat`. On a `flat` line it normally equals `amount`. Where the configured rate is finer than the currency's minor unit the two differ by a cent, and `amount` is the one that was charged.
    - `type` 'flat' | 'percent', required: How the fee is derived from the amount sent. `percent` applies the rate as a percentage of it; `flat` applies the rate as is.
    - `amount` string, required: Amount charged by this line, in `currency`, as an exact two-decimal string — the same format as the `hub2Fee` total it sums into
    - `currency` string, required: Currency the fee is charged in, ISO 4217. Always the input currency.
    - `label` string: Optional label explaining the reason for this fee
    - `taxes` CrossBorderFeeTaxDto[], required: Taxes applicable to this fee line. Reported for your records — never charged.
      - `id` string, required: Unique identifier of the tax row
      - `taxType` 'tva', required: The kind of tax applied
      - `type` 'flat' | 'percent', required: Whether the tax is a percentage of the fee or a flat amount
      - `value` string, required: Tax rate or amount, per `type`, as an exact two-decimal string
  - `hub2Rate` string, required: Exchange rate applied, frozen at funding and never recalculated
  - `description` string: Free-text description carried on the transaction
  - `failureCause` CrossBorderTransactionFailureCauseDto
    - `code` 'unknown_reason' | 'internal_error' | 'service_unavailable' | 'service_temporarily_disabled' | 'too_many_request' | 'timeout' | 'insufficient_funds' | 'hub2_insufficient_funds' | 'forbidden_by_provider' | 'forbidden_by_provider_maximum_limit' | 'canceled' | 'unsupported_currency' | 'invalid_payment_processor' | 'invalid_amount' | 'fraud_suspicion' | 'invalid_destination' | 'bad_request' | 'duplicate_request' | 'authentication_failed' | 'bad_parameters', required: Failure cause code
    - `message` string: Human-readable message, when the partner provided one
  - `duplicateConfirmation` DuplicateConfirmationDto
    - `rejectionId` string, required: The `rejection_id` of the `possible_duplicate` refusal this payout confirmed.
  - `createdAt` string, required: Creation timestamp, ISO 8601
  - `updatedAt` string, required: Timestamp of the last state change, ISO 8601. Equal to "createdAt" until the transaction first moves, so a lookup can tell a payout still awaiting its partner from one that settled without a webhook arriving.
  - `idempotentReplay` true: Present, and `true`, only when the response replays an existing payout (idempotent replay, HTTP 200 with the `X-Idempotent-Replay: true` header). Absent when the transaction has just been created.

## Other responses

- `401`: Wrong credentials
- `404`: No transaction of yours carries this externalId.
- `429`: ThrottlerException: Too Many Requests
- `500`: Internal error

## Changes

- **2026-11-03** `f6d3f87df5e0`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/hub2/apis/hub2-service-api/changes/irt/v1/transactions/external-id/:externalId/get.md)

---

[API](https://skmtc.dev/hub2/apis/hub2-service-api.md) - [All operations](https://skmtc.dev/hub2/apis/hub2-service-api/llms.txt) - [OpenAPI document](https://skmtc.dev/hub2/apis/hub2-service-api/revisions/f6d3f87df5e0?raw)
