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

# Real-time quotes (WebSocket)

> Receive live rates and firm quotes over Socket.IO instead of polling the quote endpoint.

The quote WebSocket pushes the rate, or a full quote, every time it changes. It uses the same pricing rules as [Get Quote](/stack/api-reference/liquidity-ramps/get-quote), so a quote received through the socket can be used to create an operation.

| Environment | URL | Path |
| - | - | - |
| Test | `wss://ws-test.kravata.co` | `/kmsktransaction/socket.io` |
| Production | `wss://ws.kravata.co` | `/kmsktransaction/socket.io` |

The server uses [Socket.IO](https://socket.io/) (protocol v4). Use an official Socket.IO client, such as `socket.io-client` for JavaScript or `python-socketio` for Python.

## Connect

Authenticate with the same access token you use for the REST API (see [Authentication](/stack/authentication)). Send it in the `auth` payload as `token`, or in the `Authorization: Bearer <token>` header. Your [IP allowlist](/stack/api-reference/authentication/update-ip-allowlist) also applies to the socket.

```javascript theme={null}
import { io } from "socket.io-client";

const socket = io("wss://ws.kravata.co", {
  path: "/kmsktransaction/socket.io",
  transports: ["websocket"],
  // A function, so a fresh token is used every time the client reconnects.
  auth: async (cb) => cb({ token: await getAccessToken() }),
});

socket.on("connect_error", (err) => console.error(err.message)); // "unauthorized" or "forbidden"
```

The token is validated once, when connecting. An open connection stays active after the token expires; only a reconnection needs a valid token.

| Connection error | Cause |
| - | - |
| `unauthorized` | Missing, invalid or expired token, or the token is not a client token. |
| `forbidden` | Your IP is not in your IP allowlist. |

## Subscribe

Emit `subscribe` with the same body as [Get Quote](/stack/api-reference/liquidity-ramps/get-quote).

<table>
  <colgroup>
    <col width="177" />

    <col width="77" />

    <col width="102" />

    <col width="264" />
  </colgroup>

  <thead>
    <tr>
      <td>**Field**</td>
      <td>**Type**</td>
      <td>**Required**</td>
      <td>**Description**</td>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>amount</td>
      <td>float</td>
      <td>Yes</td>
      <td>This is the amount you will operate and send.</td>
    </tr>

    <tr>
      <td>direction</td>
      <td>string</td>
      <td>Yes</td>
      <td>The type of order/ ramp you will create ("DEPOSIT": if you have Fiat and want to receive stablecoin; "WITHDRAWAL": if you have stablecoin and want to receive Fiat).</td>
    </tr>

    <tr>
      <td>symbolOrigin</td>
      <td>string</td>
      <td>Yes</td>
      <td>The symbol of the token/fiat you will send us (COP, USDC, USDT).</td>
    </tr>

    <tr>
      <td>symbolDestination</td>
      <td>string</td>
      <td>Yes</td>
      <td>The symbol of the token/fiat we will send you (COP,USDC, USDT).</td>
    </tr>

    <tr>
      <td>paymentMethod</td>
      <td>string</td>
      <td>No</td>
      <td>The channel used to move the funds. Select the value that matches your operation type and currency. Allowed values: BREB and PSE for deposit and ACH and BREB for withdrawal. Predefined values: PSE if deposit, ACH if withdrawal.</td>
    </tr>
  </tbody>
</table>

<table>
  <colgroup>
    <col width="177" />

    <col width="77" />

    <col width="102" />

    <col width="264" />
  </colgroup>

  <thead>
    <tr>
      <td>**Field**</td>
      <td>**Type**</td>
      <td>**Required**</td>
      <td>**Description**</td>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>amount</td>
      <td>float</td>
      <td>Yes</td>
      <td>This is the amount you will operate and send.</td>
    </tr>

    <tr>
      <td>direction</td>
      <td>string</td>
      <td>Yes</td>
      <td>The type of order/ ramp you will create ("DEPOSIT": if you have Fiat and want to receive stablecoin; "WITHDRAWAL": if you have stablecoin and want to receive Fiat).</td>
    </tr>

    <tr>
      <td>symbolOrigin</td>
      <td>string</td>
      <td>Yes</td>
      <td>The symbol of the token/fiat you will send us (COP, USDC, USDT).</td>
    </tr>

    <tr>
      <td>symbolDestination</td>
      <td>string</td>
      <td>Yes</td>
      <td>The symbol of the token/fiat we will send you (COP,USDC, USDT).</td>
    </tr>

    <tr>
      <td>paymentMethod</td>
      <td>string</td>
      <td>No</td>
      <td>The channel used to move the funds. Select the value that matches your operation type and currency. Allowed values: BREB and PSE for deposit and ACH and BREB for withdrawal. Predefined values: PSE if deposit, ACH if withdrawal.</td>
    </tr>
  </tbody>
</table>

The acknowledgement is `{"status": "ok"}`, or an error:

```json theme={null}
{ "status": "error", "reason": "invalid subscription", "errors": [{ "loc": ["direction"], "msg": "Field required", "type": "missing" }] }
```

Each connection has one subscription: emitting `subscribe` again replaces it. Emit `unsubscribe` to stop receiving updates without disconnecting.

## Updates

<CodeGroup>
  ```json Live rate theme={null}
  {
    "symbolOrigin": "USDC",
    "symbolDestination": "COP",
    "calculatedValues": { "calculateRate": 3910.25 },
    "date": "2026-10-01T15:04:00.123456+00:00"
  }
  ```

  ```json Live rate with rail theme={null}
  {
    "symbolOrigin": "USDC",
    "symbolDestination": "COP",
    "paymentMethod": "BREB",
    "calculatedValues": { "calculateRate": 3910.25, "CostInfra": 3500 },
    "date": "2026-10-01T15:04:00.123456+00:00"
  }
  ```

  ```json Firm quote theme={null}
  {
    "direction": "WITHDRAWAL",
    "paymentMethod": "BREB",
    "amountOrigin": 100,
    "amountDestination": 387525.0,
    "symbolOrigin": "USDC",
    "symbolDestination": "COP",
    "calculatedValues": { "calculateRate": 3910.25, "CostInfra": 3500, "amountReceive": 387525.0 },
    "quoteId": "6f1d2c3b-4a5e-4f60-9b7c-8d9e0f1a2b3c",
    "expiresAt": "2026-10-01T15:05:00Z"
  }
  ```
</CodeGroup>

If a quote cannot be calculated, `rate_update` carries `{"status": "error", "reason": "..."}`. Validation problems show their message; other failures show `Quote unavailable`.

### When updates are sent

* Immediately after you subscribe.
* Every time the market rate changes.
* In addition, every 60 seconds between **8:00 and 22:00 (Bogotá time)**, so a firm quote always has a valid `quoteId`.

## Use a firm quote

A `quoteId` is valid for **60 seconds** and for the same amount and assets it was issued for. Send it in the `quoteId` field when you [create a withdrawal](/stack/api-reference/liquidity-ramps/create-withdrawal) or a [deposit](/stack/api-reference/liquidity-ramps/create-deposit) to apply that exact quote. Every new update replaces the previous `quoteId`, so always use the latest one.


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