{"openapi":"3.1.0","info":{"title":"Benchline","version":"1.0.0","description":"HTTP access to the same functions the Benchline MCP server exposes. Each call is anonymous and limited to 60 requests a minute per address."},"servers":[{"url":"https://benchline.fabwaseem.com"}],"paths":{"/api/v1/tools/llms-txt-generator":{"post":{"operationId":"generate_llms_txt","summary":"Generate llms.txt","description":"Render llms.txt and llms-full.txt from a site name, a summary, and a list of pages. It does not crawl. Grouping follows the page URLs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteName":{"type":"string","minLength":1},"summary":{"type":"string","minLength":1},"pages":{"minItems":1,"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":"string"},"description":{"default":"","type":"string"},"excerpt":{"default":"","type":"string"}},"required":["url","title","description","excerpt"],"additionalProperties":false},"description":"Pages you already know. This tool does not fetch them."}},"required":["siteName","summary","pages"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate llms.txt","content":{"application/json":{"schema":{"type":"object","properties":{"llms":{"type":"string"},"full":{"type":"string"}},"required":["llms","full"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/ai-seo-checker":{"post":{"operationId":"score_ai_seo","summary":"Score a page for AI search","description":"Fetch a public page plus its robots.txt, sitemap, and llms.txt, then score how ready it is for AI search crawlers. Use this when you have a live URL.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A public page. The check also reads robots.txt, sitemap.xml, and llms.txt on that origin."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Score a page for AI search","content":{"application/json":{"schema":{"type":"object","properties":{"finalUrl":{"type":"string"},"status":{"type":"number"},"score":{"type":"number"},"checks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"level":{"type":"string","enum":["pass","warn","fail"]},"label":{"type":"string"},"detail":{"type":"string"},"weight":{"type":"number"}},"required":["id","level","label","detail","weight"],"additionalProperties":false}}},"required":["finalUrl","status","score","checks"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/og-image-generator":{"post":{"operationId":"build_open_graph","summary":"Build an Open Graph card","description":"Render one of the Open Graph templates as a PNG and a Next.js opengraph-image.tsx file. Pass a template id from list_og_templates, the fields that template uses, colors, a size, and optional base64 images.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"default":"editorial","description":"Template id from list_og_templates.","type":"string","enum":["editorial","aurora","blueprint","terminal","split","brutalist","launch","profile","stat","quote","event","podcast","changelog","glass","minimal-mono","product","tutorial","before-after"]},"size":{"default":"1200x630","type":"string","enum":["1200x630","1600x900","1080x1080"]},"title":{"type":"string"},"subtitle":{"type":"string"},"author":{"type":"string"},"role":{"type":"string"},"eyebrow":{"type":"string"},"badge":{"type":"string"},"date":{"type":"string"},"time":{"type":"string"},"price":{"type":"string"},"cta":{"type":"string"},"url":{"type":"string"},"stat":{"type":"string"},"statLabel":{"type":"string"},"quote":{"type":"string"},"episode":{"type":"string"},"readTime":{"type":"string"},"meta":{"type":"string"},"command":{"type":"string"},"steps":{"description":"One step per line.","type":"string"},"versions":{"description":"One version per line, as v2.3 | Note.","type":"string"},"beforeValue":{"type":"string"},"afterValue":{"type":"string"},"caption":{"type":"string"},"brand":{"description":"Brand name shown on templates that have a brand row.","type":"string"},"colors":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"},"accent":{"type":"string"},"muted":{"type":"string"}},"additionalProperties":false},"logo":{"description":"Logo image as base64, a data URI, or a public URL. Private addresses are refused. 10 MB cap.","type":"string"},"avatar":{"description":"Portrait image as base64, a data URI, or a public URL.","type":"string"},"hero":{"description":"Hero image as base64, a data URI, or a public URL.","type":"string"},"before":{"description":"Before image as base64, a data URI, or a public URL.","type":"string"},"after":{"description":"After image as base64, a data URI, or a public URL.","type":"string"},"imageUrl":{"description":"Public URL written into og:image. This does not fetch the file.","type":"string"}},"required":["template","size"],"additionalProperties":false}}}},"responses":{"200":{"description":"Build an Open Graph card","content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string"},"png":{"type":"string","description":"PNG bytes, base64 encoded."},"mimeType":{"type":"string","const":"image/png"},"width":{"type":"number"},"height":{"type":"number"},"source":{"type":"string"},"metaTags":{"type":"string"}},"required":["template","png","mimeType","width","height","source","metaTags"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/og-template-list":{"post":{"operationId":"list_og_templates","summary":"List Open Graph templates","description":"List Open Graph card templates with ids, names, categories, defaults, color presets, and field schemas.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"category":{"type":"string","enum":["Blog","Product","Dev","Social","Event"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"List Open Graph templates","content":{"application/json":{"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"kind":{"type":"string","enum":["text","textarea"]}},"required":["key","label","kind"],"additionalProperties":false}},"images":{"type":"array","items":{"type":"string"}},"defaults":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"colors":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"},"accent":{"type":"string"},"muted":{"type":"string"}},"required":["background","foreground","accent","muted"],"additionalProperties":false},"presets":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"colors":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"},"accent":{"type":"string"},"muted":{"type":"string"}},"required":["background","foreground","accent","muted"],"additionalProperties":false}},"required":["name","colors"],"additionalProperties":false}},"schema":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","name","category","fields","images","defaults","colors","presets","schema"],"additionalProperties":false}}},"required":["templates"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/jwt-decoder":{"post":{"operationId":"decode_jwt","summary":"Decode a JWT","description":"Decode a signed JSON Web Token into its header, payload, and registered claims. Dates are absolute ISO timestamps. The signature is not checked.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"A signed JWT, with or without a Bearer prefix. The signature is not verified."}},"required":["token"],"additionalProperties":false}}}},"responses":{"200":{"description":"Decode a JWT","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"},"kind":{"type":"string"},"header":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"signature":{"type":"string"},"claims":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"iso":{"type":"string"},"raw":{"type":"string"}},"required":["name","iso","raw"],"additionalProperties":false}}},"required":["ok","error","kind","header","payload","signature","claims"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/robots-txt-checker":{"post":{"operationId":"check_robots_txt","summary":"Check robots.txt","description":"Fetch a public robots.txt and report whether the wildcard group blocks the site and whether Sitemap lines are absolute. Use this when you have a URL, not a pasted file.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A public page or a robots.txt URL. A page URL is resolved to /robots.txt on that origin."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Check robots.txt","content":{"application/json":{"schema":{"type":"object","properties":{"finalUrl":{"type":"string"},"status":{"type":"number"},"text":{"type":"string"},"document":{"type":"object","properties":{"groups":{"type":"array","items":{"type":"object","properties":{"agents":{"type":"array","items":{"type":"string"}},"allow":{"type":"array","items":{"type":"string"}},"disallow":{"type":"array","items":{"type":"string"}},"crawlDelay":{"type":"string"}},"required":["agents","allow","disallow"],"additionalProperties":false}},"sitemaps":{"type":"array","items":{"type":"string"}}},"required":["groups","sitemaps"],"additionalProperties":false},"issues":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail","info"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}}},"required":["finalUrl","status","text","document","issues"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/meta-tags-inspector":{"post":{"operationId":"inspect_meta_tags","summary":"Inspect meta tags","description":"Fetch one public HTML page and report title, description, canonical, Open Graph, Twitter, and JSON-LD. Use this to see what a live URL advertises.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A public HTML page. Only that URL is fetched."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Inspect meta tags","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"redirects":{"type":"array","items":{"type":"string"}},"finalUrl":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"canonical":{"type":"string"},"robots":{"type":"string"},"viewport":{"type":"string"},"lang":{"type":"string"},"themeColor":{"type":"string"},"og":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"twitter":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"icons":{"type":"array","items":{"type":"string"}},"jsonLdTypes":{"type":"array","items":{"type":"string"}},"checks":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}}},"required":["status","redirects","finalUrl","title","description","canonical","robots","viewport","lang","themeColor","og","twitter","icons","jsonLdTypes","checks"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/schema-generator":{"post":{"operationId":"build_json_ld","summary":"Build JSON-LD","description":"Build schema.org JSON-LD for one type, plus a script tag and a list of missing fields. Use this when you already know the fields. It does not fetch a page.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["Article","BlogPosting","FAQPage","HowTo","Product","Organization","Person","LocalBusiness","BreadcrumbList","SoftwareApplication","WebSite","Event"]},"values":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"q":{"type":"string"},"a":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"url":{"type":"string"}},"additionalProperties":false}}]},"description":"Fields for the chosen schema.org type. Repeatable fields are arrays of objects."}},"required":["type","values"],"additionalProperties":false}}}},"responses":{"200":{"description":"Build JSON-LD","content":{"application/json":{"schema":{"type":"object","properties":{"json":{"$ref":"#/$defs/__schema0"},"script":{"type":"string"},"checks":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}}},"required":["json","script","checks"],"additionalProperties":false,"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}}]}}}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/ai-token-counter":{"post":{"operationId":"count_tokens","summary":"Count tokens","description":"Count tokens with the o200k or cl100k encoder and price the count against the published model table. Claude and Gemini rows are estimates, not those vendors' tokenizers.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"The prompt or document to count."},"encoding":{"default":"o200k","type":"string","enum":["o200k","cl100k"]},"modelIds":{"default":["gpt-6.1-sol","claude-sonnet-5-5","gemini-4-argon"],"description":"Price rows to return. Unknown ids are rejected.","type":"array","items":{"type":"string"}},"outputTokens":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"cachedRatio":{"default":0,"type":"number","minimum":0,"maximum":1},"requestsPerDay":{"default":0,"type":"number","minimum":0}},"required":["text","encoding","modelIds","outputTokens","cachedRatio","requestsPerDay"],"additionalProperties":false}}}},"responses":{"200":{"description":"Count tokens","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"number"},"chars":{"type":"number"},"words":{"type":"number"},"encoding":{"type":"string"},"prices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"inputUsd":{"type":"number"},"outputUsd":{"type":"number"},"requestUsd":{"type":"number"},"monthUsd":{"type":"number"}},"required":["id","label","inputUsd","outputUsd","requestUsd","monthUsd"],"additionalProperties":false}}},"required":["count","chars","words","encoding","prices"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/cron-expression-builder":{"post":{"operationId":"explain_cron","summary":"Explain a cron expression","description":"Turn a cron expression into English, the next UTC run times, and snippets for crontab, GitHub Actions, Vercel, Kubernetes, and node-cron.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expression":{"type":"string","description":"A cron expression, including @daily or @reboot."},"dialect":{"default":"standard","type":"string","enum":["standard","seconds","quartz","hosted"]},"timeZone":{"default":"UTC","description":"IANA time zone used to list the next runs. Hosted schedules stay in UTC.","type":"string"},"now":{"description":"ISO timestamp used as the clock. Omit it to use the current time.","type":"string"}},"required":["expression","dialect","timeZone"],"additionalProperties":false}}}},"responses":{"200":{"description":"Explain a cron expression","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"english":{"type":"string"},"error":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"runs":{"type":"array","items":{"type":"object","properties":{"utc":{"type":"string"}},"required":["utc"],"additionalProperties":false}},"snippets":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"code":{"type":"string"}},"required":["label","code"],"additionalProperties":false}},"hostedNote":{"type":"string"}},"required":["valid","english","error","fields","runs","snippets","hostedNote"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/nextjs-dockerfile-generator":{"post":{"operationId":"build_nextjs_dockerfile","summary":"Build a Next.js Dockerfile","description":"Generate a production Dockerfile, dockerignore, compose file, and next.config snippet for a Next.js app. Defaults match a pnpm standalone image.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"packageManager":{"default":"pnpm","type":"string","enum":["npm","pnpm","yarn","bun"]},"node":{"default":"22","type":"string","enum":["20","22","24"]},"base":{"default":"slim","type":"string","enum":["alpine","slim"]},"standalone":{"default":true,"type":"boolean"},"prisma":{"default":false,"type":"boolean"},"migrate":{"default":false,"type":"boolean"},"healthcheck":{"default":true,"type":"boolean"},"healthPath":{"default":"/api/health","type":"string"},"port":{"default":3000,"type":"integer","minimum":1,"maximum":65535},"publicEnvs":{"default":[],"type":"array","items":{"type":"string"}},"telemetryDisabled":{"default":true,"type":"boolean"},"cacheMounts":{"default":true,"type":"boolean"},"turbo":{"default":false,"type":"boolean"}},"required":["packageManager","node","base","standalone","prisma","migrate","healthcheck","healthPath","port","publicEnvs","telemetryDisabled","cacheMounts","turbo"],"additionalProperties":false}}}},"responses":{"200":{"description":"Build a Next.js Dockerfile","content":{"application/json":{"schema":{"type":"object","properties":{"dockerfile":{"type":"string"},"dockerignore":{"type":"string"},"compose":{"type":"string"},"nextConfig":{"type":"string"},"commands":{"type":"string"},"estimatedSize":{"type":"string"},"image":{"type":"string"}},"required":["dockerfile","dockerignore","compose","nextConfig","commands","estimatedSize","image"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/json-formatter":{"post":{"operationId":"format_json","summary":"Format and validate JSON","description":"Pretty-print or minify JSON. A number that does not fit in a JavaScript number keeps the digits you sent. Returns the formatted text when it is valid, or the line and column of each syntax error.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"json":{"type":"string","description":"JSON text to format or validate."},"indent":{"default":"2","type":"string","enum":["2","4","tab"]},"sortKeys":{"default":false,"description":"Sort object keys. Array order is kept.","type":"boolean"},"minify":{"default":false,"type":"boolean"}},"required":["json","indent","sortKeys","minify"],"additionalProperties":false}}}},"responses":{"200":{"description":"Format and validate JSON","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"type":"string"},"valid":{"type":"boolean"},"errors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"line":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"column":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["message","line","column"],"additionalProperties":false}}},"required":["output","valid","errors"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/json-yaml-convert":{"post":{"operationId":"convert_data_format","summary":"Convert JSON, YAML, TOML, or XML","description":"Convert between JSON, YAML, TOML, and XML. Auto-detects the source. Numbers that do not fit in a JavaScript number keep their digits. Errors include a line and column. TOML refuses null and a non-table root.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"The source document."},"from":{"default":"auto","type":"string","enum":["auto","json","yaml","toml","xml"]},"to":{"default":"json","type":"string","enum":["json","yaml","toml","xml"]}},"required":["text","from","to"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert JSON, YAML, TOML, or XML","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"output":{"type":"string"},"detected":{"type":"string"},"error":{"type":"string"},"line":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"column":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["ok","output","detected","error","line","column"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/csv-json-convert":{"post":{"operationId":"convert_csv_json","summary":"Convert CSV and JSON","description":"Convert CSV to JSON or JSON to CSV. Supports comma, tab, semicolon, and pipe delimiters, an optional header, type inference, and dotted flattening. Inferred numbers that do not fit in a JavaScript number keep their digits.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"direction":{"default":"csv-to-json","type":"string","enum":["csv-to-json","json-to-csv"]},"delimiter":{"default":"auto","description":"Comma, tab, semicolon, pipe, or auto. Auto is a comma when writing CSV.","type":"string","enum":["auto",",","\t",";","|"]},"header":{"default":true,"type":"boolean"},"inferTypes":{"default":true,"description":"Used when converting CSV to JSON.","type":"boolean"},"flatten":{"default":false,"description":"Used when converting JSON to CSV. Nested keys become dotted columns.","type":"boolean"}},"required":["text","direction","delimiter","header","inferTypes","flatten"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert CSV and JSON","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"output":{"type":"string"},"error":{"type":"string"},"warning":{"type":"string"},"rows":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"columns":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"delimiter":{"type":"string"}},"required":["ok","output","error","warning","rows","columns","delimiter"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/diff-checker":{"post":{"operationId":"diff_text","summary":"Diff two texts","description":"Compare two texts by line, word, or character, or compare JSON so object key order does not matter. Returns an inline diff, side-by-side rows for line and JSON modes, and a unified patch.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"left":{"type":"string","description":"The original text."},"right":{"type":"string","description":"The changed text."},"mode":{"default":"line","type":"string","enum":["line","word","char","json"]},"ignoreWhitespace":{"default":false,"type":"boolean"}},"required":["left","right","mode","ignoreWhitespace"],"additionalProperties":false}}}},"responses":{"200":{"description":"Diff two texts","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"},"unchanged":{"type":"boolean"},"added":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"removed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unit":{"type":"string","enum":["lines","characters"]},"patch":{"type":"string"},"pieces":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["same","add","remove"]},"value":{"type":"string"}},"required":["type","value"],"additionalProperties":false}},"rows":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["same","add","remove","change"]},"left":{"type":"string"},"right":{"type":"string"},"leftNumber":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"rightNumber":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["kind","left","right","leftNumber","rightNumber"],"additionalProperties":false}}},"required":["ok","error","unchanged","added","removed","unit","patch","pieces","rows"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/base64-codec":{"post":{"operationId":"base64_codec","summary":"Encode or decode Base64","description":"Encode UTF-8 text as Base64, or decode Base64 and data URIs. URL-safe output uses - and _ and omits padding. Decode reports the sniffed media type and whether the bytes are UTF-8 text.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"default":"encode","type":"string","enum":["encode","decode"]},"text":{"type":"string","description":"Text to encode, or Base64 or a data URI to decode."},"urlSafe":{"default":false,"description":"Encode with the URL-safe alphabet and no padding. Data URIs stay on the standard alphabet.","type":"boolean"},"dataUri":{"default":false,"type":"boolean"},"mime":{"default":"text/plain;charset=utf-8","type":"string"}},"required":["action","text","urlSafe","dataUri","mime"],"additionalProperties":false}}}},"responses":{"200":{"description":"Encode or decode Base64","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"error":{"type":"string"},"output":{"type":"string"},"mime":{"type":"string"},"filename":{"type":"string"},"binary":{"type":"boolean"}},"required":["ok","error","output","mime","filename","binary"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/image-convert":{"post":{"operationId":"convert_image","summary":"Convert an image","description":"Convert an image to JPEG, PNG, WebP, or AVIF. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns the image as base64. HEIC is not decoded here.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"target":{"default":"jpeg","type":"string","enum":["jpeg","png","webp","avif"]}},"required":["file","target"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert an image","content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string"},"filename":{"type":"string"},"mime":{"type":"string"},"extension":{"type":"string"},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Encoded image as base64."}},"required":["source","filename","mime","extension","width","height","bytes","data"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/image-compress":{"post":{"operationId":"compress_image","summary":"Compress an image","description":"Re-encode an image at a quality from 1 to 100, optionally capping the longest edge. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns the image as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"choice":{"default":"original","type":"string","enum":["original","jpeg","png","webp","avif"]},"quality":{"default":80,"type":"number"},"maxEdge":{"default":null,"description":"Longest edge in pixels. Omit it to keep the size.","anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]}},"required":["file","choice","quality","maxEdge"],"additionalProperties":false}}}},"responses":{"200":{"description":"Compress an image","content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"mime":{"type":"string"},"extension":{"type":"string"},"format":{"type":"string"},"quality":{"type":"number"},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"before":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"after":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"savedBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"savedPercent":{"type":"number"},"label":{"type":"string"},"data":{"type":"string","description":"Compressed image as base64."}},"required":["filename","mime","extension","format","quality","width","height","bytes","before","after","savedBytes","savedPercent","label","data"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/image-resize":{"post":{"operationId":"resize_image","summary":"Resize an image","description":"Resize an image by pixels or percent. Fit is contain, cover, or stretch. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns the image as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"mode":{"default":"pixels","type":"string","enum":["pixels","percent"]},"width":{"default":null,"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"height":{"default":null,"anyOf":[{"type":"number","exclusiveMinimum":0},{"type":"null"}]},"percent":{"default":100,"type":"number"},"lockAspect":{"default":true,"type":"boolean"},"fit":{"default":"contain","type":"string","enum":["contain","cover","stretch"]}},"required":["file","mode","width","height","percent","lockAspect","fit"],"additionalProperties":false}}}},"responses":{"200":{"description":"Resize an image","content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"mime":{"type":"string"},"extension":{"type":"string"},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Resized image as base64."}},"required":["filename","mime","extension","width","height","bytes","data"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/color-converter":{"post":{"operationId":"convert_color","summary":"Convert a color and check contrast","description":"Convert HEX, RGB, HSL, OKLCH, or CMYK into every format, name the nearest Tailwind token, and report the WCAG 2 contrast ratio against a background.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"color":{"type":"string","description":"HEX, rgb(), hsl(), oklch(), cmyk(), or a CSS color name."},"background":{"default":"#ffffff","description":"Background used for the WCAG contrast ratio.","type":"string"}},"required":["color","background"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert a color and check contrast","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"hex":{"type":"string"},"rgb":{"type":"string"},"hsl":{"type":"string"},"oklch":{"type":"string"},"cmyk":{"type":"string"},"tailwind":{"type":"string"},"contrastRatio":{"type":"number"},"contrastText":{"type":"string"},"aaNormal":{"type":"boolean"},"aaLarge":{"type":"boolean"},"aaaNormal":{"type":"boolean"},"aaaLarge":{"type":"boolean"}},"required":["ok","hex","rgb","hsl","oklch","cmyk","tailwind","contrastRatio","contrastText","aaNormal","aaLarge","aaaNormal","aaaLarge"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/unix-timestamp":{"post":{"operationId":"convert_unix_timestamp","summary":"Convert a unix timestamp","description":"Convert epoch seconds, milliseconds, microseconds, or nanoseconds to ISO-8601 and RFC 2822 in an IANA time zone, or convert a calendar time back to epoch.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"default":"","description":"Unix timestamp, ISO-8601, RFC 2822, or now. Leave it empty when year, month, and day are set.","type":"string"},"timeZone":{"default":"UTC","description":"IANA time zone, such as UTC or America/New_York.","type":"string"},"unit":{"default":"auto","type":"string","enum":["auto","s","ms","us","ns"]},"year":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"month":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"day":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hour":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"minute":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"second":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["input","timeZone","unit"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert a unix timestamp","content":{"application/json":{"schema":{"type":"object","properties":{"seconds":{"type":"string"},"milliseconds":{"type":"string"},"isoUtc":{"type":"string"},"isoLocal":{"type":"string"},"rfc2822":{"type":"string"},"relative":{"type":"string"},"weekday":{"type":"string"},"offset":{"type":"string"},"timeZone":{"type":"string"},"unit":{"type":"string"},"alternateIsoUtc":{"type":"string"}},"required":["seconds","milliseconds","isoUtc","isoLocal","rfc2822","relative","weekday","offset","timeZone","unit","alternateIsoUtc"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/date-difference":{"post":{"operationId":"date_difference","summary":"Difference between two dates","description":"Count calendar days, elapsed time, and business days between two dates. Business days skip weekends and any YYYY-MM-DD holidays you list.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"startDate":{"type":"string","description":"Start date as YYYY-MM-DD."},"endDate":{"type":"string","description":"End date as YYYY-MM-DD."},"startTime":{"description":"Start time as HH:MM or HH:MM:SS. Defaults to midnight.","type":"string"},"endTime":{"description":"End time as HH:MM or HH:MM:SS. Defaults to midnight.","type":"string"},"includeEnd":{"default":false,"description":"Count the end date as well as the days between.","type":"boolean"},"holidays":{"default":"","description":"Weekday holidays to exclude from business days, one YYYY-MM-DD per line.","type":"string"}},"required":["startDate","endDate","includeEnd","holidays"],"additionalProperties":false}}}},"responses":{"200":{"description":"Difference between two dates","content":{"application/json":{"schema":{"type":"object","properties":{"sign":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"years":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"months":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"countedDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"weeks":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"extraDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hours":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"seconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalHours":{"type":"string"},"businessDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"weekendDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"holidayDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["sign","years","months","days","totalDays","countedDays","weeks","extraDays","hours","minutes","seconds","totalHours","businessDays","weekendDays","holidayDays"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/hash-generator":{"post":{"operationId":"hash_data","summary":"Hash text or bytes","description":"Compute MD5, SHA-1, SHA-256, and SHA-512 for UTF-8 text or base64 bytes. Pass hmacKey for HMAC and expected to see which digest matches.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"description":"UTF-8 text to hash. Use this or base64.","type":"string"},"base64":{"description":"Raw bytes as standard base64.","type":"string"},"hmacKey":{"description":"UTF-8 HMAC key. Omit it for a plain digest.","type":"string"},"expected":{"description":"Hex or base64 digest to compare.","type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Hash text or bytes","content":{"application/json":{"schema":{"type":"object","properties":{"hashes":{"type":"array","items":{"type":"object","properties":{"algorithm":{"type":"string","enum":["MD5","SHA-1","SHA-256","SHA-512"]},"hex":{"type":"string"},"base64":{"type":"string"}},"required":["algorithm","hex","base64"],"additionalProperties":false}},"matches":{"type":"array","items":{"type":"string","enum":["MD5","SHA-1","SHA-256","SHA-512"]}},"hmac":{"type":"boolean"}},"required":["hashes","matches","hmac"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/uuid-generator":{"post":{"operationId":"generate_uuid","summary":"Generate or inspect a UUID","description":"Generate UUID version 4 or version 7 from cryptographic randomness, up to 10,000 at once, or inspect the version, variant, and v7 timestamp.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"default":"generate","type":"string","enum":["generate","inspect"]},"version":{"default":"v4","type":"string","enum":["v4","v7"]},"count":{"default":1,"type":"integer","minimum":1,"maximum":10000},"value":{"description":"UUID to inspect when action is inspect.","type":"string"}},"required":["action","version","count"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate or inspect a UUID","content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}},"version":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"variant":{"type":"string"},"timestamp":{"type":"string"}},"required":["ids","version","variant","timestamp"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/url-codec":{"post":{"operationId":"url_codec","summary":"Encode, decode, or parse a URL","description":"Percent-encode or decode text, or parse a URL into its host, path, hash, and query parameters.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"default":"parse","type":"string","enum":["encode","decode","parse"]},"value":{"type":"string"},"mode":{"default":"component","type":"string","enum":["component","full"]},"plusAsSpace":{"default":false,"description":"When decoding, treat + as a space.","type":"boolean"}},"required":["action","value","mode","plusAsSpace"],"additionalProperties":false}}}},"responses":{"200":{"description":"Encode, decode, or parse a URL","content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string"},"protocol":{"type":"string"},"username":{"type":"string"},"hostname":{"type":"string"},"port":{"type":"string"},"pathname":{"type":"string"},"hash":{"type":"string"},"query":{"type":"string"},"params":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"],"additionalProperties":false}}},"required":["value","protocol","username","hostname","port","pathname","hash","query","params"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/password-generator":{"post":{"operationId":"generate_password","summary":"Generate a password or passphrase","description":"Generate cryptographic passwords or EFF-wordlist passphrases and report the entropy in bits. Randomness comes from the platform CSPRNG.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"style":{"default":"password","type":"string","enum":["password","passphrase"]},"length":{"default":20,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lowercase":{"default":true,"type":"boolean"},"uppercase":{"default":true,"type":"boolean"},"digits":{"default":true,"type":"boolean"},"symbols":{"default":false,"type":"boolean"},"excludeAmbiguous":{"default":true,"type":"boolean"},"words":{"default":6,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"separator":{"default":"-","type":"string"},"capitalize":{"default":false,"type":"boolean"},"digit":{"default":false,"type":"boolean"},"count":{"default":1,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["style","length","lowercase","uppercase","digits","symbols","excludeAmbiguous","words","separator","capitalize","digit","count"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate a password or passphrase","content":{"application/json":{"schema":{"type":"object","properties":{"values":{"type":"array","items":{"type":"string"}},"bits":{"type":"number"},"label":{"type":"string"},"score":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["values","bits","label","score"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/chmod-calculator":{"post":{"operationId":"explain_chmod","summary":"Explain a chmod mode","description":"Convert an octal or symbolic file mode into octal, symbolic notation, and a chmod command, including setuid, setgid, and the sticky bit.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","description":"Octal such as 755 or 4755, or symbolic such as rwxr-xr-x."},"path":{"default":"file","type":"string"}},"required":["mode","path"],"additionalProperties":false}}}},"responses":{"200":{"description":"Explain a chmod mode","content":{"application/json":{"schema":{"type":"object","properties":{"octal":{"type":"string"},"symbolic":{"type":"string"},"command":{"type":"string"},"setuid":{"type":"boolean"},"setgid":{"type":"boolean"},"sticky":{"type":"boolean"}},"required":["octal","symbolic","command","setuid","setgid","sticky"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-merge":{"post":{"operationId":"merge_pdf","summary":"Merge PDF files","description":"Combine PDF files. Each file is base64 or a public URL, and can keep a page range such as 1-3,5. Private addresses are refused. Returns one PDF as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"minItems":2,"maxItems":25,"type":"array","items":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"},"name":{"default":"document.pdf","type":"string"},"pages":{"default":"","description":"Pages to keep, such as 1-3,5. Blank keeps every page.","type":"string"}},"required":["name","pages"],"additionalProperties":false}}},"required":["files"],"additionalProperties":false}}}},"responses":{"200":{"description":"Merge PDF files","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Merged PDF as base64."},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","pageCount","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-split":{"post":{"operationId":"split_pdf","summary":"Split a PDF","description":"Extract a page range into one PDF, or split into single pages or chunks of N. Send base64 or a public URL. Private addresses are refused. Returns PDF base64 and a ZIP when there are several files.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"default":"document.pdf","type":"string"},"data":{"description":"PDF bytes as base64 or a data URI. Decoded size is capped at 10 MB. Provide data or url.","type":"string"},"url":{"description":"Public URL of a PDF. Private and local addresses are refused. Provide data or url.","type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"range":{"default":"","description":"Pages to keep, such as 1-3,5. Blank keeps every page.","type":"string"},"mode":{"default":"extract","type":"string","enum":["extract","pages","chunks"]},"every":{"default":1,"description":"Used when mode is chunks.","type":"integer","minimum":1,"maximum":500}},"required":["name","range","mode","every"],"additionalProperties":false}}}},"responses":{"200":{"description":"Split a PDF","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"data":{"type":"string"}},"required":["name","data"],"additionalProperties":false}},"zip":{"description":"ZIP of the PDFs when there is more than one, otherwise null.","type":["string","null"]},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["files","zip","pageCount"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-compress":{"post":{"operationId":"compress_pdf","summary":"Compress a PDF","description":"Recompress embedded images in a PDF. Presets are light, medium, and strong. Send base64 or a public URL. Private addresses are refused. An optional target size tries harder. Returns the PDF and the sizes before and after.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"PDF bytes as base64 or a data URI. Decoded size is capped at 10 MB. Provide data or url.","type":"string"},"url":{"description":"Public URL of a PDF. Private and local addresses are refused. Provide data or url.","type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"preset":{"default":"medium","type":"string","enum":["light","medium","strong"]},"targetBytes":{"default":null,"description":"Optional size ceiling in bytes, such as 102400.","anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":20000000},{"type":"null"}]}},"required":["preset","targetBytes"],"additionalProperties":false}}}},"responses":{"200":{"description":"Compress a PDF","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"PDF bytes as base64. The original is returned when compression would grow the file."},"before":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"after":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"saved":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"percent":{"type":"number"},"pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"images":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"recompressed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"metTarget":{"type":"boolean"},"keptOriginal":{"type":"boolean"},"note":{"type":"string"}},"required":["data","before","after","saved","percent","pages","images","recompressed","metTarget","keptOriginal","note"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/image-to-pdf":{"post":{"operationId":"images_to_pdf","summary":"Build a PDF from images","description":"Turn images, sent as base64 or public URLs in order, into one PDF. JPEG and PNG are embedded directly. Other formats are converted to PNG first. Page size is A4, Letter, or fit. Private addresses are refused. Returns the PDF as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"images":{"minItems":1,"maxItems":40,"type":"array","items":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false}},"page":{"default":"a4","type":"string","enum":["a4","letter","fit"]},"orientation":{"default":"auto","type":"string","enum":["auto","portrait","landscape"]},"margin":{"default":0,"type":"number","minimum":0,"maximum":144}},"required":["images","page","orientation","margin"],"additionalProperties":false}}}},"responses":{"200":{"description":"Build a PDF from images","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"PDF bytes as base64."},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","pageCount","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/qr-code-generator":{"post":{"operationId":"generate_qr_code","summary":"Generate a QR code","description":"Build a static QR code for text, a URL, Wi-Fi, or a vCard. Returns the payload, an SVG string, and a PNG as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"default":"url","type":"string","enum":["text","url","wifi","vcard"]},"text":{"default":"","type":"string"},"url":{"default":"","type":"string"},"wifi":{"default":{"ssid":"","password":"","security":"WPA","hidden":false},"type":"object","properties":{"ssid":{"default":"","type":"string"},"password":{"default":"","type":"string"},"security":{"default":"WPA","type":"string","enum":["WPA","WEP","nopass"]},"hidden":{"default":false,"type":"boolean"}},"required":["ssid","password","security","hidden"],"additionalProperties":false},"vcard":{"default":{"name":"","phone":"","email":"","org":"","title":"","url":""},"type":"object","properties":{"name":{"default":"","type":"string"},"phone":{"default":"","type":"string"},"email":{"default":"","type":"string"},"org":{"default":"","type":"string"},"title":{"default":"","type":"string"},"url":{"default":"","type":"string"}},"required":["name","phone","email","org","title","url"],"additionalProperties":false},"ecc":{"default":"M","type":"string","enum":["L","M","Q","H"]},"dark":{"default":"#111111","type":"string"},"light":{"default":"#ffffff","type":"string"},"margin":{"default":2,"type":"integer","minimum":0,"maximum":8},"size":{"default":512,"type":"integer","minimum":128,"maximum":2048}},"required":["type","text","url","wifi","vcard","ecc","dark","light","margin","size"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate a QR code","content":{"application/json":{"schema":{"type":"object","properties":{"payload":{"type":"string"},"svg":{"type":"string"},"pngBase64":{"type":"string"}},"required":["payload","svg","pngBase64"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-to-text":{"post":{"operationId":"extract_pdf_text","summary":"Extract PDF text","description":"Read the selectable text layer of a PDF. Returns per-page text, markdown-style headings, and an o200k token count. Does not OCR scans. Send base64 or a public URL. Private addresses are refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"PDF bytes as base64 or a data URI. Decoded size is capped at 10 MB. Provide data or url.","type":"string"},"url":{"description":"Public URL of a PDF. Private and local addresses are refused. Provide data or url.","type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Extract PDF text","content":{"application/json":{"schema":{"type":"object","properties":{"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pages":{"type":"array","items":{"type":"object","properties":{"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"text":{"type":"string"},"markdown":{"type":"string"}},"required":["page","text","markdown"],"additionalProperties":false}},"text":{"type":"string"},"markdown":{"type":"string"},"tokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"emptyPages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["pageCount","pages","text","markdown","tokens","emptyPages"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-rotate-organize":{"post":{"operationId":"organize_pdf","summary":"Organize PDF pages","description":"Reorder, rotate, or drop PDF pages. Each entry names a 1-based source page and a rotation of 0, 90, 180, or 270. The same page may be listed twice. Send base64 or a public URL. Private addresses are refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"PDF bytes as base64 or a data URI. Decoded size is capped at 10 MB. Provide data or url.","type":"string"},"url":{"description":"Public URL of a PDF. Private and local addresses are refused. Provide data or url.","type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"pages":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"object","properties":{"source":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"1-based page in the original PDF. The same page may appear more than once."},"rotate":{"default":0,"anyOf":[{"type":"number","const":0},{"type":"number","const":90},{"type":"number","const":180},{"type":"number","const":270}]}},"required":["source","rotate"],"additionalProperties":false}}},"required":["pages"],"additionalProperties":false}}}},"responses":{"200":{"description":"Organize PDF pages","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Organized PDF as base64."},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","pageCount","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-to-image":{"post":{"operationId":"render_pdf_pages","summary":"Render PDF pages","description":"Render PDF pages to PNG or JPEG. DPI is 72 to 216. A page range such as 1-3,5 is optional. At most 24 pages and 25 MB of images. Send base64 or a public URL. Private addresses are refused. Returns image base64 and a ZIP when there is more than one page.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"PDF bytes as base64 or a data URI. Decoded size is capped at 10 MB. Provide data or url.","type":"string"},"url":{"description":"Public URL of a PDF. Private and local addresses are refused. Provide data or url.","type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"format":{"default":"png","type":"string","enum":["png","jpeg"]},"dpi":{"default":72,"type":"integer","minimum":72,"maximum":216},"range":{"default":"","description":"Pages to render, such as 1-3,5. Blank renders every page, up to 24.","type":"string"},"quality":{"default":82,"description":"JPEG quality from 1 to 100. Ignored for PNG.","type":"integer","minimum":1,"maximum":100}},"required":["format","dpi","range","quality"],"additionalProperties":false}}}},"responses":{"200":{"description":"Render PDF pages","content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"data":{"type":"string","description":"Image bytes as base64."},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["name","data","width","height"],"additionalProperties":false}},"zip":{"description":"ZIP of the images when there is more than one, otherwise null.","type":["string","null"]},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["images","zip","pageCount"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-protect-unlock":{"post":{"operationId":"protect_pdf","summary":"Protect or unlock a PDF","description":"Protect a PDF with AES-256, or unlock one when the password is known. action is protect or unlock. password is the user password. ownerPassword is optional. permissions cover printing, copying, modifying, annotating, filling forms, accessibility, and assembly. Send base64 or a public URL. Private addresses are refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"PDF bytes as base64 or a data URI. Decoded size is capped at 10 MB. Provide data or url.","type":"string"},"url":{"description":"Public URL of a PDF. Private and local addresses are refused. Provide data or url.","type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"action":{"default":"protect","type":"string","enum":["protect","unlock"]},"password":{"default":"","description":"User password. Required to protect or unlock. Unlock only works when this is the known password.","type":"string"},"ownerPassword":{"default":"","description":"Owner password. Blank uses the user password.","type":"string"},"permissions":{"default":{"printing":true,"copying":false,"modifying":false,"annotating":false,"fillingForms":true,"contentAccessibility":true,"documentAssembly":false},"type":"object","properties":{"printing":{"default":true,"type":"boolean"},"copying":{"default":false,"type":"boolean"},"modifying":{"default":false,"type":"boolean"},"annotating":{"default":false,"type":"boolean"},"fillingForms":{"default":true,"type":"boolean"},"contentAccessibility":{"default":true,"type":"boolean"},"documentAssembly":{"default":false,"type":"boolean"}},"required":["printing","copying","modifying","annotating","fillingForms","contentAccessibility","documentAssembly"],"additionalProperties":false}},"required":["action","password","ownerPassword","permissions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Protect or unlock a PDF","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"PDF bytes as base64."},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"encrypted":{"type":"boolean"}},"required":["data","bytes","encrypted"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/markdown-html":{"post":{"operationId":"convert_markdown_html","summary":"Convert Markdown and HTML","description":"Convert GitHub-flavored Markdown to HTML, or HTML to Markdown. to is html or markdown. sanitize strips scripts from the text output. The conversion does not fetch a URL.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"default":"# Hello\n","type":"string"},"to":{"default":"html","type":"string","enum":["html","markdown"]},"sanitize":{"default":true,"type":"boolean"}},"required":["text","to","sanitize"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert Markdown and HTML","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"type":"string"},"direction":{"type":"string","enum":["html","markdown"]}},"required":["output","direction"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/html-to-markdown-url":{"post":{"operationId":"fetch_page_markdown","summary":"Fetch a page as Markdown","description":"Fetch a public HTML page and return the article as Markdown, plus a title, excerpt, and o200k token count. Private and local addresses are refused. The response is capped at 800 KB.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"Public http or https URL. Private and local addresses are refused."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Fetch a page as Markdown","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"title":{"type":"string"},"markdown":{"type":"string"},"excerpt":{"type":"string"},"tokens":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"chars":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["url","title","markdown","excerpt","tokens","chars"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/qr-code-reader":{"post":{"operationId":"read_barcode","summary":"Read a QR code or barcode","description":"Read QR codes and barcodes from an image. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns each code's text and format. An image with no code returns an empty list.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."}},"required":["file"],"additionalProperties":false}}}},"responses":{"200":{"description":"Read a QR code or barcode","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"codes":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"format":{"type":"string"},"label":{"type":"string"}},"required":["text","format","label"],"additionalProperties":false}}},"required":["count","codes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/svg-optimizer":{"post":{"operationId":"optimize_svg","summary":"Optimize an SVG","description":"Minify an SVG with SVGO. Send markup or a file as base64 or a public URL. Private addresses are refused and the file is capped at 10 MB. The viewBox is kept unless removeViewBox is true. Returns the optimized markup and the byte counts.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"svg":{"description":"SVG markup. Provide svg or file.","type":"string"},"file":{"description":"An SVG file. Provide svg or file.","type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false},"precision":{"default":3,"type":"integer","minimum":0,"maximum":8},"removeViewBox":{"default":false,"type":"boolean"},"removeDimensions":{"default":false,"type":"boolean"}},"required":["precision","removeViewBox","removeDimensions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Optimize an SVG","content":{"application/json":{"schema":{"type":"object","properties":{"svg":{"type":"string"},"beforeBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"afterBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"savedBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"savedPercent":{"type":"number"}},"required":["svg","beforeBytes","afterBytes","savedBytes","savedPercent"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/exif-viewer-remover":{"post":{"operationId":"read_exif","summary":"Read or strip photo metadata","description":"Read EXIF tags, including GPS, or strip them. action is read or strip. scope is all or gps. gps-only removal keeps the other JPEG tags. Other formats are re-encoded, which drops every tag. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The photo. Provide url or data."},"action":{"default":"read","type":"string","enum":["read","strip"]},"scope":{"default":"all","description":"Used when action is strip. gps removes the GPS block from a JPEG. all re-encodes and drops every tag.","type":"string","enum":["all","gps"]}},"required":["file","action","scope"],"additionalProperties":false}}}},"responses":{"200":{"description":"Read or strip photo metadata","content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"mime":{"type":"string"},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Cleaned image as base64. Empty when action is read."},"stripped":{"type":"string","enum":["none","all","gps"]},"camera":{"type":"string"},"when":{"type":"string"},"gps":{"anyOf":[{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"},"label":{"type":"string"},"map":{"type":"string"}},"required":["latitude","longitude","label","map"],"additionalProperties":false},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"note":{"type":"string"}},"required":["filename","mime","width","height","bytes","data","stripped","camera","when","gps","tags","note"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/image-crop":{"post":{"operationId":"crop_image","summary":"Crop an image","description":"Crop an image to a pixel box or a 0 to 1 ratio box. circle cuts a round mask. format is png, jpeg, or webp. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns the image as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"x":{"default":0,"type":"number"},"y":{"default":0,"type":"number"},"width":{"default":1,"type":"number","exclusiveMinimum":0},"height":{"default":1,"type":"number","exclusiveMinimum":0},"unit":{"default":"px","description":"px is source pixels. ratio is a 0 to 1 share of the source.","type":"string","enum":["px","ratio"]},"circle":{"default":false,"type":"boolean"},"format":{"default":"png","type":"string","enum":["png","jpeg","webp"]}},"required":["file","x","y","width","height","unit","circle","format"],"additionalProperties":false}}}},"responses":{"200":{"description":"Crop an image","content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"mime":{"type":"string"},"extension":{"type":"string"},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Cropped image as base64."}},"required":["filename","mime","extension","width","height","bytes","data"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/favicon-generator":{"post":{"operationId":"generate_favicon","summary":"Generate a favicon pack","description":"Build a favicon pack from an image or up to three letters. The ZIP contains favicon.ico, PNG sizes, a web manifest, an HTML snippet, and a Next.js metadata snippet. Letters are drawn with a built-in bitmap font so the result does not depend on a system font. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"description":"A square-or-any image. Provide file or text.","type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false},"text":{"description":"Up to three letters drawn as the mark. Provide file or text.","type":"string","maxLength":8},"background":{"default":"#111111","type":"string"},"color":{"default":"#ffffff","type":"string"},"name":{"default":"App","type":"string","maxLength":40}},"required":["background","color","name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate a favicon pack","content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"mime":{"type":"string"},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"ZIP of the favicon files as base64."},"html":{"type":"string"},"nextMetadata":{"type":"string"},"manifest":{"type":"string"},"preview":{"type":"string","description":"32 pixel PNG as base64."}},"required":["filename","mime","bytes","data","html","nextMetadata","manifest","preview"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/ocr-image-to-text":{"post":{"operationId":"read_image_text","summary":"Read text from an image","description":"Extract text from an image with Tesseract. language defaults to eng. Other codes in the list are fetched when first used. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns the text and a confidence from 0 to 100. An image with no text returns an empty string.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"language":{"default":"eng","description":"A Tesseract language code such as eng, spa, fra, deu, or jpn.","type":"string"}},"required":["file","language"],"additionalProperties":false}}}},"responses":{"200":{"description":"Read text from an image","content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"confidence":{"type":"number"},"language":{"type":"string"}},"required":["text","confidence","language"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/background-remover":{"post":{"operationId":"remove_background","summary":"Remove a solid image background","description":"Remove a solid or near-solid background by flood-filling from the border. color is an optional #rrggbb. The portrait model runs in the browser, not in this handler: MODNet is Apache-2.0, RMBG-1.4 is non-commercial, and the ONNX runtime is too large for the serverless function. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns a PNG as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"tolerance":{"default":42,"description":"How far a border pixel may be from the background color, in RGB distance.","type":"number","minimum":0,"maximum":180},"feather":{"default":true,"type":"boolean"},"color":{"description":"Background color as #rgb or #rrggbb. Blank samples the corners.","type":"string"}},"required":["file","tolerance","feather"],"additionalProperties":false}}}},"responses":{"200":{"description":"Remove a solid image background","content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"mime":{"type":"string"},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"PNG with transparency as base64."},"method":{"type":"string","const":"solid"},"note":{"type":"string"}},"required":["filename","mime","width","height","bytes","data","method","note"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/word-counter":{"post":{"operationId":"count_text","summary":"Count words and characters","description":"Count words, code points, graphemes, sentences, and paragraphs, and compare the length with SEO and social limits.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":200000,"description":"Text to count."}},"required":["text"],"additionalProperties":false}}}},"responses":{"200":{"description":"Count words and characters","content":{"application/json":{"schema":{"type":"object","properties":{"words":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"uniqueWords":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"characters":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"charactersNoSpaces":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"graphemes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sentences":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"paragraphs":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"readingLabel":{"type":"string"},"speakingLabel":{"type":"string"},"platforms":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"over":{"type":"boolean"}},"required":["id","label","limit","count","over"],"additionalProperties":false}}},"required":["words","uniqueWords","characters","charactersNoSpaces","graphemes","sentences","paragraphs","lines","readingLabel","speakingLabel","platforms"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/case-converter":{"post":{"operationId":"convert_case","summary":"Convert text case","description":"Convert text to camelCase, snake_case, kebab-case, CONSTANT_CASE, and AP or Chicago title case. Returns every style unless one is requested.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","maxLength":100000,"description":"Text to convert. Each line is converted on its own."},"style":{"description":"Return one style. Omit it to return every style.","type":"string","enum":["lower","upper","sentence","capital","title-ap","title-chicago","camel","pascal","snake","constant","kebab","dot","path","train","alternating","inverse"]}},"required":["text"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert text case","content":{"application/json":{"schema":{"type":"object","properties":{"cases":{"type":"array","items":{"type":"object","properties":{"style":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["style","label","text"],"additionalProperties":false}}},"required":["cases"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/lorem-ipsum":{"post":{"operationId":"generate_fake_data","summary":"Generate lorem ipsum or fake rows","description":"Generate seeded lorem ipsum, or fake JSON, CSV, or SQL rows from a list of field types.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"default":"lorem","type":"string","enum":["lorem","rows"]},"kind":{"default":"paragraphs","type":"string","enum":["words","sentences","paragraphs"]},"count":{"default":3,"type":"integer","minimum":1,"maximum":500},"seed":{"default":1,"type":"integer","minimum":0,"maximum":2147483647},"rows":{"default":10,"type":"integer","minimum":1,"maximum":200},"format":{"default":"json","type":"string","enum":["json","csv","sql"]},"table":{"default":"records","type":"string"},"fields":{"maxItems":30,"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string","enum":["fullName","firstName","lastName","email","username","company","jobTitle","phone","city","country","street","uuid","boolean","int","float","date","word","sentence","url","ipv4","price"]}},"required":["name","kind"],"additionalProperties":false}}},"required":["mode","kind","count","seed","rows","format","table"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate lorem ipsum or fake rows","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"type":"string"},"format":{"type":"string","enum":["text","json","csv","sql"]},"rows":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["output","format","rows"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/regex-tester":{"post":{"operationId":"test_regex","summary":"Test a JavaScript regular expression","description":"Run a JavaScript regular expression against a sample and return every match, capture group, a short explanation, and an optional replacement.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pattern":{"type":"string","description":"JavaScript regular expression body, without slashes."},"flags":{"default":"","type":"string"},"text":{"type":"string","description":"Sample to search."},"replacement":{"description":"When set, the sample is replaced and returned.","type":"string"}},"required":["pattern","flags","text"],"additionalProperties":false}}}},"responses":{"200":{"description":"Test a JavaScript regular expression","content":{"application/json":{"schema":{"type":"object","properties":{"matches":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"length":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"value":{"type":"string"},"groups":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}}},"required":["index","length","value","groups"],"additionalProperties":false}},"truncated":{"type":"boolean"},"explanation":{"type":"array","items":{"type":"string"}},"replacement":{"type":["string","null"]}},"required":["matches","truncated","explanation","replacement"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/sql-formatter":{"post":{"operationId":"format_sql","summary":"Format SQL","description":"Format SQL for PostgreSQL, MySQL, BigQuery, Snowflake, and other dialects. Choose keyword case and an indent of 2 or 4 spaces.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sql":{"type":"string","description":"SQL to format."},"dialect":{"default":"postgresql","type":"string","enum":["postgresql","mysql","mariadb","sqlite","transactsql","bigquery","snowflake","redshift","spark","hive","plsql","trino","sql"]},"keywordCase":{"default":"upper","type":"string","enum":["upper","lower","preserve"]},"indent":{"default":2,"anyOf":[{"type":"number","const":2},{"type":"number","const":4}]}},"required":["sql","dialect","keywordCase","indent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Format SQL","content":{"application/json":{"schema":{"type":"object","properties":{"sql":{"type":"string"}},"required":["sql"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/json-schema-validate":{"post":{"operationId":"validate_json_schema","summary":"Infer or validate JSON Schema","description":"Infer a JSON Schema from a sample, or validate JSON against a schema. Returns error paths plus TypeScript and Zod generated from the sample.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"json":{"type":"string","description":"JSON document to infer from or validate."},"schema":{"description":"JSON Schema. Omit it to infer a schema from the document.","type":"string"}},"required":["json"],"additionalProperties":false}}}},"responses":{"200":{"description":"Infer or validate JSON Schema","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"schema":{"type":"string"},"typescript":{"type":"string"},"zod":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"],"additionalProperties":false}}},"required":["valid","schema","typescript","zod","errors"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/loan-emi-calculator":{"post":{"operationId":"calculate_emi","summary":"Calculate a loan EMI","description":"Calculate a reducing-balance loan installment and its amortization schedule. Money is rounded half up to cents. An optional extra monthly payment reduces principal.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"principal":{"description":"Amount borrowed, such as 100000.","type":["string","number"]},"annualRate":{"description":"Annual interest rate in percent, such as 10.","type":["string","number"]},"months":{"type":"integer","minimum":1,"maximum":600,"description":"Term in months."},"extraMonthly":{"default":0,"description":"Extra principal paid every month.","type":["string","number"]}},"required":["principal","annualRate","months","extraMonthly"],"additionalProperties":false}}}},"responses":{"200":{"description":"Calculate a loan EMI","content":{"application/json":{"schema":{"type":"object","properties":{"emi":{"type":"string"},"totalPayment":{"type":"string"},"totalInterest":{"type":"string"},"totalPrincipal":{"type":"string"},"payoffMonths":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"schedule":{"type":"array","items":{"type":"object","properties":{"month":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"payment":{"type":"string"},"principal":{"type":"string"},"interest":{"type":"string"},"extra":{"type":"string"},"balance":{"type":"string"}},"required":["month","payment","principal","interest","extra","balance"],"additionalProperties":false}},"csv":{"type":"string"}},"required":["emi","totalPayment","totalInterest","totalPrincipal","payoffMonths","schedule","csv"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/percentage-calculator":{"post":{"operationId":"calculate_percentage","summary":"Calculate a percentage","description":"Calculate percent of a value, what percent one number is of another, percent change, the reverse, an increase or decrease, and margin versus markup.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"default":"of","description":"of, is, change, reverse, increase, decrease, or margin.","type":"string","enum":["of","is","change","reverse","increase","decrease","margin"]},"a":{"description":"First value. For of and increase, this is the percent.","type":["string","number"]},"b":{"description":"Second value. For of and increase, this is the amount.","type":["string","number"]}},"required":["mode","a","b"],"additionalProperties":false}}}},"responses":{"200":{"description":"Calculate a percentage","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"type":"string"},"unit":{"type":"string","enum":["number","percent"]},"formula":{"type":"string"},"parts":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"],"additionalProperties":false}}},"required":["result","unit","formula","parts"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/unit-converter":{"post":{"operationId":"convert_units","summary":"Convert units","description":"Convert length, mass, volume, temperature, area, speed, time, and data size. Decimal bytes (kB, MB) and binary bytes (KiB, MiB) are separate categories.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"category":{"type":"string","enum":["length","mass","volume","temperature","area","speed","time","data-decimal","data-binary"]},"from":{"type":"string","description":"Source unit id, such as m, C, MB, or MiB."},"to":{"type":"string","description":"Target unit id from the same category."},"value":{"type":["string","number"]},"precision":{"default":6,"type":"integer","minimum":0,"maximum":12}},"required":["category","from","to","value","precision"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert units","content":{"application/json":{"schema":{"type":"object","properties":{"result":{"type":"string"},"rows":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"value":{"type":"string"}},"required":["id","label","value"],"additionalProperties":false}}},"required":["result","rows"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/dns-lookup":{"post":{"operationId":"lookup_dns","summary":"Look up DNS records","description":"Query A, AAAA, MX, TXT, CNAME, and CAA for a public hostname over DNS-over-HTTPS, and parse SPF and DMARC. Private names are refused. The resolver is Cloudflare or Google.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Public hostname, such as example.com. Private names are refused."},"types":{"default":["A","AAAA","MX","TXT","CNAME","CAA"],"type":"array","items":{"type":"string","enum":["A","AAAA","MX","TXT","CNAME","CAA"]}},"resolver":{"default":"cloudflare","type":"string","enum":["cloudflare","google"]},"mail":{"default":true,"description":"Also fetch the _dmarc TXT record and parse SPF.","type":"boolean"}},"required":["name","types","resolver","mail"],"additionalProperties":false}}}},"responses":{"200":{"description":"Look up DNS records","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"resolver":{"type":"string","enum":["cloudflare","google"]},"records":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"},"ttl":{"type":"number"},"data":{"type":"string"}},"required":["type","name","ttl","data"],"additionalProperties":false}},"queries":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["A","AAAA","MX","TXT","CNAME","CAA"]},"rcode":{"type":"string"}},"required":["type","rcode"],"additionalProperties":false}},"spf":{"anyOf":[{"type":"object","properties":{"raw":{"type":"string"},"all":{"type":"string"},"mechanisms":{"type":"array","items":{"type":"object","properties":{"qualifier":{"type":"string"},"mechanism":{"type":"string"},"value":{"type":"string"}},"required":["qualifier","mechanism","value"],"additionalProperties":false}}},"required":["raw","all","mechanisms"],"additionalProperties":false},{"type":"null"}]},"dmarc":{"anyOf":[{"type":"object","properties":{"raw":{"type":"string"},"policy":{"type":"string"},"subdomainPolicy":{"type":"string"},"rua":{"type":"string"},"pct":{"type":"string"}},"required":["raw","policy","subdomainPolicy","rua","pct"],"additionalProperties":false},{"type":"null"}]}},"required":["name","resolver","records","queries","spf","dmarc"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/ip-cidr-calculator":{"post":{"operationId":"calculate_cidr","summary":"Calculate a CIDR block","description":"Return the network, broadcast, host range, and host count for an IPv4 or IPv6 CIDR. Optionally test whether an address is inside it, split it, or merge it with other CIDRs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cidr":{"type":"string","description":"IPv4 or IPv6 CIDR, such as 192.168.1.0/24 or 2001:db8::/32. A dotted mask may follow the address."},"contains":{"description":"Address to test for membership.","type":"string"},"splitPrefix":{"description":"Longer prefix to split into, at most 256 networks.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"merge":{"description":"Extra CIDRs to aggregate with cidr.","maxItems":64,"type":"array","items":{"type":"string"}}},"required":["cidr"],"additionalProperties":false}}}},"responses":{"200":{"description":"Calculate a CIDR block","content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"object","properties":{"version":{"anyOf":[{"type":"number","const":4},{"type":"number","const":6}]},"input":{"type":"string"},"network":{"type":"string"},"prefix":{"type":"number"},"netmask":{"type":"string"},"wildcard":{"type":"string"},"broadcast":{"type":["string","null"]},"firstHost":{"type":"string"},"lastHost":{"type":"string"},"addressCount":{"type":"string"},"usableHosts":{"type":"string"}},"required":["version","input","network","prefix","netmask","wildcard","broadcast","firstHost","lastHost","addressCount","usableHosts"],"additionalProperties":false},"contains":{"type":["boolean","null"]},"containsDetail":{"type":"string"},"split":{"type":"array","items":{"type":"string"}},"splitCount":{"type":"string"},"merged":{"type":"array","items":{"type":"string"}}},"required":["summary","contains","containsDetail","split","splitCount","merged"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/htpasswd-bcrypt":{"post":{"operationId":"hash_password","summary":"Hash or verify a password","description":"Hash a password with bcrypt or argon2id, or verify a hash. Returns an htpasswd line when a username is set. The password is not stored or logged. The page in the browser never sends the password; this call only hashes the arguments you send.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","description":"Password to hash or verify. It is used only for this call and is not stored."},"algorithm":{"default":"bcrypt","type":"string","enum":["bcrypt","argon2id"]},"cost":{"default":10,"description":"Bcrypt cost factor, from 4 to 12.","type":"integer","minimum":4,"maximum":12},"iterations":{"default":2,"type":"integer","minimum":1,"maximum":4},"memory":{"default":8192,"description":"Argon2id memory in KiB.","type":"integer","minimum":8,"maximum":19456},"parallelism":{"default":1,"type":"integer","minimum":1,"maximum":2},"username":{"default":"","description":"Optional htpasswd username. A colon is not allowed.","type":"string"},"hash":{"description":"Existing bcrypt or argon2id hash. When set, the password is verified instead of hashed.","type":"string"}},"required":["password","algorithm","cost","iterations","memory","parallelism","username"],"additionalProperties":false}}}},"responses":{"200":{"description":"Hash or verify a password","content":{"application/json":{"schema":{"type":"object","properties":{"algorithm":{"type":"string","enum":["bcrypt","argon2id"]},"hash":{"type":"string"},"htpasswd":{"type":"string"},"verified":{"type":["boolean","null"]}},"required":["algorithm","hash","htpasswd","verified"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/rsa-keypair":{"post":{"operationId":"generate_keypair","summary":"Generate or convert a key pair","description":"Generate an RSA, EC, or Ed25519 key pair as PEM and JWK, or convert between PEM and JWK. The private key is returned in the result and is not stored. The page in the browser generates keys locally and does not send them.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"default":"generate","type":"string","enum":["generate","to_jwk","to_pem"]},"alg":{"default":"ES256","type":"string","enum":["RS256","RS384","RS512","PS256","ES256","ES384","ES512","Ed25519"]},"modulusLength":{"default":2048,"anyOf":[{"type":"number","const":2048},{"type":"number","const":4096}]},"pem":{"description":"SPKI or PKCS8 PEM to convert. Required for to_jwk.","type":"string"},"jwk":{"description":"JWK JSON to convert. Required for to_pem.","type":"string"}},"required":["action","alg","modulusLength"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate or convert a key pair","content":{"application/json":{"schema":{"type":"object","properties":{"alg":{"type":"string","enum":["RS256","RS384","RS512","PS256","ES256","ES384","ES512","Ed25519"]},"publicPem":{"type":"string"},"privatePem":{"type":"string"},"publicJwk":{"type":"string"},"privateJwk":{"type":"string"},"jwks":{"type":"string"}},"required":["alg","publicPem","privatePem","publicJwk","privateJwk","jwks"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/csp-generator":{"post":{"operationId":"build_csp","summary":"Build a Content-Security-Policy","description":"Build a Content-Security-Policy from directives, or lint an existing policy. Returns the header line, a Next.js headers() snippet, and warnings for unsafe sources.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"policy":{"description":"An existing Content-Security-Policy value to lint. When set, directive fields are ignored.","type":"string"},"sources":{"type":"object","propertyNames":{"type":"string","enum":["default-src","script-src","style-src","img-src","font-src","connect-src","frame-src","frame-ancestors","media-src","object-src","base-uri","form-action","worker-src","manifest-src"]},"additionalProperties":{"type":"string"},"required":["default-src","script-src","style-src","img-src","font-src","connect-src","frame-src","frame-ancestors","media-src","object-src","base-uri","form-action","worker-src","manifest-src"]},"upgradeInsecureRequests":{"default":true,"type":"boolean"},"blockAllMixedContent":{"default":false,"type":"boolean"}},"required":["upgradeInsecureRequests","blockAllMixedContent"],"additionalProperties":false}}}},"responses":{"200":{"description":"Build a Content-Security-Policy","content":{"application/json":{"schema":{"type":"object","properties":{"policy":{"type":"string"},"header":{"type":"string"},"nextConfig":{"type":"string"},"checks":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail","info"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}}},"required":["policy","header","nextConfig","checks"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/sitemap-validator":{"post":{"operationId":"validate_sitemap","summary":"Validate or generate a sitemap","description":"Validate sitemap XML or a public sitemap URL, including a sitemap index and a sample of HTTP statuses. Or generate a urlset from a list of URLs. Private addresses are refused and responses are size-capped.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"description":"Public sitemap URL. Private addresses are refused.","type":"string"},"xml":{"description":"Sitemap XML. Use this or url.","type":"string"},"urls":{"description":"URLs to place in a generated sitemap. When set, url and xml are ignored.","maxItems":5000,"type":"array","items":{"type":"string"}},"probe":{"default":true,"description":"Request a sample of locations and report HTTP status.","type":"boolean"}},"required":["probe"],"additionalProperties":false}}}},"responses":{"200":{"description":"Validate or generate a sitemap","content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["urlset","index","unknown"]},"urlCount":{"type":"number"},"sitemapCount":{"type":"number"},"urls":{"type":"array","items":{"type":"object","properties":{"loc":{"type":"string"},"lastmod":{"type":"string"},"changefreq":{"type":"string"},"priority":{"type":"string"}},"required":["loc","lastmod","changefreq","priority"],"additionalProperties":false}},"sitemaps":{"type":"array","items":{"type":"string"}},"issues":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail","info"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}},"xml":{"type":"string"},"source":{"type":"string"},"probes":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"number"},"error":{"type":"string"}},"required":["url","status","error"],"additionalProperties":false}}},"required":["kind","urlCount","sitemapCount","urls","sitemaps","issues","xml","source","probes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/http-headers-checker":{"post":{"operationId":"check_http_headers","summary":"Check HTTP response headers","description":"Fetch a public URL, follow redirects, and grade HSTS, Content-Security-Policy, framing, nosniff, and Referrer-Policy. Private addresses are refused. The body is not stored.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Public http or https URL. Private addresses are refused."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Check HTTP response headers","content":{"application/json":{"schema":{"type":"object","properties":{"finalUrl":{"type":"string"},"status":{"type":"number"},"redirects":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"status":{"type":"number"},"location":{"type":"string"}},"required":["url","status","location"],"additionalProperties":false}},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"grade":{"type":"string","enum":["A","B","C","D","F"]},"checks":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail","info"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}},"elapsedMs":{"type":"number"}},"required":["finalUrl","status","redirects","headers","grade","checks","elapsedMs"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/ssl-checker":{"post":{"operationId":"check_ssl","summary":"Check a TLS certificate","description":"Connect to a public host on port 443 and report certificate expiry, subject alternative names, protocol, and chain. Private addresses are refused. The handshake times out after 8 seconds.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"host":{"type":"string","description":"Public hostname or https URL. Only port 443 is contacted. Private addresses are refused."}},"required":["host"],"additionalProperties":false}}}},"responses":{"200":{"description":"Check a TLS certificate","content":{"application/json":{"schema":{"type":"object","properties":{"host":{"type":"string"},"authorized":{"type":"boolean"},"protocol":{"type":"string"},"authorizationError":{"type":"string"},"subject":{"type":"string"},"commonName":{"type":"string"},"issuer":{"type":"string"},"validFrom":{"type":"string"},"validTo":{"type":"string"},"sans":{"type":"array","items":{"type":"string"}},"fingerprint":{"type":"string"},"serial":{"type":"string"},"bits":{"type":["number","null"]},"daysRemaining":{"type":["number","null"]},"grade":{"type":"string","enum":["A","B","C","D","F"]},"checks":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["pass","warn","fail","info"]},"label":{"type":"string"},"detail":{"type":"string"}},"required":["level","label","detail"],"additionalProperties":false}},"chain":{"type":"array","items":{"type":"object","properties":{"subject":{"type":"string"},"issuer":{"type":"string"},"validTo":{"type":"string"}},"required":["subject","issuer","validTo"],"additionalProperties":false}}},"required":["host","authorized","protocol","authorizationError","subject","commonName","issuer","validFrom","validTo","sans","fingerprint","serial","bits","daysRemaining","grade","checks","chain"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/totp-generator":{"post":{"operationId":"generate_totp","summary":"Generate a TOTP/HOTP one-time code","description":"Compute RFC 4226/6238 one-time passcodes from a base32 secret. Supports 6/8 digits, SHA1/SHA256/SHA512, and custom periods.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"type":"string","minLength":1,"description":"Base32 TOTP/HOTP secret"},"mode":{"default":"totp","type":"string","enum":["totp","hotp"]},"digits":{"default":6,"anyOf":[{"type":"number","const":6},{"type":"number","const":8}]},"period":{"default":30,"description":"TOTP period in seconds","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"algorithm":{"default":"SHA1","type":"string","enum":["SHA1","SHA256","SHA512"]},"at":{"description":"Unix time in milliseconds; defaults to now","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"counter":{"default":0,"description":"HOTP counter","type":"integer","minimum":0,"maximum":9007199254740991}},"required":["secret","mode","digits","period","algorithm","counter"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate a TOTP/HOTP one-time code","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"mode":{"type":"string","enum":["totp","hotp"]},"secondsRemaining":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"period":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"digits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"algorithm":{"type":"string"}},"required":["code","mode","secondsRemaining","period","digits","algorithm"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/jsonpath-tester":{"post":{"operationId":"query_jsonpath","summary":"Run a JSONPath query","description":"Evaluate a JSONPath Plus query against a JSON document and return the matches with their paths. A number that does not fit in a JavaScript number is returned as its original digits, with a precision warning.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"json":{"type":"string","minLength":1,"description":"JSON document text"},"query":{"type":"string","minLength":1,"description":"JSONPath query, e.g. $.store.book[*].author"},"limit":{"default":50,"description":"Maximum matches to return","type":"integer","minimum":1,"maximum":500}},"required":["json","query","limit"],"additionalProperties":false}}}},"responses":{"200":{"description":"Run a JSONPath query","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"truncated":{"type":"boolean"},"warning":{"type":"string"},"matches":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"value":{}},"required":["path","value"],"additionalProperties":false}}},"required":["count","truncated","warning","matches"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/programmer-calculator":{"post":{"operationId":"calculate_programmer","summary":"Evaluate a programmer expression","description":"Evaluate integer expressions with C-like precedence (hex/octal/binary literals, bitwise ops, shifts) and report base conversions plus signed/unsigned interpretations.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expression":{"description":"Integer expression, e.g. '0xFF & 0x0F | (1 << 4)'","type":"string"},"op":{"description":"Bitwise operation (alternative to expression)","type":"string","enum":["and","or","xor","not","shl","shr"]},"a":{"description":"First operand, e.g. '0xFF' or '255'","type":"string"},"b":{"description":"Second operand (not needed for 'not')","type":"string"},"bits":{"default":"64","description":"Bit width for masking and signed interpretation","type":"string","enum":["8","16","32","64"]}},"required":["bits"],"additionalProperties":false}}}},"responses":{"200":{"description":"Evaluate a programmer expression","content":{"application/json":{"schema":{"type":"object","properties":{"decimal":{"type":"string"},"hex":{"type":"string"},"octal":{"type":"string"},"binary":{"type":"string"},"unsigned":{"type":"string"},"signed":{"type":"string"},"bits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["decimal","hex","octal","binary","unsigned","signed","bits"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/aes-crypto":{"post":{"operationId":"aes_crypt","summary":"Encrypt or decrypt with AES-GCM","description":"AES-256-GCM encryption with PBKDF2-SHA256 key derivation. Encrypt returns a base64 bundle (salt, IV, ciphertext); decrypt reverses it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["encrypt","decrypt"]},"passphrase":{"type":"string","minLength":1},"text":{"description":"Plaintext to encrypt (encrypt mode)","type":"string"},"bundle":{"description":"Base64 bundle from a previous encryption (decrypt mode)","type":"string"},"iterations":{"default":100000,"type":"integer","minimum":10000,"maximum":2000000}},"required":["mode","passphrase","iterations"],"additionalProperties":false}}}},"responses":{"200":{"description":"Encrypt or decrypt with AES-GCM","content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["encrypt","decrypt"]},"bundle":{"type":"string"},"plaintext":{"type":"string"}},"required":["mode"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/har-analyzer":{"post":{"operationId":"analyze_har","summary":"Analyze a HAR file","description":"Parse a HAR (HTTP Archive) capture and summarize it: request counts, status distribution, slowest and largest requests, top hosts, and per-request timings.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"har":{"type":"string","minLength":1,"description":"HAR file contents as JSON text"},"top":{"default":5,"description":"How many slowest/largest requests and top hosts to include","type":"integer","minimum":1,"maximum":20}},"required":["har","top"],"additionalProperties":false}}}},"responses":{"200":{"description":"Analyze a HAR file","content":{"application/json":{"schema":{"type":"object","properties":{"totalRequests":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalTimeMs":{"type":"number"},"totalBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"truncated":{"type":"boolean"},"statusGroups":{"type":"object","properties":{"2xx":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"3xx":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"4xx":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"5xx":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"other":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["2xx","3xx","4xx","5xx","other"],"additionalProperties":false},"slowest":{"type":"array","items":{"type":"object","properties":{"method":{"type":"string"},"url":{"type":"string"},"host":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"timeMs":{"type":"number"},"sizeBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"timings":{"type":"object","properties":{"blocked":{"type":"number"},"dns":{"type":"number"},"connect":{"type":"number"},"send":{"type":"number"},"wait":{"type":"number"},"receive":{"type":"number"}},"required":["blocked","dns","connect","send","wait","receive"],"additionalProperties":false}},"required":["method","url","host","status","timeMs","sizeBytes","timings"],"additionalProperties":false}},"largest":{"type":"array","items":{"type":"object","properties":{"method":{"type":"string"},"url":{"type":"string"},"host":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"timeMs":{"type":"number"},"sizeBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"timings":{"type":"object","properties":{"blocked":{"type":"number"},"dns":{"type":"number"},"connect":{"type":"number"},"send":{"type":"number"},"wait":{"type":"number"},"receive":{"type":"number"}},"required":["blocked","dns","connect","send","wait","receive"],"additionalProperties":false}},"required":["method","url","host","status","timeMs","sizeBytes","timings"],"additionalProperties":false}},"topHosts":{"type":"array","items":{"type":"object","properties":{"host":{"type":"string"},"requests":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["host","requests","bytes"],"additionalProperties":false}}},"required":["totalRequests","totalTimeMs","totalBytes","truncated","statusGroups","slowest","largest","topHosts"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/json-to-types":{"post":{"operationId":"convert_json_to_types","summary":"Convert JSON to type definitions","description":"Infer types from a JSON document and generate TypeScript interfaces, Zod schemas, Python Pydantic models or dataclasses, and Go structs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"json":{"type":"string","minLength":1,"maxLength":500000},"rootName":{"default":"Root","type":"string","maxLength":80},"targets":{"default":["typescript"],"minItems":1,"type":"array","items":{"type":"string","enum":["typescript","zod","pydantic","dataclass","go"]}}},"required":["json","rootName","targets"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert JSON to type definitions","content":{"application/json":{"schema":{"type":"object","properties":{"outputs":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}},"required":["outputs","warnings"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/code-minifier":{"post":{"operationId":"minify_code","summary":"Minify JavaScript, CSS, or HTML","description":"Minify source code with Terser (JS), csso (CSS), or a structural HTML pass and report before/after byte counts.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"language":{"type":"string","enum":["js","css","html"]},"code":{"type":"string","minLength":1,"maxLength":500000},"jsMangle":{"default":true,"type":"boolean"},"jsCompress":{"default":true,"type":"boolean"},"cssLevel":{"default":2,"anyOf":[{"type":"number","const":1},{"type":"number","const":2}]},"htmlAggressive":{"default":false,"type":"boolean"}},"required":["language","code","jsMangle","jsCompress","cssLevel","htmlAggressive"],"additionalProperties":false}}}},"responses":{"200":{"description":"Minify JavaScript, CSS, or HTML","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"beforeBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"afterBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"savedBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"savedPct":{"type":"number"}},"required":["code","beforeBytes","afterBytes","savedBytes","savedPct"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/curl-converter":{"post":{"operationId":"convert_curl","summary":"Convert a curl command to code","description":"Parse a curl command and generate equivalent JavaScript fetch, Python requests, Go, PHP, or Rust code.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"command":{"type":"string","minLength":1,"maxLength":20000},"target":{"default":"fetch","type":"string","enum":["fetch","python","go","php","rust"]}},"required":["command","target"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert a curl command to code","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"method":{"type":"string"},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"],"additionalProperties":false}},"body":{"type":"string"},"snippet":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["url","method","headers","snippet","warnings"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/graphql-client":{"post":{"operationId":"execute_graphql","summary":"Execute a GraphQL query","description":"Send a GraphQL query with optional variables and headers to a public http or https endpoint on port 80 or 443 and return the response data or errors. Local, private, and internal addresses are refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string","maxLength":2000,"format":"uri"},"query":{"type":"string","minLength":1,"maxLength":50000},"variables":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"timeoutMs":{"default":15000,"type":"integer","minimum":1000,"maximum":60000}},"required":["endpoint","query","timeoutMs"],"additionalProperties":false}}}},"responses":{"200":{"description":"Execute a GraphQL query","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"durationMs":{"type":"number"},"data":{},"errors":{},"error":{"type":"string"}},"required":["ok","status","durationMs"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/websocket-tester":{"post":{"operationId":"validate_websocket_url","summary":"Validate a WebSocket URL","description":"Validate and parse a ws:// or wss:// URL into its components, and optionally decode a WebSocket close code.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2000},"explainCloseCode":{"type":"integer","minimum":1000,"maximum":4999}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Validate a WebSocket URL","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"protocol":{"type":"string","enum":["ws","wss"]},"secure":{"type":"boolean"},"host":{"type":"string"},"port":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"path":{"type":"string"},"error":{"type":"string"},"closeCode":{"type":"string"}},"required":["valid"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/resume-builder":{"post":{"operationId":"generate_resume","summary":"Generate a resume PDF","description":"Build a resume PDF from profile, experience, education, and skills. A name plus at least one experience, education, or skills entry is required. Choose the clean, modern, or compact template. Returns the A4 PDF as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resume":{"type":"object","properties":{"profile":{"type":"object","properties":{"name":{"type":"string","minLength":1},"title":{"default":"","type":"string"},"email":{"default":"","type":"string"},"phone":{"default":"","type":"string"},"location":{"default":"","type":"string"},"website":{"default":"","type":"string"},"summary":{"default":"","type":"string"}},"required":["name","title","email","phone","location","website","summary"],"additionalProperties":false},"experience":{"default":[],"type":"array","items":{"type":"object","properties":{"title":{"default":"","type":"string"},"company":{"default":"","type":"string"},"location":{"default":"","type":"string"},"start":{"default":"","type":"string"},"end":{"default":"","type":"string"},"current":{"default":false,"type":"boolean"},"bullets":{"default":[],"type":"array","items":{"type":"string","minLength":1}}},"required":["title","company","location","start","end","current","bullets"],"additionalProperties":false}},"education":{"default":[],"type":"array","items":{"type":"object","properties":{"degree":{"default":"","type":"string"},"school":{"default":"","type":"string"},"location":{"default":"","type":"string"},"year":{"default":"","type":"string"}},"required":["degree","school","location","year"],"additionalProperties":false}},"skills":{"default":[],"type":"array","items":{"type":"string","minLength":1}}},"required":["profile","experience","education","skills"],"additionalProperties":false},"template":{"default":"clean","type":"string","enum":["clean","modern","compact"]}},"required":["resume","template"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate a resume PDF","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Resume PDF as base64."},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","pageCount","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/invoice-generator":{"post":{"operationId":"generate_invoice","summary":"Generate an invoice or quote PDF","description":"Build an invoice or quote PDF from company and client details, line items with quantities and rates, a tax rate, and an optional percent or flat discount. All money is computed in integer cents, so there are no float rounding errors. Returns the PDF as base64 plus the total.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invoice":{"type":"object","properties":{"kind":{"type":"string","enum":["invoice","quote"]},"number":{"type":"string","minLength":1},"issueDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"dueDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"currency":{"type":"string","pattern":"^[A-Za-z]{3}$"},"from":{"type":"object","properties":{"name":{"type":"string","minLength":1},"address":{"default":"","type":"string"},"email":{"default":"","type":"string"}},"required":["name","address","email"],"additionalProperties":false},"to":{"type":"object","properties":{"name":{"type":"string","minLength":1},"address":{"default":"","type":"string"},"email":{"default":"","type":"string"}},"required":["name","address","email"],"additionalProperties":false},"items":{"minItems":1,"type":"array","items":{"type":"object","properties":{"description":{"type":"string","minLength":1},"quantity":{"type":"number","exclusiveMinimum":0},"rate":{"type":"number","minimum":0}},"required":["description","quantity","rate"],"additionalProperties":false}},"taxRate":{"type":"number","minimum":0,"maximum":100},"discount":{"type":"object","properties":{"type":{"type":"string","enum":["percent","flat"]},"value":{"type":"number","minimum":0}},"required":["type","value"],"additionalProperties":false},"notes":{"default":"","type":"string"}},"required":["kind","number","issueDate","dueDate","currency","from","to","items","taxRate","discount","notes"],"additionalProperties":false}},"required":["invoice"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate an invoice or quote PDF","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Invoice or quote PDF as base64."},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Grand total in integer cents."},"currency":{"type":"string","description":"ISO currency code used for the invoice."},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"PDF size in bytes."}},"required":["data","totalCents","currency","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-signature":{"post":{"operationId":"sign_pdf","summary":"Sign a PDF with a PNG signature","description":"Stamp a PNG signature image onto one or more PDF pages at given positions (fractions of the page, x and y measured from the top-left, width as a fraction of page width). The signature keeps its aspect ratio. Returns the signed PDF as base64.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"},"name":{"default":"document.pdf","type":"string"},"pages":{"default":"","description":"Pages to keep, such as 1-3,5. Blank keeps every page.","type":"string"}},"required":["name","pages"],"additionalProperties":false,"description":"The PDF to sign."},"signature":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The signature as a PNG image, base64 or a public URL."},"placements":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"page":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"1-based page number."},"x":{"type":"number","minimum":0,"maximum":1,"description":"Horizontal position from the left, as a fraction of page width."},"y":{"type":"number","minimum":0,"maximum":1,"description":"Vertical position from the top, as a fraction of page height."},"width":{"type":"number","minimum":0.05,"maximum":1,"description":"Signature width, as a fraction of page width."}},"required":["page","x","y","width"],"additionalProperties":false}}},"required":["file","signature","placements"],"additionalProperties":false}}}},"responses":{"200":{"description":"Sign a PDF with a PNG signature","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Signed PDF as base64."},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","pageCount","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/social-image-resizer":{"post":{"operationId":"resize_social_image","summary":"Resize an image to social media dimensions","description":"Crop and resize an image to an exact social media preset: instagram-post (1080x1080), instagram-portrait (1080x1350), instagram-story (1080x1920), youtube-thumbnail (1280x720), x-post (1200x675), x-header (1500x500), linkedin-post (1200x627), or facebook-post (1200x630). The cover crop keeps the center subject. Send base64 or a public URL. Private addresses are refused and the decoded file is capped at 10 MB. Returns the image as base64 PNG.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"The image. Provide url or data."},"preset":{"type":"string","enum":["instagram-post","instagram-portrait","instagram-story","youtube-thumbnail","x-post","x-header","linkedin-post","facebook-post"],"description":"Social platform preset with exact pixel dimensions."}},"required":["file","preset"],"additionalProperties":false}}}},"responses":{"200":{"description":"Resize an image to social media dimensions","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Resized image as base64 PNG."},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","width","height","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/audio-trimmer":{"post":{"operationId":"trim_audio","summary":"Trim a WAV audio file","description":"Trim a WAV audio file to a time range with optional fade in and out, returning a 16-bit PCM WAV as base64. Only WAV is accepted; the web UI handles MP3/OGG/M4A.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false},"startSec":{"type":"number","minimum":0,"description":"Trim start in seconds."},"endSec":{"type":"number","exclusiveMinimum":0,"description":"Trim end in seconds, after startSec."},"fadeInSec":{"default":0,"description":"Linear fade-in length in seconds.","type":"number","minimum":0},"fadeOutSec":{"default":0,"description":"Linear fade-out length in seconds.","type":"number","minimum":0}},"required":["file","startSec","endSec","fadeInSec","fadeOutSec"],"additionalProperties":false}}}},"responses":{"200":{"description":"Trim a WAV audio file","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"Trimmed audio as a 16-bit PCM WAV, base64."},"durationSec":{"type":"number","description":"Duration of the trimmed audio in seconds."},"sampleRate":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Sample rate in Hz."},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"WAV file size in bytes."}},"required":["data","durationSec","sampleRate","bytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/currency-converter":{"post":{"operationId":"convert_currency","summary":"Convert an amount between currencies","description":"Convert money between ISO 4217 currencies using live exchange rates from the Frankfurter API, fetched through the SSRF-safe outbound guard. Supports historical dates.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"default":1,"type":"number","exclusiveMinimum":0,"maximum":1000000000000000},"from":{"default":"USD","description":"ISO 4217 currency code.","type":"string","minLength":3,"maxLength":3},"to":{"default":"EUR","description":"ISO 4217 currency code.","type":"string","minLength":3,"maxLength":3},"date":{"description":"Historical date; omit for the latest rates.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["amount","from","to"],"additionalProperties":false}}}},"responses":{"200":{"description":"Convert an amount between currencies","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"amount":{"type":"number"},"from":{"type":"string"},"to":{"type":"string"},"rate":{"type":"number"},"result":{"type":"number"},"date":{"type":"string"},"error":{"type":"string"}},"required":["ok"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/meme-generator":{"post":{"operationId":"generate_meme","summary":"Generate a meme image","description":"Render a classic top/bottom-caption meme as a PNG. Give it an image (base64, data URI, or public URL) or pick a gradient style, and it returns captioned meme artwork.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"image":{"description":"Base image as base64, a data URI, or a public URL. Private addresses are refused. 10 MB cap. Omit to use a gradient style background.","type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false},"styleId":{"description":"Gradient style id when no image is given: sunset, ocean, grape, forest, mono, candy. Default: sunset.","type":"string"},"top":{"default":"","type":"string","maxLength":500},"bottom":{"default":"","type":"string","maxLength":500},"upper":{"default":true,"description":"Uppercase captions, classic meme style.","type":"boolean"},"fontScale":{"default":1,"description":"Caption size multiplier.","type":"number","minimum":0.5,"maximum":1.5}},"required":["top","bottom","upper","fontScale"],"additionalProperties":false}}}},"responses":{"200":{"description":"Generate a meme image","content":{"application/json":{"schema":{"type":"object","properties":{"png":{"type":"string","description":"PNG bytes, base64 encoded."},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"mimeType":{"type":"string","const":"image/png"}},"required":["png","width","height","mimeType"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/zip-tools":{"post":{"operationId":"zip_files","summary":"Zip files or unzip an archive","description":"Create a ZIP archive from files or list and extract the contents of a ZIP archive. Everything is handled in memory; no files are stored.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"default":"zip","type":"string","enum":["zip","unzip"]},"files":{"description":"Files to zip (zip mode).","maxItems":200,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":256},"data":{"type":"string","description":"Base64 file bytes."}},"required":["name","data"],"additionalProperties":false}},"archive":{"description":"Archive to extract (unzip mode).","type":"object","properties":{"data":{"type":"string","description":"Base64 ZIP bytes."},"name":{"type":"string"}},"required":["data"],"additionalProperties":false}},"required":["mode"],"additionalProperties":false}}}},"responses":{"200":{"description":"Zip files or unzip an archive","content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["zip","unzip"]},"zip":{"description":"Base64 ZIP bytes (zip mode).","type":"string"},"files":{"description":"Extracted files (unzip mode).","type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"data":{"type":"string","description":"Base64 file bytes."}},"required":["name","bytes","data"],"additionalProperties":false}},"fileCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalBytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["mode","fileCount","totalBytes"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/photo-collage":{"post":{"operationId":"make_collage","summary":"Make a photo collage","description":"Arrange up to 9 photos into a collage layout (duo, trio, focus, quad, six, nine) with a gap and background color, and get back a square PNG.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"images":{"minItems":1,"maxItems":9,"type":"array","items":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false},"description":"Photos as base64, data URIs, or public URLs. Private addresses are refused. 10 MB cap each."},"layout":{"default":"quad","description":"Layout id: duo, duo-stack, trio, focus, quad, six, nine. Unknown ids fall back to quad.","type":"string"},"gap":{"default":8,"description":"Gap between cells in pixels.","type":"integer","minimum":0,"maximum":64},"background":{"default":"#000000","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"width":{"default":1600,"description":"Output width in pixels; the collage is square.","type":"integer","minimum":256,"maximum":4096}},"required":["images","layout","gap","background","width"],"additionalProperties":false}}}},"responses":{"200":{"description":"Make a photo collage","content":{"application/json":{"schema":{"type":"object","properties":{"png":{"type":"string","description":"PNG bytes, base64 encoded."},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"mimeType":{"type":"string","const":"image/png"},"cells":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cells in the layout; cells beyond the image count stay background-colored."}},"required":["png","width","height","mimeType","cells"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}},"/api/v1/tools/pdf-form-filler":{"post":{"operationId":"fill_pdf_form","summary":"Fill a PDF form","description":"Fill an interactive PDF form's text fields, checkboxes, dropdowns, and radios by field name, with an option to flatten the result. Pass inspectOnly to list the fields first.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"object","properties":{"url":{"description":"Public http or https URL. Private and local addresses are refused.","type":"string"},"data":{"description":"Base64 bytes or a data URI. Decoded size is capped at 10 MB.","type":"string"},"mimeType":{"description":"MIME type when you know it.","type":"string"},"filename":{"description":"File name, including the extension when you have one.","type":"string"}},"additionalProperties":false,"description":"PDF as base64, a data URI, or a public URL. Private addresses are refused. 10 MB cap."},"values":{"default":{},"description":"Field name to value. Checkboxes take booleans; dropdowns and radios take one of their options.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","boolean"]}},"flatten":{"default":false,"description":"Flatten the form so fields become plain page content.","type":"boolean"},"inspectOnly":{"default":false,"description":"List the form fields without changing anything.","type":"boolean"}},"required":["file","values","flatten","inspectOnly"],"additionalProperties":false}}}},"responses":{"200":{"description":"Fill a PDF form","content":{"application/json":{"schema":{"type":"object","properties":{"pdf":{"description":"Filled PDF bytes, base64 encoded.","type":"string"},"fields":{"description":"Detected form fields (inspectOnly).","type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["text","checkbox","dropdown","radio","list","unknown"]},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"required":{"type":"boolean"},"readOnly":{"type":"boolean"},"maxLength":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"options":{"type":"array","items":{"type":"string"}},"value":{"type":"string"}},"required":["name","type","page","required","readOnly","value"],"additionalProperties":false}},"filled":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"mimeType":{"type":"string","const":"application/pdf"}},"required":["filled","pageCount","mimeType"],"additionalProperties":false}}}},"400":{"description":"The arguments were rejected, or the tool could not finish."},"404":{"description":"No tool uses that slug."},"429":{"description":"More than 60 calls from this address in a minute."}}}}}}