Programmatically run JAD tools through the local @jadapps/runner agent. Available on every paid tier — Pro and Pro + Media have hourly rate limits; Developer and Enterprise are uncapped.
JAD's API is **runner-mediated**. The server-side endpoints under https://jadapps.app/api/v1/... issue tokens, expose tool schemas, and enforce rate limits. They never accept file content. To execute a tool you pair an [@jadapps/runner](/docs/runner) instance to your account; the runner exposes a matching API on http://127.0.0.1:9789 that runs every transform locally.
API keys are available on every **paid** tier. Free accounts can use the in-app tools but cannot mint long-lived API keys or run the MCP server.
Server-side endpoints accept a Bearer token in the Authorization header. API keys are issued from **Settings → API Keys** (any paid tier) and have the prefix jad_live_.
curl https://jadapps.app/api/v1/account \ -H "Authorization: Bearer jad_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Limits are enforced per API key on a sliding hourly window.
| Tier | Requests/hour |
|---|---|
| Pro | 100 |
| Pro + Media | 500 |
| Developer | Unlimited |
| Enterprise | Unlimited |
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. On Developer and Enterprise, the Limit and Remaining headers are returned as the literal string unlimited. A 429 response carries the same headers and a resetAt ISO timestamp in the body.
Returns the full catalogue with slug, category, accepted file types, and a hint at whether the tool is browser-only.
curl https://jadapps.app/api/v1/tools \ -H "Authorization: Bearer jad_live_xxx"
Response
{
"tools": [
{
"slug": "csv-validator",
"title": "CSV Validator",
"category": "CSV",
"isBrowserOnly": false,
"acceptedFileTypes": {
"label": "CSV",
"extensions": [".csv"],
"mimeTypes": ["text/csv"]
}
}
],
"count": 480
}Returns the JSON Schema for the tool's options and a description of accepted inputs. MCP/SDK clients use this to build payloads before dispatching them to their local runner.
curl https://jadapps.app/api/v1/tools/csv-validator \ -H "Authorization: Bearer jad_live_xxx"
**This endpoint never executes uploads.** JAD's API/MCP layer is intentionally upload-free — it always returns 400 Runner required with a payload telling the caller where the local runner lives. Send the same body to your runner's loopback URL (http://127.0.0.1:9789/v1/tools/{slug}/run) instead, and the transform runs locally.
This indirection is the reason files never reach JAD's infrastructure: the only execution path is the one on your own machine.
# Calling the server returns runner-pairing info: curl -X POST https://jadapps.app/api/v1/tools/csv-validator/run \ -H "Authorization: Bearer jad_live_xxx" # Calling the local runner actually runs the tool: curl -X POST http://127.0.0.1:9789/v1/tools/csv-validator/run \ -H "Authorization: Bearer jad_live_xxx" \ -F "[email protected]"
Response
// 400 from the JAD server (always)
{
"error": "Runner required",
"reason": "JAD's API/MCP never accepts uploads. Pair an @jadapps/runner...",
"schemaEndpoint": "https://jadapps.app/api/v1/tools/csv-validator",
"runnerEndpoint": "http://127.0.0.1:9789/v1/tools/csv-validator/run",
"installRunner": "https://jadapps.app/docs/runner",
"tool": { "slug": "csv-validator", "category": "CSV" }
}
// 200 from the local runner (after pairing)
{
"tool": "csv-validator",
"result": {
"valid": true,
"rows": 150,
"columns": 8,
"issues": []
}
}Returns your tier, permissions, scopes, and the rate limit applied to this key. rateLimit.perHour is null for Developer and Enterprise tiers (unlimited).
curl https://jadapps.app/api/v1/account \ -H "Authorization: Bearer jad_live_xxx"
Response
{
"userId": "google:1234567890",
"tier": "pro_media",
"permissions": ["read", "write"],
"scopes": ["*"],
"rateLimit": { "perHour": 500 }
}Key creation and revocation use **session authentication**, not Bearer auth — they're called from the dashboard with cookies, not from another script. Any paid tier can mint keys; free accounts get a 403. The raw key is shown **once** on creation; store it immediately.
# List keys (session auth)
curl https://jadapps.app/api/v1/auth/keys -b cookies.txt
# Create key (session auth — any paid tier)
curl -X POST https://jadapps.app/api/v1/auth/keys \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"name": "CI Pipeline"}'
# Revoke key (session auth)
curl -X DELETE "https://jadapps.app/api/v1/auth/keys?id=KEY_UUID" \
-b cookies.txtErrors follow a consistent JSON shape:
| Status | Meaning |
|---|---|
| 400 | Bad request — including the always-400 /run endpoint |
| 401 | Missing or invalid API key |
| 403 | Tier doesn't allow this action (e.g. minting a key on free) |
| 404 | Tool or key not found |
| 429 | Rate limit exceeded |
Response
{
"error": "Rate limit exceeded",
"resetAt": "2026-05-09T15:00:00.000Z"
}The API is versioned via the URL prefix (/v1/...). Breaking changes will increment the version; the previous version stays online for at least 6 months after the new one ships.