Meta Ads Integration¶
The buyer agent integrates with the Meta Marketing API to book and report on social channel campaigns across Facebook and Instagram. This page covers authentication setup, the booking flow, and reporting endpoints.
The buyer agent calls graph.facebook.com directly using a system user access token. This is the same endpoint used by the official Meta Marketing API SDKs — no browser OAuth is required.
Configuration¶
| Variable | Type | Default | Description |
|---|---|---|---|
META_ACCESS_TOKEN |
str |
"" |
System user access token from Meta Business Manager |
META_AD_ACCOUNT_ID |
str |
"" |
Ad account ID — format act_XXXXXXXXX |
META_PAGE_ID |
str |
"" |
Facebook Page ID — required for ad creative creation |
META_API_VERSION |
str |
v21.0 |
Meta Graph API version |
Add these to your .env file:
META_ACCESS_TOKEN=your-system-user-token
META_AD_ACCOUNT_ID=act_XXXXXXXXX
META_PAGE_ID=XXXXXXXXX
META_API_VERSION=v21.0
Generating a System User Token¶
- Open Meta Business Manager → Business Settings → System Users
- Create or select a system user
- Click Generate Token → select your app
- Required scopes:
ads_management,ads_read,business_management - Assign the system user to your ad account: Business Settings → System Users → Add Assets → Ad Accounts
Installation¶
Sandbox accounts
Meta provides sandbox ad accounts for development. Campaigns created in a sandbox account are API-only and not visible in the Ads Manager UI. They are created in PAUSED state and never serve impressions.
Booking Flow¶
When a booking brief includes "channels": ["social"] or "channels": ["meta"], the buyer agent routes through the Meta booking path.
sequenceDiagram
participant Buyer as Buyer Agent
participant Meta as graph.facebook.com
Buyer->>Meta: GET /{account}/reachestimate
Meta-->>Buyer: Reach + CPM estimates
Note over Buyer: Awaiting approval
loop Per placement (Instagram Reels, Facebook Feed, etc.)
Buyer->>Meta: POST /act_{id}/campaigns
Meta-->>Buyer: campaign_id (PAUSED)
Buyer->>Meta: POST /act_{id}/adsets
Meta-->>Buyer: ad_set_id (PAUSED)
end
Research Phase¶
The SocialCrew uses MetaInventoryTool to call GET /{account}/reachestimate and estimate reach and CPM for four placements:
- Instagram Reels
- Facebook Video Feeds
- Instagram Feed
- Facebook Feed
If the reach estimate API returns an error, the tool falls back to static estimates.
Booking Phase¶
After the user approves recommendations, the buyer agent creates two resources per placement:
| Step | API Call | Status |
|---|---|---|
| 1 | POST /act_{id}/campaigns |
PAUSED |
| 2 | POST /act_{id}/adsets |
PAUSED |
Creative step
Ad creative creation (step 3) requires an uploaded image asset. This step is skipped — campaign and ad set creation is sufficient to confirm booking.
Objective Mapping¶
| IAB Objective | Meta Objective |
|---|---|
brand_awareness, reach |
OUTCOME_AWARENESS |
traffic |
OUTCOME_TRAFFIC |
conversions |
OUTCOME_SALES |
video_views |
OUTCOME_ENGAGEMENT |
lead_generation |
OUTCOME_LEADS |
Budget Allocation¶
The PortfolioCrew LLM allocates budget across channels based on campaign objectives, audience fit, and KPIs. If channels is specified in the brief, the LLM is instructed to allocate only to those channels:
The LLM will distribute the $15,000 across branding, ctv, and social based on which best fits the campaign objectives.
Example Booking Request¶
{
"brief": {
"name": "Summer Campaign 2026",
"objectives": ["brand_awareness", "reach"],
"budget": 5000,
"start_date": "2026-06-01",
"end_date": "2026-06-30",
"channels": ["social"],
"target_audience": {
"demographics": {"age": "18-45"},
"interests": ["technology", "gaming"]
}
},
"auto_approve": false
}
Poll GET /bookings/{job_id} until status: awaiting_approval, then approve:
Booked lines for the social channel will have booking_status: "paused".
Reporting¶
List Campaigns¶
Returns all campaigns in the ad account — no booking job ID required.
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
int |
10 |
Number of campaigns to return |
{
"ad_account_id": "act_XXXXXXXXX",
"campaigns": [
{
"id": "23856xxxxxxxxx",
"name": "Summer Campaign 2026 — Instagram Reels",
"effective_status": "PAUSED",
"objective": "OUTCOME_AWARENESS",
"daily_budget": "125000",
"created_time": "2026-05-11T15:35:59+0530"
}
],
"count": 10
}
Campaign Report¶
Returns campaign details combined with delivery insights for one or more campaign IDs.
| Parameter | Type | Default | Description |
|---|---|---|---|
campaign_ids |
string |
required | Comma-separated Meta campaign IDs |
date_preset |
string |
last_30d |
last_7d / last_14d / last_30d / last_90d |
{
"ad_account_id": "act_XXXXXXXXX",
"date_preset": "last_30d",
"campaigns": [
{
"campaign_id": "23856xxxxxxxxx",
"campaign_name": "Summer Campaign 2026 — Instagram Reels",
"status": "PAUSED",
"objective": "OUTCOME_AWARENESS",
"daily_budget": "125000",
"created_time": "2026-05-11T15:35:59+0530",
"spend": 0.0,
"impressions": 0,
"reach": 0,
"frequency": 0.0,
"clicks": 0,
"ctr": 0.0,
"cpm": 0.0
}
],
"summary": {
"total_spend": 0.0,
"total_impressions": 0,
"total_clicks": 0,
"total_reach": 0
}
}
Job-Scoped Report¶
To report on all campaigns booked within a specific job:
The buyer agent automatically identifies Meta campaign IDs from booked_lines and pulls insights for each. IAB OpenDirect order IDs in the same job are routed to the seller agent's delivery performance endpoint. See Bookings API for details.
Access token security
The Meta access token is never exposed in API error responses. It is automatically redacted to *** before any error message reaches the HTTP response.
Related¶
- Seller Agent Integration --- How buyer and seller agents communicate
- Bookings API --- Full booking flow reference
- Configuration Reference --- All environment variables