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

# Applications

> Application configuration and public reporting

`getApplicationConfig` is session-authenticated (call it after a user logs in). The five reporting methods are public: they need no session or key, and each selects its application by `clientId` — the same public client ID your frontend logs in with. An unknown or inactive client ID returns `404`.

The reporting methods are rate limited per client IP: 60 requests per minute sustained, with a burst of 120. Over the limit the API returns `429` with a `Retry-After` header.

```typescript theme={null}
import { MonacoSDK } from "@0xmonaco/core";

// Session auth (after user login)
await sdk.applications.getApplicationConfig();

// Public reporting: select the application by client ID
const clientId = "6fe0da813f1a4adcbe675d52ca530a43";

await sdk.applications.listApplicationOrders({ clientId, status: "FILLED" });
await sdk.applications.listApplicationUsers({ clientId, isActive: true });
await sdk.applications.listApplicationMovements({ clientId, transactionType: "TRADE" });
await sdk.applications.listApplicationBalances({ clientId, assetId: "..." });
await sdk.applications.getApplicationStats({ clientId, since: "2026-01-01T00:00:00Z" });
```

<ResponseField name="getApplicationConfig" type="() => Promise<ApplicationConfigResponse>">
  Retrieve application configuration for the current client ID. Session-authenticated.

  **Returns:** `ApplicationConfigResponse`:

  * `id`: string — application UUID
  * `name`: string — application name
  * `allowedOrigins`: string\[] — CORS-allowed origins
  * `webhookUrl?`: string — webhook URL for event delivery
  * `vaultContractAddress`: string — vault contract address for this application
  * `clientId`: string — application client ID, embedded in on-chain deposit calls
</ResponseField>

<ResponseField name="listApplicationOrders" type="(params: ListAppOrdersParams) => Promise<ListAppOrdersResponse>">
  List orders placed by the application's users. Public.

  **Parameters:**

  * `params`: `ListAppOrdersParams`
    * `clientId`: string — the application's public client ID (required)
    * `pageSize?`: number — items per page, 1 to 1000 (default 20); a larger value is rejected
    * `pageToken?`: string — cursor pagination. Omitted or `""` starts the walk; otherwise pass the previous response's `nextPageToken`. There is no `page`: the SDK rejects one with a `ValidationError` before sending, and a raw REST request carrying it gets `400`. The filters must match the request that minted the token
    * `status?`: string — filter by order status (e.g. `SUBMITTED`, `PARTIALLY_FILLED`, `FILLED`, `SETTLED`, `CANCELLED`, `EXPIRED`, `REJECTED`)
    * `userId?`: string — filter by user UUID
    * `tradingPairId?`: string — filter by trading pair UUID
    * `side?`: string — filter by side: `BUY` or `SELL`
    * `orderType?`: string — filter by order type (e.g. `LIMIT`, `MARKET`, `STOP_LOSS`, `TAKE_PROFIT`, `STOP_LIMIT`, `TRAILING_STOP`)

  **Returns:** `ListAppOrdersResponse`:

  * `orders`: `AppOrder[]` — matching orders
  * `pageSize`: number — items per page
  * `nextPageToken`: string — cursor for the next page, `""` once the walk is exhausted. Each page over-fetches one row, so an empty token is definitive: follow a non-empty token, stop on an empty one

  No item count: this listing spans the hot order table and the archive, so counting behind a filter would walk the application's whole lifetime prefix on every page.
</ResponseField>

<ResponseField name="listApplicationUsers" type="(params: ListAppUsersParams) => Promise<ListAppUsersResponse>">
  List the application's users. Public.

  **Parameters:**

  * `params`: `ListAppUsersParams`
    * `clientId`: string — the application's public client ID (required)
    * `pageSize?`: number — items per page, 1 to 1000 (default 20); a larger value is rejected
    * `pageToken?`: string — cursor pagination. Omitted or `""` starts the walk; otherwise pass the previous response's `nextPageToken`. There is no `page`: the SDK rejects one with a `ValidationError` before sending, and a raw REST request carrying it gets `400`. The filters must match the request that minted the token
    * `isActive?`: boolean — filter by active status
    * `accountType?`: string — filter by account type: `master` or `sub`
    * `address?`: string — filter by wallet address (partial match, case-insensitive)

  **Returns:** `ListAppUsersResponse`:

  * `users`: `AppUser[]` — matching users
  * `total`: number — users matching the filter, bounded by the server count ceiling
  * `pageSize`: number — items per page
  * `totalPages`: number — pages at this `pageSize`, bounded by the same ceiling
  * `nextPageToken`: string — cursor for the next page, `""` once the walk is exhausted. Each page over-fetches one row, so an empty token is definitive: follow a non-empty token, stop on an empty one
  * `totalCapped`: boolean — `true` when more than the server ceiling matched, so `total` / `totalPages` are a lower bound

  Ordered by user id ascending, **not** newest-first: `created_at` is nullable on this table, so it cannot be a total cursor key, and excluding the rows without one would hide users from the listing an application reconciles against.
</ResponseField>

<ResponseField name="listApplicationMovements" type="(params: ListAppMovementsParams) => Promise<ListAppMovementsResponse>">
  List ledger movements (deposits, withdrawals, trades, fees, etc.) for the application's users. Public.

  **Parameters:**

  * `params`: `ListAppMovementsParams`
    * `clientId`: string — the application's public client ID (required)
    * `pageSize?`: number — items per page, 1 to 1000 (default 20); a larger value is rejected
    * `pageToken?`: string — cursor pagination. Omitted or `""` starts the walk; otherwise pass the previous response's `nextPageToken`. There is no `page`: the SDK rejects one with a `ValidationError` before sending, and a raw REST request carrying it gets `400`. The filters must match the request that minted the token
    * `userId?`: string — filter by user UUID
    * `transactionType?`: string — filter by transaction type (e.g. `DEPOSIT`, `WITHDRAWAL`, `TRADE`, `FEE`, `FUNDING`, `LIQUIDATION`, `INTEREST`, `REWARD`)
    * `entryType?`: string — filter by entry type (e.g. `CREDIT`, `DEBIT`, `LOCK`, `UNLOCK`, `FEE`)
    * `assetId?`: string — filter by asset UUID

  **Returns:** `ListAppMovementsResponse`:

  * `movements`: `AppMovement[]` — matching movements
  * `pageSize`: number — items per page
  * `nextPageToken`: string — cursor for the next page, `""` once the walk is exhausted. Each page over-fetches one row, so an empty token is definitive: follow a non-empty token, stop on an empty one

  No item count: the underlying ledger is too large to count behind a filter. A movement with no recorded timestamp is not listed — the column is nullable, and a NULL has no position in the cursor's sort key.
</ResponseField>

<ResponseField name="listApplicationBalances" type="(params: ListAppBalancesParams) => Promise<ListAppBalancesResponse>">
  List user balances held within the application. Public.

  **Parameters:**

  * `params`: `ListAppBalancesParams`
    * `clientId`: string — the application's public client ID (required)
    * `pageSize?`: number — items per page, 1 to 1000 (default 20); a larger value is rejected
    * `pageToken?`: string — cursor pagination. Omitted or `""` starts the walk; otherwise pass the previous response's `nextPageToken`. There is no `page`: the SDK rejects one with a `ValidationError` before sending, and a raw REST request carrying it gets `400`. The filters must match the request that minted the token
    * `userId?`: string — filter by user UUID
    * `assetId?`: string — filter by asset UUID

  **Returns:** `ListAppBalancesResponse`:

  * `balances`: `AppBalance[]` — matching balances
  * `total`: number — balances matching the filter, bounded by the server count ceiling
  * `pageSize`: number — items per page
  * `totalPages`: number — pages at this `pageSize`, bounded by the same ceiling
  * `nextPageToken`: string — cursor for the next page, `""` once the walk is exhausted. Each page over-fetches one row, so an empty token is definitive: follow a non-empty token, stop on an empty one
  * `totalCapped`: boolean — `true` when more than the server ceiling matched, so `total` / `totalPages` are a lower bound

  Ordered by balance id ascending. **Not** by `updatedAt`, which the removed page-number mode sorted on: that column changes on every balance movement, so a walk over it could repeat or skip rows with no concurrent insert at all.
</ResponseField>

<ResponseField name="getApplicationStats" type="(params: GetAppStatsParams) => Promise<GetAppStatsResponse>">
  Fetch aggregate volume and fee metrics for an application. Public.

  Stats are scoped to trades where this application's users were the taker.

  **Parameters:**

  * `params`: `GetAppStatsParams`
    * `clientId`: string — the application's public client ID (required)
    * `since?`: string — ISO 8601 datetime, e.g. `"2026-01-01T00:00:00Z"`. Omit for all-time

  **Returns:** `GetAppStatsResponse`:

  * `volume`: string — total quote volume (normalized, human-readable)
  * `makerFee`: string — total maker fees collected
  * `takerFee`: string — total taker fees collected
  * `applicationTakerFee`: string — application revenue share from taker fees
  * `tradeCount`: number — total number of trades

  **Example:**

  ```typescript theme={null}
  const stats = await sdk.applications.getApplicationStats({
    clientId: "6fe0da813f1a4adcbe675d52ca530a43",
    since: "2026-05-01T00:00:00Z",
  });
  console.log(`Volume: ${stats.volume}, App fee: ${stats.applicationTakerFee}`);
  ```
</ResponseField>


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