> For the complete documentation index, see [llms.txt](https://docs.gage.cash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gage.cash/ai-agents/api.md).

# HTTP API

The hosted HTTP API at mcp.gage.cash, its routes, parameters, answers and errors, and the bug report endpoint for agents.

Base URL:

```
https://mcp.gage.cash
```

The same reads and prepares as the [MCP server](/ai-agents/mcp.md), over HTTP, on Robinhood Chain mainnet (`4663`). No key or sign-in. Requests and answers are JSON, and every amount is a raw integer as a decimal string. Answers carry `Cache-Control: no-store`, and browsers may call the API from any origin, without credentials.

## First request

```sh
curl --fail-with-body https://mcp.gage.cash/v1/capabilities
```

Check `network` (`mainnet`), `chainId` (`4663`) and `app` (`https://gage.cash`, where review links open). Read the allowed terms and the rules from this answer rather than hard-coding them. `GET /` answers the plain-text guide; `GET /health` reports liveness only.

## Routes

| Route                        | Parameters                                                                                            | Answers                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GET /v1/capabilities`       | None                                                                                                  | `network`, `chainId`, `contracts` (`usdg`, `core`, `factory`, `loopRouter`), `terms` (`seconds`, `days`), `originationFeeBps`, `newLoansPaused`, `usdgDecimals`, `actions`, `rules`, `app` and `lendAssets` (each stock token gage also lends: `token`, `symbol`, `decimals`, `stable`, `core`, `factory`, `terms`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `GET /v1/assets`             | None                                                                                                  | `assets`, each token gage takes as collateral now: `token`, `symbol`, `name`, `decimals`, `lane`, `minAmount`, `maxPerLoan` (`null` for no per-loan cap, as on the core new loans use; the minimum still applies), `leverage`, `link` (its Borrow page, `https://gage.cash/borrow/<link>`, or `null`) and `asset`, what a loan against it is paid in                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `GET /v1/borrow-quote`       | `token`, `term`, and `maxCollateral`, or `collateral` and `principal`; optional `wallet`, `lendAsset` | With `maxCollateral`, the largest loan the partner vaults fund whole now: `pledge`, `collateralValueUSDG`, `principal`, `receive` (after the origination fee), `originationFee`, `repay`, `costBps`, `ltvBps`, `vaultsThatCanFund`, `expiresAt`, `summary` and a `prepare` object. With `collateral` and `principal`, that one loan priced as gage.cash prices a chosen amount (`mode: "exact"`): `pledge`, `collateralValueUSDG`, `principal`, `receive`, `originationFee`, `repay`, `costBps`, `ltvBps`, `fundsNow`, `accepted`, `waitsFor` (why it would wait, or `null`), `largestAccepted` (the most the vaults take at that cost), `summary` and a `prepare` object                                                                                                                                                                        |
| `GET /v1/leverage-quote`     | `token`, `own`, `multiple` (1.1 to 3, at most two decimals), `term`; optional `wallet`                | A preview, nothing reserved: `own`, `buy`, `held`, `principal`, `repay`, `costBps`, `maxPurchaseCostUSDG`, `pledgeValueUSDG`, `expiresAt`, `summary` and a `prepare` object                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `GET /v1/loans/{id}`         | Optional `engine` (the current core when omitted; a lend asset's core for its loans)                  | `state`, `borrower`, `reclaimRightHolder`, `token`, `symbol`, `collateral`, `principal`, `repay`, `costBps`, `term`, `fundedQuarters`, `fundingDeadline`, `fundedAt`, `endsAt`, `lenders`, `actions` (what can be done now: `cancel` a listing; `reclaim`, `cash_out`, `roll` and `auto_roll` a running loan, and `cancel_auto_roll` while an instruction stands; `collect` the collateral of a loan repaid or cancelled, until it is taken. Those this service does not prepare read as done on gage.cash, a hand roll there in the loan's last day), `closedBy` (`roll` or `cash_out` for a loan they repaid, whose collateral does not come back; else `null`) and `autoRoll`, the loan's instruction to roll over by itself (`borrower`, `executor`, `term`, `window`, `rollsLeft`, `withRewards`, `until`, `maxCost`, `maxTopUp`) or `null` |
| `GET /v1/portfolio/{wallet}` | None                                                                                                  | `loans` the wallet borrowed or holds the reclaim right of, on every gage engine and lend asset's core, each with `sgageClaimable` (raw sGAGE, 18 decimals, earned and not yet claimed; a loan on an earlier engine may pay it in parts) and `autoRoll` (`true` while an instruction to roll it over by itself stands); `earn`, its partner vault holdings (`shares`, `valueUSDG`, `withdrawableNowUSDG`, `claimsReady`, `rewards`, `link`; a stock-token vault's `value` and `withdrawableNow` are in its `asset`); `usdgCredit`, and `credits`, each lend asset's credit apart                                                                                                                                                                                                                                                                  |
| `GET /v1/earn/vaults`        | None                                                                                                  | `vaults`: `vault`, `name`, `link` (`https://gage.cash/v/<link>`, or `null`), `lends`, `performanceFeeBps`, `longestLoanDays`, `tokens`, `asset`, and for a USDG vault `totalAssetsUSDG`, `freeCashUSDG` and `usdgPerShare`, the raw USDG one whole share (10^18 raw) redeems for now; a stock-token vault's are `totalAssets`, `freeCash` and `assetsPerShare`, in its asset                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `POST /v1/prepare`           | JSON body `{ action, wallet, … }`                                                                     | The next unsigned transaction, the steps after it, a summary, a review link and, when a vault's settle must be mined first, `again: true`: see [Prepare a transaction](/ai-agents/transactions.md)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |

A quote for at most 5 tokens of 18 decimals, for 7 days, then one exact loan, 500 USDG on 5 tokens:

```sh
curl --fail-with-body 'https://mcp.gage.cash/v1/borrow-quote?token=<a token from /v1/assets>&maxCollateral=5000000000000000000&term=604800'
curl --fail-with-body 'https://mcp.gage.cash/v1/borrow-quote?token=<a token from /v1/assets>&collateral=5000000000000000000&principal=500000000&term=604800'
```

A loan's `state` is `FUNDING`, `ACTIVE`, `REPAID`, `DEFAULTED` or `CANCELLED`. `lendAsset` is USDG when omitted; another asset is accepted only once `capabilities` lists it under `lendAssets`. Inputs are strict: an unknown field in a prepare body, or an unknown query key on the quote and loan routes, is refused (`INVALID_INPUT`).

## Prepare bodies

| `action`            | Fields besides `wallet`                                                                                                                                                                            |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `borrow`            | `token`, `collateral`, `principal`, `cap` (the repayment) and `term`; optional `lendAsset`. The borrow quote's `prepare` object holds all of them.                                                 |
| `leverage`          | `token`, `own`, `multiple`, `term` and `maxCostBps` (1 to 5,000: the highest loan cost accepted, in bps of the amount borrowed). The leverage quote's `prepare` object sets it to the quoted cost. |
| `cancel`, `reclaim` | `loanId`; optional `engine`                                                                                                                                                                        |
| `earn_deposit`      | `vault` and `amount`; optional `maxSlippageBps` (0 to 500, 50 when omitted)                                                                                                                        |
| `earn_redeem`       | `vault`; optional `shares` (everything the vault can pay now when omitted) and `maxSlippageBps`                                                                                                    |
| `collect`           | None                                                                                                                                                                                               |
| `feedback`          | `score`, a whole number from 0 to 100: the wallet's own rating of gage, once a wallet ([Rate gage](/ai-agents/mcp.md#rate-gage))                                                                   |

`roll`, `auto_roll`, `cancel_auto_roll` and `cash_out` are gage-sdk's and gage-mcp's: here they answer `400 ACTION_NOT_SERVED`, and the wallet's owner rolls or cashes out on gage.cash.

Add `wallet`, the address that will sign, to a quote's `prepare` object and post it as the body. For example, a deposit of 10 USDG into a partner vault; the vault lends it, so you may end up holding the collateral instead of USDG:

```sh
curl --fail-with-body -X POST https://mcp.gage.cash/v1/prepare \
  -H 'content-type: application/json' \
  -d '{"action":"earn_deposit","wallet":"<your wallet>","vault":"<a vault from /v1/earn/vaults>","amount":"10000000"}'
```

The answer, with `view` left out:

```json
{
  "action": "earn_deposit",
  "wallet": "0x…",
  "status": "approval_required",
  "summary": { "title": "Deposit 10.00 USDG into …", "rows": [{ "label": "You deposit", "value": "10.00 USDG" }] },
  "next": {
    "label": "Approve USDG",
    "kind": "approve",
    "final": false,
    "transaction": { "from": "0x…", "to": "0x…", "data": "0x…", "value": "0", "chainId": 4663, "gas": "…" }
  },
  "then": ["Deposit"],
  "notes": [],
  "review": { "url": "https://gage.cash/review#…", "expiresAt": 1792072800 }
}
```

`view` carries the figures the review page draws. The review page's own routes, `POST /v1/reviews/open` and `POST /v1/reviews/advance`, take the link's token in the body; they serve gage.cash, and an agent has no need of them.

## Errors

```json
{ "error": { "code": "TERM_NOT_ALLOWED", "message": "Allowed terms: 7 days, 21 days", "retryable": false } }
```

Branch on `code`, never on `message`. `retryable` says whether the same request may succeed later, unchanged. Some refusals add `details`, figures to act on, as over MCP: `details.minimum` (`token`, `symbol`, `decimals`, `raw`) with `COLLATERAL_BELOW_MINIMUM`, `details.maxPrincipal` with `PRINCIPAL_TOO_HIGH`.

| HTTP status | Codes                                                                                                                                                                                                                                                                                                                                                                                               | What to do                                                                                                                                    |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| 400         | `INVALID_INPUT` (the message names the field), `UNKNOWN_LEND_ASSET`, `ACTION_NOT_SERVED`                                                                                                                                                                                                                                                                                                            | Correct the request. Roll over or cash out on gage.cash, or with gage-mcp for an agent's own wallet.                                          |
| 403         | `NOT_YOUR_LOAN`, `OWN_ENTRY`                                                                                                                                                                                                                                                                                                                                                                        | Prepare for the borrower, or for the holder of the loan's reclaim right. A wallet that owns or operates gage's ERC-8004 entry cannot rate it. |
| 404         | `NOT_FOUND`, `LOAN_NOT_FOUND`, `UNKNOWN_ENGINE`, `UNKNOWN_VAULT`                                                                                                                                                                                                                                                                                                                                    | Check the route, the id or the address. A private loan answers as an unknown one.                                                             |
| 409         | `TERM_NOT_ALLOWED`, `UNSUPPORTED_COLLATERAL`, `COLLATERAL_BELOW_MINIMUM`, `COLLATERAL_ABOVE_MAXIMUM`, `PRINCIPAL_TOO_HIGH`, `SETTLEMENT_DUE`, `LISTINGS_PAUSED`, `INSUFFICIENT_BALANCE`, `INSUFFICIENT_CAPACITY`, `PRICE_ABOVE_LIMIT`, `PRICE_MOVED`, `TERM_ENDED`, `NOT_REPAYABLE`, `NOT_CANCELLABLE`, `FUNDING_CLOSED`, `INSUFFICIENT_LIQUIDITY`, `ALREADY_RATED`, `SIMULATION_FAILED` and others | Read the current state and resolve the reason before preparing again.                                                                         |
| 410         | `REVIEW_EXPIRED`                                                                                                                                                                                                                                                                                                                                                                                    | The review link is over 30 minutes old: prepare again.                                                                                        |
| 413         | `BODY_TOO_LARGE`                                                                                                                                                                                                                                                                                                                                                                                    | Keep the body under 32 KiB.                                                                                                                   |
| 429         | `RATE_LIMITED`                                                                                                                                                                                                                                                                                                                                                                                      | Wait the seconds in `Retry-After`.                                                                                                            |
| 503         | `UNAVAILABLE`, `UPSTREAM_UNAVAILABLE`, `RATES_UNAVAILABLE`                                                                                                                                                                                                                                                                                                                                          | Try again shortly when `retryable` is `true`.                                                                                                 |

The ceilings are 600 requests and 120 prepares a minute for every caller together, and 120 requests and 30 prepares from one address. See [Data and limits](/ai-agents/data-and-limits.md).

## Submit a finding

Read the [agent research checklist](/ai-agents/security-research.md) first. Prioritize customer funds in partner lending and native V2, and identify the actual engine, custody account and connected contracts from the [target inventory](/protocol/bounty-targets.md). Historical-only or future-conditional findings must be labelled, and a paid submission needs the wallet owner's authorization.

Agents reviewing gage contracts can send a bug bounty report straight to the team. The endpoint lives on the support service, not on `mcp.gage.cash`, and is priced by [x402](https://x402.org): a refundable deposit of 15 USDC on Base (`eip155:8453`), returned with every valid report and kept for duplicates, non-reproducible claims and spam. The full policy is on [Bug bounty](/protocol/bug-bounty.md).

```
POST https://support-production-707f.up.railway.app/reports
```

Without a payment the endpoint answers `402` with a `PAYMENT-REQUIRED` header describing the deposit. An x402 client signs a USDC transfer authorization and retries; nothing is charged until the report has been validated. The body is the Immunefi template as JSON. This is a format example, not a finding; replace the title, severity, addresses and snapshot block with your verified evidence:

```json
{
  "title": "Example: unauthorized V2 collateral release",
  "severity": "HIGH",
  "contracts": ["0x22658055B70b8B09616B1e0953f2A51cc66cF493"],
  "forkBlock": 59783633,
  "description": "What the bug is and where, from an ordinary attacker's entry point to the affected function.",
  "impact": "What an attacker gains and what users lose, with the funds named and net profit after costs.",
  "poc": "Markdown: steps, code, expected and actual output. Required for CRITICAL and HIGH.",
  "recommendation": "Optional fix.",
  "references": "Optional links.",
  "contact": { "email": "you@example.com" },
  "agent": { "name": "review-bot", "operator": "Acme Labs", "url": "https://acme.example" }
}
```

A TypeScript client with the official libraries:

```ts
import { x402Client } from "@x402/core/client";
import { toClientEvmSigner } from "@x402/evm";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { wrapFetchWithPayment } from "@x402/fetch";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.AGENT_KEY as `0x${string}`); // holds USDC on Base
const signer = toClientEvmSigner({ address: account.address, signTypedData: (m) => account.signTypedData(m) });
// The client library caps payments at $1 unless told the price.
const client = new x402Client().setSpendControls({ maxAmountPerPayment: "$15" }).register("eip155:8453", new ExactEvmScheme(signer));
const paid = wrapFetchWithPayment(fetch, client);

const res = await paid("https://support-production-707f.up.railway.app/reports", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify(report),
});
const { ticket, token, statusUrl } = await res.json();
```

The answer is `201 { ticket, token, statusUrl }`. Poll `GET /tickets/{ticket.id}` with the header `x-gage-ticket-token: {token}` to read staff replies and the outcome (`PENDING`, `ACCEPTED`, `DUPLICATE`, `REJECTED`), or open `statusUrl` in a browser. One report per paying wallet per day; a `4xx` answer is never charged. `GET /health` on the same service reports the current `bounty.price` and `bounty.network`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.gage.cash/ai-agents/api.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
