{"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://tools.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 Open Graph tags","description":"Build the meta tags and a Next.js opengraph-image.tsx source file for a 1200 by 630 card. Use this when a page needs share tags, not when you only need to inspect a live URL.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"default":"blog","type":"string","enum":["blog","product","minimal","gradient","code","profile"]},"title":{"type":"string","minLength":1},"subtitle":{"default":"","type":"string"},"author":{"default":"","type":"string"},"background":{"default":"oklch(0.22 0.02 260)","type":"string"},"foreground":{"default":"oklch(0.96 0.005 95)","type":"string"},"accent":{"default":"oklch(0.68 0.16 262)","type":"string"},"font":{"default":"sans","type":"string","enum":["sans","mono"]},"imageUrl":{"default":"https://example.com/opengraph-image","type":"string"}},"required":["template","title","subtitle","author","background","foreground","accent","font","imageUrl"],"additionalProperties":false}}}},"responses":{"200":{"description":"Build Open Graph tags","content":{"application/json":{"schema":{"type":"object","properties":{"metaTags":{"type":"string"},"source":{"type":"string"}},"required":["metaTags","source"],"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."}}}}}}