Market intelligence API
The same Liquidity Health Report the Korrin app shows, for any agent or service: executable depth in a price band, read from Tempo’s DEX, with every unknown marked as unknown. Previews are free. A full report costs one MPP payment and can be fetched again without paying twice.
Try the free preview
GET /v1/markets/tempo-moderato:betausd-pathusd/health/preview
Free and read-only. It reads Tempo when you press the button.
Endpoints
| Endpoint | Access | Returns |
|---|---|---|
| GET/v1 | Public | Discovery document: endpoints, price, network. |
| GET/v1/markets | Public | Supported markets with IDs and best prices. |
| GET/v1/markets/{marketId}/health/preview | Public | Free summary: quality, best prices, spread, levels read. |
| GET/v1/intelligence/markets/{marketId}/health | MPP | The full, immutable report for the current block. |
| GET/v1/reports/{reportId} | Entitlement | Fetch a report you already paid for. Never charges. |
| POST/mcp | Public / entitlement | Read-only MCP tools over Streamable HTTP. |
Paying with MPP
- 1
Challenge
Request the report. Korrin pins an immutable report and answers 402 with a tempo.charge challenge bound to its report ID.
- 2
Payment
Your client checks the price and pays 0.01 pathUSD on Moderato before the challenge expires (2 minutes).
- 3
Verified
The server verifies the payment with mppx and records one entitlement per payment reference.
- 4
Report ready
You get the report, a Payment-Receipt header and a Korrin-Entitlement token for fetching it again.
Retrying with the same credential returns the same report and receipt without a second charge, so a dropped connection after payment never costs twice. A report is fixed before you pay: paying for an older challenge gets you that report, not a newer one, and the response tells you its age. The price is a testnet value for proving the flow, not a commercial price.
import { Mppx, tempo } from 'mppx/client'
import { privateKeyToAccount } from 'viem/accounts'
const mppx = Mppx.create({ methods: [tempo({ account: privateKeyToAccount(process.env.KEY) })], polyfill: false })
const url = 'https://korrin-steel.vercel.app/v1/intelligence/markets/tempo-moderato:betausd-pathusd/health'
const challenge = await mppx.rawFetch(url) // 402 with the MPP challenge
const credential = await mppx.createCredential(challenge)
const res = await fetch(url, { headers: { authorization: credential } })
const { report, entitlement } = await res.json() // also: res.headers.get('payment-receipt')
// Later, without paying again:
await fetch(`https://korrin-steel.vercel.app/v1/reports/${report.reportId}`, {
headers: { 'korrin-entitlement': entitlement.retrieve.token },
})A complete client that also checks retries, tampering and concurrency is in the repository at scripts/mpp-buy-report.ts.
MCP
Point any MCP client at the Streamable HTTP endpoint. Every tool is read-only; none can sign, trade or read an operator’s private plan.
{ "mcpServers": { "korrin": { "url": "https://korrin-steel.vercel.app/mcp" } } }- list_supported_marketsfree
- get_market_health_previewfree
- get_market_exceptionsfree
- get_market_healthneeds an entitlement token
- get_liquidity_coverageneeds an entitlement token
- explain_liquidity_changeneeds two entitlement tokens
- get_mandate_statusalways refuses: private plans are not exposed
What a report contains
- Network, market and the block the book was read at. Freshness is computed when you read it, so the report body never changes.
- Bid and ask depth inside the band. Price levels the RPC cannot read make the total unknown, with a lower bound. They are never counted as zero.
- Quality (HIGH, DEGRADED or UNAVAILABLE) with the reasons, best prices, spread and book shape.
- A keccak256 digest over the canonical body. The report ID is derived from it, so any edit is detectable.
- Public reports never include anyone’s plan, orders or balances. Those appear only inside the operator’s own workspace.
Errors
Every error is { error: { code, message, retryable, traceId } }.
| UNSUPPORTED_PAIR | 404 | The market ID is not one Korrin reports on. |
| INVALID_INPUT | 400 | A parameter is malformed, such as bandBps outside 1 to 50. |
| PAYMENT_REQUIRED | 402 | No credential. The response carries the MPP challenge. |
| PAYMENT_NOT_VERIFIED | 402 | The credential failed verification. Nothing is delivered. |
| ENTITLEMENT_REQUIRED | 401 | Retrieval without a valid token or credential. |
| REPORT_NOT_FOUND | 404 | The pinned report expired before payment. Nothing was charged. |
| REPORT_TEMPORARILY_UNAVAILABLE | 503 | The market could not be read. No challenge is issued. |
| PAYMENT_NOT_CONFIGURED | 503 | Paid reports are switched off on this deployment. |
| RATE_LIMITED | 429 | Too many requests. Honour retry-after. |
Testnet only. Reports describe resting orders at one block and are not a guarantee of future liquidity, a peg, or a price. See the product for how operators use the same reports.