The AutoAdy REST API is one POST endpoint per tool. Read live account numbers, generate creative, and push ads — from a script, a cron job, or an agent framework.
Authorization header.curl https://www.autoady.io/api/mcp/list-accounts \
-H "Authorization: Bearer adk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{}'That returns every ad account the key can reach. Take an account_id from it and ask for results:
curl https://www.autoady.io/api/mcp/results \
-H "Authorization: Bearer adk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"account_id":"act_1234567890","level":"campaign","date_preset":"last_7d"}'Successful responses are wrapped in an envelope. The result you want is always under data:
{
"source": "AutoAdy — AI Meta Ads Optimization (autoady.io)",
"data": { "...": "tool result" }
}The full machine-readable contract lives at /api/openapi as an OpenAPI 3.1 document — point a client generator at it rather than hand-writing types.
Send your key as a bearer token. This is the only way to authenticate against the REST API — there is no query-parameter, cookie, or basic-auth path.
Authorization: Bearer adk_YOUR_KEY
A key that is missing, malformed, revoked, or expired gets HTTP 401 with an unwrapped body:
{ "error": "Invalid or missing API key. Include: Authorization: Bearer adk_..." }Most failures reuse the success envelope with a non-2xx status and the message under data.error. Three do not — handle both shapes:
| Status | Body | Meaning |
|---|---|---|
| 207 | wrapped | A multi-step write applied only partially — both outcomes are listed under data. Not a success: check the status, not just res.ok. |
| 400 | wrapped | The body failed validation. |
| 401 | bare | Key missing, malformed, revoked, or expired. |
| 403 | wrapped | Your plan does not include this tool (an upgrade_url is included), or the requested account is not one this workspace can act on. |
| 404 | wrapped | Unknown tool name, or no reachable ad account. |
| 409 | wrapped | A write was refused — duplicate request, spent write budget, or missing confirmation. |
| 429 | bare | Over 60 requests per minute for this key. |
| 502 | wrapped | An upstream step failed or answered with something that was not JSON. |
| 503 | bare | AutoAdy’s rate-limiting backend is degraded — not a limit you hit. Retry shortly. |
Four tools report soft failures inside a 200 instead of a 4xx: benchmarks, compare, fatigue and get-skill answer an unrecognised input with data.error. Check that field as well as the status.
60 requests per minute per API key. A 429 carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and Retry-After — back off for Retry-After seconds rather than retrying immediately. Creative workflows can run for minutes; allow a 300-second client timeout.
A key grants access to your AutoAdy workspace and can move real budget. Keep it in an environment variable, never in version control or client-side code. If one leaks, revoke it in Settings → API Keys and generate a replacement.
22 tools, all POST, all under the same path shape. Request and response schemas for each are in the OpenAPI document.
Live account data and diagnostics. Available on every plan, including Free.
POST /api/mcp/list-accounts
Returns every Meta ad account this API key's workspace can act on, with id, name and currency. Call this first — the `account_id` values it returns are the only ones the other tools accept. The request body is ignored; send `{}`.
POST /api/mcp/results
Live Meta delivery numbers for one account — spend, results, CPA/CPL, CTR, CPM — aggregated at the level you ask for. Figures come from the Meta Marketing API through AutoAdy's conversion-counting layer, so they match what the app shows.
POST /api/mcp/health
Scores the account across delivery, efficiency, creative freshness and structure, and returns the component scores behind the headline number. Uses the active account when `account_id` is omitted.
POST /api/mcp/winner-insights
Analyses the account's top performers and reports the patterns they share — formats, hooks, angles, and the creative traits that correlate with results. Uses the active account when `account_id` is omitted.
POST /api/mcp/fatigue-alerts
Flags ads whose frequency is climbing while CTR decays — the ones that need rotating before they burn budget. Uses the active account when `account_id` is omitted.
Pure calculation — no ad account is read and no Meta connection is needed.
POST /api/mcp/benchmarks
Returns AutoAdy's Meta ads benchmarks (CPM, CTR, CPA) for one industry, or for every industry when `niche` is omitted. Pure lookup — it touches no ad account and needs no Meta connection. Note: an unrecognised `niche` still answers **HTTP 200**, with `data.error` naming the available niches. Check `data.error` as well as the status.
POST /api/mcp/compare
Scores your CPM, CTR and/or CPL against the benchmark for a niche and says whether each is ahead or behind. Supply at least one of the three metrics. Pure calculation — no ad account is read. Note: a missing or unknown `niche`, or no metric at all, still answers **HTTP 200** with `data.error`.
POST /api/mcp/fatigue
Given a frequency, a CTR trend and a run length, returns a fatigue verdict and what to do about it. Pure calculation on the numbers you pass — use `fatigue-alerts` instead if you want AutoAdy to pull the numbers from a live account. Note: validation failures answer **HTTP 200** with `data.error`.
AutoAdy's media-buying methodology, published in full.
POST /api/mcp/list-skills
Returns every published AutoAdy skill with its slug, title and summary — the methodology the AI itself runs on. Use the slugs with `get-skill`. The request body is ignored; send `{}`.
POST /api/mcp/get-skill
Returns the complete text of one published skill — the thresholds, decision rules and worked reasoning behind it. The `slug` is trimmed and lowercased before lookup. Note: a missing or unknown `slug` still answers **HTTP 200**, with `data.error` naming the valid slugs. Check `data.error` as well as the status.
Copy generation, the creative library, and the one direct ad write on this surface.
POST /api/mcp/ad-copy
ProWrites primary text, headlines and descriptions for a Meta ad. Give it either a `url` to read the offer from, or a `description` you write yourself — at least one is required.
POST /api/mcp/hooks
ProProduces opening lines and hook concepts for video or static ads. Give it either a `url` or a `description` — at least one is required.
POST /api/mcp/save-creative
Stores externally generated images in the AutoAdy creative library so they can be pushed to an ad set later. Supply `image_urls` (up to 10) or a single `image_url`. URLs must be public `http`/`https`. Loopback, link-local and private-range hosts are rejected.
POST /api/mcp/push-creative
ProUploads an image or video to Meta, builds the creative, and creates an ad inside an existing ad set. This is a real write against the ad account. Requirements: exactly one of `image_url` / `video_url`, and exactly one destination (`website_url` or `lead_gen_form_id`). Media URLs must be public `http`/`https`; private and loopback hosts are rejected. `request_id` is a caller-chosen idempotency key — reusing one returns the original outcome instead of creating a second ad. Ads are created **PAUSED** unless `status` is `"ACTIVE"`, and going straight to ACTIVE additionally requires `hard_confirm_text`. Writes are metered per ad account (200 per hour) on top of the per-key request limit.
Multi-step creative pipelines. These can run for minutes — set a generous timeout.
POST /api/mcp/creative-dna
ProReads a brand's site and derives its voice, palette, claims and visual signature, then stores that profile so later creative generation stays on-brand. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
POST /api/mcp/analyze-winning-ad
ProDeconstructs a single high-performing ad — hook, angle, visual structure, offer framing — into a reusable brief you can build variations from. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`.
POST /api/mcp/url-to-ads
ProScrapes a product or landing page and generates a batch of ad creatives across several angles. Generated images consume the account's image quota. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
POST /api/mcp/multiply-winner
ProTakes one proven creative — by `ad_id` or by direct `image_url` — and produces variations that keep what works and change what is worth testing. Generated images consume the account's image quota. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
POST /api/mcp/competitor-creatives
ProPulls a competitor's live ads from the public Meta Ad Library, reads what they are running, and generates on-brand creatives that answer it. Identify the competitor by name or by Meta page id. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
POST /api/mcp/creative-matrix
ProGenerates the cross-product of the angles, hooks and visual styles you pass, so a single call produces a structured test grid rather than a loose batch. The grid is capped: `angles.length × hooks.length × visual_styles.length` must not exceed **27**, or the call is rejected with 400. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
POST /api/mcp/creative-loop
ProFinds fatiguing ads, generates replacements from what is winning, and stages them in the account. New creatives are created **PAUSED** unless `auto_launch` is `true`. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
POST /api/mcp/emergency-recovery
ProFinds ads spending well above the account's average cost per result and pauses them. This is a real write, so it takes an idempotency key and is metered by the per-account write budget (200 writes per hour). A partially applied run answers **207**. Runs directly against the account this API key can reach — the same execution path as the MCP server. **404** means no reachable Meta ad account (none connected, or the `account_id` you passed is not one this workspace can act on); **403** means the plan does not cover the tool or the key belongs to a read-only Client Viewer; **400** carries a tool-level failure under `data.error`. This workflow writes to the ad account, so it is metered by the per-account write budget and is idempotent on the request body: retrying an identical body replays the first run's result instead of writing twice. To force a genuinely new run of the same input, pass a fresh `request_id`. A run the write boundary refused answers **409**.
The same tools are exposed over the Model Context Protocol, so Claude, ChatGPT connectors, IDE assistants and custom agents can call them directly. One remote endpoint:
https://www.autoady.io/api/mcp
Clients that implement the MCP authorization flow, claude.ai among them, connect over OAuth 2.1: add the URL, sign in, approve. No key handling at all.
That opens claude.ai’s Add-connector dialog pre-filled; press Add to confirm. To do it manually instead, paste https://www.autoady.io/api/mcp under Settings → Connectors → Add custom connector.
Clients that read a config file use an API key instead. For Claude Desktop and Claude Code:
{
"mcpServers": {
"autoady": {
"command": "npx",
"args": ["-y", "@autoady/mcp-server"],
"env": { "AUTOADY_API_KEY": "adk_YOUR_KEY" }
}
}
}The read tools are shaped for an agent that runs on a schedule and compares each run against its own history:
since and until (ISO dates) as an alternative to date_preset. So “this window versus the same window last week” is one call each, not a preset that almost fits.get_account_insights and get_campaign_insights take a breakdown: placement, country, age_gender, device, hour and more. Returning one row per value instead of a single total.structuredContent block with raw numerics, an explicit currency code, and the window that was actually applied. Nothing to parse out of a formatted string, and no guessing which currency an account bills in.get_connected_account reports whether the account can still spend, why it cannot if it cannot, and any spending limit. A disabled account reports healthy metrics right up until it stops delivering. Check this first.The MCP surface is wider than the REST one: it exposes the full tool registry, including campaign writes and budget moves. See the MCP server page for the complete catalog and the safety model.
For shells, cron jobs and CI, the CLI wraps the same endpoints without the curl boilerplate. No install step. Run it with npx:
npx -y @autoady/cli accounts
Installing it once puts a short autoady command on your PATH. The examples below use that form:
npm install -g @autoady/cli
Authenticate by exporting your key (a per-command --key flag exists as a last resort, but it lands in shell history and process listings. Prefer the env var):
export AUTOADY_API_KEY=adk_YOUR_KEY autoady results --account act_1234567890 --date-preset last_7d autoady health
| Command | What it does |
|---|---|
| accounts | List the ad accounts your key can reach. |
| results | Live spend, results and efficiency for an account. |
| health | Account health score with its component breakdown. |
| benchmarks | Industry benchmarks for CPM, CTR and CPA. |
| compare | Score your own metrics against a benchmark. |
| fatigue | Fatigue verdict from a frequency and CTR trend. |
| ad-copy | Generate Meta ad copy. Requires Pro. |
| hooks | Generate scroll-stopping hooks. Requires Pro. |
| call | Escape hatch. Call any tool by name with a raw JSON body. |
Anything without a dedicated command is still one call away. Every tool in the reference above works with call:
autoady call winner-insights --json-body '{"account_id":"act_1234567890"}'
autoady call get-skill --json-body '{"slug":"audit"}'| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | The API rejected the call. Wrong plan, invalid arguments, rate limit. |
| 2 | Usage or auth error. Unknown command, missing required flag, or a missing/invalid API key. |
In CI, that means set -e does the right thing, and you can tell “you called it wrong” apart from “the API said no” without parsing output.
The complete contract, every request schema, every response shape and every status code, is published as an OpenAPI 3.1 document:
https://www.autoady.io/api/openapi
It needs no authentication, so you can point a client generator, a Postman import, or an agent’s tool loader straight at it. The reference above is rendered from the same document at build time, which is why the two can never disagree.
Want AutoAdy running on a schedule inside Claude rather than from your own cron? Scheduled routines has ready-made prompts and the connector setup.
Questions, or something here that does not match what you see? Get in touch.