> 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

Public Agent API v1 endpoints, request conventions, pagination and errors.

Base URL:

```
https://agent-api-production-6a97.up.railway.app
```

The public API requires no key. It serves Robinhood Chain mainnet (`4663`) and accepts JSON. The [OpenAPI specification](https://agent-api-production-6a97.up.railway.app/openapi.json) contains the complete request and response schemas.

## First request

```sh
curl --fail-with-body \
  https://agent-api-production-6a97.up.railway.app/v1/capabilities
```

Verify `deployment.chainId`, `dealVault`, `registry` and `usdg` against the deployment on [AI Agents](https://docs.gage.cash/ai-agents/overview). Read supported terms and grace from this response rather than hard-coding them.

## Endpoints

| Method and path                    | Purpose                                                                      |
| ---------------------------------- | ---------------------------------------------------------------------------- |
| `GET /v1/capabilities`             | Deployment, terms, pause state, USDG decimals and settlement rules.          |
| `GET /v1/assets`                   | Indexed, approved stock collateral.                                          |
| `GET /v1/listings`                 | Indexed stock listings for supported terms.                                  |
| `GET /v1/deals/{dealId}`           | Direct chain state, `termsHash`, gross repayment math and claim eligibility. |
| `GET /v1/deals/{dealId}/valuation` | Fresh stock collateral reference valuation.                                  |
| `GET /v1/portfolio/{wallet}`       | Indexed positions and credits, plus current USDG credit from chain.          |
| `POST /v1/transactions/prepare`    | Simulate and prepare one unsigned action or approval.                        |

`GET /health` reports process liveness. It does not establish that the indexer or valuation service is usable. Capabilities checks the RPC chain and vault identity; discovery and valuation verify their own dependencies.

The API also serves `/openapi.json` and `/.well-known/agent.json`. The latter is a gage discovery document, not an A2A agent card.

## Listing filters

```sh
curl --fail-with-body \
  'https://agent-api-production-6a97.up.railway.app/v1/listings?term=604800&limit=25&sort=newest'
```

| Query    | Accepted value                               |
| -------- | -------------------------------------------- |
| `term`   | `604800` (7 days) or `1814400` (21 days).    |
| `asset`  | Stock token address.                         |
| `sort`   | `newest`, `expiry`, `cap` or `cost`.         |
| `limit`  | 1–100; default 25.                           |
| `cursor` | The previous response's opaque `nextCursor`. |

All filters are optional. Sorting follows the indexer's ordering; it is not a recommendation. Keep filters unchanged when following a cursor. Continue until `nextCursor` is `null`, including after an empty filtered page.

## Request and response conventions

* Amounts and deal IDs are decimal strings in raw units. Timestamps and terms are integer seconds. `blockNumber` and `indexedBlock` are decimal strings.
* Each v1 success includes `evidence`: chain ID, block number/hash, block timestamp and observation time. Indexed results also include a checkpoint.
* Use current token decimals to format amounts. USDG has 6 decimals in this deployment; `"1000000"` is 1 USDG. Stock display adjustments are separate from raw token quantities.
* Request objects are strict. Private keys, arbitrary destination addresses and caller-supplied calldata are not accepted.
* Responses use `Cache-Control: no-store`. Browser CORS is supported without credentials.

See [Prepare a transaction](https://docs.gage.cash/ai-agents/transactions) for POST bodies and approval handling.

## Submit a finding

Agents reviewing gage contracts can send a bug bounty report straight to the team. The endpoint lives on the support service, not the Agent API, 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](https://docs.gage.cash/protocol/bug-bounty).

```
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:

```json
{
  "title": "Reclaim can be front-run at expiry",
  "severity": "HIGH",
  "contracts": ["0x3D979740785ABd8b7Dd5c2Ff7Bf100CBe86fcBDF"],
  "forkBlock": 114500000,
  "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:*", 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`.

## Errors

```json
{
  "error": {
    "code": "TERMS_CHANGED",
    "message": "Listing differs from the reviewed terms; fetch and review it again",
    "retryable": false
  }
}
```

| HTTP status | Examples                                                                                                                             | What to do                                                     |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
| 400         | `INVALID_INPUT`, `CHAIN_MISMATCH`                                                                                                    | Correct the input or selected network.                         |
| 404         | `DEAL_NOT_FOUND`, `NOT_FOUND`                                                                                                        | Refresh discovery or correct the route.                        |
| 409         | `TERMS_CHANGED`, `SPEND_LIMIT`, `NOT_FUNDABLE`, `GRACE_NOT_OVER`, `SIMULATION_FAILED`, `INSUFFICIENT_BALANCE`, `NOTHING_TO_WITHDRAW` | Read current state and resolve the reason before trying again. |
| 413         | `BODY_TOO_LARGE`                                                                                                                     | Reduce the request body.                                       |
| 429         | `RATE_LIMITED`                                                                                                                       | Respect the `Retry-After` header.                              |
| 503         | `STALE_CHAIN`, `STALE_INDEXER`, `STALE_VALUATION`, `DEPLOYMENT_MISMATCH`, `UPSTREAM_UNAVAILABLE`                                     | Wait for verified, fresh dependencies before acting.           |

The instance has shared limits of 300 API requests and 30 preparation requests per minute, with a 16 KiB request-body limit. These are capacity ceilings across callers, not reserved per-agent quotas. See [Data and limits](https://docs.gage.cash/ai-agents/data-and-limits) for freshness and valuation boundaries.


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
