Ad .create
Add one Ad to a Campaign; it shows once its review passes.
- Action class
publish- Approval
- Publishes on its own
- Emits
Ad.created- Sites
- 9 sites
- Price
- Free
POST https: //api.sb/ {your-domain}/ ads/ create
Builds one ad in a Campaign on your connected ad account; it runs once the site’s review passes. This Verb is a sketch on the hub’s Ad Noun.
Inputs
| Name | Type | Default | Meaning |
|---|---|---|---|
campaign | Campaign | Required | The Campaign it runs in, sharing its budget and window, as on the hub’s Ad. |
format | 'search' | 'display' | 'image' | 'video' | Required | One of the hub’s Ad formats. The per-account table under Effects lists the formats each account takes. |
headline | string | Required | The headline. The per-account table under Effects lists each account’s character limit. |
body | string | null | The text above or beside the media. Unset: the headline stands alone. |
media | File[] | [] | The image or video Files. An image or video Ad needs one. |
landingUrl | string | Required | The page a click lands on. The platform adds utm_ tags, so each signup credits this Ad. |
cta | string | 'learn-more' | The button, such as learn-more, sign-up or book-now, mapped to the nearest button each ad account offers. |
offer | Offer | null | The offer it sells, as on the hub’s Ad. |
variant | string | null | The angle it tests, so the readout compares Ads by angle. |
Outputs
| Field | Type | What null means |
|---|---|---|
ad | Ad | Never null. |
ad.state | string | Never null: inReview until the ad network’s review ends, then live or rejected. |
ad.format | string | Never null: the format sent. |
ad.spend | money, in USD | Null until the ad account reports a first day of spend. |
ad.outside | json | Null in try mode and until the ad account returns its own id for the Ad. |
Effects
- Action class
publish: an approval rule onpublishcan make it wait for your OK- Modes
try: Checks the words and media against the ad specs of the account and the landing page’s status, and returns the Ad as it would be submitted; nothing is submitted.send: Returns a pending Action;Ad.createdfires when the ad account holds the Ad, andAd.updatedwhen its review ends.do: Waits until the ad account holds the Ad and returns itinReview.
- Idempotency
Only with a key: the same
Idempotency-Keyand input return the first Action, and the same key with other input returns409. A repeat with the same key never submits a second Ad.- Saved or shared
The Ad is saved with its id on the ad account and, as the account reports it, its spend. A rejected Ad keeps the review’s reason.
- Emits
Ad.createdwith{ ad,campaign, venue, format, state } - Performed by
- Price
Free on your own account: the platform charges nothing for the call.
- Standing approval
It goes out on its own, inside the Limits of your standing approval: a
Mandategranted withMandate.authorize. One approval rule makes it wait for your OK.
On each Venue
| Site | Fields | Formats |
|---|---|---|
| Google Search and Google Display and YouTube | paign.objective, paign.budget, headline, body, landingUrl | 2 |
paign.objective, paign.budget, body, headline, landingUrl | 3 | |
| Facebook and Instagram | paign.objective, paign.budget, body, headline, landingUrl | 5 |
| Bing | paign.objective, paign.budget, headline, body, landingUrl, path | 1 |
paign.objective, paign.budget, headline, landingUrl, callToAction, media | 3 | |
| TikTok | paign.objective, paign.budget, media, callToAction, landingUrl | 2 |
Google Search and Google Display and YouTube
Through Google Ads.
| Our field | Google Ads’s field |
|---|---|
Campaign.objective | campaign.advertising_channel_type (With a conversion goal; leads runs a SEARCH campaign bidding toward your signup conversion) |
Campaign.budget | campaign_budget.amount_micros (A daily amount in millionths: $40 is 40000000) |
Ad.headline | ad_group_ad.ad.responsive_search_ad.headlines (3 to 15, each 30 characters) |
Ad.body | ad_group_ad.ad.responsive_search_ad.descriptions (2 to 4, each 90 characters) |
Ad.landingUrl | ad_group_ad.ad.final_urls |
- Ad review. Google reviews every ad; a disapproval comes back as
venue-rejectedwith the policy it names.
Through LinkedIn Ads.
| Our field | LinkedIn Ads’s field |
|---|---|
Campaign.objective | adCampaign.objectiveType (leads is LEAD_GENERATION with LinkedIn’s lead form, traffic WEBSITE_VISIT, conversions WEBSITE_CONVERSION) |
Campaign.budget | adCampaign.dailyBudget or adCampaign.totalBudget ({ amount,, the amount as a decimal string; a lifetime budget runs on lifetime pacing, which LinkedIn recommends) |
Ad.body | post commentary (The creative references a post; 3,000 characters, 150 show before it truncates) |
Ad.headline | post content.article.title (200 characters; 70 show before it truncates) |
Ad.landingUrl | post content.article.source, |
- Ad review. LinkedIn reviews every ad; a rejection comes back as
venue-rejectedwith the reason.
Facebook and Instagram
Through Meta Ads.
| Our field | Meta Ads’s field |
|---|---|
Campaign.objective | campaign.objective (leads is OUTCOME_LEADS, traffic OUTCOME_TRAFFIC, conversions OUTCOME_SALES) |
Campaign.budget | adset.daily_budget or adset.lifetime_budget (In the account currency’s smallest unit: $40.00 is 4000) |
Ad.body | object_story_spec.link_data.message (The primary text) |
Ad.headline | object_story_spec.link_data.name |
Ad.landingUrl | object_story_spec.link_data.link |
- Ad review. Meta reviews every new ad before it runs; a disapproval comes back as
venue-rejectedwith Meta’s reason.
Bing
Through Microsoft Ads.
| Our field | Microsoft Ads’s field |
|---|---|
Campaign.objective | campaign goal (Set in Microsoft Ads’ own screens; leads bids toward the signup conversion the import brings over) |
Campaign.budget | campaign daily budget |
Ad.headline | responsive search ad headlines (Up to 15, each 30 characters) |
Ad.body | responsive search ad descriptions (Up to 4, each 90 characters) |
Ad.landingUrl | final URL |
Ad.path | display URL path 1 and path 2 (15 characters each, shown after your domain) |
- Ads per ad group. Three enabled responsive search ads; a fourth waits until one is paused.
- Ad review. Microsoft reviews every ad; a disapproval comes back as
venue-rejectedwith the reason.
Through Reddit Ads.
| Our field | Reddit Ads’s field |
|---|---|
Campaign.objective | campaign objective (Picked in Ads Manager: traffic sends readers to your page; leads bids toward your signup event) |
Campaign.budget | ad group budget |
Ad.headline | post title (A promoted post keeps the title it earned replies under) |
Ad.landingUrl | destination URL |
Ad.callToAction | call to action button (Such as Learn More or Sign Up) |
Ad.media | the promoted post’s image or video (As posted; a new image means a new post) |
- Ad review. Reddit reviews every ad; a rejection comes back as
venue-rejectedwith the reason. - Comments on a promoted post. Stay open; each one reaches you as a Message, and your agent drafts the answer.
TikTok
Through TikTok Ads.
| Our field | TikTok Ads’s field |
|---|---|
Campaign.objective | campaign objective_type (traffic is TRAFFIC; leads is LEAD_GENERATION with TikTok’s instant form; conversions is WEB_CONVERSIONS on your pixel) |
Campaign.budget | adgroup budget with budget_mode BUDGET_MODE_DAY (Over $20; the campaign budget stays unset unless you ask, and then it is over $50) |
Ad.media | ad tiktok_item_id (A Spark Ad: your own post, authorized for the ad, keeping its likes and comments) |
Ad.callToAction | ad call_to_action (Such as LEARN_MORE or SIGN_UP) |
Ad.landingUrl | ad landing_page_url |
- Spark Ads. Promote a post already on your TikTok account, with its likes and comments kept.
- Ad review. TikTok reviews every ad; a rejection comes back as
venue-rejectedwith the reason.
What try does
| Account | What try does |
|---|---|
| Google Ads | Sends every change with validate_only set: Google Ads checks the whole build and returns any error, and creates nothing. |
| LinkedIn Ads | Reads your ad account, the matched count of each audience and the targeting facets, and checks the campaign against LinkedIn’s budget minimums; LinkedIn has no validate-only call, so nothing is sent to it and nothing is created. |
| Meta Ads | Sends the whole build with Meta’s validate_only execution option: Meta runs every check and creates nothing, and the response names any field it would reject. |
| Microsoft Ads | Returns what the import would bring over, term by term with the budget it would set, and the steps the browser agent would take; no session opens and nothing changes. |
| Reddit Ads | Returns the campaign and the promoted post as Ads Manager will hold them, with the steps the browser agent would take; no session opens and nothing is created. |
| TikTok Ads | Returns the Spark Ad and its ad group as Ads Manager will hold them, checked against TikTok’s budget floors, with the steps the browser agent would take; nothing is created. |
Refuses when
| Check | Error | Fix | Then call |
|---|---|---|---|
| A landing page fails its status or Price check | landing | Fix what the reason names, then turn the Play back on. | Campaign.update |
Every call through an account can also meet the shared account refusals: grant-missing, needs-reauth, account-not-connected, over-mandate, quota-reached, venue-rejected.
The landing payload
{
"type": "https://startupbuilder.dev/errors/landing" ,
"title": "Landing",
"status": 422,
"detail": "A landing Page fails its status or Price check.",
"fix": "Fix what the reason names, then turn the Play back on." ,
"next": {
"verb": "Campaign.update",
"input": {}
},
"instance": "https://api.sb/leaseline.app/actions/action_1"
}When it waits
| Fact | Value |
|---|---|
send returns | A pending Action until the ad account holds the Ad; the review outcome arrives later as Ad.updated. |
| Delivered by | Ad.created |
Example
Add the third ad to the LinkedIn test: the renewal-notice angle, with
the checklist image.To retry, send the same Idempotency-Key: the retry returns the first answer for $0. A new key reads again.
Test values
A sk_test_ key answers these the same way every time, at $0 (every test value).
| Test value | Always returns | What it is for |
|---|---|---|
headline: | Refuses with venue-rejected | The test ad account rejects it at review with the reason Misleading claims, passed through in detail, so your agent’s rewrite path runs. |
maxCost: | Refuses with max-cost | Any priced call with a maxCost of 0.0001 is refused before it spends: the price is above the cap. |
rate-limited.test | Refuses with rate-limited | Any call naming this hostname answers 429 with Retry-After, so your retry logic runs. |
sources-busy.test | Refuses with sources-busy | Any call naming this hostname answers 503 as if every route were busy, and nothing is spent. |
Used by
- Integrations: Google Ads · LinkedIn Ads · Meta Ads · Microsoft Ads · Reddit Ads · TikTok Ads