Developers
API quickstart
Every API-backed YATools tool is available over HTTP. No API keys, no signup — just call the endpoint.
Base URL & the deal
All browser calls go through https://yatools-tan.vercel.app/api/v1/* — you never talk to upstream providers directly. That gives you one stable interface, normalized errors, and built-in fallback cascades when a provider is down.
The response envelope
Every JSON endpoint returns the same envelope. provider names the backend that served the request (usually yatools); fallbackUsed is true when a fallback cascade kicked in after the primary failed.
{
"ok": true,
"provider": "yatools",
"fallbackUsed": false,
"data": { /* endpoint-specific payload */ }
}{
"ok": false,
"provider": "yatools",
"fallbackUsed": false,
"error": {
"code": "MISSING_URL",
"message": "Human-readable explanation of what went wrong."
}
}Endpoints that return files on success — screenshots, PDFs, audio, generated images — stream bytes with the correct content-type plus X-Provider and X-Fallback-Used headers. They return the JSON error shape only when they fail, so always check the content-type before parsing — see the error reference.
Your first call
Screenshot of example.com in three languages:
# Full-page screenshot of any public URL
curl "https://yatools-tan.vercel.app/api/v1/websnap?url=https://example.com" \
--output screenshot.png
# The response is a PNG. On error you get JSON instead:
# {"ok":false,"provider":"yatools","fallbackUsed":false,
# "error":{"code":"RATE_LIMITED","message":"..."}}const res = await fetch(
"https://yatools-tan.vercel.app/api/v1/websnap?url=" +
encodeURIComponent("https://example.com")
);
const contentType = res.headers.get("content-type") ?? "";
if (!res.ok || contentType.includes("application/json")) {
// Normalized error shape: { ok, provider, fallbackUsed, error: { code, message } }
const body = await res.json();
throw new Error(body.error.message);
}
const png = await res.blob(); // screenshot bytesimport requests
r = requests.get(
"https://yatools-tan.vercel.app/api/v1/websnap",
params={"url": "https://example.com"},
timeout=60,
)
if "application/json" in r.headers.get("content-type", ""):
# Normalized error: {"ok": False, ..., "error": {"code": ..., "message": ...}}
raise SystemExit(r.json()["error"]["message"])
with open("screenshot.png", "wb") as f:
f.write(r.content) # PNG bytesEndpoint reference
Twelve proxy routes, one per API-backed tool. Query parameters go in the URL for GET routes; POST routes take a JSON body.
| Method | Endpoint | Parameters | Purpose |
|---|---|---|---|
GET | /api/v1/websnap | url (required) | Full-page website screenshot — returns PNG bytes. |
POST | /api/v1/transcribe | JSON: audio as data:audio/* data URL (required, ≤ 25 MB), language, timestamps | Transcribe an uploaded audio file to text. |
POST | /api/v1/tts | JSON: text (required), voiceIndex, rate, pitch | Convert text to spoken audio, including Urdu voices. |
GET / POST | /api/v1/hand | text (required), font, style, paper, lang … | Render typed text as handwriting on ruled paper (PNG). |
GET | /api/v1/wikipdf | query — Wikipedia article URL or title (required) | Convert a Wikipedia article to a clean, selectable-text PDF. |
GET | /api/v1/n8n | q, limit, category, complexity, triggerType, page | Search n8n workflow templates by keyword. |
POST | /api/v1/tti | JSON: prompt, 1–500 chars (required), ratio | Generate an AI image from a text prompt (POST only). |
GET | /api/v1/msearch | q (required) | Search movies and TV shows — ratings, cast, posters. |
POST | /api/v1/certificate | JSON: name, date, signature, details, templateId 1–8 (required), format pdf|jpg|png | Generate a novelty certificate (not an official credential). |
POST | /api/v1/imgchat | JSON: image as data:image/* data URL (required, ≤ 5 MB), userPrompt (required) | Ask AI questions about an uploaded image. |
GET | /api/v1/alldl | url (required, public video/audio page URL) | Get download links for a video/audio URL — only for content you own or have the right to save. |
GET | /api/v1/mail | action=create|inbox|read|delete; mail (address), id (message id) as required per action | Temporary receive-only email addresses. Addresses expire; never use for account recovery. |
Daily quotas
Limits apply per tool, per IP, per day (resets at midnight UTC). The six client-side tools — QR Code Generator, Word Counter, JSON Formatter, Password Generator, Case Converter, Color Picker — run entirely in your browser and have no limits at all.
| Tool | Route | Limit (per IP / day) |
|---|---|---|
| Website Screenshot | /api/v1/websnap | 20 / day |
| Audio to Text | /api/v1/transcribe | 10 / day |
| Text to Speech | /api/v1/tts | 30 / day |
| Wikipedia to PDF | /api/v1/wikipdf | 20 / day |
| n8n Workflow Search | /api/v1/n8n | 100 / day |
| AI Image Generator | /api/v1/tti | 10 / day |
| Movie & TV Search | /api/v1/msearch | 50 / day |
| Certificate Maker | /api/v1/certificate | 10 / day |
| AI Vision Chat | /api/v1/imgchat | 10 / day |
| Universal Downloader | /api/v1/alldl | 10 / day |
| Temporary Email | /api/v1/mail | 20 / day |
What happens on 429
Exceed a quota and the API returns 429 Too Many Requests with a Retry-After header (seconds until the quota resets) and this body:
// HTTP 429 — also carries a Retry-After header (seconds)
{
"ok": false,
"provider": "yatools",
"fallbackUsed": false,
"error": {
"code": "RATE_LIMITED",
"message": "Daily limit reached for this tool — try again tomorrow."
},
"tool": "websnap"
}The correct behavior is simple: back off, show the user a friendly message, and retry after the reset — don't hammer the endpoint. Full details on the rate limits page.
Keep reading
- Rate limits & fair use — the numbers above in context, plus the fair-use policy.
- Error reference — every error code, the normalized shape, and how to handle binary-route failures.
- Changelog — what shipped and when.