Build
API reference
One base URL, one header, five endpoints — four pull, one push.
Base URL https://api.metera.xyz. Auth by Authorization: Bearer mk_live_… (or x-api-key).
GET /v1/types
The servable catalog: the canonical types live today, with the max level each reaches.
{
"types": [
{ "type": "token.price", "providers": 5, "requiredParams": [], "maxLevel": "anchored", "capReason": null },
{ "type": "spot.price", "providers": 4, "requiredParams": ["symbol"], "maxLevel": "consensus", "capReason": null },
{ "type": "funding.rate", "providers": 3, "requiredParams": ["symbol","venue"], "maxLevel": "single_source",
"capReason": "each venue reports its own rate — three venues are three quantities, not three observations" }
]
}POST /v1/ask
Body { "query": string }. A model classifies the question into a canonical type, it never answers from its own knowledge. Returns the delivery shape, or no_source for anything no feed measures.
// non-measurable question -> honest no_source (HTTP 200, nothing charged)
{ "status": "no_source",
"message": "No source measures that. Metera answers from data feeds (prices, social metrics, live counts), not general knowledge." }POST /v1/get_data
Body { "type": string, "params": object }. Direct canonical call, no model in the path.
curl -X POST https://api.metera.xyz/v1/get_data \
-H "Authorization: Bearer mk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"type":"spot.price","params":{"symbol":"BTC"}}'POST /v1/gate
Body { pool, payer, inputTokenAccount, outputTokenAccount, amountIn, policy }. Runs solana.swap_quote and solana.token_risk on a Raydium CPMM or Meteora DAMM V2 trade and returns allow / allow_with_caveat / refuse, decided by a policy YOU supply — see the Gates page for the full reference, the honesty guarantees, and why the checked mint cannot be spoofed by a caller.
curl -X POST https://api.metera.xyz/v1/gate \
-H "Authorization: Bearer mk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"pool":"...","payer":"...","inputTokenAccount":"...","outputTokenAccount":"...","amountIn":"10000000","policy":{"maxRiskScore":50,"maxPriceImpactBps":1000}}'POST /v1/watch — the one push endpoint
Body { type, params, condition?, webhookUrl, minIntervalSeconds? }. Register an address to watch; Metera calls your webhookUrl when it changes, each delivery independently re-verified, never forwarded from the trigger alone — see the Webhooks page for the full reference, the HMAC signature, and how to verify a delivery.
curl -X POST https://api.metera.xyz/v1/watch \
-H "Authorization: Bearer mk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"type":"solana.can_sign","params":{"signer":"...","target":"..."},"webhookUrl":"https://your-service.example/hooks/metera"}'The delivery object
Field by field, this is the product surface.
{
"status": "delivered", // delivered | no_source | refused | error
"data": { ... }, // the datum (shape depends on the type)
"verification": {
"level": "anchored", // single_source | consensus | anchored
"source": "bitstamp", // the source that delivered
"cost": "0.0015", // engine-internal charged amount, informational
"traceId": "tr_elxvqz" // audit id for this decision
},
"type": "token.price",
"params": { "token": "SOL" },
"debitedCredits": 1, // what YOU are billed, in credits
"balanceAfter": 2999 // your remaining credit balance
}Error codes
401 INVALID_KEY { "error":"Missing or invalid API key", "code":"INVALID_KEY" }
400 MISSING_QUERY query is required (/v1/ask)
400 MISSING_TYPE type is required (/v1/get_data)
404 TYPE_NOT_FOUND { "error":"Unknown or unservable type", "code":"TYPE_NOT_FOUND" }
400 MISSING_PARAM found a source but the identifier is missing (e.g. social handle)
402 INSUFFICIENT_CREDITS { "status":"error", "code":"INSUFFICIENT_CREDITS", "balance": 0 }
409 NO_QUALIFYING_DELIVERY refused: no delivery met the required level, nothing charged
429 RATE_LIMIT { "error":"Rate limit: 10/min", "code":"RATE_LIMIT" }
500 RESOLVE_FAILED internal resolve error
400 MISSING_POLICY policy.maxPriceImpactBps is required (/v1/gate) — no server-side default
400 BAD_MIN_LEVEL policy.minLevel must be single_source, consensus or anchored (/v1/gate)
400 WATCH_REJECTED unsupported type, missing required param, or invalid webhookUrl (/v1/watch)
404 NOT_FOUND no watch with that id for this account (DELETE /v1/watch/:id)
// no_source is a 200, not an error. It is the honest answer.