{"openapi":"3.1.0","info":{"title":"Buddy Code Tools JSON API","version":"1.0.0","description":"Five protected JSON endpoints, disabled by default. Bearer API key and approved account required. 30 requests/minute/key; 1000 requests/UTC day/key and account. 16 KiB request bodies, 32-level nesting limit, 12000-character JSON text limit and 512 KiB formatted output limit. Finite numbers only. Invalid input returns 400. Browser-only tools have no upload endpoint. No MCP server or billing is provided."},"servers":[{"url":"https://www.buddycode.tech"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Buddy Code Tools API key"}}},"paths":{"/api/tools/percentage":{"get":{"operationId":"percentage","summary":"Calculate a percentage, share or change.","description":"Finite numbers only. Undefined divisions are rejected. Results use floating-point precision.","parameters":[{"name":"mode","in":"query","required":false,"schema":{"type":"string","enum":["of","what","change"],"default":"of"}},{"name":"a","in":"query","required":true,"schema":{"type":"number"}},{"name":"b","in":"query","required":true,"schema":{"type":"number"}}],"responses":{"200":{"description":"Successful result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"type":"number"},"unit":{"type":"string"}},"required":["result","unit"]},"example":{"result":30,"unit":"number"}}}},"400":{"description":"Invalid input, including undefined calculations and invalid JSON.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"408":{"description":"Request body read timeout","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"413":{"description":"Body, nesting or output limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"414":{"description":"Query string too large","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"415":{"description":"Unsupported content type or encoding","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit or allowance reached","headers":{"Retry-After":{"description":"Seconds until reset","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Execution disabled, not configured, or service unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/tools/pace":{"get":{"operationId":"pace","summary":"Convert running pace and calculate constant-pace finish times.","description":"Constant pace is an assumption, not a race prediction.","parameters":[{"name":"minutes","in":"query","required":true,"schema":{"type":"integer","minimum":0,"maximum":999}},{"name":"seconds","in":"query","required":true,"schema":{"type":"integer","minimum":0,"maximum":59}},{"name":"unit","in":"query","required":false,"schema":{"type":"string","enum":["mi","km"],"default":"mi"}}],"responses":{"200":{"description":"Successful result","content":{"application/json":{"schema":{"type":"object","properties":{"secondsPerKm":{"type":"number"},"secondsPerMile":{"type":"number"},"converted":{"type":"object","properties":{"seconds":{"type":"number"},"formatted":{"type":"string"},"unit":{"type":"string","enum":["min/km","min/mile"]}},"required":["seconds","formatted","unit"]},"finishTimes":{"type":"array","items":{"type":"object","properties":{"distance":{"type":"string"},"seconds":{"type":"number"},"formatted":{"type":"string"}},"required":["distance","seconds","formatted"]}}},"required":["secondsPerKm","secondsPerMile","converted","finishTimes"]},"example":{"secondsPerKm":298.2581722739203,"secondsPerMile":480.00000000000006,"converted":{"seconds":298.2581722739203,"formatted":"4:58","unit":"min/km"},"finishTimes":[{"distance":"5K","seconds":1491.2908613696015,"formatted":"24:51"},{"distance":"10K","seconds":2982.581722739203,"formatted":"49:43"},{"distance":"10 miles","seconds":4800,"formatted":"1:20:00"},{"distance":"Half marathon","seconds":6292.501789549034,"formatted":"1:44:53"},{"distance":"Marathon","seconds":12585.003579098067,"formatted":"3:29:45"},{"distance":"50K","seconds":14912.908613696016,"formatted":"4:08:33"}]}}}},"400":{"description":"Invalid input, including undefined calculations and invalid JSON.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"408":{"description":"Request body read timeout","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"413":{"description":"Body, nesting or output limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"414":{"description":"Query string too large","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"415":{"description":"Unsupported content type or encoding","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit or allowance reached","headers":{"Retry-After":{"description":"Seconds until reset","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Execution disabled, not configured, or service unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/tools/convert":{"get":{"operationId":"convert","summary":"Convert units within a measurement category.","description":"Floating-point arithmetic; display uses up to 12 significant digits. US and Imperial volumes differ.","parameters":[{"name":"value","in":"query","required":true,"schema":{"type":"number"}},{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["Length","Mass","Temperature","Volume","Area","Speed"],"default":"Length"}},{"name":"from","in":"query","required":true,"schema":{"type":"string","description":"Unit ID in the selected category; see /api/tools for all supported IDs."}},{"name":"to","in":"query","required":true,"schema":{"type":"string","description":"Unit ID in the same category as from."}}],"responses":{"200":{"description":"Successful result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"type":"number"},"unit":{"type":"string"}},"required":["result","unit"]},"example":{"result":0.621371192237334,"unit":"mi"}}}},"400":{"description":"Invalid input, including undefined calculations and invalid JSON.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"408":{"description":"Request body read timeout","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"413":{"description":"Body, nesting or output limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"414":{"description":"Query string too large","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"415":{"description":"Unsupported content type or encoding","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit or allowance reached","headers":{"Retry-After":{"description":"Seconds until reset","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Execution disabled, not configured, or service unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/tools/json":{"post":{"operationId":"json","summary":"Validate and format JSON text.","description":"Up to 1 million characters. Duplicate keys retain the last value; large numbers may lose precision.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":12000},"indent":{"type":"integer","enum":[0,2,4],"default":2}},"required":["text"]},"example":{"text":"{\"hello\":1}","indent":2}}}},"responses":{"200":{"description":"Successful result","content":{"application/json":{"schema":{"type":"object","properties":{"formatted":{"type":"string"},"valid":{"type":"boolean","const":true}},"required":["formatted","valid"]},"example":{"formatted":"{\n  \"hello\": 1\n}","valid":true}}}},"400":{"description":"Invalid input, including undefined calculations and invalid JSON.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"408":{"description":"Request body read timeout","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"413":{"description":"Body, nesting or output limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"414":{"description":"Query string too large","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"415":{"description":"Unsupported content type or encoding","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit or allowance reached","headers":{"Retry-After":{"description":"Seconds until reset","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Execution disabled, not configured, or service unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/api/tools/time-zones":{"post":{"operationId":"time_zones","summary":"Resolve a dated local time across IANA time zones.","description":"Up to 12 destinations. The weekday 09:00–17:00 indicator excludes holidays and personal schedules.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"local":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$"},"zone":{"type":"string","description":"Source IANA time zone"},"zones":{"type":"array","minItems":1,"maxItems":12,"items":{"type":"string","description":"Destination IANA time zone"}},"disambiguation":{"type":"string","enum":["reject","earlier","later"],"default":"reject"}},"required":["local","zone","zones"]},"example":{"local":"2026-09-14T14:00","zone":"Europe/London","zones":["America/New_York","Asia/Tokyo"],"disambiguation":"reject"}}}},"responses":{"200":{"description":"Successful result","content":{"application/json":{"schema":{"type":"object","properties":{"instant":{"type":"string"},"source":{"type":"string"},"times":{"type":"array","items":{"type":"object","properties":{"timeZone":{"type":"string"},"date":{"type":"string"},"time":{"type":"string"},"offset":{"type":"string"},"workingHours":{"type":"boolean"}},"required":["timeZone","date","time","offset","workingHours"]}}},"required":["instant","source","times"]},"example":{"instant":"2026-09-14T13:00:00Z","source":"2026-09-14T14:00:00+01:00[Europe/London]","times":[{"timeZone":"America/New_York","date":"2026-09-14","time":"09:00","offset":"-04:00","workingHours":true},{"timeZone":"Asia/Tokyo","date":"2026-09-14","time":"22:00","offset":"+09:00","workingHours":false}]}}}},"400":{"description":"Invalid input, including undefined calculations and invalid JSON.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"408":{"description":"Request body read timeout","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"413":{"description":"Body, nesting or output limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"414":{"description":"Query string too large","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"415":{"description":"Unsupported content type or encoding","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit or allowance reached","headers":{"Retry-After":{"description":"Seconds until reset","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"Execution disabled, not configured, or service unavailable","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}}}}