Developers

Run My Ads API

Every endpoint the Run My Ads Zapier app uses, with examples, written so a person or an AI agent can use them.

Who this is for. The Run My Ads Zapier app, and anyone connecting their own system, uses these endpoints to get new leads, booked calls and ad alerts out of Run My Ads, and to send booked calls and sales back in, so Ados judges each ad on real results and not only clicks.

What Run My Ads is

Ados is your AI media buyer and graphic designer, for any business that advertises on Meta, Google, ChatGPT and Snapchat: it makes the visuals, reviews every result and recommends what to launch, pause and scale. You approve every change. Run it yourself on Autopilot, or have our team run your ads on Done For You. Billed every 30 days. No trials. Cancel anytime.

Ados is the AI inside Run My Ads. It runs ads for the business, in its own ad account or ours, makes the ad images and videos, and reports what each ad cost per lead, per booked call and per sale. This API is how leads, booked calls and ad alerts get out to other tools, and how booked calls and sales come back in. AI agents: start here.

Overview

  • Base URL: https://app.runmyads.com. Every call uses HTTPS.
  • Bodies are JSON (Content-Type: application/json), and replies are JSON.
  • Replies never include a lead's name, email or phone, except the trigger payloads sent to your own Zap and the made-up sample from Get a sample record.

Endpoints

Authentication

Every call carries your account's Run My Ads Conversions key. It starts with vcbo_.

  • Where to get it: sign in at app.runmyads.com/ads/conversions, open Connect your CRM and select Make a key. Only an account admin can make one.
  • It is shown once. Copy it before you close the box. We keep only a fingerprint of it, so we cannot show it to you again.
  • One live key per account. Making a new key retires the old one and switches off every Zap that was turned on with it. Reconnect those Zaps with the new key.
  • How to send it: the Authorization header as Bearer <key>. The X-API-Key: <key> header also works. Never put the key in a URL.
Header
Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY

Every key on this page is a placeholder. Treat your key like a password: anyone with it can send results into your account and receive your new leads' names, emails and phone numbers through a Zap. If it leaks, make a new key at once; that retires the old one.

Test the key

GEThttps://app.runmyads.com/api/webhooks/rma/zapier/auth

Used by: Connecting the account.

Checks the key and returns your account's name, so you can tell two connections apart. No body, no query.

Request
curl https://app.runmyads.com/api/webhooks/rma/zapier/auth \
  -H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY"
Response 200
{
  "ok": true,
  "agency_name": "Acme Roofing"
}
StatusWhen
405Any method other than GET.
401No key was sent, or the key is wrong or has been replaced by a newer one.
429More than 120 calls a minute with one key. Wait a minute and try again.
503A temporary problem on our side. Try again shortly.

Subscribe a webhook

POSThttps://app.runmyads.com/api/webhooks/rma/zapier/subscribe

Used by: Turning a trigger Zap on.

Registers a webhook address for one trigger. From then on, each new event of that kind is posted to the address (see Webhook payloads). Sending the same event and address again turns the existing subscription back on and returns the same id.

Body

event string Required
One of ads.lead_created, ads.call_booked, ads.alert.
target_url string Required
The HTTPS address to post events to. It must be a Zapier hook address on hooks.zapier.com.
Request
curl -X POST https://app.runmyads.com/api/webhooks/rma/zapier/subscribe \
  -H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event":"ads.lead_created","target_url":"https://hooks.zapier.com/hooks/standard/1234567/abcdef/"}'
Response 201
{
  "id": "3b2a8c1d-5e4f-4a6b-9c8d-7e6f5a4b3c2d"
}
StatusWhen
400event is not one of the three trigger events, target_url is not a Zapier hook address, or the body is not JSON.
405Any method other than POST or DELETE.
413The body is over 16 KB.
429The account already has 50 Run My Ads subscriptions (turn an old Zap off first), or more than 120 calls a minute with one key.
401No key, or the key is wrong or retired.
503A temporary problem on our side. Try again shortly.

Unsubscribe a webhook

DELETEhttps://app.runmyads.com/api/webhooks/rma/zapier/subscribe

Used by: Turning a trigger Zap off.

Removes a subscription. Send the id the subscribe call returned, as a query parameter (or as {"id": "..."} in a JSON body). A subscription can only be removed with a key from the same account.

Query

id string (uuid) Required
The id returned when the subscription was made.
Request
curl -X DELETE "https://app.runmyads.com/api/webhooks/rma/zapier/subscribe?id=3b2a8c1d-5e4f-4a6b-9c8d-7e6f5a4b3c2d" \
  -H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY"
Response 200
{
  "ok": true
}
StatusWhen
400id is missing or is not a valid id.
401No key was sent, or the key is wrong or has been replaced by a newer one.
429More than 120 calls a minute with one key. Wait a minute and try again.
503A temporary problem on our side. Try again shortly.

Get a sample record

GEThttps://app.runmyads.com/api/webhooks/rma/zapier/triggers

Used by: Testing a trigger in the Zap editor.

Returns one made-up sample record for a trigger, in exactly the shape the webhook sends, so a Zap can be built and tested before a real event happens. It never returns real lead data.

Query

event string Required
One of ads.lead_created, ads.call_booked, ads.alert.
Request
curl "https://app.runmyads.com/api/webhooks/rma/zapier/triggers?event=ads.call_booked" \
  -H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY"
Response 200 (a list with one record)
[
  {
    "id": "9f1c5a2e-7b3d-4c8a-9e11-2f6d8b4a0c73",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "+15551234567",
    "state": "TX",
    "zip": "77002",
    "created_at": "2026-10-29T14:32:00.000Z",
    "source": "booking",
    "platform": "meta",
    "campaign_id": "120210000000000001",
    "adset_id": "120210000000000002",
    "ad_id": "120210000000000003",
    "event_id": "booked_9f1c5a2e",
    "occurred_at": "2026-10-30T16:00:00.000Z",
    "value": 150,
    "currency": "USD"
  }
]
StatusWhen
400event is missing or is not one of the three trigger events.
405Any method other than GET.
401No key was sent, or the key is wrong or has been replaced by a newer one.
429More than 120 calls a minute with one key. Wait a minute and try again.
503A temporary problem on our side. Try again shortly.

Send a result

POSThttps://app.runmyads.com/api/webhooks/rma/conversions

Used by: Every action (Send Lead, Send Booked Call, Send Sale, Send Other Result).

Sends one result from your own system (a CRM, a booking tool, a store) back to Run My Ads. Run My Ads matches it to the lead that came from your ads by email or phone, and counts it toward that ad. Each Zapier action posts one event here:

  • Send Lead sends "event": "lead".
  • Send Booked Call sends "event": "booked".
  • Send Sale sends "event": "sold" with a value.
  • Send Other Result sends the result you pick: lead, contacted, booked, showed, sold, resold, cross_sold, refund, bad_lead.

Body

event string Required
The result: lead (a new lead), contacted, booked (a booked call), showed (showed up), sold, resold (a repeat sale), cross_sold (another product sold), refund or bad_lead.
email string Email or phone
The lead's email. Send the email, the phone, or both, so the result can be matched to the lead.
phone string Email or phone
The lead's phone number, in any format.
first_name string Optional
The lead's first name.
last_name string Optional
The lead's last name.
value number Required for Send Sale
The amount, for example 1200.00. Used for booked calls and sales.
currency string Optional
Three letters, for example USD.
order_id string Required for resold and cross_sold
The order or invoice id, so a repeat or extra sale is never counted twice.
external_id string Optional
Your system's id for this lead, call or deal. Sending the same id twice is counted once.
occurred_at string (ISO 8601) Optional
When it happened, within the last two years. Leave it out to use the time it is sent.
test boolean Optional
true checks the connection and the match, and saves nothing.
source string Optional
A label for where the result came from. The Zapier app sends zapier.
Request
curl -X POST https://app.runmyads.com/api/webhooks/rma/conversions \
  -H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event":"sold","source":"zapier","email":"jane@example.com","phone":"+15551234567","value":1200,"currency":"USD","external_id":"deal_123"}'
Response 200
{
  "ok": true,
  "matched": true,
  "event_id": "crm_webhook:deal_123:sold",
  "duplicate": false
}

Reply fields

ok boolean Always
The result was read and saved.
matched boolean Always
It was matched to a lead from your ads. false means it was kept and listed under results we could not match.
event_id string or null Always
Our id for the saved result.
duplicate boolean Always
The same result was already counted, so it was not counted again.
test boolean Optional
Present and true on a test send.
error string Optional
Present when ok is false: what to fix.

You can also send up to 100 events in one call, as a JSON list or as {"events": [...]}. The reply is then {"ok": ..., "results": [...]} with one entry per event, in order.

Response 400 (one event that cannot be read)
{
  "ok": false,
  "matched": false,
  "event_id": null,
  "duplicate": false,
  "error": "Send lead_id (our lead id), leadgen_id, or the lead's phone or email."
}
StatusWhen
400The body is not JSON, the event is unknown, there is no email or phone, occurred_at is not a date in the last two years, or a resold / cross_sold has no order_id. The reply's error says which.
401The key is wrong or retired, or an optional signature header was sent and does not match.
404No key was sent (or it does not start with vcbo_).
405Any method other than POST (or GET, which returns when the last test and last event arrived).
413The body is over 512 KB, or more than 100 events.
429More than 600 calls a minute with one key. Wait a minute and try again.
503A save failed and is safe to retry. Results already saved are not counted twice.

Webhook payloads for the 3 triggers

When an event happens, Run My Ads sends an HTTPS POST with a JSON body to every address subscribed to it:

Body shape
{
  "event": "ads.lead_created",
  "occurred_at": "2026-10-29T14:32:05.000Z",
  "data": {
    "...": "the record below"
  }
}

The Zapier app hands your Zap the data object, so fields read first_name, not data__first_name. Any field can be null when we do not have it.

  • Delivery waits up to 10 seconds for your address to reply with a 2xx.
  • A 410 Gone reply turns the subscription off at once. After 5 failed deliveries in a row it is turned off too; subscribe again to turn it back on.
  • Redirects are not followed.

New Lead (ads.lead_created)

A new lead came in from your Run My Ads ads: a Meta instant form, your landing page or an Ados page. Leads your own system sent to Run My Ads are not sent back. A lead carries only what your ad form or page collected, plus the ad ids. It carries no form answers, and nothing we added except a state worked out from the ZIP or phone area code when the form did not ask for one.

data
{
  "id": "9f1c5a2e-7b3d-4c8a-9e11-2f6d8b4a0c73",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "phone": "+15551234567",
  "state": "TX",
  "zip": "77002",
  "created_at": "2026-10-29T14:32:00.000Z",
  "source": "lead_form",
  "platform": "meta",
  "campaign_id": "120210000000000001",
  "adset_id": "120210000000000002",
  "ad_id": "120210000000000003",
  "event_id": "lead_9f1c5a2e",
  "occurred_at": "2026-10-29T14:32:00.000Z"
}
id string Optional
Our id for the lead.
first_name, last_name, email, phone, zip string Optional
What the lead entered on your ad form or page.
state string Optional
The lead's state, from the form, or from the ZIP or phone area code when the form did not ask for one.
created_at string (ISO 8601) Optional
When the lead was created.
source string Optional
How it came in, for example lead_form.
platform string Optional
meta, tiktok, google or openai.
campaign_id, adset_id, ad_id string Optional
The ad platform's ids for the ad that brought the lead.
event_id string Optional
Our id for this event. Use it to ignore a repeat.
occurred_at string (ISO 8601) Optional
When it happened.

New Booked Call (ads.call_booked)

A lead from your ads booked a call. Every New Lead field, plus the value when one is set. Calls your own system sent to Run My Ads are not sent back.

data
{
  "id": "9f1c5a2e-7b3d-4c8a-9e11-2f6d8b4a0c73",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "phone": "+15551234567",
  "state": "TX",
  "zip": "77002",
  "created_at": "2026-10-29T14:32:00.000Z",
  "source": "booking",
  "platform": "meta",
  "campaign_id": "120210000000000001",
  "adset_id": "120210000000000002",
  "ad_id": "120210000000000003",
  "event_id": "booked_9f1c5a2e",
  "occurred_at": "2026-10-30T16:00:00.000Z",
  "value": 150,
  "currency": "USD"
}
value number or null Optional
The value set on a booked call.
currency string or null Optional
Three letters, for example USD.

New Ad Alert (ads.alert)

Run My Ads sent an ad alert you have switched on: an ad rejected, spending with no leads, a spend cap reached, a reconnect needed and the rest. It carries no lead details.

data
{
  "id": "no_leads:120210000000000001:2026-10-29T15:00:00.000Z",
  "type": "no_leads",
  "label": "Spending with no leads",
  "title": "Spending with no leads on Spring Promo",
  "message": "$84 spent in the last 24 hours and no leads came in.",
  "link": "https://app.runmyads.com/ads",
  "sent_at": "2026-10-29T15:00:00.000Z"
}
id string Optional
A unique id for this alert.
type string Optional
The kind of alert, for example no_leads.
label string Optional
The kind of alert in plain words.
title string Optional
The alert's headline.
message string Optional
The alert's text. Several lines are joined by line breaks.
link string or null Optional
Where to fix it in Run My Ads.
sent_at string (ISO 8601) Optional
When the alert was sent.

Using Zapier

  1. In Zapier, pick the Run My Ads app.
  2. When asked to connect, paste your Conversions key from app.runmyads.com/ads/conversions (Connect your CRM, then Make a key). Zapier tests it and shows your account's name.
  3. Triggers: New Lead, New Booked Call and New Ad Alert. Use them to send new leads to your CRM, a sheet or your team's chat, or to get alerts where you work.
  4. Actions: Send Lead, Send Booked Call, Send Sale and Send Other Result. Use them when your CRM or booking tool learns a lead booked, showed up or bought, so Ados can judge each ad on booked calls and sales.
  5. Turn the Zap on. Turning it off removes the subscription; making a new key switches off every Zap that used the old one.

For AI agents using this API

If you are an AI agent acting for a Run My Ads user, these are the steps. The full detail for each call is above.

  1. Get the key. The user (an account admin) signs in at app.runmyads.com, opens Ads, then Conversions (app.runmyads.com/ads/conversions), and selects Make a key. It starts with vcbo_ and is shown once.
  2. Test it. GET /api/webhooks/rma/zapier/auth with the key. A 200 with the account name means it works.
  3. Get events out. POST /api/webhooks/rma/zapier/subscribe with an event (ads.lead_created, ads.call_booked or ads.alert) and a Zapier hook address. Each new event is then posted there.
  4. Send results in. POST /api/webhooks/rma/conversions with an event (for example booked or sold) and the lead's email or phone. Send test: true before real results to check the match without saving.
  • Only ask the user for their Conversions key when they want you to make these calls. Treat it as a password and never repeat it back in the chat.
  • Machine-readable: openapi.json (these endpoints as OpenAPI 3.1) and llms.txt.

Questions or a problem with the API? Email support@runmyads.com. We reply within one business day, Monday to Friday.