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.

Tempo Moderato testnetPaid reports off on this deployment

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

EndpointAccessReturns
GET/v1PublicDiscovery document: endpoints, price, network.
GET/v1/marketsPublicSupported markets with IDs and best prices.
GET/v1/markets/{marketId}/health/previewPublicFree summary: quality, best prices, spread, levels read.
GET/v1/intelligence/markets/{marketId}/healthMPPThe full, immutable report for the current block.
GET/v1/reports/{reportId}EntitlementFetch a report you already paid for. Never charges.
POST/mcpPublic / entitlementRead-only MCP tools over Streamable HTTP.

Paying with MPP

  1. 1

    Challenge

    Request the report. Korrin pins an immutable report and answers 402 with a tempo.charge challenge bound to its report ID.

  2. 2

    Payment

    Your client checks the price and pays 0.01 pathUSD on Moderato before the challenge expires (2 minutes).

  3. 3

    Verified

    The server verifies the payment with mppx and records one entitlement per payment reference.

  4. 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_PAIR404The market ID is not one Korrin reports on.
INVALID_INPUT400A parameter is malformed, such as bandBps outside 1 to 50.
PAYMENT_REQUIRED402No credential. The response carries the MPP challenge.
PAYMENT_NOT_VERIFIED402The credential failed verification. Nothing is delivered.
ENTITLEMENT_REQUIRED401Retrieval without a valid token or credential.
REPORT_NOT_FOUND404The pinned report expired before payment. Nothing was charged.
REPORT_TEMPORARILY_UNAVAILABLE503The market could not be read. No challenge is issued.
PAYMENT_NOT_CONFIGURED503Paid reports are switched off on this deployment.
RATE_LIMITED429Too 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.