Close Menu
GeekBlog

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    Smartwatch for Epilepsy: Seizure Detection Options in 2026

    October 11, 2026

    Marvel Made a Show About an AI Mind. The Crew Hand Built Every Glitch.

    October 10, 2026

    Garmin Approach S72 Is Here: Titanium, ECG and a $799.99 Price Tag

    October 10, 2026
    Facebook
    GeekBlog
    • Home
    • Mobile
    • Tech News
    • Blog
    • Gaming
    • Smartwatch
    • How-To Guides
    • AI & Software
    Facebook
    GeekBlog
    Home»Blog»How to Create and Manage Facebook Ads Through the API
    Blog

    How to Create and Manage Facebook Ads Through the API

    Ethan CaldwellBy Ethan CaldwellSeptember 4, 202610 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Email Copy Link
    Hand holding a phone showing Facebook and Instagram
    Photo via Pexels
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link

    Creating Facebook ads through the Marketing API means building four objects in order: a campaign, an ad set, an ad creative, and an ad that ties the last two together. Each one is a POST to an edge under your ad account node, and each one fails loudly if a required field is missing. The current release is v26.0, published on July 29, 2026, and every path below is versioned against it.

    Quick answer: POST to /v26.0/act_<AD_ACCOUNT_ID>/campaigns with name, objective, status and special_ad_categories, then to /adsets with a budget, billing_event, optimization_goal and targeting, then to /adcreatives, then to /ads with the ad set ID and creative ID. You need the ads_management permission with Advanced Access, which requires App Review and business verification, and you should create everything with status=PAUSED until you have reviewed it.

    The API is unforgiving in a useful way: it validates the whole object graph server side, so a campaign built correctly through the API behaves identically to one built in Ads Manager. What trips teams up is not the object model, it is the access tiers, the rate limit accounting, and the fact that budgets are expressed in the minor unit of the account currency.

    Access levels, permissions and App Review

    A new app gets Standard Access to the ads permissions, which sounds generous and is not. Standard Access works only against ad accounts and Pages where the person authorizing the token holds a role on your app, or where the asset is owned by your own business. The moment you want to manage a customer’s ad account, you need Advanced Access.

    PermissionWhat it unlocksNeeds App Review
    ads_readReading campaigns, ad sets, ads and insightsYes, for Advanced Access
    ads_managementCreating and editing ad objects, audiences, creativesYes, for Advanced Access
    business_managementReading and managing Business Manager assetsYes
    pages_show_listListing Pages the user administersNo

    Advanced Access to Ads Management also requires business verification of the legal entity behind the app. Budget real time for it. The review itself wants a screen recording that shows a person authorizing your app, the permission dialog, and your product then doing something with the granted data. A slide deck will be rejected.

    For production automation, stop using a personal user token and create a system user inside Business Manager instead. System user tokens issued with Standard Access to the Marketing API do not carry an expiry time, which removes the single most common cause of a pipeline breaking at 3am. The token mechanics are covered in detail in our guide to Facebook API authentication and access tokens.

    The object model

    Four nodes, one hierarchy. The campaign holds the objective and any campaign level budget. The ad set holds the money, the schedule, the audience and the optimization goal. The creative holds the actual content. The ad joins a creative to an ad set.

    Ad Account  act_<AD_ACCOUNT_ID>
     └── Campaign        objective, special_ad_categories, budget optimization
          └── Ad Set     budget, schedule, targeting, optimization_goal, billing_event
               └── Ad    links one ad set to one ad creative
                    └── Ad Creative   page, link, copy, image or video

    The objective values are the outcome based set that replaced the older objective names: OUTCOME_AWARENESS, OUTCOME_TRAFFIC, OUTCOME_ENGAGEMENT, OUTCOME_LEADS, OUTCOME_APP_PROMOTION and OUTCOME_SALES. Pick the one that matches the conversion you actually care about, because it constrains which optimization goals the ad set will accept.

    Creating a campaign, ad set and ad with curl

    Start with the campaign. special_ad_categories is required even when nothing applies, in which case you send an empty array.

    Recommended for you:

    The Updated Google Ads Keyword Planner: What Changed
    Blog·Sep 4, 2026

    The Updated Google Ads Keyword Planner: What Changed

    curl -X POST \
      "https://graph.facebook.com/v26.0/act_<AD_ACCOUNT_ID>/campaigns" \
      -F "name=Fall Traffic Push" \
      -F "objective=OUTCOME_TRAFFIC" \
      -F "status=PAUSED" \
      -F "special_ad_categories=[]" \
      -F "access_token=<YOUR_ACCESS_TOKEN>"

    The response is a JSON object containing the new campaign ID. Feed that into the ad set. Budgets are integers in the minor unit of the account currency, so 2500 on a USD account is twenty five dollars, not twenty five hundred.

    curl -X POST \
      "https://graph.facebook.com/v26.0/act_<AD_ACCOUNT_ID>/adsets" \
      -F "name=US Adults 25 to 54" \
      -F "campaign_id=<CAMPAIGN_ID>" \
      -F "daily_budget=2500" \
      -F "billing_event=IMPRESSIONS" \
      -F "optimization_goal=LINK_CLICKS" \
      -F "bid_strategy=LOWEST_COST_WITHOUT_CAP" \
      -F "targeting={\"geo_locations\":{\"countries\":[\"US\"]},\"age_min\":25,\"age_max\":54}" \
      -F "status=PAUSED" \
      -F "access_token=<YOUR_ACCESS_TOKEN>"

    Then the creative, and finally the ad that references both IDs.

    curl -X POST \
      "https://graph.facebook.com/v26.0/act_<AD_ACCOUNT_ID>/ads" \
      -F "name=Fall Traffic Ad 01" \
      -F "adset_id=<AD_SET_ID>" \
      -F "creative={\"creative_id\":\"<CREATIVE_ID>\"}" \
      -F "status=PAUSED" \
      -F "access_token=<YOUR_ACCESS_TOKEN>"
    Tip: Build everything paused, then flip status to ACTIVE in a separate call once a human or a validation job has looked at it. A bug that creates a live campaign with a mistyped budget spends real money before your next deploy.

    The Business SDK in Python

    Hand rolling requests works, but the Business SDK saves you from string escaping the targeting spec and gives you typed field constants. Install it from PyPI.

    pip install facebook_business
    import os
    from facebook_business.api import FacebookAdsApi
    from facebook_business.adobjects.adaccount import AdAccount
    from facebook_business.adobjects.campaign import Campaign
    
    FacebookAdsApi.init(
        app_id=os.environ["FB_APP_ID"],
        app_secret=os.environ["FB_APP_SECRET"],
        access_token=os.environ["FB_ACCESS_TOKEN"],
        api_version="v26.0",
    )
    
    account = AdAccount("act_" + os.environ["FB_AD_ACCOUNT_ID"])
    
    campaign = account.create_campaign(params={
        Campaign.Field.name: "Fall Traffic Push",
        Campaign.Field.objective: "OUTCOME_TRAFFIC",
        Campaign.Field.status: Campaign.Status.paused,
        Campaign.Field.special_ad_categories: [],
    })
    
    print(campaign["id"])

    Keep the app secret and the token in environment variables or a secret manager. Never commit them, and never ship an app secret inside a mobile binary. If your product also has a mobile client, the split between what belongs on the device and what belongs on your server is spelled out in our walkthrough of using the Facebook SDKs in mobile app development.

    Rate limits and how to read the headers

    Marketing API throttling is scored per ad account. A read call costs one point and a write call costs three. Meta documents a maximum score of 60 on the development tier and 9000 on the standard tier, with a decay window of 300 seconds. The standard tier also blocks for only 60 seconds when you cross the line, which is the practical reason to care about upgrading. A separate limit of 100 queries per second applies to mutations on campaigns, ad sets and ads.

    Two response headers tell you where you stand. X-Ad-Account-Usage carries acc_id_util_pct, reset_time_duration and ads_api_access_tier. X-Business-Use-Case-Usage carries call_count, total_cputime, total_time and estimated_time_to_regain_access.

    curl -sD - -o /dev/null \
      "https://graph.facebook.com/v26.0/act_<AD_ACCOUNT_ID>/campaigns?fields=name,status&access_token=<YOUR_ACCESS_TOKEN>" \
      | grep -i "usage"
    Warning: Do not treat a throttling error as a transient failure to retry immediately. Read estimated_time_to_regain_access and back off for at least that long. Tight retry loops are the fastest way to keep an account blocked for the rest of the hour.

    Pulling insights without melting your quota

    Reporting lives on an /insights edge that hangs off the ad account, campaign, ad set or ad node. Small queries can run synchronously.

    curl -G \
      "https://graph.facebook.com/v26.0/act_<AD_ACCOUNT_ID>/insights" \
      -d "level=campaign" \
      -d "fields=campaign_name,impressions,clicks,spend,cpm,ctr" \
      -d "date_preset=last_7d" \
      -d "access_token=<YOUR_ACCESS_TOKEN>"

    Anything large should go asynchronous. POST to the same edge, keep the returned report_run_id, poll that node until async_status reads Job Completed and async_percent_completion reaches 100, then read the results from /<REPORT_RUN_ID>/insights. Meta notes that an asynchronous request can take up to an hour including retries, and that the run ID expires after 30 days.

    curl -X POST \
      "https://graph.facebook.com/v26.0/act_<AD_ACCOUNT_ID>/insights" \
      -F "level=ad" \
      -F "fields=ad_name,impressions,spend,actions" \
      -F "time_range={\"since\":\"2026-08-01\",\"until\":\"2026-08-31\"}" \
      -F "breakdowns=publisher_platform" \
      -F "access_token=<YOUR_ACCESS_TOKEN>"

    Spread report jobs through the day instead of firing them all at midnight, filter down to the objects you care about, and split long date ranges into chunks. The same reporting fields are what you would see in the interface, and our piece on retrieving insights and analytics data maps the API names to the columns marketers recognize.

    Troubleshooting

    Error 200 with a permissions message. The token holder does not have the right role on the ad account, or your app is still on Standard Access and the account is not one you own. Check both before you assume the permission itself is missing.

    Invalid parameter on adset creation. Nine times out of ten the targeting spec is a string that was not valid JSON after shell escaping, or the optimization goal is not compatible with the campaign objective. Post the targeting spec through a file with -F "targeting=<spec.json" to sidestep quoting problems.

    Budget rejected as below the minimum. Minimums are enforced per currency and per billing event. Remember the value is in minor units, so a daily budget of 100 is one dollar and will be refused.

    Insights returns fewer rows than Ads Manager. The default attribution setting and the default time zone are account level properties. Set action_attribution_windows explicitly and confirm the account time zone before you accuse the API of losing data.

    A version error appears after a quiet weekend. A version you pinned reached its expiration date and calls now resolve against a newer default. Read the Graph API changelog and move the pin deliberately rather than dropping the version segment from the URL.

    Recommended for you:

    How to Declare a Float Variable in C++ (2026 Guide)
    Blog·Sep 4, 2026

    How to Declare a Float Variable in C++ (2026 Guide)

    Frequently asked questions

    Can I use the Marketing API without App Review?

    Yes, in a limited way. Standard Access lets you manage ad accounts owned by your own business and accounts where the authorizing person holds a role on your app. That is enough to build and test. Managing a client’s account in production requires Advanced Access and business verification.

    Which token type should a scheduled job use?

    A system user token issued from Business Manager. User tokens expire and get invalidated when the person changes their password or revokes the app. System user tokens with Standard Access to the Marketing API carry no expiry time, which is what a nightly sync needs.

    How do I upload an image for a creative?

    POST the file to the /act_<AD_ACCOUNT_ID>/adimages edge first. The response returns a hash, and you reference that hash in the creative’s object story spec. Videos follow the same pattern through the /advideos edge and need a moment to finish processing.

    What is the difference between a campaign objective and an optimization goal?

    The objective sits on the campaign and describes the business outcome. The optimization goal sits on the ad set and tells delivery which event to chase. The API only accepts combinations that make sense, so an objective mistake surfaces as an ad set validation error.

    Should I build in the API or in Ads Manager?

    Use the interface for one off campaigns and creative experiments. Use the API when you are generating campaigns from a product feed, syncing budgets from a finance system, or managing more accounts than a person can click through. Our guide to setting up a Facebook ad campaign covers the manual path.

    The bottom line

    The Marketing API is a straightforward CRUD surface once you accept its two rules: build objects from the top down, and treat the ad account as the unit that gets rate limited. Pin your calls to v26.0, create everything paused, and read the usage headers on every response so your backoff logic has real numbers to work with.

    The work that actually takes time is upstream of the code. Get Advanced Access and business verification started early, move automation onto a system user token, and put your app secret somewhere a repository scan will never find it. Do that and the rest is just JSON.

    About this article: GeekBlog covers U.S. technology news, AI, phones, smartwatches and gaming. Every story is written and checked under our Editorial Policy. Spotted a mistake or have a story tip? Contact our editors.

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Telegram Email Copy Link
    Previous ArticleHow to Create and Manage a TikTok Challenge
    Next Article Connecticut or Indiana: Which Is Better to Visit?
    Ethan Caldwell

      Ethan Caldwell is GeekBlog's resident Apple specialist, covering the entire Apple ecosystem: iPhone, iPad, Mac, Apple Watch, AirPods and the software that ties them together. A longtime iOS user and gadget collector, Ethan tracks Cupertino's every move, breaking down Apple keynotes, A- and M-series chip benchmarks, iOS feature updates and the rumor mill into clear, practical takes that help readers decide whether the latest Apple hardware is worth the upgrade.

      Related Posts

      10 Mins Read

      Google Ads Keyword Planner: How It Shows the Most Relevant Keywords

      11 Mins Read

      How to Use Remarketing Techniques for Better Conversions

      11 Mins Read

      How to Conduct A/B Testing for Marketing Campaigns

      10 Mins Read

      AMP for WP Plugin Vulnerability: What Was Fixed and What to Do

      11 Mins Read

      How to Create a Facebook Business Page in 2026

      11 Mins Read

      How to Convert GMT Time to Other Time Zones in C++

      Top Posts

      Every iPhone Camera Ranked in 2026 (Best to Worst)

      July 6, 2026242 Views

      Best Stores for Buying MP3 and Digital Music You Can Keep Forever (2026)

      August 2, 2025158 Views

      Windows 11 vs Windows 10: Should You Upgrade in 2026?

      July 7, 2026105 Views
      Stay In Touch
      • Facebook

      Subscribe to Updates

      Get the latest tech news from FooBar about tech, design and biz.

      Most Popular

      iPhone Battery Replacement Cost: Every Model, Apple vs Repair Shop

      October 6, 202664 Views

      Best Offline Music App in 2026: Free and Paid Picks

      October 7, 202651 Views

      One UI 9 Watch Beta Now Covers Three Galaxy Watch Generations: What You Get and How to Join

      October 4, 202651 Views
      Our Picks

      Smartwatch for Epilepsy: Seizure Detection Options in 2026

      October 11, 2026

      Marvel Made a Show About an AI Mind. The Crew Hand Built Every Glitch.

      October 10, 2026

      Garmin Approach S72 Is Here: Titanium, ECG and a $799.99 Price Tag

      October 10, 2026

      Subscribe to Updates

      Get the latest creative news from FooBar about art, design and business.

      HEICJPG.online - Convert HEIC to JPG online
      Facebook
      • About Us
      • Contact us
      • Privacy Policy
      • Disclaimer
      • Terms and Conditions
      • Editorial Policy
      • Cookie Policy
      • Your Privacy Choices
      © 2026 GeekBlog

      Type above and press Enter to search. Press Esc to cancel.