> For a complete page index, fetch https://docs.transak.com/llms.txt

# WebSockets

Transak uses WebSockets to push real-time order updates to your server and sends event data continuously over a live connection to ensure faster updates.

Transak WebSockets are powered by **Pusher Channels**. Use the **Pusher client library** for your platform, as a plain WebSocket client is not compatible.

**Pusher App Key:** `1d9ffac87de599c61283` | **Cluster:** `ap2`

## When to Use?

<thead>
  <tr>
    <th>
      Use Case
    </th>

    <th>
      Channel
    </th>

    <th>
      How to track
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Track a single order in your frontend
    </td>

    <td>
      Public
    </td>

    <td>
      By Order ID
    </td>
  </tr>

  <tr>
    <td>
      Track a specific order using your own reference
    </td>

    <td>
      Public
    </td>

    <td>
      By API Key + 

      `partnerOrderId`
    </td>
  </tr>

  <tr>
    <td>
      Track all orders server-side
    </td>

    <td>
      Private
    </td>

    <td>
      Encrypted, backend only
    </td>
  </tr>
</tbody>

---

## Channels

<thead>
  <tr>
    <th>
      Channel
    </th>

    <th>
      Channel Name
    </th>

    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Receive order updates using the order ID
    </td>

    <td>
      <code />
    </td>

    <td>
      **Public channel**

      : Track an order by entering the order ID in the channel name.
    </td>
  </tr>

  <tr>
    <td>
      Receive order updates using your API Key and 

      `partnerOrderId`
    </td>

    <td>
      <code />
    </td>

    <td>
      **Public channel**

      : Track an order using your API key and your own order reference (

      `partnerOrderId`

      ). Generate a unique order ID and pass it as the 

      `partnerOrderId`

       query parameter before opening the widget.
    </td>
  </tr>

  <tr>
    <td>
      Receive all order updates using your API Key & Access Token
    </td>

    <td>
      <code />
    </td>

    <td>
      **Private channel**

      : Track all orders using your 

      `API_KEY`

       & 

      `ACCESS_TOKEN`

      . The payload is encrypted - decrypt it with your 

      `ACCESS_TOKEN`

       using the 

      `jsonwebtoken`

       npm library.
    </td>
  </tr>
</tbody>

For the private channel stream, ensure the WebSocket connection is handled by your backend application, as exposing it on the client side may compromise your Access Token.

## Events

#### On Ramp / NFT Checkout

<thead>
  <tr>
    <th>
      WebSocket Event Code
    </th>

    <th>
      Status
    </th>

    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      ORDER\_CREATED
    </td>

    <td>
      `AWAITING_PAYMENT_FROM_USER`
    </td>

    <td>
      When the order has been created but the payment has not yet been received.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_PAYMENT\_VERIFYING
    </td>

    <td>
      `PAYMENT_DONE_MARKED_BY_USER`
    </td>

    <td>
      When the user marks the payment as done but Transak has not yet received it.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_PROCESSING
    </td>

    <td>
      `PROCESSING`
    </td>

    <td>
      Orders in the PROCESSING state have passed checks and the user's payment information has been validated.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_PROCESSING
    </td>

    <td>
      `PENDING_DELIVERY_FROM_TRANSAK`
    </td>

    <td>
      When the payment is received and being exchanged & transferred via Transak or a liquidity partner.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_COMPLETED
    </td>

    <td>
      `COMPLETED`
    </td>

    <td>
      When Transak has received the payment and the crypto has been sent successfully to the user.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_FAILED
    </td>

    <td>
      `EXPIRED`
    </td>

    <td>
      When the user failed to make the payment within the timeframe.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_FAILED
    </td>

    <td>
      `FAILED`
    </td>

    <td>
      When the order failed because the card was declined.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_FAILED
    </td>

    <td>
      `CANCELLED`
    </td>

    <td>
      When the user cancels the order.
    </td>
  </tr>
</tbody>

#### Off Ramp

<thead>
  <tr>
    <th>
      WebSocket Event Code
    </th>

    <th>
      Status
    </th>

    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      ORDER\_CREATED
    </td>

    <td>
      `AWAITING_PAYMENT_FROM_USER`
    </td>

    <td>
      When the order is created but the payment has not yet been received.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_PAYMENT\_VERIFYING
    </td>

    <td>
      `PAYMENT_DONE_MARKED_BY_USER`
    </td>

    <td>
      When the user marks the payment as done but it has not been received by Transak yet.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_PROCESSING
    </td>

    <td>
      `PENDING_DELIVERY_FROM_TRANSAK`
    </td>

    <td>
      When the payment is received and reconciled and Transak has initiated a fiat transfer to the user.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_PROCESSING
    </td>

    <td>
      `ON_HOLD_PENDING_DELIVERY_FROM_TRANSAK`
    </td>

    <td>
      When the crypto payment is received & fiat is being transferred via the banking partner but the system is unable to send fiat to the user.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_COMPLETED
    </td>

    <td>
      `COMPLETED`
    </td>

    <td>
      When Transak has received the crypto payment and fiat has been sent successfully to the user's bank account.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_FAILED
    </td>

    <td>
      `EXPIRED`
    </td>

    <td>
      When the user failed to make the payment within the timeframe.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_FAILED
    </td>

    <td>
      `FAILED`
    </td>

    <td>
      Due to third-party failure.
    </td>
  </tr>

  <tr>
    <td>
      ORDER\_FAILED
    </td>

    <td>
      `CANCELLED`
    </td>

    <td>
      When the user manually cancels the order.
    </td>
  </tr>
</tbody>

---

## Integration

Select your framework, then choose a channel type to get started.

#### React / React Native

#### Install Dependency

#### React

```bash
npm install pusher-js
```

#### React Native

```bash
npm install pusher-js @react-native-community/netinfo
```

#### Subscribe to a Channel

#### By Order ID

```javascript
import { useEffect } from 'react';
import Pusher, { Channel } from 'pusher-js';

function App() {
  const transakOrderId: string = 'TRANSAK_ORDER_ID'; // Replace with your Transak Order ID

  useEffect(() => {
    const pusher: Pusher = new Pusher('1d9ffac87de599c61283', {
      cluster: 'ap2',
    });

    const orderChannel: Channel = pusher.subscribe(transakOrderId);

    orderChannel.bind('ORDER_COMPLETED', (data: any) => {
      console.log(`${transakOrderId} ORDER_COMPLETED:`, data);
    });

    return () => {
      orderChannel.unbind_all();
      pusher.unsubscribe(transakOrderId);
      pusher.disconnect();
    };
  }, []);

  return <div>{/* Your UI */}</div>;
}

export default App;
```

#### By Partner Order ID

```javascript
import { useEffect } from 'react';
import Pusher, { Channel } from 'pusher-js';

function App() {
  const apiKey: string = 'YOUR_API_KEY';           // Replace with your API Key
  const partnerOrderId: string = 'PARTNER_ORDER_ID'; // Replace with your Partner Order ID

  useEffect(() => {
    const pusher: Pusher = new Pusher('1d9ffac87de599c61283', {
      cluster: 'ap2',
    });

    const channelName = `${apiKey}_${partnerOrderId}`;
    const partnerOrderChannel: Channel = pusher.subscribe(channelName);

    partnerOrderChannel.bind_global((eventId: string, orderData: any) => {
      if (eventId !== 'pusher:subscription_succeeded') {
        console.log(`${partnerOrderId} ${eventId}:`, orderData);
      }
    });

    return () => {
      partnerOrderChannel.unbind_all();
      pusher.unsubscribe(channelName);
      pusher.disconnect();
    };
  }, []);

  return <div>{/* Your UI */}</div>;
}

export default App;
```

#### All Orders

```javascript
import { useEffect } from 'react';
import Pusher, { Channel } from 'pusher-js';
import { jwtDecode } from 'jwt-decode';

function App() {
  const partnerApiKey: string = 'YOUR_API_KEY'; // Replace with your API Key

  useEffect(() => {
    const pusher: Pusher = new Pusher('1d9ffac87de599c61283', {
      cluster: 'ap2',
    });

    const allOrdersChannel: Channel = pusher.subscribe(partnerApiKey);

    allOrdersChannel.bind_global((event: string, data: any) => {
      if (event !== 'pusher:subscription_succeeded') {
        try {
          const decoded = jwtDecode(data);
          console.log(`[allOrders] ${event} Decoded:`, decoded);
        } catch (err) {
          console.warn('Failed to decode JWT. Using raw data.', err);
        }
      }
    });

    return () => {
      allOrdersChannel.unbind_all();
      pusher.unsubscribe(partnerApiKey);
      pusher.disconnect();
    };
  }, []);

  return <div></div>;
}

export default App;
```

#### Node.js

#### Install Dependency

```bash
npm install pusher-js
```

#### Subscribe to a Channel

#### By Order ID

```javascript
const Pusher = require('pusher-js');

const orderId = 'TRANSAK_ORDER_ID'; // Replace with your Transak Order ID

const pusher = new Pusher('1d9ffac87de599c61283', { cluster: 'ap2' });
const orderChannel = pusher.subscribe(orderId);

orderChannel.bind('ORDER_COMPLETED', (data) => {
  console.log(`${orderId} ORDER_COMPLETED:`, data);
});

```

#### By Partner Order ID

```javascript
const Pusher = require('pusher-js');

const apiKey = 'YOUR_API_KEY';           // Replace with your API Key
const partnerOrderId = 'PARTNER_ORDER_ID'; // Replace with your Partner Order ID

const channelName = `${apiKey}_${partnerOrderId}`;
const pusher = new Pusher('1d9ffac87de599c61283', { cluster: 'ap2' });
const partnerOrderChannel = pusher.subscribe(channelName);

partnerOrderChannel.bind_global((eventId, data) => {
  if (eventId !== 'pusher:subscription_succeeded') {
    console.log(`${partnerOrderId} ${eventId}:`, data);
  }
});
```

#### All Orders

```javascript
const Pusher = require('pusher-js');
const jwt = require('jsonwebtoken');

const apiKey = 'YOUR_API_KEY';       // Replace with your API Key
const accessToken = 'ACCESS_TOKEN';  // Replace with your Access Token

const pusher = new Pusher('1d9ffac87de599c61283', { cluster: 'ap2' });
const allOrdersChannel = pusher.subscribe(apiKey);

allOrdersChannel.bind_global((eventId, encryptedData) => {
  if (eventId !== 'pusher:subscription_succeeded') {
    try {
      const decoded = jwt.verify(encryptedData, accessToken);
      console.log(`${apiKey} ${eventId} Decoded:`, decoded);
    } catch (err) {
      console.warn('Failed to decode JWT:', err);
    }
  }
});
```

#### JavaScript (Browser)

#### Add the Pusher script

Add Pusher script to your HTML `<head>`:

```html
<script src="https://js.pusher.com/6.0/pusher.min.js"></script>
```

#### Subscribe to a Channel

#### By Order ID

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Transak WebSocket – Order ID</title>
  <script src="https://js.pusher.com/6.0/pusher.min.js"></script>
</head>
<body>
  <script>
    const orderId = 'TRANSAK_ORDER_ID'; // Replace with your Transak Order ID

    const pusher = new Pusher('1d9ffac87de599c61283', { cluster: 'ap2' });
    const orderChannel = pusher.subscribe(orderId);

    orderChannel.bind('ORDER_COMPLETED', (data) => {
      console.log(`${orderId} ORDER_COMPLETED:`, data);
    });

  </script>
</body>
</html>
```

#### By Partner Order ID

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Transak WebSocket – Partner Order ID</title>
  <script src="https://js.pusher.com/6.0/pusher.min.js"></script>
</head>
<body>
  <script>
    const apiKey = 'YOUR_API_KEY';           // Replace with your API Key
    const partnerOrderId = 'PARTNER_ORDER_ID'; // Replace with your Partner Order ID

    const channelName = `${apiKey}_${partnerOrderId}`;
    const pusher = new Pusher('1d9ffac87de599c61283', { cluster: 'ap2' });
    const partnerOrderChannel = pusher.subscribe(channelName);

    partnerOrderChannel.bind_global((eventId, data) => {
      if (eventId !== 'pusher:subscription_succeeded') {
        console.log(`${partnerOrderId} ${eventId}:`, data);
      }
    });
  </script>
</body>
</html>
```

#### All Orders

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Transak WebSocket – All Orders</title>
  <script src="https://js.pusher.com/6.0/pusher.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/jwt-decode@4.0.0/build/cjs/index.min.js"></script>
</head>
<body>
  <script>
    const apiKey = 'YOUR_API_KEY';      // Replace with your API Key
    const accessToken = 'ACCESS_TOKEN'; // Replace with your Access Token

    const pusher = new Pusher('1d9ffac87de599c61283', { cluster: 'ap2' });
    const allOrdersChannel = pusher.subscribe(apiKey);

    allOrdersChannel.bind_global((eventId, encryptedData) => {
      if (eventId !== 'pusher:subscription_succeeded') {
        try {
          const decoded = jwtDecode(encryptedData);
          console.log(`${apiKey} ${eventId} Decoded:`, decoded);
        } catch (err) {
          console.warn('Failed to decode JWT:', err);
        }
      }
    });
  </script>
</body>
</html>
```

#### Mobile

Follow the official Pusher guides for your mobile platform:

#### [Java (Android)](https://pusher.com/docs/channels/getting_started/android)

Set up Pusher Channels in your Android app using the Java SDK.

#### [iOS (Swift)](https://pusher.com/docs/channels/getting_started/ios)

Set up Pusher Channels in your iOS app using the Swift SDK.

#### [Flutter](https://pusher.com/docs/channels/getting_started/flutter)

Set up Pusher Channels in your Flutter app for cross-platform support.

---

### Sample Response

A typical event payload received on any channel looks like this:

```json
{
  "event": "ORDER_CREATED",
  "data": {
    "id": "aa39d8e1-…-ce7f",
    "walletAddress": "0xD902…BEFeE",
    "createdAt": "2025-04-04T13:11:47.260Z",
    "status": "AWAITING_PAYMENT_FROM_USER",
    "fiatCurrency": "GBP",
    "userId": "243a8ce2-…-b19a3",
    "cryptoCurrency": "ETH",
    "isBuyOrSell": "BUY",
    "fiatAmount": 30,
    "ipAddress": "14.142.***.***",
    "amountPaid": 0,
    "paymentOptionId": "gbp_bank_transfer",
    "walletLink": "https://sepolia.etherscan.io/address/0xD902…BEFeE",
    "quoteId": "9291a8bc-…-04e85",
    "orderProcessingType": "NORMAL",
    "addressAdditionalData": false,
    "network": "ethereum",
    "conversionPrice": 0.0006130127560164107,
    "cryptoAmount": 0.01759347,
    "totalFeeInFiat": 1.3,
    "fiatAmountInUsd": 33.05,
    "countryCode": "GB",
    "partnerOrderId": "partner-order-id",
    "stateCode": "London",
    "orderChannelType": "WIDGET",
    "tokenContractAddress": "0x0000…0000",
    "userKycType": "STANDARD",
    "updatedAt": "2025-04-04T13:11:48.374Z",
    "cardPaymentData": {},
    "conversionPriceData": {},
    "partnerFeeInLocalCurrency": 0.3,
    "statusHistories": []
  }
}
```