# Criptonlabs Agent APIs: documentation

> Markdown docs for agents covering the XRP Ledger and Solana. Each endpoint page has purpose, parameters, examples, errors, caching and the MCP tool equivalent. XRPL responses carry `ledger_index` in `meta`; Solana responses carry `slot` and `commitment`.

## Endpoints

- [GET /v1/xrpl/fee](https://api.criptonlabs.com/docs/xrpl-fee.md): Current XRPL fee tiers in drops with a congestion score.
- [GET /v1/xrpl/ledger/latest](https://api.criptonlabs.com/docs/xrpl-ledger-latest.md): Latest validated ledger index, hash and close time.
- [GET /v1/xrpl/health](https://api.criptonlabs.com/docs/xrpl-health.md): Overall and per-node health of the upstream XRPL nodes (alias of network health).
- [GET /v1/xrpl/network/health](https://api.criptonlabs.com/docs/xrpl-network-health.md): Overall and per-node health of the upstream XRPL nodes.
- [GET /v1/xrpl/health/history](https://api.criptonlabs.com/docs/xrpl-health-history.md): Bucketed upstream probe history with uptime and latency per node.
- [GET /v1/xrpl/orderbook](https://api.criptonlabs.com/docs/xrpl-orderbook.md): CLOB order book for a currency pair with unfunded offers removed.
- [GET /v1/xrpl/slippage](https://api.criptonlabs.com/docs/xrpl-slippage.md): Slippage and average price for buying an amount of base currency.
- [GET /v1/xrpl/amm/{a}/{b}](https://api.criptonlabs.com/docs/xrpl-amm.md): AMM pool reserves and trading fee for an asset pair.
- [GET /v1/xrpl/account/{address}/summary](https://api.criptonlabs.com/docs/xrpl-account-summary.md): XRP balance, sequence, owner count, transfer rate and trust lines (capped) for an account.
- [GET /v1/xrpl/account/{address}/lines](https://api.criptonlabs.com/docs/xrpl-account-lines.md): One page of an account's trust lines, with an opaque cursor for the next page.
- [GET /v1/xrpl/account/{address}/transactions](https://api.criptonlabs.com/docs/xrpl-account-transactions.md): One page of an account's most recent validated transactions, newest first.
- [GET /v1/xrpl/token/{asset}](https://api.criptonlabs.com/docs/xrpl-token.md): Issuer data for an issued asset: flags, domain, transfer fee and total issued.
- [GET /v1/xrpl/payment-readiness](https://api.criptonlabs.com/docs/xrpl-payment-readiness.md): Pre-payment check: can this payment from source to destination succeed now?
- [GET /v1/xrpl/paths](https://api.criptonlabs.com/docs/xrpl-paths.md): Multi-hop payment paths and their source cost.
- [GET /v1/solana/transfer-readiness](https://api.criptonlabs.com/docs/solana-transfer-readiness.md): Will this Solana transfer succeed? A verdict for SOL or an SPL or Token-2022 token.
- [GET /v1/solana/token/{mint}](https://api.criptonlabs.com/docs/solana-token.md): Is this Solana token safe to hold or receive? A SAFE, WARN or DANGER verdict.
- [GET /v1/solana/slot/latest](https://api.criptonlabs.com/docs/solana-slot-latest.md): Latest finalized Solana slot and its block time.
- [GET /v1/solana/health](https://api.criptonlabs.com/docs/solana-health.md): Whether Solana data is currently being served: latest probe status and finalized slot.
- [GET /v1/solana/health/history](https://api.criptonlabs.com/docs/solana-health-history.md): Bucketed history of Solana probe results over 1 hour, 24 hours or 7 days.
- [GET /v1/pro/*](https://api.criptonlabs.com/docs/pro.md): Pro mirror of the data routes with its own rate tier; the page states whether calls are currently paid.

## Guides

- [Freshness and the meta object](https://api.criptonlabs.com/docs/guides/freshness.md)
- [Currencies and amounts](https://api.criptonlabs.com/docs/guides/currencies-and-amounts.md)
- [Rate limits](https://api.criptonlabs.com/docs/guides/rate-limits.md)
- [Errors](https://api.criptonlabs.com/docs/guides/errors.md)
- [Choosing a tool](https://api.criptonlabs.com/docs/guides/choosing-a-tool.md)
- [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md)
- [Solana verdicts](https://api.criptonlabs.com/docs/guides/solana.md)
- [A2A endpoint](https://api.criptonlabs.com/docs/guides/a2a.md)
- [Paying for pro access (x402)](https://api.criptonlabs.com/docs/guides/payments.md)

## Errors

- [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md): 400 Bad Request
- [bad-request](https://api.criptonlabs.com/errors/bad-request.md): 400 Bad Request
- [not-found](https://api.criptonlabs.com/errors/not-found.md): 404 Not Found
- [solana-mint-not-found](https://api.criptonlabs.com/errors/solana-mint-not-found.md): 404 Not Found
- [unknown-route](https://api.criptonlabs.com/errors/unknown-route.md): 404 Not Found
- [method-not-allowed](https://api.criptonlabs.com/errors/method-not-allowed.md): 405 Method Not Allowed
- [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md): 429 Too Many Requests
- [internal-error](https://api.criptonlabs.com/errors/internal-error.md): 500 Internal Server Error
- [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md): 503 Service Unavailable
- [payment-required](https://api.criptonlabs.com/errors/payment-required.md): 402 Payment Required
- [payments-unavailable](https://api.criptonlabs.com/errors/payments-unavailable.md): 503 Service Unavailable
- [payment-settlement-failed](https://api.criptonlabs.com/errors/payment-settlement-failed.md): 402 Payment Required
- [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md): 402 Payment Required
- [payer-blocked](https://api.criptonlabs.com/errors/payer-blocked.md): 403 Forbidden
- [payer-limit-reached](https://api.criptonlabs.com/errors/payer-limit-reached.md): 429 Too Many Requests

---

# GET /v1/xrpl/fee

Current XRPL fee tiers in drops with a congestion score.

## Purpose

Returns economy, standard and priority fees in drops plus a 0-100 congestion score and band (`low`, `medium`, `high`) computed from queue fill, open-ledger fee pressure and load factor.

## When to use

Before submitting a transaction, to choose a `Fee` and to decide whether the network is congested.

## When not to use

Not a price feed and not a historical series; it describes the latest validated ledger only.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/fee"
```

## Response example (200)

```json
{
  "fee": {
    "economy": "10",
    "standard": "10",
    "priority": "11"
  },
  "congestion": {
    "score": 4,
    "band": "low",
    "load_factor_assumed": false
  },
  "base_fee": "10",
  "median_fee": "5000",
  "minimum_fee": "10",
  "open_ledger_fee": "10",
  "current_queue_size": "0",
  "max_queue_size": "2000",
  "meta": {
    "ledger_index": 100234567,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 1,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_fee` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/ledger/latest

Latest validated ledger index, hash and close time.

## Purpose

Returns the index, hash and close time (ISO 8601 or `null`) of the latest validated ledger.

## When to use

To anchor other readings to a ledger or to check how current the network view is.

## When not to use

Not for transaction data or account state; use the account endpoint for those.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/ledger/latest"
```

## Response example (200)

```json
{
  "ledger_index": 100234566,
  "close_time": "2026-10-06T12:00:01.000Z",
  "ledger_hash": "A1B2C3D4E5F60718293A4B5C6D7E8F90A1B2C3D4E5F60718293A4B5C6D7E8F90",
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_latest_ledger` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/health

Overall and per-node health of the upstream XRPL nodes (alias of network health).

## Purpose

The same view as the network-health page, served from stored probe samples, with no call to the nodes.

## When to use

A short alias when you only need the service status.

## When not to use

To see a time series use the health-history page.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/health"
```

## Response example (200)

```json
{
  "status": "degraded",
  "nodes": [
    {
      "member": "ripple-s1",
      "state": "up",
      "latency_ms": 180,
      "ledger_index": 100234566,
      "ledger_age_s": 2,
      "load_factor": 1,
      "error": null,
      "sampled_at": "2026-10-06T12:00:00.000Z"
    },
    {
      "member": "honeycluster",
      "state": "down",
      "latency_ms": null,
      "ledger_index": null,
      "ledger_age_s": null,
      "load_factor": null,
      "error": "timeout",
      "sampled_at": "2026-10-06T12:00:00.000Z"
    }
  ],
  "ledger_index": 100234566,
  "last_probe_at": "2026-10-06T12:00:00.000Z",
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 1,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

There is no MCP tool for this endpoint; use REST.

---

# GET /v1/xrpl/network/health

Overall and per-node health of the upstream XRPL nodes.

## Purpose

Returns `status` (`ok`, `degraded`, `down` or `unknown`) and one entry per upstream node with state, latency, ledger index and age, load factor and last error. Served from stored probe samples.

## When to use

To decide whether to trust or retry data, or to explain a 503 from another endpoint.

## When not to use

Not a probe of your own connectivity; it reports the service's upstream nodes.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/network/health"
```

## Response example (200)

```json
{
  "status": "degraded",
  "nodes": [
    {
      "member": "ripple-s1",
      "state": "up",
      "latency_ms": 180,
      "ledger_index": 100234566,
      "ledger_age_s": 2,
      "load_factor": 1,
      "error": null,
      "sampled_at": "2026-10-06T12:00:00.000Z"
    },
    {
      "member": "honeycluster",
      "state": "down",
      "latency_ms": null,
      "ledger_index": null,
      "ledger_age_s": null,
      "load_factor": null,
      "error": "timeout",
      "sampled_at": "2026-10-06T12:00:00.000Z"
    }
  ],
  "ledger_index": 100234566,
  "last_probe_at": "2026-10-06T12:00:00.000Z",
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 1,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_network_health` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/health/history

Bucketed upstream probe history with uptime and latency per node.

## Purpose

Aggregates probe samples into buckets (`1h` -> 300 s, `24h` -> 3600 s, `7d` -> 21600 s). Each bucket lists, per node, `samples`, `up`, `uptime_pct` and `avg_latency_ms`. Buckets without samples are omitted.

## When to use

To judge reliability over time before depending on the service.

## When not to use

Not for current state; use the network-health page.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `window` | query | no | History window. | `1h` (default), `24h` or `7d` | `24h` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/health/history?window=24h"
```

## Response example (200)

```json
{
  "window": "24h",
  "bucket_seconds": 3600,
  "buckets": [
    {
      "start": "2026-10-06T11:00:00.000Z",
      "members": [
        {
          "member": "ripple-s1",
          "samples": 30,
          "up": 30,
          "uptime_pct": 100,
          "avg_latency_ms": 175
        }
      ]
    }
  ],
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 60 seconds; on upstream failure the last good value is served for up to 600 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

There is no MCP tool for this endpoint; use REST.

---

# GET /v1/xrpl/orderbook

CLOB order book for a currency pair with unfunded offers removed.

## Purpose

Returns asks (best price first) and bids as levels `{gets, pays, price}`. Funded amounts are used when the ledger reports them and zero-amount levels are dropped. Price is `pays` per `gets` in human units (XRP, not drops).

## When to use

To read executable liquidity for a pair on the XRPL central limit order book (CLOB).

## When not to use

Not for AMM liquidity (use the amm page) and not for a cost estimate (use the slippage page).

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `base` | query | yes | Base currency of the pair. | `XRP` or `CODE.issuer`. `XRP` takes no issuer; any other code needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased; the issuer is a valid classic XRPL address (r..., checksum verified) | `XRP` |
| `quote` | query | yes | Quote currency of the pair. | `XRP` or `CODE.issuer`. `XRP` takes no issuer; any other code needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased; the issuer is a valid classic XRPL address (r..., checksum verified) | `USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |
| `depth` | query | no | Order book levels per side. | Positive integer, rounded up to 10, 50, 100 or 200 and capped at 200 (so 11 becomes 50 and 500 becomes 200); default 10 | `10` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/orderbook?base=XRP&quote=USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh&depth=10"
```

## Response example (200)

```json
{
  "base": "XRP",
  "quote": "USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "depth": 10,
  "asks": [
    {
      "gets": "1500",
      "pays": "3150",
      "price": "2.1"
    }
  ],
  "bids": [
    {
      "gets": "1000",
      "pays": "2090",
      "price": "2.09"
    }
  ],
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 2,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 30 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_orderbook` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/slippage

Slippage and average price for buying an amount of base currency.

## Purpose

Walks the asks of the cached order book to estimate the average price and `slippage_pct` (a percentage; `null` when liquidity is insufficient) of buying `amount` of `base` paying `quote`. For an issued currency the issuer's transfer fee is reported when it can be loaded. The top-level fields describe the CLOB; `venues` compares the CLOB with the AMM pool for the same amount (`best` is the cheaper venue by average price, ties go to the CLOB, no routing split) and `venues.amm_status` is `ok`, `stale`, `no_pool` or `unavailable`. `venues.amm` is `null` when the pair has no pool or the pool could not be read; the response never fails because of the AMM. CLOB slippage is measured against the best ask and AMM slippage against the pool spot price (so it includes the trading fee).

## When to use

Before placing a market-style trade, to size it against available depth and to see whether the CLOB or the AMM pool is the cheaper venue.

## When not to use

It is an estimate, not a quote, and it does not split an amount across venues or route through other pairs. To read pool reserves, use the amm page.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `base` | query | yes | Currency to buy. | `XRP` or `CODE.issuer`. `XRP` takes no issuer; any other code needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased; the issuer is a valid classic XRPL address (r..., checksum verified) | `XRP` |
| `quote` | query | yes | Currency paid. | `XRP` or `CODE.issuer`. `XRP` takes no issuer; any other code needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased; the issuer is a valid classic XRPL address (r..., checksum verified) | `USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |
| `amount` | query | yes | Amount of `base` to buy, as a decimal string. | Positive decimal such as `1000` or `0.5`; never a number literal in JSON | `1000` |
| `depth` | query | no | Order book levels per side. | Positive integer, rounded up to 10, 50, 100 or 200 and capped at 200 (so 11 becomes 50 and 500 becomes 200); default 200 | `10` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/slippage?base=XRP&quote=USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh&amount=1000"
```

## Response example (200)

```json
{
  "base": "XRP",
  "quote": "USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "side": "buy",
  "depth": 200,
  "amount": "1000",
  "filled": "1000",
  "partial": false,
  "insufficient_liquidity": false,
  "best_price": "2.1",
  "avg_price": "2.1042",
  "slippage_pct": "0.2",
  "transfer_fee_applied": false,
  "transfer_fee": null,
  "avg_price_after_fees": null,
  "venues": {
    "best": "clob",
    "amm_status": "ok",
    "clob": {
      "avg_price": "2.1042",
      "cost": "2104.2",
      "slippage_pct": "0.2",
      "insufficient_liquidity": false,
      "avg_price_after_fees": null
    },
    "amm": {
      "avg_price": "2.1331",
      "cost": "2133.1",
      "slippage_pct": "1.5762",
      "insufficient_liquidity": false,
      "avg_price_after_fees": null,
      "spot_price": "2.1",
      "trading_fee": "0.005"
    }
  },
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 2,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 30 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_slippage` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/amm/{a}/{b}

AMM pool reserves and trading fee for an asset pair.

## Purpose

Returns the reserves of both assets in the order requested and the trading fee as a decimal fraction (`0.005` is 0.5 %).

## When to use

To read AMM pool depth and fee for a pair.

## When not to use

It does not estimate slippage or compare venues (use the slippage page for the CLOB vs AMM comparison); a pair without a pool returns 404.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `a` | path | yes | First asset of the pool. | `XRP` or `CODE.issuer`. `XRP` takes no issuer; any other code needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased; the issuer is a valid classic XRPL address (r..., checksum verified) | `XRP` |
| `b` | path | yes | Second asset of the pool. | `XRP` or `CODE.issuer`. `XRP` takes no issuer; any other code needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased; the issuer is a valid classic XRPL address (r..., checksum verified) | `USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/amm/XRP/USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"
```

## Response example (200)

```json
{
  "asset_a": "XRP",
  "asset_b": "USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "reserve_a": "250000",
  "reserve_b": "525000",
  "trading_fee": "0.005",
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 4,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 8 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_amm` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/account/{address}/summary

XRP balance, sequence, owner count, transfer rate and trust lines (capped) for an account.

## Purpose

Returns the XRP balance as a decimal string, `sequence`, `owner_count`, the account `transfer_rate` (`1000000000` means no fee) and up to 50 trust lines; `lines_truncated` is `true` when there are more.

## When to use

To inspect an account before building a transaction for it.

## When not to use

Not for transaction history, reserves or account flags; it is a summary, not a full account dump.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `address` | path | yes | Classic XRPL account address. | Valid classic XRPL address: starts with `r`, 25 to 35 base58 characters, checksum verified | `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/account/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh/summary"
```

## Response example (200)

```json
{
  "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "balance_xrp": "1234.567891",
  "sequence": 42,
  "owner_count": 3,
  "transfer_rate": 1000000000,
  "trust_lines": [
    {
      "currency": "USD",
      "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq",
      "balance": "10.5",
      "limit": "1000000"
    }
  ],
  "lines_truncated": false,
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 3,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 10 seconds; on upstream failure the last good value is served for up to 120 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_account_summary` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/account/{address}/lines

One page of an account's trust lines, with an opaque cursor for the next page.

## Purpose

Returns one page of trust lines: peer, canonical currency, balance, limit, peer limit and the `no_ripple`, `freeze` and `authorized` flags of both sides; amounts are decimal strings. `limit` is 10 to 400 lines (default 100), `peer` keeps only lines with that counterparty, and `marker` is an opaque cursor: send it back unchanged to get the next page; it is `null` on the last page and only valid for the address that produced it.

## When to use

To list every trust line of an account (balances, limits, freeze and authorization flags), page by page.

## When not to use

For a quick capped overview with the XRP balance, use `/v1/xrpl/account/{address}/summary`; for issued totals of a token, use the token endpoint.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `address` | path | yes | Classic XRPL account address. | Valid classic XRPL address: starts with `r`, 25 to 35 base58 characters, checksum verified | `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |
| `limit` | query | no | Lines per page. | Integer from 10 to 400; default 100 | `100` |
| `peer` | query | no | Only lines with this counterparty. | Valid classic XRPL address | `rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B` |
| `marker` | query | no | Opaque cursor from the previous page's `marker`. | Exactly as returned for this address; any other value is rejected with 400 | `eyJ2IjoxLCJlIjoibGluZXMiLCJhIjoiciIsIm0iOiIxIn0` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/account/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh/lines?limit=100"
```

## Response example (200)

```json
{
  "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "limit": 100,
  "peer": null,
  "lines": [
    {
      "peer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
      "currency": "USD",
      "balance": "-10.5",
      "limit": "0",
      "peer_limit": "1000000",
      "no_ripple": true,
      "no_ripple_peer": false,
      "freeze": false,
      "freeze_peer": false,
      "authorized": false,
      "peer_authorized": false
    }
  ],
  "marker": null,
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 3,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 10 seconds; on upstream failure the last good value is served for up to 120 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_account_lines` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/account/{address}/transactions

One page of an account's most recent validated transactions, newest first.

## Purpose

Returns one page of the account's most recent validated transactions, newest first, in a compact shape: hash, ledger index, close time, transaction type, result code, counterparty (when the transaction names one) and delivered amount as a decimal string (when reported). `limit` is 1 to 50 transactions (default 20) and `marker` is an opaque cursor: send it back unchanged to get the next (older) page; it is `null` on the last page and only valid for the address that produced it. No history depth is promised: history depth depends on the serving node (how far back pages go depends on the ledger history of the node that serves the request), and older pages may be slower because they can be served by a node that keeps a longer history.

## When to use

To check what an account did recently (payments sent or received, offers, trust line changes) and whether each transaction succeeded.

## When not to use

For balances and trust lines, use `/v1/xrpl/account/{address}/summary` or `/v1/xrpl/account/{address}/lines`; for full archival history, use a full-history node or indexer: history depth depends on the serving node and older pages may be slower.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `address` | path | yes | Classic XRPL account address. | Valid classic XRPL address: starts with `r`, 25 to 35 base58 characters, checksum verified | `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |
| `limit` | query | no | Transactions per page. | Integer from 1 to 50; default 20 | `20` |
| `marker` | query | no | Opaque cursor from the previous page's `marker`. | Exactly as returned for this address; any other value is rejected with 400 | `eyJ2IjoxLCJlIjoidHgiLCJhIjoiciIsIm0iOjF9` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/account/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh/transactions?limit=20"
```

## Response example (200)

```json
{
  "address": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "limit": 20,
  "transactions": [
    {
      "hash": "C53ECF838647FA5A4C780377025FEC7999AB4182590510CA461444B207AB74A9",
      "ledger_index": 100234566,
      "close_time": "2026-10-11T09:30:12.000Z",
      "type": "Payment",
      "result": "tesSUCCESS",
      "counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
      "delivered": {
        "asset": "USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
        "value": "25.5"
      }
    }
  ],
  "marker": null,
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 2,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 30 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_account_transactions` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/token/{asset}

Issuer data for an issued asset: flags, domain, transfer fee and total issued.

## Purpose

Returns the issuer data for an issued asset `CODE.issuer`: issuer flags (`global_freeze`, `no_freeze`, `require_auth`, `default_ripple`), the issuer `domain` decoded to text when set, `transfer_rate` (1000000000 = no fee) and `transfer_fee_pct`, and `obligations`, the total issued of that currency as a decimal string (`"0"` when the issuer has not issued it). When the node cannot report obligations, the response is still 200 with `obligations: null` and `obligations_status: "unavailable"`. Holder counts are not returned.

## When to use

Before accepting or sending an issued token: check that the issuer exists, is not frozen, whether holders need authorization, and the transfer fee charged on every transfer between non-issuer accounts.

## When not to use

For XRP (not an issued asset; 400), for one account's own balances use `/v1/xrpl/account/{address}/lines`, and for prices use `/v1/xrpl/orderbook` or `/v1/xrpl/amm/{a}/{b}`.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `asset` | path | yes | Issued asset as `CODE.issuer`, split on the first dot. | `CODE` is 3 characters (not `XRP`, case-insensitive) or 40 hex; `issuer` is a valid classic XRPL address | `USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/token/USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"
```

## Response example (200)

```json
{
  "issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "currency": "USD",
  "global_freeze": false,
  "no_freeze": false,
  "require_auth": false,
  "default_ripple": true,
  "domain": "example.com",
  "transfer_rate": 1002000000,
  "transfer_fee_pct": "0.2",
  "obligations": "1250000.5",
  "obligations_status": "ok",
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 12,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 10 seconds; on upstream failure the last good value is served for up to 120 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_token` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/payment-readiness

Pre-payment check: can this payment from source to destination succeed now?

## Purpose

Checks, before you sign, whether a payment of `asset` (default `XRP`) from `source` to `destination` can succeed on the validated ledger, and returns a `verdict`: `ready`, `not_ready` (at least one blocking reason) or `unknown` (no blocking reason, but a sub-check could not run; never treat `unknown` as `ready`). A missing account is a reason, not an error: this endpoint never answers 404. Without `amount` the amount-dependent checks are skipped. `spendable_xrp` is the source XRP above its live reserve (base plus owner count times increment, from the server state) and the standard fee; `transfer_fee_pct` is the issuer transfer fee when it applies. Warnings never change the verdict.

Reason codes: `source_not_found`, `insufficient_xrp_balance`, `source_line_missing`, `insufficient_token_balance`, `source_line_frozen`, `destination_not_found`, `amount_below_destination_reserve`, `destination_tag_required`, `deposit_not_authorized`, `destination_line_missing`, `destination_line_limit_exceeded`, `destination_line_frozen`, `issuer_not_found`, `issuer_global_freeze`.

Warning codes: `destination_will_be_created`, `transfer_fee`, `high_fee`, `network_degraded`.

Sub-check codes: `source_account`, `destination_account`, `deposit_authorized`, `source_line`, `destination_line`, `issuer`, `fee`, `network_health`.

## When to use

Right before sending a payment: to catch a missing or unfunded destination, a required destination tag, deposit authorization, missing or frozen trust lines, insufficient balance and issuer freezes, in one call.

## When not to use

To find a multi-hop route or the source amount needed for a cross-currency payment (use the paths endpoint), or to list balances (use `/v1/xrpl/account/{address}/summary`).

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `source` | query | yes | Sending account. | Valid classic XRPL address (r..., checksum verified) | `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |
| `destination` | query | yes | Receiving account. | Valid classic XRPL address, different from `source` | `rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B` |
| `asset` | query | no | Asset to deliver. | `XRP` (default) or `CODE.issuer`: a 3-character or 40-hex code and a valid classic issuer address | `XRP` |
| `amount` | query | no | Amount to deliver, in units of `asset`. | Positive decimal string (no exponent); omit to skip amount-dependent checks | `10` |
| `destination_tag` | query | no | Destination tag you will send. | Integer from 0 to 4294967295 | `12345` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/payment-readiness?source=rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh&destination=rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B&amount=10"
```

## Response example (200)

```json
{
  "verdict": "not_ready",
  "reasons": [
    "destination_tag_required"
  ],
  "warnings": [],
  "checks_failed": [],
  "spendable_xrp": "98.995",
  "transfer_fee_pct": null,
  "source": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
  "destination": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
  "asset": "XRP",
  "amount": "10",
  "destination_tag": null,
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 2,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_payment_readiness` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/xrpl/paths

Multi-hop payment paths and their source cost.

## Purpose

Runs a live path search (`ripple_path_find`) on the validated ledger for delivering `amount` of `asset` from `source` to `destination`, and returns the `alternatives`: each with the estimated `source_amount` the source would spend (asset and decimal string), `paths_count` and the computed `paths` as compact steps (`account`, `currency`, `issuer`). A call can take up to about 20 seconds, because path finding is heavy for the node. Results are best effort: `paths_may_be_non_optimal` is always `true`, a cheaper path may exist and the amounts are estimates that can change by the time you submit. No alternative is a 200 with `alternatives: []`. A destination account that does not exist gives `alternatives: []` and the warning `destination_not_found`; a source account that does not exist is a 404. Answers are never cached: every call reads the ledger.

## When to use

Before a cross-currency or multi-hop payment: to see whether a route exists and how much the source would spend to deliver the amount. A call can take up to about 20 seconds and paths may be non-optimal.

## When not to use

To check whether a direct payment can succeed (use `/v1/xrpl/payment-readiness`), or for the single-hop cost of a trade on one pair (use `/v1/xrpl/slippage`, which compares the order book and the AMM).

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `source` | query | yes | Sending account. | Valid classic XRPL address (r..., checksum verified) | `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh` |
| `destination` | query | yes | Receiving account. | Valid classic XRPL address | `rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B` |
| `asset` | query | yes | Asset the destination receives. | `XRP` or `CODE.issuer`: a 3-character or 40-hex code and a valid classic issuer address | `XRP` |
| `amount` | query | yes | Amount the destination receives, in units of `asset`. | Positive decimal string (no exponent); for `XRP` at most 6 decimals (1 drop) | `1` |
| `send_max_asset` | query | no | Asset of `send_max`. | `XRP` or `CODE.issuer`, as in `asset`; required with `send_max` | `XRP` |
| `send_max` | query | no | Most the source may spend, in units of `send_max_asset`. | Positive decimal string (for `XRP` at most 6 decimals); required with `send_max_asset`; not with `source_assets` | `2` |
| `source_assets` | query | no | Assets the source may spend, comma-separated. | 1 to 4 assets, comma-separated, each `XRP` or `CODE.issuer`; not with `send_max_asset`/`send_max` | `XRP` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/xrpl/paths?source=rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh&destination=rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B&asset=XRP&amount=1"
```

## Response example (200)

```json
{
  "paths_may_be_non_optimal": true,
  "warnings": [],
  "alternatives": [
    {
      "source_amount": {
        "asset": "USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
        "value": "1.394"
      },
      "paths_count": 1,
      "paths": [
        [
          {
            "currency": "XRP"
          }
        ]
      ]
    }
  ],
  "meta": {
    "ledger_index": 100234566,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Never cached: every call is a live read of the validated ledger (`meta.cache` is `miss`, `meta.stale` is `false`, `Cache-Control: no-store`), and no stale value is ever served; when no node answers, the service answers 503.

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `xrpl_paths` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/solana/transfer-readiness

Will this Solana transfer succeed? A verdict for SOL or an SPL or Token-2022 token.

## Purpose

Checks one planned transfer of SOL or of an SPL Token or Token-2022 token against finalized on-chain state and returns `ready`, every matched blocker and warning code, and the derived figures: the raw amount, whether the destination token account must be created and its rent, the Token-2022 transfer fee and the net amount. Blockers: insufficient_balance, insufficient_sol_for_fees (5,000 lamports for one signature, priority fees excluded, plus the account rent when the destination token account is missing, plus the amount for SOL), source_below_rent_exempt, destination_below_rent_exempt, source_frozen, destination_frozen, non_transferable, mint_paused. Warnings: destination_off_curve, memo_required. The rent-exempt minimum is read live and never hardcoded. Every figure is read at finalized commitment, so it can lag the tip of the chain by about 13 seconds; `meta.slot` is the context slot of the read. The amount is not part of any cache key, so the verdict is computed per request.

## When to use

Before building or signing a Solana transfer, to learn whether it will fail and what it will cost in rent and fees.

## When not to use

Not a simulation of the exact transaction (no priority fee, no program logic), not a token price or holder lookup, and not a way to read raw accounts.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `source` | query | yes | Sending wallet. | A base58 string that decodes to exactly 32 bytes (a Solana public key); anything else is a 400 | `83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri` |
| `destination` | query | yes | Receiving wallet (not its token account). | A base58 string that decodes to exactly 32 bytes (a Solana public key); anything else is a 400 | `A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd` |
| `mint` | query | yes | `SOL` for native SOL, or the mint address of an SPL Token or Token-2022 token. | `SOL` or a base58 string that decodes to exactly 32 bytes (a solana public key); anything else is a 400 | `SOL` |
| `amount` | query | yes | Amount to send in UI units (SOL or tokens, not lamports or raw units). | Decimal string strictly greater than 0; at most 9 decimals for SOL and at most the mint's decimals for a token (a mint read decides) | `0.5` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/solana/transfer-readiness?source=83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri&destination=A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd&mint=SOL&amount=0.5"
```

## Response example (200)

```json
{
  "ready": true,
  "blockers": [],
  "source": "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
  "destination": "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd",
  "mint": "SOL",
  "amount": "0.5",
  "amount_raw": "500000000",
  "decimals": 9,
  "token_program": null,
  "warnings": [],
  "requires_ata_creation": false,
  "ata_creation_lamports": null,
  "transfer_fee": null,
  "net_amount": "500000000",
  "meta": {
    "slot": 456943158,
    "commitment": "finalized",
    "as_of": "2026-10-14T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 404 [solana-mint-not-found](https://api.criptonlabs.com/errors/solana-mint-not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 30 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `solana_transfer_readiness` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/solana/token/{mint}

Is this Solana token safe to hold or receive? A SAFE, WARN or DANGER verdict.

## Purpose

Decodes an SPL Token or Token-2022 mint (including its extensions) and returns the token program, decimals, exact supply, the authorities, the extension names and a verdict with every matched reason code. DANGER: permanent_delegate, transfer_hook, pausable, default_account_frozen. WARN: mint_authority_set, freeze_authority_set, transfer_fee, mint_close_authority, unknown_extension. SAFE has no reasons. The verdict is the highest level matched. Every figure is read at finalized commitment, so it can lag the tip of the chain by about 13 seconds; `meta.slot` is the context slot of the read. It returns no holders, liquidity, price or metadata.

## When to use

Before accepting or swapping into an unfamiliar token, to see whether its mint can freeze, mint more, move or tax balances.

## When not to use

Not a price, liquidity or holder lookup and not an audit of the token's project; it reads only the mint account.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `mint` | path | yes | Mint address of the token. | A base58 string that decodes to exactly 32 bytes (a Solana public key); anything else is a 400 | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/solana/token/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
```

## Response example (200)

```json
{
  "verdict": "WARN",
  "reasons": [
    "mint_authority_set",
    "freeze_authority_set"
  ],
  "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "token_program": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
  "decimals": 6,
  "supply": "9150000000000000",
  "mint_authority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
  "freeze_authority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
  "extensions": [],
  "transfer_fee": null,
  "meta": {
    "slot": 456943158,
    "commitment": "finalized",
    "as_of": "2026-10-14T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 404 [solana-mint-not-found](https://api.criptonlabs.com/errors/solana-mint-not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 60 seconds; on upstream failure the last good value is served for up to 600 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `expensive`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `solana_token` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/solana/slot/latest

Latest finalized Solana slot and its block time.

## Purpose

Returns the latest finalized slot and the time of its block (null when the node does not have it yet). Every figure is read at finalized commitment, so it can lag the tip of the chain by about 13 seconds; `meta.slot` is the context slot of the read.

## When to use

To check how fresh the finalized view of Solana is, or to anchor a read to a slot.

## When not to use

Not a tip-of-chain feed: it is finalized, not processed or confirmed, and it is cached for 2 seconds.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/solana/slot/latest"
```

## Response example (200)

```json
{
  "slot": 456943158,
  "block_time": "2026-10-14T11:59:51.000Z",
  "meta": {
    "slot": 456943158,
    "commitment": "finalized",
    "as_of": "2026-10-14T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 2 seconds; on upstream failure the last good value is served for up to 30 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `solana_latest_slot` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/solana/health

Whether Solana data is currently being served: latest probe status and finalized slot.

## Purpose

Reports the result of the latest stored probe (`up`, `down`, `unknown`) with its finalized slot and latency, without calling Solana. The status is `unavailable` while Solana data is not configured on this service, and `unknown` before the first probe is stored; in both cases `slot` is null and `meta.slot` is 0 because there is no finalized slot to report. It does not name the upstream provider.

## When to use

Before relying on the Solana verdict endpoints, or to explain a 503 from them.

## When not to use

Not a measure of the Solana network itself, only of this service's access to it; use the latest-slot endpoint to see chain progress.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/solana/health"
```

## Response example (200)

```json
{
  "status": "up",
  "slot": 456943158,
  "latency_ms": 180,
  "last_probe_at": "2026-10-14T12:00:00.000Z",
  "meta": {
    "slot": 456943158,
    "commitment": "finalized",
    "as_of": "2026-10-14T12:00:03.000Z",
    "age_seconds": 1,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

The MCP tool `solana_network_health` returns the same data. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# GET /v1/solana/health/history

Bucketed history of Solana probe results over 1 hour, 24 hours or 7 days.

## Purpose

Aggregates the stored probes into time buckets with sample count, successful samples, uptime percentage and average latency. It returns whatever samples are stored, even while Solana data is not configured, and never names the upstream provider.

## When to use

To see whether Solana data was reliable over the last hour, day or week.

## When not to use

Not a record of chain activity; it describes this service's access to Solana.

## Parameters

| Name | In | Required | Description | Constraints | Example |
|---|---|---|---|---|---|
| `window` | query | no | History window. | One of `1h`, `24h`, `7d`; default `1h` | `24h` |

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/solana/health/history?window=1h"
```

## Response example (200)

```json
{
  "window": "1h",
  "bucket_seconds": 300,
  "buckets": [
    {
      "start": "2026-10-14T11:55:00.000Z",
      "samples": 2,
      "up": 2,
      "uptime_pct": 100,
      "avg_latency_ms": 175
    }
  ],
  "meta": {
    "slot": 456943158,
    "commitment": "finalized",
    "as_of": "2026-10-14T12:00:03.000Z",
    "age_seconds": 0,
    "cache": "miss",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Fresh for 4 seconds; on upstream failure the last good value is served for up to 60 seconds (`meta.stale` is `true`), then the service answers 503. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md).

## Rate limit

Tier `cheap`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

There is no MCP tool for this endpoint; use REST.

---

# GET /v1/pro/*

Pro mirror of the data routes with its own rate tier; the page states whether calls are currently paid.

## Purpose

Every data route is mirrored under `/v1/pro` with the same parameters and response bodies, counted in its own `pro` rate tier. The paid MCP endpoint `/mcp/pro` offers the same tools as `/mcp`. Paid access is announced but not active: pro routes currently serve free data, identical to the free routes, and no payment is required.

## Paid access

Pro routes currently serve free data: no payment is required and none is charged, and `https://api.criptonlabs.com/mcp/pro` behaves the same. Paid access via x402 is announced but not active; the [payments guide](https://api.criptonlabs.com/docs/guides/payments.md) explains how paying will work and this page lists the prices once it is activated. `GET https://api.criptonlabs.com/v1/pro/requirements?resource=<path>` is free and returns the current `accepts` (`resource` may also be `mcp://criptonlabs/pro/<tool>`). Without `resource` it returns the price index: every paid route and tool with its price and links. It is counted in the `cheap` rate tier and is never charged.

## When to use

When you were told to use the pro namespace or need its own rate limit; the free routes carry the same data.

## When not to use

Do not rely on it for anything the free routes do not offer; there are no extra fields.

## Parameters

This endpoint takes no parameters.

## Request example

```sh
curl -s "https://api.criptonlabs.com/v1/pro/xrpl/fee"
```

This request needs no payment and returns the same data as the free route.

## Response example (200)

```json
{
  "fee": {
    "economy": "10",
    "standard": "10",
    "priority": "11"
  },
  "congestion": {
    "score": 4,
    "band": "low",
    "load_factor_assumed": false
  },
  "base_fee": "10",
  "median_fee": "5000",
  "minimum_fee": "10",
  "open_ledger_fee": "10",
  "current_queue_size": "0",
  "max_queue_size": "2000",
  "meta": {
    "ledger_index": 100234567,
    "as_of": "2026-10-06T12:00:03.000Z",
    "age_seconds": 1,
    "cache": "hit",
    "stale": false
  }
}
```

## Errors

- 400 [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md)
- 400 [bad-request](https://api.criptonlabs.com/errors/bad-request.md)
- 404 [not-found](https://api.criptonlabs.com/errors/not-found.md)
- 429 [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md)
- 503 [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md)

## Caching

Same as the corresponding free route: fee, ledger and health 4 s fresh, 60 s max-stale; order book and slippage 4 s fresh, 30 s max-stale; AMM 8 s fresh, 60 s max-stale; account summary 10 s fresh, 120 s max-stale. See the [freshness guide](https://api.criptonlabs.com/docs/guides/freshness.md). Paid answers (a 200 that carried a settled payment, and every 402 challenge) carry `Cache-Control: no-store`.

## Rate limit

Tier `pro`. See the [rate-limits guide](https://api.criptonlabs.com/docs/guides/rate-limits.md).

## MCP tool

There is no MCP tool for this endpoint pattern; the paid MCP endpoint `/mcp/pro` exposes the same tools as `/mcp`. See the [MCP quickstart](https://api.criptonlabs.com/docs/guides/mcp-quickstart.md).

---

# Freshness and the meta object

Every data response carries a `meta` object that tells you how current the data is.

| Field | Meaning |
|---|---|
| `ledger_index` | Validated ledger the data comes from |
| `as_of` | When the data was read from the ledger (ISO 8601) |
| `age_seconds` | Age of the data when the response was produced |
| `cache` | `hit` (served fresh from cache), `miss` (loaded from a node), `stale` (expired, served because the nodes failed) |
| `stale` | `true` only when `cache` is `stale` |

Composite answers (for example an account summary built from two ledger reads) report the worst case of their parts.

## How to use it

- A new ledger closes roughly every 4 seconds. Data is cached for a few seconds (the TTL is on each endpoint page), so calling faster than the TTL returns the same value.
- If `stale` is `true`, the upstream nodes failed and you are reading the last good value. It is never older than the endpoint's max-stale; beyond that the service answers 503 `upstream-unavailable` instead.
- For decisions that depend on recency, compare `age_seconds` with your own tolerance and, when it matters, `ledger_index` with the latest ledger.
- Solana responses carry `slot` and `commitment` instead of `ledger_index`; see https://api.criptonlabs.com/docs/guides/solana.md.

---

# Currencies and amounts

## Currency format

A currency is `XRP` or `CODE.issuer`, for example `USD.rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh`. `XRP` never has an issuer; every other currency needs one. The code is 3 letters or digits (A-Z, 0-9) or 40 hexadecimal digits and is upper-cased. The issuer must be a valid classic XRPL address (starts with `r`, 25 to 35 base58 characters, checksum verified); anything else is a 400 `invalid-parameters`.

Account addresses (for example on the account summary) follow the same rule.

## Amounts are strings

Amounts, prices and reserves travel as decimal strings, never as JSON numbers, so no precision is lost. Parse them with a decimal library, not a float. Request amounts (for example `amount` on the slippage endpoint) must also be positive decimal strings.

## Units

- Fees are in drops (1 XRP = 1,000,000 drops).
- Order book prices are in human units (XRP, not drops): `price` is `pays` per `gets`.
- `slippage_pct` is a percentage (`0.2` means 0.2 %).
- AMM `trading_fee` is a decimal fraction (`0.005` means 0.5 %).

---

# Rate limits

Requests are limited per client IP per minute, by tier. Defaults:

| Tier | Routes | Default limit per minute |
|---|---|---|
| `cheap` | fee, ledger, health, network health, health history | 120 |
| `expensive` | orderbook, slippage, amm, account (summary, lines, transactions), token, payment-readiness, paths | 30 |
| `pro` | everything under `/v1/pro` | 120 |
| `mcp` | every request to `/mcp` | 120 |

The MCP tools for these routes also draw from the `expensive` tier, so MCP is not a way around it. Limits are best-effort counters and can differ per deployment.

## When you are limited

The response is 429 with `application/problem+json`, a `Retry-After` header and a `retry_after_seconds` field. Wait that long before retrying. See [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md).

## RateLimit headers (advisory)

When the service knows the counters it adds `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` (seconds until the window resets) to `/v1/*` responses, including 429. They are advisory and per instance, so the real limit can be looser than they suggest, and they may be absent. Always honor `Retry-After` on a 429.

## Staying under the limit

- Respect the cache TTL on each endpoint page; faster polling returns identical data.
- Prefer one slippage call over many order book calls: the book is cached and the amount is not part of the cache key.
- Back off on 429 and 503 instead of retrying immediately.

---

# Errors

All errors are RFC 9457 `application/problem+json` with `type`, `title`, `status`, `detail` and `instance`; validation errors add `errors[]` with `field` and `message`. The `type` is a URL of the form `https://api.criptonlabs.com/errors/<slug>.md` and resolves to a page describing the problem.

| Status | Type slug | Retry? |
|---|---|---|
| 400 | [invalid-parameters](https://api.criptonlabs.com/errors/invalid-parameters.md), [bad-request](https://api.criptonlabs.com/errors/bad-request.md) | No, fix the request |
| 404 | [not-found](https://api.criptonlabs.com/errors/not-found.md), [unknown-route](https://api.criptonlabs.com/errors/unknown-route.md) | No |
| 429 | [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md) | Yes, after `Retry-After` |
| 500 | [internal-error](https://api.criptonlabs.com/errors/internal-error.md) | Yes, with backoff |
| 503 | [upstream-unavailable](https://api.criptonlabs.com/errors/upstream-unavailable.md) | Yes, after `Retry-After` |

Client errors reported by the XRP Ledger itself (such as a missing account) are not retried by the service and surface as 400 or 404.

Over MCP, the same problem body is returned as the text of a tool result with `isError: true`.

---

# Choosing a tool

| You want to... | Use |
|---|---|
| Pick a transaction fee or see congestion | fee (`xrpl_fee`) |
| Know the latest validated ledger | ledger-latest (`xrpl_latest_ledger`) |
| Check whether the service and its nodes are healthy | network-health (`xrpl_network_health`) or health |
| See reliability over time | health-history |
| Read CLOB liquidity for a pair | orderbook (`xrpl_orderbook`) |
| Estimate the cost of a market-style buy | slippage (`xrpl_slippage`) |
| Read AMM pool reserves and fee | amm (`xrpl_amm`) |
| Inspect an account before transacting | account-summary (`xrpl_account_summary`) |
| Check, before you send a payment, that it can succeed now (destination, destination tag, deposit authorization, trust lines, balance and reserve, issuer freezes) | payment-readiness (`xrpl_payment_readiness`) |
| Find a multi-hop or cross-currency route and what the source would spend | paths (`xrpl_paths`) |
| Page through all trust lines of an account | account-lines (`xrpl_account_lines`) |
| Read the recent validated transactions of an account | account-transactions (`xrpl_account_transactions`) |
| Do due diligence on an issuer before holding or accepting its token (flags, domain, transfer fee, total issued) | token (`xrpl_token`) |

Notes:

- Slippage reports the CLOB at top level and compares it with the AMM pool in `venues` (`best` is the cheaper venue, `amm_status` says whether the pool was read). Read the amm page for the pool reserves.
- The health history route has no MCP tool; use REST. The pro routes have no MCP tool of their own: the same tools are offered on the paid endpoint `/mcp/pro` (see the payments guide).
- Every endpoint has a Markdown page at `/docs/<name>.md`.

---

# MCP quickstart

The service exposes a stateless MCP server over Streamable HTTP at `https://api.criptonlabs.com/mcp`. There is no session and no authentication. `GET https://api.criptonlabs.com/` with `Accept: application/json` returns a JSON index with this MCP URL, the endpoint list and the same documentation links as `/llms.txt`; a browser gets a landing page with the same "Connect via MCP" snippets and copy buttons.

## Connect

The server needs no authentication. Use the URL `https://api.criptonlabs.com/mcp` and the name `agent-apis` in any client.

### Claude Code

```sh
claude mcp add --transport http agent-apis https://api.criptonlabs.com/mcp
```

Or in `.mcp.json`:

```json
{ "mcpServers": { "agent-apis": { "type": "http", "url": "https://api.criptonlabs.com/mcp" } } }
```

### Claude Desktop and claude.ai

In Customize > Connectors choose + Add > Add custom connector, enter the name `agent-apis` and the URL `https://api.criptonlabs.com/mcp`, and set Authentication to "No sign in". Free plans allow one custom connector; on Team and Enterprise plans the owner adds it in Organization settings > Connectors.

### Cursor

In `~/.cursor/mcp.json` or `.cursor/mcp.json`:

```json
{ "mcpServers": { "agent-apis": { "url": "https://api.criptonlabs.com/mcp" } } }
```

Or open the install link `cursor://anysphere.cursor-deeplink/mcp/install?name=agent-apis&config=eyJ1cmwiOiJodHRwczovL2FwaS5rcmlwdG9uaWFubGFicy5jb20vbWNwIn0=`.

### VS Code and Copilot

In `.vscode/mcp.json`:

```json
{ "servers": { "agent-apis": { "type": "http", "url": "https://api.criptonlabs.com/mcp" } } }
```

### Gemini CLI

```sh
gemini mcp add --transport http agent-apis https://api.criptonlabs.com/mcp
```

The command writes to the project scope by default; add `-s user` for all projects. Or in `settings.json` (`httpUrl` is the streamable HTTP field):

```json
{ "mcpServers": { "agent-apis": { "httpUrl": "https://api.criptonlabs.com/mcp" } } }
```

### Codex CLI

```sh
codex mcp add agent-apis --url https://api.criptonlabs.com/mcp
```

Or in `~/.codex/config.toml`:

```toml
[mcp_servers.agent-apis]
url = "https://api.criptonlabs.com/mcp"
```

### Windsurf

In `mcp_config.json` (`~/.config/devin/mcp_config.json` on macOS and Linux, `%APPDATA%\devin\mcp_config.json` on Windows):

```json
{ "mcpServers": { "agent-apis": { "serverUrl": "https://api.criptonlabs.com/mcp" } } }
```

### Zed

In `settings.json`:

```json
{ "context_servers": { "agent-apis": { "url": "https://api.criptonlabs.com/mcp" } } }
```

Zed may show an OAuth prompt when the entry has no Authorization header; this server needs no authentication, so the prompt is not needed.

## Endpoints and views

`/mcp` lists the tools of every network. To load only the tools of one network, use a view: `/mcp/xrpl` lists only the XRPL tools and `/mcp/solana` only the Solana tools. Their paid twins `/mcp/pro` (all tools), `/mcp/pro/xrpl` and `/mcp/pro/solana` follow the payment mode like `/mcp/pro`. A view returns the same payloads as `/mcp` for the tools it lists; a tool of another network is not found on it. Prefer a view when you work on one network only, to save context; prefer `/mcp` when you need both.

## Tools

`xrpl_fee`, `xrpl_latest_ledger`, `xrpl_network_health`, `xrpl_orderbook`, `xrpl_slippage`, `xrpl_amm`, `xrpl_account_summary`, `xrpl_account_lines`, `xrpl_account_transactions`, `xrpl_token`, `xrpl_payment_readiness`, `xrpl_paths`, `solana_transfer_readiness`, `solana_token`, `solana_latest_slot` and `solana_network_health`. Each returns the same body as its REST endpoint (including `meta`) as structured content and as JSON text.

## Behavior

- Errors come back as a tool result with `isError: true` whose text is the problem+json body.
- Every `/mcp` request counts against the `mcp` rate tier; every tool except `xrpl_fee`, `xrpl_network_health`, `xrpl_latest_ledger`, `solana_latest_slot` and `solana_network_health` also counts against the `expensive` tier. See the rate-limits guide.
- Browser origins other than localhost are rejected; use a server-side client.
- The paid twin `/mcp/pro` offers the same tools; see the payments guide for when it is charged.
- Prefer A2A? The same tools are available as skills at `/a2a`; see the A2A guide.

## Try it with curl

```sh
curl -s https://api.criptonlabs.com/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

---

# Solana verdicts

The Solana endpoints answer one question each and return a **verdict**, not raw chain data. Every figure is read at `finalized` commitment, so it can lag the tip of the chain by about 13 seconds. They are a second data network next to the XRP Ledger; the XRPL endpoints are unchanged.

| Question | Endpoint | MCP tool and A2A skill |
|---|---|---|
| Will this transfer of SOL or an SPL or Token-2022 token succeed? | `GET /v1/solana/transfer-readiness` | `solana_transfer_readiness` |
| Is this token safe to hold or receive? | `GET /v1/solana/token/{mint}` | `solana_token` |
| How fresh is the finalized view? | `GET /v1/solana/slot/latest` | `solana_latest_slot` |
| Is Solana data being served right now? | `GET /v1/solana/health` | `solana_network_health` |
| How reliable was it? | `GET /v1/solana/health/history` | none (REST only) |

## The meta object

Solana responses carry `meta` with `slot` (the finalized context slot of the read), `commitment` (always `finalized`), `as_of`, `age_seconds`, `cache` and `stale`. There is no `ledger_index`. On the health endpoint `meta.slot` is 0 while no probe sample is stored or Solana data is not configured.

## Verdicts

- Transfer readiness returns `ready`, every matched blocker and warning code and the derived figures (raw amount, rent of a missing destination token account, Token-2022 transfer fee, net amount). It is not a simulation of the exact transaction: priority fees and program logic are out of scope.
- Token returns `SAFE`, `WARN` or `DANGER` with every matched reason code. It reads only the mint account: no holders, liquidity, price or metadata.
- A mint with no account or that is not an SPL Token or Token-2022 mint answers 404 `solana-mint-not-found`.

## Using the paid mirror

Each endpoint has a mirror under `/v1/pro/solana/*` and the same tools exist on `/mcp/pro`; see the payments guide for when they are charged.

---

# A2A endpoint

The service speaks A2A 1.0 (JSON-RPC 2.0 over HTTP) at `POST https://api.criptonlabs.com/a2a`. It is stateless and free in every payment mode: there is no task, no session and no authentication, and every call is answered synchronously with a `message`. Paid access stays on `/mcp/pro` and `/v1/pro/*` (see the payments guide).

## Call a skill

Send `SendMessage` with one `data` part `{"skill": "<tool name>", "arguments": {...}}`. The skill ids are the 16 MCP tool names: `xrpl_fee`, `xrpl_latest_ledger`, `xrpl_network_health`, `xrpl_orderbook`, `xrpl_slippage`, `xrpl_amm`, `xrpl_account_summary`, `xrpl_account_lines`, `xrpl_account_transactions`, `xrpl_token`, `xrpl_payment_readiness`, `xrpl_paths`, `solana_transfer_readiness`, `solana_token`, `solana_latest_slot` and `solana_network_health`. The `arguments` are validated with the same schemas as the REST query parameters and the MCP tool inputs.

```sh
curl -s https://api.criptonlabs.com/a2a \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{"message":{"messageId":"m1","role":"ROLE_USER","parts":[{"data":{"skill":"xrpl_fee","arguments":{}},"mediaType":"application/json"}]}}}'
```

The reply holds `result.message` with `role` `ROLE_AGENT`, a fresh `messageId` and one `data` part (`mediaType` `application/json`) with the same JSON body the REST endpoint returns, `meta` included. A message with only `text` parts is not an error: the reply is a help message listing every skill and the `data` part format, and nothing is fetched.

## Stateless by design

- `ListTasks` returns an empty list. `GetTask` and `CancelTask` answer -32001 (task not found).
- Streaming, task subscription and the extended agent card answer -32004 (unsupported operation); the push notification config methods answer -32003.
- Any other method answers -32601; for 0.3-style names such as `message/send` the error hint says to use `SendMessage`.

## Version

Send `A2A-Version: 1.0` as a header or as the `A2A-Version` query parameter. When it is absent, 1.0 is assumed. Any other value, including an empty one, answers -32009.

## Errors

Errors are JSON-RPC errors (HTTP 200). `error.data` is an array with one `google.rpc.ErrorInfo` (`@type`, `reason`, `domain`, `metadata`). For service failures `metadata` carries the RFC 9457 fields (`type`, `title`, `status`, `detail`), so the `type` URL is a Markdown page with the cause and the fix.

| Code | Meaning |
|---|---|
| -32700 | The body is not valid JSON |
| -32600 | Invalid request: not a JSON-RPC 2.0 envelope, a batch (arrays are not accepted), an `id` that is not a string, number or null, or a body over 64 KB |
| -32601 | Unknown method |
| -32602 | Invalid params: unknown skill, invalid `arguments`, a part that is not `{skill, arguments}`, or no parts |
| -32603 | The service failed (for example all upstream nodes are down) |
| -32005 | The message has only `raw` or `url` parts |
| -32009 | Unsupported A2A version |

## Limits

- `GET` and `HEAD` answer 405 with `Allow: POST`.
- Every request counts against the `mcp` rate tier and the expensive skills also against the `expensive` tier; over the limit the endpoint answers HTTP 429 with `Retry-After`. See the rate-limits guide.
- No CORS headers: call it from a server-side client.
- The agent card at `/.well-known/agent-card.json` lists this endpoint first.

---

# Paying for pro access (x402)

Paid access with [x402](https://www.x402.org) is announced but not active. This guide is rendered from the service configuration, so it always states the current mode. Everything under `/v1/` except `/v1/pro/*`, and the `/mcp` endpoint, is free.

## Status

Paid access is announced but **not active**. Pro routes (`/v1/pro/*`) and the pro MCP endpoint (`/mcp/pro`) currently serve free data: no payment is required and none is charged. This page lists the network, asset and prices once paid access is activated.

The rest of this page describes how paying will work, so a client can be built ahead of time.

## Paying over REST

1. Call a pro route with a plain `GET` and no payment. The answer is 402 with the problem type [payment-required](https://api.criptonlabs.com/errors/payment-required.md) and a `PAYMENT-REQUIRED` header.
2. `PAYMENT-REQUIRED` is base64 of JSON: `{ "x402Version": 2, "error": ..., "resource": { "url": ... }, "accepts": [ ... ] }`. Each `accepts` entry is one way to pay: `scheme`, `network`, `asset`, `amount` (atomic units), `payTo`, `maxTimeoutSeconds`, `resource` and `extra.feePayer`.
3. Choose the `accepts` entry whose `extra.feePayer` belongs to the facilitator you want to settle through, and sign a payment for exactly that entry.
4. Repeat the same `GET` with the payment in the `PAYMENT-SIGNATURE` header (base64 of the JSON payment payload).
5. On 200 the `PAYMENT-RESPONSE` header carries the settlement result (base64 of JSON, including the transaction signature) and the body carries the data.

Rules that always hold:

- **One payment per call.** A payment key can be used once; sending it again answers 402 [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md).
- **Only `GET` on the exact paths is charged.** `HEAD` and every other method on a priced path answer 405 [method-not-allowed](https://api.criptonlabs.com/errors/method-not-allowed.md); a path with a trailing slash is 404 and is never priced.
- **A payment is bound to the exact resource.** It covers the path without the query string (`https://api.criptonlabs.com/v1/pro/xrpl/fee`), so one payment covers one call to that path with any query. A payment signed for another path is refused with 402.
- **Size cap.** `PAYMENT-SIGNATURE` and the MCP payment value are limited to 8192 bytes; larger values are refused with 402 before they are decoded.
- **Settlement comes first.** The service settles only after the data route answered 2xx, and releases the data only if settlement succeeded. If settlement fails the answer is 402 [payment-settlement-failed](https://api.criptonlabs.com/errors/payment-settlement-failed.md) with no data. A route that answers 4xx or 5xx is not charged.
- **A failed or expired payment is spent.** If verification failed, the facilitator was unavailable or settlement failed, the payment key cannot be reused: sign a new payment. The same holds when the route answered a handler error or any non-2xx status: nothing was charged and the reservation ends as `expired` with the flag `not_served`, yet the same signed payment answers 402 [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md). Sign a new payment.

## Paying over MCP

`/mcp/pro` is the paid twin of `/mcp`: the same tools, schemas and docs resources. `initialize`, `tools/list`, resources and prompts are free; only `tools/call` is charged.

1. Call a tool without payment. The result has `isError: true` and its `structuredContent` is the same PaymentRequired object as the REST header (`x402Version`, `error`, `resource`, `accepts`) merged with the problem fields.
2. Sign a payment for the `accepts` entry you chose and send it in the call as `_meta["x402/payment"]` (the JSON payload object, not base64), at most 8192 bytes serialized.
3. On success the result carries `_meta["x402/payment-response"]` with the settlement result.

A payment is bound to one tool: its resource is `mcp://criptonlabs/pro/<tool>`, so a payment signed for `xrpl_fee` is refused for `xrpl_orderbook` even when both cost the same.

## Prepay: skip the 402 round trip

`GET /v1/pro/requirements?resource=<resource>` is free (cheap rate tier) and never asks for payment. It returns `{ "x402Version": 2, "resource": { "url": ... }, "accepts": [ ... ], "payments_mode": ... }`. `resource` is a `/v1/pro/*` path without a query string, or `mcp://criptonlabs/pro/<tool>` for a paid tool. Fetch `accepts`, sign, and send the payment on the first call.

Without `resource`, `GET /v1/pro/requirements` returns the price index instead: every paid route and tool with its price, the network, asset and mint in x402 mode, and a link to each per-resource offer. It is free, uncharged and in the cheap rate tier too.

The offer is deterministic for one price table and one facilitator set, so a prepaid payment stays valid only while those facilitators stay available and healthy. When it changes, the call answers 402 with the current offer. The live source of the current `accepts` is the 402 `PAYMENT-REQUIRED` header or this route, never a copy of an earlier answer. While `payments_mode` is off or gateway, `accepts` is empty and `payments_mode` says so.

## Discovery metadata

`https://api.criptonlabs.com/openapi.json` marks every free operation with `security: []`. While x402 payments are enabled and healthy, each priced `/v1/pro/*` operation also carries `x-payment-info` (`protocols: [{"x402": {}}]` and a fixed price in `EUR` as a human decimal amount, for example `0.005`, not atomic units) next to its documented 402 response, and declares no `security` requirement. Otherwise no operation carries `x-payment-info`. `info.contact` and `info["x-guidance"]` give a short agent summary.

`https://api.criptonlabs.com/.well-known/x402` lists the absolute URL of every priced `/v1/pro/*` route as `{ "version": 1, "resources": [...] }` while x402 payments are enabled and healthy, and answers 404 otherwise. The runtime 402 challenge stays the authoritative source of the offer. `https://api.criptonlabs.com/.well-known/ard.json` lists the MCP Server Card and the agent card for Agentic Resource Discovery clients.

## Server-side clients only

Paid access is designed for server-side clients and agents. Browsers are not supported: pro routes send no CORS headers, so a page script cannot read their answers or send the payment headers.

## Statuses

| Status | Problem type | Meaning | What to do |
|---|---|---|---|
| 402 | [payment-required](https://api.criptonlabs.com/errors/payment-required.md) | No payment, or one that was not accepted (wrong amount, network, asset or resource, bad signature, too large, or rejected on verification). Carries `PAYMENT-REQUIRED`. | Sign one of the listed options and repeat the call. |
| 402 | [payment-settlement-failed](https://api.criptonlabs.com/errors/payment-settlement-failed.md) | Settlement failed or could not be confirmed in time. No data. Carries `PAYMENT-REQUIRED`. | Sign a new payment and repeat the call. If your wallet was debited, keep the transaction signature and check it before paying again. |
| 402 | [payment-already-used](https://api.criptonlabs.com/errors/payment-already-used.md) | This payment was already used. Carries `PAYMENT-REQUIRED`. | Sign a new payment for every call. |
| 403 | [payer-blocked](https://api.criptonlabs.com/errors/payer-blocked.md) | This payer cannot use paid access. | Use another payer or the free routes. |
| 405 | [method-not-allowed](https://api.criptonlabs.com/errors/method-not-allowed.md) | A priced path answers `GET` only. | Use `GET`. |
| 429 | [payer-limit-reached](https://api.criptonlabs.com/errors/payer-limit-reached.md) | The payer reached its daily limit of failed settlements. `Retry-After` is the time to 00:00 UTC. | Wait for `Retry-After`. |
| 429 | [rate-limited](https://api.criptonlabs.com/errors/rate-limited.md) | Per-IP rate limit (the `pro` tier for paid calls). `Retry-After` says how long. | Wait, then retry. |
| 503 | [payments-unavailable](https://api.criptonlabs.com/errors/payments-unavailable.md) | Paid access is temporarily unavailable (verification could not be completed, or the configuration is invalid). Nothing was served or charged. | Retry later with a new payment, or use the free routes. |

---

# 400 Bad Request: invalid-parameters

Problem type `https://api.criptonlabs.com/errors/invalid-parameters.md` (RFC 9457, `application/problem+json`).

## Status

400

## Meaning

One or more request parameters failed validation. The body carries `errors[]` with `field` and `message` for each problem.

## Retry

No. The same request fails again.

## Fix

Correct the listed fields (currency format `XRP` or `CODE.issuer`, positive decimal `amount`, `depth` a positive integer (rounded up to 10, 50, 100 or 200), valid `window`) and call again.

---

# 400 Bad Request: bad-request

Problem type `https://api.criptonlabs.com/errors/bad-request.md` (RFC 9457, `application/problem+json`).

## Status

400

## Meaning

The XRP Ledger node rejected the request with a client error code.

## Retry

No. Client errors from the ledger are not retried.

## Fix

Check the parameters against the endpoint page; the `detail` field names the ledger error code.

---

# 404 Not Found: not-found

Problem type `https://api.criptonlabs.com/errors/not-found.md` (RFC 9457, `application/problem+json`).

## Status

404

## Meaning

The ledger has no such object, for example an unfunded account or a pair without an AMM pool.

## Retry

No, unless the object may be created later (for example a new account is funded).

## Fix

Verify the address or currency pair. A missing AMM pool is a normal answer, not an outage.

---

# 404 Not Found: solana-mint-not-found

Problem type `https://api.criptonlabs.com/errors/solana-mint-not-found.md` (RFC 9457, `application/problem+json`).

## Status

404

## Meaning

The `mint` address has no account on Solana, is not owned by the SPL Token or Token-2022 program, or its data does not decode as a mint.

## Retry

No, unless the mint may be created later.

## Fix

Check the mint address (not a wallet or a token account) and that it exists on Solana. For native SOL use `mint=SOL` on transfer readiness.

---

# 404 Not Found: unknown-route

Problem type `https://api.criptonlabs.com/errors/unknown-route.md` (RFC 9457, `application/problem+json`).

## Status

404

## Meaning

The path does not exist on this service.

## Retry

No.

## Fix

Use a path from `/openapi.json` or `/llms.txt`.

---

# 405 Method Not Allowed: method-not-allowed

Problem type `https://api.criptonlabs.com/errors/method-not-allowed.md` (RFC 9457, `application/problem+json`).

## Status

405

## Meaning

A paid route answers GET only; no payment is read, reserved or charged for other methods.

## Retry

No. Repeat the call with GET.

## Fix

Use GET on the exact path; the `Allow` header lists the accepted method.

---

# 429 Too Many Requests: rate-limited

Problem type `https://api.criptonlabs.com/errors/rate-limited.md` (RFC 9457, `application/problem+json`).

## Status

429

## Meaning

The per-IP request budget for this tier is exhausted for the current window.

## Retry

Yes, after the delay in the `Retry-After` header (also `retry_after_seconds` in the body).

## Fix

Wait for the delay, slow down, and reuse cached answers: data is fresh for only a few seconds, so polling faster than the TTL gains nothing.

---

# 500 Internal Server Error: internal-error

Problem type `https://api.criptonlabs.com/errors/internal-error.md` (RFC 9457, `application/problem+json`).

## Status

500

## Meaning

An unexpected error occurred. The body is intentionally opaque.

## Retry

Yes, a few times with backoff. If it persists, stop and report it.

## Fix

There is nothing to fix in the request.

---

# 503 Service Unavailable: upstream-unavailable

Problem type `https://api.criptonlabs.com/errors/upstream-unavailable.md` (RFC 9457, `application/problem+json`).

## Status

503

## Meaning

No upstream XRP Ledger node could serve the request and no cached value is recent enough to serve as a stale fallback.

## Retry

Yes, after the `Retry-After` delay (5 seconds).

## Fix

Retry with backoff. Check `/v1/xrpl/network/health` for the state of the upstream nodes.

---

# 402 Payment Required: payment-required

Problem type `https://api.criptonlabs.com/errors/payment-required.md` (RFC 9457, `application/problem+json`).

## Status

402

## Meaning

This paid route needs a payment, or the payment sent was not accepted (missing, oversized or undecodable header, wrong amount, network, asset or resource, or rejected by verification). The `PAYMENT-REQUIRED` header carries the accepted payment options.

## Retry

Yes, with a valid payment: sign a payment for one of the listed options and repeat the request with it in the `PAYMENT-SIGNATURE` header.

## Fix

Read `accepts` from the `PAYMENT-REQUIRED` header (or `GET /v1/pro/requirements`), sign a payment for exactly that amount, asset, network and resource, and send it with the request. The free routes under `/v1/` need no payment.

---

# 503 Service Unavailable: payments-unavailable

Problem type `https://api.criptonlabs.com/errors/payments-unavailable.md` (RFC 9457, `application/problem+json`).

## Status

503

## Meaning

Paid access is temporarily unavailable: payment verification could not be completed, or paid access is not configured. No data was served and nothing was charged.

## Retry

Yes, later with backoff, with a new payment: the earlier one was released and cannot be used again.

## Fix

Retry after a short delay, or use the free routes under `/v1/`, which serve the same data without payment.

---

# 402 Payment Required: payment-settlement-failed

Problem type `https://api.criptonlabs.com/errors/payment-settlement-failed.md` (RFC 9457, `application/problem+json`).

## Status

402

## Meaning

The payment was accepted for verification but settlement failed or could not be confirmed in time. No data was served.

## Retry

Yes, with a new payment: sign again and repeat the request.

## Fix

Sign a new payment and resend. If your wallet was debited without a response, keep the transaction signature and check it on the network before paying again.

---

# 402 Payment Required: payment-already-used

Problem type `https://api.criptonlabs.com/errors/payment-already-used.md` (RFC 9457, `application/problem+json`).

## Status

402

## Meaning

This exact payment was already used for an earlier request. One payment covers exactly one call. A payment also counts as used when its call failed verification or settlement, and when the route answered a handler error or any non-2xx status: in that last case the reservation expires with the flag `not_served` and nothing was charged, but the same signed payment still answers this error.

## Retry

Yes, with a new payment.

## Fix

Sign a new payment for every call; never resend a payment that was already submitted.

---

# 403 Forbidden: payer-blocked

Problem type `https://api.criptonlabs.com/errors/payer-blocked.md` (RFC 9457, `application/problem+json`).

## Status

403

## Meaning

This payer cannot use paid access.

## Retry

No.

## Fix

Use a different payer wallet, or the free routes under `/v1/`, which need no payment.

---

# 429 Too Many Requests: payer-limit-reached

Problem type `https://api.criptonlabs.com/errors/payer-limit-reached.md` (RFC 9457, `application/problem+json`).

## Status

429

## Meaning

This payer reached its daily limit of failed settlements. The limit resets at 00:00 UTC.

## Retry

Yes, after the time in the `Retry-After` header (seconds until 00:00 UTC).

## Fix

Wait for the delay. Check that the payer wallet holds enough balance and that payments are signed correctly to avoid failed settlements.
