<!-- ZenPays documentation · https://docs.zenpayz.com/docs/rest-api/endpoints/ramp/transaction-status -->

# Get Transaction Status

Poll the status of an on-ramp or off-ramp transaction. Use the `transactionId` returned from a checkout response.

<EndpointHeader verb="GET" path="/payment/api/v1/on-ramp/transactions/:transactionId" />

<EndpointHeader verb="GET" path="/payment/api/v1/off-ramp/transactions/:transactionId" />

## Request

### Headers

<ParamTable
  label="Header"
  rows={[
    { name: "x-request-id", desc: "Custom request ID for tracing" },
  ]}
/>

:::note Public Endpoint
This endpoint does not require authentication headers.
:::

### Path Parameters

<ParamTable
  rows={[
    { name: "transactionId", type: "string", required: true, desc: "Transaction ID from checkout response" },
  ]}
/>

## Response

### Success (200 OK)

```json
{
  "success": true,
  "data": {
    "transactionId": "txn_abc123",
    "status": "completed",
    "transactionType": "buy",
    "inAmount": 100,
    "outAmount": 0.00112,
    "sourceCurrency": "usd",
    "targetCurrency": "btc_bitcoin",
    "onramp": "moonpay",
    "paymentMethod": "creditcard",
    "walletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    "transactionHash": null,
    "statusDate": "2026-03-11T04:50:00.000Z"
  },
  "message": "Transaction retrieved"
}
```

### Response Fields

<ParamTable
  rows={[
    { name: "transactionId", type: "string", desc: "Unique transaction identifier" },
    { name: "status", type: "string", desc: "Current status (see table below)" },
    { name: "transactionType", type: "string", desc: "`buy` or `sell`" },
    { name: "inAmount", type: "number", desc: "Amount in source currency" },
    { name: "outAmount", type: "number", desc: "Amount in destination currency" },
    { name: "sourceCurrency", type: "string", desc: "Source currency ID" },
    { name: "targetCurrency", type: "string", desc: "Destination currency ID" },
    { name: "onramp", type: "string", desc: "Provider that processed the transaction" },
    { name: "paymentMethod", type: "string", desc: "Payment method used" },
    { name: "walletAddress", type: "string", desc: "Crypto wallet address" },
    { name: "transactionHash", type: "string", desc: "Blockchain transaction hash (when available)" },
    { name: "statusDate", type: "string", desc: "ISO 8601 timestamp of last status update" },
  ]}
/>

### Transaction Statuses

| Status | Description |
|--------|-------------|
| `pending` | Transaction created, awaiting user action |
| `processing` | Payment is being processed |
| `completed` | Transaction completed successfully |
| `failed` | Transaction failed |
| `expired` | Transaction expired |
| `refunded` | Transaction was refunded |

### Error Responses

<ErrorTable
  rows={[
    { code: "UNAUTHORIZED", status: "401", message: "Invalid transaction ID" },
    { code: "RAMP_TRANSACTION_FAILED", status: "500", message: "Failed to get on-ramp transaction" },
    { code: "OFFRAMP_STATUS_FAILED", status: "500", message: "Failed to get off-ramp transaction" },
  ]}
/>

<CodeRail>

## Examples

<Tabs groupId="language">
  <TabItem value="curl" label="cURL" default>

```bash
# On-ramp transaction
curl "https://api.zenpayz.com/payment/api/v1/on-ramp/transactions/txn_abc123"

# Off-ramp transaction
curl "https://api.zenpayz.com/payment/api/v1/off-ramp/transactions/txn_def456"
```

  </TabItem>
  <TabItem value="javascript" label="JavaScript">

```javascript
// Poll until completed or failed
async function pollTransaction(transactionId, type = 'on-ramp') {
  const maxAttempts = 60;
  const delayMs = 5000;

  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `https://api.zenpayz.com/payment/api/v1/${type}/transactions/${transactionId}`
    );
    const { data } = await response.json();

    if (data.status === 'completed') {
      console.log(`Completed: ${data.inAmount} ${data.sourceCurrency} → ${data.outAmount} ${data.targetCurrency}`);
      console.log(`Provider: ${data.onramp}, Hash: ${data.transactionHash}`);
      return data;
    }

    if (data.status === 'failed' || data.status === 'expired') {
      throw new Error(`Transaction ${data.status}`);
    }

    await new Promise(resolve => setTimeout(resolve, delayMs));
  }

  throw new Error('Polling timeout');
}

await pollTransaction('txn_abc123');
```

  </TabItem>
  <TabItem value="python" label="Python">

```python
import requests
import time

def poll_transaction(transaction_id, ramp_type="on-ramp", max_attempts=60, delay=5):
    for _ in range(max_attempts):
        response = requests.get(
            f"https://api.zenpayz.com/payment/api/v1/{ramp_type}/transactions/{transaction_id}"
        )
        data = response.json()["data"]

        if data["status"] == "completed":
            print(f"Completed: {data['inAmount']} {data['sourceCurrency']} → {data['outAmount']} {data['targetCurrency']}")
            print(f"Provider: {data['onramp']}, Hash: {data['transactionHash']}")
            return data

        if data["status"] in ("failed", "expired"):
            raise Exception(f"Transaction {data['status']}")

        time.sleep(delay)

    raise Exception("Polling timeout")

poll_transaction("txn_abc123")
```

  </TabItem>
</Tabs>

</CodeRail>

## Next Steps

- [Buy Checkout](/docs/rest-api/endpoints/ramp/buy-checkout) -- Create a buy checkout
- [Sell Checkout](/docs/rest-api/endpoints/ramp/sell-checkout) -- Create a sell checkout
