> ## Documentation Index
> Fetch the complete documentation index at: https://docs.olympex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Get on-chain transaction status

> Check whether a transaction you broadcast is pending, succeeded, reverted or unknown, on any enabled chain.

`GET /transactions/{hash}` returns the on-chain status of a transaction on the chain you name in `?chainId=`: `pending`, `success`, `reverted` or `not_found`, with its block number, confirmations and gas used once it's mined. It works for any transaction on a chain from [`GET /chains`](/api-reference/chains/list-chains), not only Olympex swaps: use it to confirm an approval, or a swap you sent with calldata from [`POST /swap`](/api-reference/swap/build-swap). For the bridge leg of a cross-chain transfer, use [`POST /tx-status`](/api-reference/transactions/get-transaction-status).

Signed endpoint with no request body. Send `Content-Type: application/json` and the four headers `x-api-key-id`, `x-value-info`, `x-passphrase` and `x-signature` described in [Sign requests](/authentication/sign-requests), signed over the method, the path, the canonical query and the empty string. The path parameter `hash` is `0x` and 64 hexadecimal characters. The query parameter `chainId` is required and must be an integer from `GET /chains`, for example `/transactions/0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322?chainId=137`. The response `data` has `hash` (lowercase), `chainId` (a number), `status` (`pending`, `success`, `reverted` or `not_found`), `blockNumber` (`null` until mined), `confirmations` (`0` until mined) and `gasUsed` (a decimal string, `null` until mined). An unknown hash, or a hash sent with another chain's `chainId`, returns `200` with `status` `not_found`. A malformed hash, a missing `chainId` or a chain that isn't enabled returns `400 VALIDATION_ERROR`. `500 TX_STATUS_ERROR` means the request to the chain's RPC failed: retry with backoff.

## When to use it

| You want to know | Call |
| - | - |
| Whether a transaction you broadcast was mined, and whether it succeeded: a single-chain swap, an approval, or the source transaction of a cross-chain transfer. | `GET /transactions/{hash}?chainId=`, with the chain you sent it on. |
| Whether a cross-chain transfer arrived on the destination chain. | [`POST /tx-status`](/api-reference/transactions/get-transaction-status), with the source transaction hash, the source chain ID and the `dexHash` from the cross-chain `POST /swap`. |

For a cross-chain transfer, use both: confirm the source transaction here, then poll `POST /tx-status` until the transfer is final.

## Read the status

| `status` | Meaning | What to do |
| - | - | - |
| `pending` | The transaction is in the mempool: broadcast, but not mined yet. | Keep polling. |
| `success` | Mined, and the transaction succeeded. | Stop polling, or keep polling until `confirmations` reaches the number you need. For a cross-chain transfer, start polling `POST /tx-status`. |
| `reverted` | Mined, but the transaction reverted: only gas was spent. | Stop polling and show the failure. For a swap, request a new quote before you try again. |
| `not_found` | The node doesn't know the hash on this chain: the transaction isn't broadcast yet, was dropped, or was sent on another chain. | Right after you broadcast, keep polling. If it persists, check the hash and the `chainId`, and whether your wallet dropped or replaced the transaction. |

`blockNumber` and `gasUsed` are `null`, and `confirmations` is `0`, until the transaction is mined. `confirmations` counts the block that included the transaction. `gasUsed` is a decimal string, and `hash` comes back in lowercase.

## Poll after you broadcast

* **Start right away.** An unknown hash returns `200` with `not_found`, not an error, so you can poll as soon as you broadcast.
* **Poll at a steady pace**, for example every 5 to 15 seconds depending on the chain's block time. Results are cached for a few seconds, so polling faster returns the same answer.
* **Sign every attempt again.** Nonces are single-use, and the reference clients sign each call for you.
* **Retry `500 TX_STATUS_ERROR` with backoff.** It means the request to the chain's RPC failed, not that the transaction failed. Stop on a `400`: fix the hash or the `chainId` instead of retrying.
* **Set a deadline** that fits the chain. If the status is still `pending` or `not_found` when it passes, check the transaction in a block explorer and in your wallet.

<Note>
  The endpoint reads only the chain you name. A hash sent with another chain's `chainId` returns `not_found`, exactly like a transaction that was never broadcast, so always send the chain you broadcast on. It reports only the receipt status: it doesn't check which contract the transaction called, so `success` doesn't prove that the transaction was an Olympex swap.
</Note>

<RequestExample>
  ```bash cURL theme={null}
  # On-chain status of a transaction on Polygon (chain ID 137). Replace TX_HASH with your transaction hash.
  # Needs openssl, curl and OLYMPEX_API_KEY_ID, OLYMPEX_SECRET_KEY, OLYMPEX_PASSPHRASE.
  TX_HASH='0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322'
  METHOD=GET
  ENDPOINT="/transactions/$TX_HASH"
  QUERY='chainId=137'
  BODY='' # GET has no body: the signature covers the empty string
  TS="${OLYMPEX_TIMESTAMP:-$(date +%s)}"
  NONCE="${OLYMPEX_NONCE:-$(openssl rand -hex 12)}"
  BODY_HASH="$(printf '%s' "$BODY" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')"
  VALUE_INFO="$(printf '%s\n%s\n%s' "$TS" "$NONCE" "$BODY_HASH")"
  MESSAGE="$(printf 'OLPX-HMAC-SHA256-V2\n%s\n%s\n%s\n%s\n%s\n%s' "$TS" "$NONCE" "$METHOD" "/api/v1$ENDPOINT" "$QUERY" "$BODY_HASH")"
  curl -sS -X "$METHOD" "https://api-rest.olympex.io/api/v1$ENDPOINT${QUERY:+?$QUERY}" \
    -H "content-type: application/json" \
    -H "x-api-key-id: $OLYMPEX_API_KEY_ID" \
    -H "x-value-info: $(printf '%s' "$VALUE_INFO" | openssl base64 -A)" \
    -H "x-passphrase: $OLYMPEX_PASSPHRASE" \
    -H "x-signature: $(printf '%s' "$MESSAGE" | openssl dgst -sha256 -hmac "$OLYMPEX_SECRET_KEY" -binary | od -An -v -tx1 | tr -d ' \n')"
  ```

  ```ts TypeScript theme={null}
  import { OlympexApiError, olympexRequest } from "./sign-request.ts"; // /authentication/sign-requests

  type OnchainStatus = {
    hash: string;
    chainId: number;
    status: "pending" | "success" | "reverted" | "not_found";
    blockNumber: number | null;
    confirmations: number;
    gasUsed: string | null;
  };
  const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

  // Polls until the transaction is mined. Returns the last status if the deadline (epoch ms) passes first.
  const waitForTransaction = async (hash: string, chainId: number, deadline: number): Promise<OnchainStatus | undefined> => {
    let last: OnchainStatus | undefined;
    let signedAgain = false;
    while (Date.now() < deadline) {
      try {
        last = await olympexRequest<OnchainStatus>("GET", `/transactions/${hash}?chainId=${chainId}`); // signs each attempt
        if (last.status === "success" || last.status === "reverted") return last;
      } catch (error) {
        if (error instanceof OlympexApiError && error.status < 500) {
          // A gateway 401 or 403 gets one new signature. Any other 4xx won't fix itself.
          const gatewayAuth = error.code === "HTTP_401" || error.code === "HTTP_403";
          if (!gatewayAuth || signedAgain) throw error;
          signedAgain = true;
        }
        // TX_STATUS_ERROR, other 5xx and network errors: try again
      }
      await sleep(5_000);
    }
    return last;
  };

  const tx = await waitForTransaction(
    "0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322", // your transaction
    137,
    Date.now() + 5 * 60_000, // pick a deadline that fits the chain
  );
  console.log(tx?.status ?? "unknown", tx?.blockNumber, tx?.gasUsed);
  ```

  ```python Python theme={null}
  import time

  import requests

  from sign_request import OlympexApiError, olympex_request  # /authentication/sign-requests


  def wait_for_transaction(tx_hash, chain_id, deadline):
      """Poll until the transaction is mined. Return the last status if the deadline (time.monotonic()) passes first."""
      last = None
      signed_again = False
      while time.monotonic() < deadline:
          try:
              last = olympex_request("GET", f"/transactions/{tx_hash}?chainId={chain_id}")  # signs each attempt
              if last["status"] in ("success", "reverted"):
                  return last
          except OlympexApiError as error:
              if error.status < 500:
                  # A gateway 401 or 403 gets one new signature. Any other 4xx won't fix itself.
                  if error.code not in ("HTTP_401", "HTTP_403") or signed_again:
                      raise
                  signed_again = True
          except requests.RequestException:
              pass  # network error: try again
          time.sleep(5)
      return last


  tx = wait_for_transaction(
      "0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322",  # your transaction
      137,
      deadline=time.monotonic() + 5 * 60,  # pick a deadline that fits the chain
  )
  print(tx["status"] if tx else "unknown", tx and tx["blockNumber"], tx and tx["gasUsed"])
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Success theme={null}
  {
    "success": true,
    "data": {
      "hash": "0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322",
      "chainId": 137,
      "status": "success",
      "blockNumber": 89993588,
      "confirmations": 5183189,
      "gasUsed": "1771889"
    },
    "meta": {
      "requestId": "E7etVi19oAMEbXQ=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 200 Not found theme={null}
  {
    "success": true,
    "data": {
      "hash": "0xabababababababababababababababababababababababababababababababab",
      "chainId": 137,
      "status": "not_found",
      "blockNumber": null,
      "confirmations": 0,
      "gasUsed": null
    },
    "meta": {
      "requestId": "E7ehjiyBIAMEZWw=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 400 Invalid hash theme={null}
  {
    "success": false,
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid transaction hash",
      "details": [
        {
          "field": "hash",
          "message": "hash must be a 0x-prefixed 32-byte hex string"
        }
      ]
    },
    "meta": {
      "requestId": "E7ehpjcyoAMEZUw=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 400 chainId missing theme={null}
  {
    "success": false,
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "Invalid query parameters",
      "details": [
        {
          "field": "chainId",
          "message": "Invalid input: expected number, received NaN"
        }
      ]
    },
    "meta": {
      "requestId": "E7ehvhqOIAMEZUQ=",
      "version": "v1",
      "accountType": "integrator",
      "apiKeyId": "00000000-0000-4000-8000-000000000000"
    }
  }
  ```

  ```json 403 Gateway theme={null}
  {
    "message": "Forbidden"
  }
  ```
</ResponseExample>


## OpenAPI

````yaml api-reference/openapi.json GET /transactions/{hash}
openapi: 3.0.3
info:
  title: Olympex REST API
  version: 1.0.0
  description: >-
    Aggregated swap quotes and transactions, limit orders and DCA strategies on
    EVM chains, plus the chain and token catalog. Every response uses the same
    envelope, except the API gateway's own responses (`{"message": …}`): `401`
    or `403` when the signed headers are missing or rejected, `429` when it
    throttles requests, and `500` or `503` when it can't get a response from
    Olympex in time. Chain IDs are integers on every endpoint. Signed endpoints
    require four signed headers; see [Sign
    requests](https://docs.olympex.io/authentication/sign-requests).
  termsOfService: https://docs.olympex.io/legal/terms
  contact:
    name: Olympex partnerships
    email: partners@olympex.io
    url: https://docs.olympex.io
servers:
  - url: https://api-rest.olympex.io/api/v1
    description: Olympex REST API v1
security: []
tags:
  - name: Accounts
    description: Create API credentials.
  - name: Quotes
    description: Aggregated single-chain and cross-chain quotes.
  - name: Swap
    description: Unsigned transaction calldata for a quoted route.
  - name: TxStatus
    description: Track a cross-chain transfer after you broadcast it.
  - name: Transactions
    description: On-chain status of a transaction you broadcast.
  - name: Chains and tokens
    description: Enabled chains and the tokens listed on each.
  - name: Limit orders
    description: Orders that Olympex executes when the market reaches your price.
  - name: DCA
    description: Strategies that buy a token in equal orders over time.
  - name: Docs
    description: Machine-readable API description.
paths:
  /transactions/{hash}:
    get:
      tags:
        - Transactions
      summary: Get on-chain transaction status
      description: >-
        Returns the on-chain status of a transaction on an enabled chain, read
        from that chain's RPC: `pending` (known to the node, not mined yet),
        `success` or `reverted` (mined, from the receipt), or `not_found`
        (unknown to the node: not broadcast yet, dropped, or sent on another
        chain). It works for any transaction hash, not only Olympex swaps. An
        unknown hash returns `200` with `not_found`, so you can poll right after
        you broadcast. Results are cached for a few seconds. For the bridge
        status of a cross-chain transfer, use `POST /tx-status`. No request
        body: sign the empty string. The query string is signed in canonical
        form.
      operationId: getTransaction
      parameters:
        - name: hash
          in: path
          required: true
          description: 'Transaction hash: `0x` and 64 hexadecimal characters.'
          schema:
            type: string
            pattern: ^0x[0-9a-fA-F]{64}$
          example: '0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322'
        - name: chainId
          in: query
          required: true
          description: >-
            Chain ID, for example `137`. It must be one of the chains from `GET
            /chains`.
          schema:
            type: integer
            minimum: 1
          example: 137
      responses:
        '200':
          description: >-
            Transaction status. An unknown hash returns `not_found`, not an
            error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionStatusSuccessResponse'
              examples:
                success:
                  summary: Mined and successful
                  value:
                    success: true
                    data:
                      hash: >-
                        0xcf2337ce50fd03cc2d8f9a312ff1409adf96a7468e7b0ecd352203088d884322
                      chainId: 137
                      status: success
                      blockNumber: 89993588
                      confirmations: 5183189
                      gasUsed: '1771889'
                    meta:
                      requestId: E7etVi19oAMEbXQ=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
                notFound:
                  summary: Unknown hash
                  value:
                    success: true
                    data:
                      hash: >-
                        0xabababababababababababababababababababababababababababababababab
                      chainId: 137
                      status: not_found
                      blockNumber: null
                      confirmations: 0
                      gasUsed: null
                    meta:
                      requestId: E7ehjiyBIAMEZWw=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
        '400':
          description: >-
            `hash` isn't `0x` and 64 hexadecimal characters, `chainId` is
            missing or not a positive integer, or the chain isn't enabled.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: VALIDATION_ERROR
                  message: Invalid transaction hash
                  details:
                    - field: hash
                      message: hash must be a 0x-prefixed 32-byte hex string
                meta:
                  requestId: E7ehpjcyoAMEZUw=
                  version: v1
                  accountType: integrator
                  apiKeyId: 00000000-0000-4000-8000-000000000000
        '401':
          description: >-
            A signing header is missing. The gateway answers with
            `{"message":"Unauthorized"}` before your request reaches Olympex;
            the handler answers with the `UNAUTHORIZED` envelope when the
            authorizer context is missing.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ErrorResponse'
              example:
                message: Unauthorized
        '403':
          description: >-
            Authentication failed: unknown key, wrong passphrase, invalid
            signature, timestamp outside the ±300 s window, reused nonce, or
            inactive account (gateway `{"message":"Forbidden"}`). The handler
            answers with the `FORBIDDEN` envelope when the signed `bodyHash` is
            not the hash of an empty body.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ErrorResponse'
              examples:
                gateway:
                  summary: Signature rejected by the gateway
                  value:
                    message: Forbidden
                bodyHash:
                  summary: Body does not match the signed hash
                  value:
                    success: false
                    error:
                      code: FORBIDDEN
                      message: Invalid body hash
                      details: []
                    meta:
                      requestId: ENXGDhsXIAMEMEw=
                      version: v1
                      accountType: integrator
                      apiKeyId: 00000000-0000-4000-8000-000000000000
        '404':
          description: >-
            Unknown path or wrong method (`NOT_FOUND`). `error.message` names
            the method and path.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: NOT_FOUND
                  message: No route for GET /api/v1/quote
                  details: []
                meta:
                  requestId: E7edogG4IAMEPYA=
                  version: v1
        '500':
          description: >-
            Olympex could not read the transaction from the chain's RPC
            (`TX_STATUS_ERROR`) or hit an unexpected error (`INTERNAL_ERROR`),
            or the gateway could not get a response (`{"message":"Internal
            Server Error"}`), for example after a timeout of about 30 seconds.
            Retry with backoff.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ErrorResponse'
                  - $ref: '#/components/schemas/GatewayError'
        '503':
          description: >-
            The gateway could not get a response in time (the integration
            timeout is about 30 seconds) or the service is briefly unavailable.
            Returned by the gateway. Retry with backoff.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayError'
              example:
                message: Service Unavailable
      security:
        - ApiKeyId: []
          ValueInfo: []
          Passphrase: []
          Signature: []
components:
  schemas:
    TransactionStatusSuccessResponse:
      type: object
      required:
        - success
        - data
        - meta
      properties:
        success:
          type: boolean
          enum:
            - true
        data:
          $ref: '#/components/schemas/TransactionStatus'
        meta:
          $ref: '#/components/schemas/Meta'
    ErrorResponse:
      type: object
      required:
        - success
        - error
        - meta
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          $ref: '#/components/schemas/ErrorBody'
        meta:
          $ref: '#/components/schemas/Meta'
    GatewayError:
      type: object
      required:
        - message
      description: >-
        Returned by the API gateway itself: `401` or `403` when the signed
        headers are missing or rejected, `429` when it throttles requests, and
        `500` or `503` when it can't get a response from Olympex in time. It has
        no `success`, `error` or `meta`.
      properties:
        message:
          type: string
          example: Forbidden
    TransactionStatus:
      type: object
      required:
        - hash
        - chainId
        - status
        - blockNumber
        - confirmations
        - gasUsed
      properties:
        hash:
          type: string
          description: The transaction hash, in lowercase.
        chainId:
          type: integer
          description: The chain you queried.
        status:
          type: string
          enum:
            - pending
            - success
            - reverted
            - not_found
          description: >-
            `pending`: known to the node, not mined yet. `success` or
            `reverted`: mined, from the receipt's status. `not_found`: the node
            doesn't know the transaction, because it hasn't been broadcast yet,
            was dropped or was sent on another chain.
        blockNumber:
          type: integer
          nullable: true
          description: Block that included the transaction. `null` until it's mined.
        confirmations:
          type: integer
          minimum: 0
          description: >-
            Blocks since inclusion, counting the inclusion block. `0` until it's
            mined.
        gasUsed:
          type: string
          nullable: true
          description: Gas used, as a decimal string. `null` until it's mined.
    Meta:
      type: object
      required:
        - requestId
        - version
      properties:
        requestId:
          type: string
          description: Unique ID for this request. Include it when you contact support.
        version:
          type: string
          default: v1
          description: API version that served the request.
        accountType:
          type: string
          description: >-
            Account type resolved by the signature check, for example
            `integrator`. Present when the request was authenticated; absent on
            the `404` for an unknown path or method.
        apiKeyId:
          type: string
          format: uuid
          description: >-
            The API key ID that signed the request. Present when the request was
            authenticated; absent on the `404` for an unknown path or method.
    ErrorBody:
      type: object
      required:
        - code
        - message
        - details
      properties:
        code:
          type: string
          description: >-
            Machine-readable error code. `VALIDATION_ERROR` (400),
            `UNAUTHORIZED` (401), `FORBIDDEN` (403), `NOT_FOUND` (404, also for
            an unknown path or method), `CONFLICT` (409), `NO_ROUTE` (422), and
            for 500: `QUOTE_ERROR`, `CROSS_CHAIN_QUOTE_ERROR`, `SWAP_ERROR`,
            `CROSS_CHAIN_SWAP_ERROR`, `SUPPORT_CHAIN_ERROR`,
            `ENABLED_CHAINS_ERROR`, `TOKEN_LIST_ERROR`, `TX_STATUS_ERROR`,
            `INTERNAL_ERROR`. Olympex can add codes: handle an unknown code by
            its HTTP status.
        message:
          type: string
          description: Human-readable summary. Don't parse it.
        details:
          type: array
          items:
            $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      type: object
      additionalProperties: true
      description: >-
        Validation errors carry `field` and `message`; other errors carry
        `message` only.
      properties:
        field:
          type: string
          description: >-
            Dot path of the invalid field, for example `params.chainId`. Empty
            for the top level.
        message:
          type: string
  securitySchemes:
    ApiKeyId:
      type: apiKey
      in: header
      name: x-api-key-id
      description: >-
        Your API key ID (UUID). See [Sign
        requests](https://docs.olympex.io/authentication/sign-requests).
    ValueInfo:
      type: apiKey
      in: header
      name: x-value-info
      description: >-
        Base64 of `timestamp + "\n" + nonce + "\n" + bodyHash`, where
        `timestamp` is Unix seconds, `nonce` is 24 new hexadecimal characters
        and `bodyHash` is the unpadded base64url SHA-256 of the canonical body.
    Passphrase:
      type: apiKey
      in: header
      name: x-passphrase
      description: Your account passphrase. Treat it like the secret key.
    Signature:
      type: apiKey
      in: header
      name: x-signature
      description: >-
        Lowercase hex HMAC-SHA256 (signature v2), keyed with your secret key
        string (UTF-8, not decoded), of seven lines joined with `\n`, with no
        trailing newline: `OLPX-HMAC-SHA256-V2`, `timestamp`, `nonce`, the
        uppercase method, `path`, `canonicalQuery` and `bodyHash`. `path` is the
        request path including `/api/v1`, without the query string, for example
        `/api/v1/limit-order/<id>`. `canonicalQuery` is the query parameters
        decoded (`+` is a space), sorted by key and then by value, re-encoded
        per RFC 3986 and joined with `&`, or the empty string when there is no
        query. Headers signed for one request are rejected on any other. See
        [Sign requests](https://docs.olympex.io/authentication/sign-requests).

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.