mimirapi
v0.1.0
Published
Official isomorphic TypeScript/JavaScript client for MimirAPI — pay-per-call tools for agents over x402 (USDC on Base). No API key, no signup. Zero dependencies; runs on Node, Bun, browsers, and Cloudflare Workers.
Downloads
148
Maintainers
Readme
mimirapi
Official isomorphic TypeScript/JavaScript client for MimirAPI — pay-per-call tools for agents over x402 (USDC on Base).
No API key. No signup. Discovery is free; paid routes quote a price with HTTP 402, you settle it, and retry. Zero dependencies — runs on Node 18+, Bun, browsers, and Cloudflare Workers.
npm install mimirapiBrowse the shelf (free)
import { MimirApiClient } from 'mimirapi';
const mimir = new MimirApiClient();
const { skus } = await mimir.catalog();
for (const sku of skus) {
console.log(`${sku.id} — $${sku.priceUsd}/call — ${sku.method} ${sku.path}`);
}catalog(), sku(id), and health() are never metered.
Call a paid tool
Without a settler, a paid route throws PaymentRequiredError carrying the quote:
import { PaymentRequiredError } from 'mimirapi';
try {
await mimir.call('/v1/ping');
} catch (err) {
if (err instanceof PaymentRequiredError) {
console.log(err.accepts); // [{ scheme: 'exact', network: 'base', maxAmountRequired: '1000' }]
// Settle one of these, then retry the same request.
}
}Bring your own wallet
This package ships no wallet. Bundling signing keys into a client library is how people lose money — you plug in a settler and the client handles everything around it: the 402 round trip, the price ceiling, and the retry.
const mimir = new MimirApiClient({
maxPriceUsd: 0.05,
settle: async (challenge, { url }) => {
// Sign an EIP-3009 authorization for challenge.accepts[0] and return the
// PAYMENT-SIGNATURE header value. Return null to decline.
return signWithYourWallet(challenge, url);
},
});
const pong = await mimir.call('/v1/ping'); // pays $0.001 and returns the resultThe safety rails
maxPriceUsd(default0.25) is checked before the settler is invoked. A counter that raises its price — or a bug — cannot drain a wallet; you getPriceCeilingErrorinstead.- An unparseable or absent quote is treated as
Infinity, never as free. - A second 402 is never retried. If settlement did not take, retrying risks paying twice, so the client throws instead.
Input shapes
method follows the catalog row: GET SKUs take query params, POST SKUs take a JSON body.
await mimir.call('/v1/qr', { method: 'GET', input: { data: 'hello' } });
await mimir.call('/v1/db', { input: { ttlSeconds: 300 } }); // POST inferred from inputErrors
| Class | When |
|---|---|
| PaymentRequiredError | 402 with no settler, a declined settle, or a second 402 |
| PriceCeilingError | quote exceeded maxPriceUsd; the settler was never called |
| MimirApiError | any other non-2xx, plus network failures (status: 0, code: 'network_error') |
Discovery surfaces
MimirAPI is agent-native. Beyond this client:
- Catalog —
https://mimirapi.com/v1/catalog - Agent overview —
https://mimirapi.com/llms.txt - MCP server —
POST https://mimirapi.com/mcp - OpenAPI 3.1 —
https://mimirapi.com/.well-known/openapi.json
License
MIT
