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
- GETTest the key
- POSTSubscribe a webhook
- DELETEUnsubscribe a webhook
- GETGet a sample record
- POSTSend a result
- Webhook payloads for the 3 triggers
- Using Zapier
- For AI agents using this API
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
Authorizationheader asBearer <key>. TheX-API-Key: <key>header also works. Never put the key in a URL.
Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEYEvery 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.
curl https://app.runmyads.com/api/webhooks/rma/zapier/auth \
-H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY"{
"ok": true,
"agency_name": "Acme Roofing"
}| Status | When |
|---|---|
405 | Any method other than GET. |
401 | No key was sent, or the key is wrong or has been replaced by a newer one. |
429 | More than 120 calls a minute with one key. Wait a minute and try again. |
503 | A 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
eventstring Required- One of
ads.lead_created,ads.call_booked,ads.alert. target_urlstring Required- The HTTPS address to post events to. It must be a Zapier hook address on
hooks.zapier.com.
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/"}'{
"id": "3b2a8c1d-5e4f-4a6b-9c8d-7e6f5a4b3c2d"
}| Status | When |
|---|---|
400 | event is not one of the three trigger events, target_url is not a Zapier hook address, or the body is not JSON. |
405 | Any method other than POST or DELETE. |
413 | The body is over 16 KB. |
429 | The account already has 50 Run My Ads subscriptions (turn an old Zap off first), or more than 120 calls a minute with one key. |
401 | No key, or the key is wrong or retired. |
503 | A 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
idstring (uuid) Required- The id returned when the subscription was made.
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"{
"ok": true
}| Status | When |
|---|---|
400 | id is missing or is not a valid id. |
401 | No key was sent, or the key is wrong or has been replaced by a newer one. |
429 | More than 120 calls a minute with one key. Wait a minute and try again. |
503 | A 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
eventstring Required- One of
ads.lead_created,ads.call_booked,ads.alert.
curl "https://app.runmyads.com/api/webhooks/rma/zapier/triggers?event=ads.call_booked" \
-H "Authorization: Bearer vcbo_YOUR_CONVERSIONS_KEY"[
{
"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"
}
]| Status | When |
|---|---|
400 | event is missing or is not one of the three trigger events. |
405 | Any method other than GET. |
401 | No key was sent, or the key is wrong or has been replaced by a newer one. |
429 | More than 120 calls a minute with one key. Wait a minute and try again. |
503 | A 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 avalue. - Send Other Result sends the result you pick:
lead,contacted,booked,showed,sold,resold,cross_sold,refund,bad_lead.
Body
eventstring 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),refundorbad_lead. emailstring Email or phone- The lead's email. Send the email, the phone, or both, so the result can be matched to the lead.
phonestring Email or phone- The lead's phone number, in any format.
first_namestring Optional- The lead's first name.
last_namestring Optional- The lead's last name.
valuenumber Required for Send Sale- The amount, for example
1200.00. Used for booked calls and sales. currencystring Optional- Three letters, for example
USD. order_idstring Required for resold and cross_sold- The order or invoice id, so a repeat or extra sale is never counted twice.
external_idstring Optional- Your system's id for this lead, call or deal. Sending the same id twice is counted once.
occurred_atstring (ISO 8601) Optional- When it happened, within the last two years. Leave it out to use the time it is sent.
testboolean Optionaltruechecks the connection and the match, and saves nothing.sourcestring Optional- A label for where the result came from. The Zapier app sends
zapier.
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"}'{
"ok": true,
"matched": true,
"event_id": "crm_webhook:deal_123:sold",
"duplicate": false
}Reply fields
okboolean Always- The result was read and saved.
matchedboolean Always- It was matched to a lead from your ads.
falsemeans it was kept and listed under results we could not match. event_idstring or null Always- Our id for the saved result.
duplicateboolean Always- The same result was already counted, so it was not counted again.
testboolean Optional- Present and
trueon a test send. errorstring Optional- Present when
okisfalse: 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.
{
"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."
}| Status | When |
|---|---|
400 | The 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. |
401 | The key is wrong or retired, or an optional signature header was sent and does not match. |
404 | No key was sent (or it does not start with vcbo_). |
405 | Any method other than POST (or GET, which returns when the last test and last event arrived). |
413 | The body is over 512 KB, or more than 100 events. |
429 | More than 600 calls a minute with one key. Wait a minute and try again. |
503 | A 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:
{
"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 Gonereply 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.
{
"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"
}idstring Optional- Our id for the lead.
first_name, last_name, email, phone, zipstring Optional- What the lead entered on your ad form or page.
statestring 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_atstring (ISO 8601) Optional- When the lead was created.
sourcestring Optional- How it came in, for example
lead_form. platformstring Optionalmeta,tiktok,googleoropenai.campaign_id, adset_id, ad_idstring Optional- The ad platform's ids for the ad that brought the lead.
event_idstring Optional- Our id for this event. Use it to ignore a repeat.
occurred_atstring (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.
{
"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"
}valuenumber or null Optional- The value set on a booked call.
currencystring 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.
{
"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"
}idstring Optional- A unique id for this alert.
typestring Optional- The kind of alert, for example
no_leads. labelstring Optional- The kind of alert in plain words.
titlestring Optional- The alert's headline.
messagestring Optional- The alert's text. Several lines are joined by line breaks.
linkstring or null Optional- Where to fix it in Run My Ads.
sent_atstring (ISO 8601) Optional- When the alert was sent.
Using Zapier
- In Zapier, pick the Run My Ads app.
- 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.
- 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.
- 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.
- 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.
- 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.
- Test it. GET /api/webhooks/rma/zapier/auth with the key. A 200 with the account name means it works.
- 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.
- 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.