API and MCP setup
The same engine behind the web page is exposed as markdown, a JSON API, and an MCP server. All four surfaces are thin wrappers over one pure function, so they cannot disagree.
MCP server
Streamable HTTP at https://due-date.gumballtools.com/api/mcp. No authentication required.
Claude Code
claude mcp add --transport http due-date https://due-date.gumballtools.com/api/mcpClaude Desktop or Cursor
{
"mcpServers": {
"due-date": {
"type": "http",
"url": "https://due-date.gumballtools.com/api/mcp"
}
}
}Verify it works
curl -X POST 'https://due-date.gumballtools.com/api/mcp' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'JSON API
Every endpoint accepts GET with query parameters or POST with a JSON body. CORS is open. Full machine-readable description at /.well-known/openapi.json.
# From a last menstrual period
curl 'https://due-date.gumballtools.com/api/v1/estimate?method=lmp&date=2025-01-01'
# With a known cycle length
curl 'https://due-date.gumballtools.com/api/v1/estimate?method=lmp&date=2025-01-01&cycleLength=35'
# An ultrasound compared against a period date, which runs the
# ACOG Committee Opinion 700 redating check
curl 'https://due-date.gumballtools.com/api/v1/estimate?method=ultrasound&date=2025-03-04\
&scanWeeks=8&scanDays=0&lmp=2025-01-01'Markdown instead of HTML
Every page has a markdown representation at the same canonical URL. Send Accept: text/markdown or append ?format=md. Responses set Vary: Accept. Do not parse the HTML.
curl -H 'Accept: text/markdown' 'https://due-date.gumballtools.com/'Errors
Every failure returns the same shape, with a stable code and a hint describing what to change before retrying.
{
"error": {
"code": "invalid_input",
"message": "...",
"fix_hint": "...",
"docs": "https://due-date.gumballtools.com/docs"
}
}Rate limits and pricing
- Free: 250 calls per UTC day per caller, on every surface. Quotas apply to humans and agents alike.
- Past the quota: HTTP 402 with an x402 v1 payment requirement — $0.001 per call in USDC on base.
- Settlement is not live yet. While that is true the 402 body carries
payment_enabled: false, so do not attempt payment — wait for the reset time inquota.resetsAt.