Qty API
Qty parses and converts quantities in code. It does not call a model. It does not invent numbers. Temperature is affine. US and imperial gallons differ. The international foot is the default foot. Pace is not speed unless a speed unit is requested. Every JSON response has a top-level see object pointing at docs.
Version 1.0.0. This page is rendered from the same document as /openapi.json.
GET /health
health
Returns ok. No payment, no Redis, no network.
Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"ok": true,
"service": "qty",
"version": "1.0.0"
}GET /units
listUnits
Call this before convert when you are unsure of a code. Free.
Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"units": [
{
"code": "mi",
"aliases": [
"mile",
"statute mile"
],
"dimension": "length",
"definitionId": "length.mile.statute"
}
]
}POST /v1/convert
convert
Use when you already have a number and two codes from GET /units, such as 10 mi to km or 32 F to C. Temperature is affine. If the text is messy (5'11", a stick of butter, a price, a size, a date), this returns 400 use_parse and you must call POST /v1/parse. Deterministic. assumptions is always an array. Limited to 60 requests per 60 seconds per client. Over the limit returns 429 rate_limited with Retry-After. The hint points at paid POST /v1/batch ($0.01). The client is ipAddress() from @vercel/functions (x-real-ip), otherwise the first public address in x-vercel-forwarded-for, then x-forwarded-for. Ports and non-addresses are ignored. The address is not stored. Responses include x-ratelimit-source (redis, memory, or none), x-ratelimit-key-prefix (first 8 hex chars of the client hash), and x-ratelimit-window (the fixed window id). The counter is shared through the same Redis as the feed (KV_REST_API_* or UPSTASH_REDIS_REST_*). A Redis error does not fail the route.
Example request
{
"value": 10,
"from": "mi",
"to": "km"
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"result": 16.09344,
"from": "mi",
"to": "km",
"formula": "10 mi × 1.609344 km/mi = 16.09344 km",
"definitionId": "length.mile.statute",
"assumptions": []
}GET /v1/feed
feed
Free. Cached for about 2 seconds. Events contain route, kind, from value and unit, to value and unit, or a short category, plus a timestamp. Raw text, receipts, wallets, IPs, and headers are never stored. Empty when Redis is not configured.
Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"events": [],
"totals": {
"all": 0,
"routes": {}
},
"configured": false
}GET /v1/parse
parseQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/parse ($0.002). The handler does not run.
POST /v1/parse
parse
Interpret messy quantity text into a list of quantities. Call this when convert returns use_parse. Deterministic. Never invents a number: unknown amounts are null with a reason. Same text always returns the same quantities. Does not call a model or any other service. Price $0.002 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"text": "5'11\"",
"to": "cm"
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"quantities": [
{
"value": 180.34,
"unit": "cm",
"siValue": 1.8034,
"siUnit": "m",
"formula": "5 ft × 0.3048 m + 11 in × 0.0254 m = 1.8034 m; 1.8034 m = 180.34 cm",
"definitionId": "length.foot.international",
"confidence": 0.98,
"warnings": [],
"assumptions": [
"Feet and inches use the international foot (0.3048 m) and the international inch (0.0254 m)."
],
"reason": null,
"label": "height"
}
]
}GET /v1/batch
batchQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/batch ($0.01). The handler does not run.
POST /v1/batch
batch
Parse up to 100 messy texts for a flat price. One bad row does not fail the batch. Each row is ok with quantities or ok:false with a stable error code. Deterministic. No per-row upto pricing in v1. Price $0.01 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"items": [
{
"text": "10 mi",
"to": "km"
},
{
"text": "not a quantity"
}
]
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"results": [
{
"index": 0,
"ok": true,
"quantities": []
},
{
"index": 1,
"ok": false,
"error": {
"code": "unparsed"
}
}
]
}GET /v1/receipt
receiptQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/receipt ($0.001). The handler does not run.
POST /v1/receipt
receipt
Canonical audit JSON plus sha256 of a previous Qty result. Includes input, definition ids, formulas, and a timestamp. The hash ignores the timestamp so the same payload always hashes the same. No chain write. Price $0.001 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"quantities": [
{
"value": 180.34,
"unit": "cm",
"formula": "5 ft + 11 in",
"definitionId": "length.foot.international"
}
]
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"document": {
"kind": "qty.receipt.v1",
"definitions": [],
"formulas": [],
"timestamp": "2026-10-05T00:00:00.000Z"
},
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
}GET /v1/compare-prices
compare-pricesQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/compare-prices ($0.002). The handler does not run.
POST /v1/compare-prices
compare-prices
Normalise unit prices and say which offer is cheaper. Currency is a label only; Qty never converts between currencies. Multipacks are totalled first. Returns price per base unit (litre, kilogram, or each). Price $0.002 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"offers": [
"£2.50 for 750ml",
"£3 for 1L"
]
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"comparison": {
"cheaperIndex": 1,
"currency": "GBP",
"baseUnit": "L"
}
}GET /v1/scale-recipe
scale-recipeQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/scale-recipe ($0.002). The handler does not run.
POST /v1/scale-recipe
scale-recipe
Scale ingredient amounts by servings or a factor. Cup, tbsp, tsp, and stick convert between us, imperial, and si using the labelled assumption table. Mass and volume convert only for flour, sugar, butter, water, milk, and rice. Anything else is null with a reason. Price $0.002 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"fromServings": 4,
"toServings": 6,
"ingredients": [
"2 cups flour",
"1 stick of butter"
]
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"recipe": {
"factor": 1.5,
"definitionId": "recipe.scale.servings.v1"
}
}GET /v1/size
sizeQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/size ($0.002). The handler does not run.
POST /v1/size
size
Convert shoe and clothing sizes using Qty size table v1. Men's UK 9 shoe is EU 43 and US 10. Ambiguous gender or category returns null and a reason. Brand variance is always a warning. No interpolation. Price $0.002 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"text": "UK 9 men's shoe",
"to": "EU"
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"quantities": [
{
"value": 43,
"unit": "EU",
"definitionId": "size.shoe.men.v1"
}
]
}GET /v1/date
dateQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/date ($0.002). The handler does not run.
POST /v1/date
date
Parse ISO-8601 durations, add N days from an explicit date, and convert IANA time zones. Working days skip Saturday and Sunday plus an optional caller holiday list. Daylight-saving gaps and overlaps are reported. There is no built-in holiday calendar. If the text needs a date and none was given, the value is null with a reason. Qty never uses the current clock. Price $0.002 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"text": "2026-01-15T12:00 America/New_York to Europe/London"
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"quantities": [
{
"textValue": "2026-01-15T17:00:00+00:00",
"unit": "Europe/London",
"definitionId": "date.timezone.v1"
}
]
}GET /v1/estimate
estimateQuote
GET returns HTTP 402 with the x402 price quote for POST /v1/estimate ($0.003). The handler does not run.
POST /v1/estimate
estimate
Estimate paint, tiles, concrete, or gravel. Paint uses 10 m² per litre per coat and defaults to 2 coats. Tiles default to 0.30 m × 0.30 m. A 25 kg concrete bag yields 0.012 m³. Gravel uses 1600 kg/m³. Waste defaults to 10 percent and is stated on the result. Assumptions are labels, not a quote from a supplier. Price $0.003 exact USDC on eip155:8453 (0x41F7c3FfC3Cda926797Eb388bB65Ccd8A1deC352) and solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp (GhBZyUbBH2qdTbUXtNjFnbiqeh9c7rsReVU6kjJVCbp6). Unpaid POST and GET calls return 402 and do not include the result. Settlement happens only after a 2xx.
Example request
{
"kind": "paint",
"area": 40,
"unit": "m2",
"coats": 2,
"wastePercent": 10
}Example response
{
"see": {
"llms": "/llms.txt",
"llmsFull": "/llms-full.txt",
"openapi": "/openapi.json",
"docs": "/docs",
"x402": "/.well-known/x402.json",
"agentCard": "/.well-known/agent-card.json",
"mcp": "/mcp",
"tools": "/tools/openai.json",
"anthropicTools": "/tools/anthropic.json",
"aiSdk": "/tools/ai-sdk.ts",
"credits": "/docs/prepaid-credits"
},
"quantities": [
{
"value": 8.8,
"unit": "L",
"definitionId": "building.paint.v1",
"assumptions": [
"Paint coverage is 10 m² per litre per coat (Qty building assumption table v1)."
]
}
]
}GET /tools/openai.json
openaiTools
Function tools for convert, units, and every paid route. Free.
GET /tools/anthropic.json
anthropicTools
input_schema objects matching the MCP tool inputs. Free.
GET /tools/ai-sdk.ts
aiSdkExample
Copy-paste tool() calls using jsonSchema. Free.
POST /mcp
mcp
Tools: convert and units are free. parse, batch, receipt, compare-prices, scale-recipe, size, date, and estimate are paid with the same x402 prices as the HTTP routes. Schemas match /tools/openai.json and /tools/anthropic.json. A paid tool call without payment returns payment_required and does not include the result.