REST API reference
Base URL https://lazyads.ai/api/v1. Every request requires Authorization: Bearer <api_key> and a Growth, Scale, or Enterprise plan; BYOA and Starter keys use the MCP server instead. Download the machine-readable spec from openapi.json (OpenAPI 3.1, importable into Postman, Insomnia, or any generator).
curl https://lazyads.ai/api/v1/campaigns?status=active&limit=20 \
-H "Authorization: Bearer la_your_api_key"Conventions
- JSON in, JSON out. Successful responses wrap the payload in
data; list endpoints addpagination(limit,offset,has_moreor anext_cursor). - Response fields are
snake_case; request bodies use the samecamelCasenames as the dashboard and MCP tools (for exampledailyBudgetUsd,platformCampaignId). - Writes propagate to the live ad platform (pause, resume, budgets, bids, targeting, keywords) and are recorded in your Activity Log with the
APIactor. - Optional key scopes are listed per group below. Agencies pass
X-LazyAds-Client: <client user id>to act inside a client workspace; viewer members are read-only. - Rate limits: Growth 100, Scale 500, Enterprise 1000 requests per minute per key, with
X-RateLimit-*headers on every response.
Campaigns
scope:campaigns/campaignsList campaigns/campaignsCreate a draft campaign/campaigns/{id}Get a campaign/campaigns/{id}Update campaign name or end date/campaigns/{id}/pausePause a campaign/campaigns/{id}/resumeResume a campaign/campaigns/{id}/budgetSet a campaign daily budget/campaigns/{id}/automationToggle Tracking and Management on a campaignAI campaign builds
scope:campaigns/campaigns/buildStart an AI campaign buildAI plan/campaigns/build/{taskId}Poll an AI campaign buildAI planImport live campaigns
scope:campaigns/campaigns/importableList live campaigns you can import/campaigns/importImport live campaigns into Lazy AdsAd sets and ads
scope:campaigns/ad-sets/{id}/pausePause an ad set/ad-sets/{id}/resumeResume an ad set/ad-sets/{id}/budgetSet an ad set daily budget/ad-sets/{id}/bidSet a manual ad-set bid (LinkedIn, TikTok, ChatGPT, Snapchat)/ad-sets/{id}/targetingUpdate ad set targeting/ad-sets/{id}/keywordsAdd search keywords/ads/{id}/pausePause an ad/ads/{id}/resumeResume an adPerformance, creatives, and activity
scope:performance · creatives · campaigns/performanceGet performance metrics/creativesList creatives/activityList user activityCompetitors
scope:competitors/competitorsList tracked competitors/competitorsAdd a competitor/competitors/adsSearch competitor ads (Meta Ad Library)AI planAccount, AI chat, and conversions
scope:connections · notifications · chat · performance/connectionsList platform connections/connectionsConnect ChatGPT/notificationsList recent notifications/chatChat with the LazyAds AI assistantAI plan/eventsIngest first-party conversion eventsWebhook subscriptions (REST Hooks)
scope:webhooks/webhooksList webhook subscriptions/webhooksSubscribe to webhook events (REST Hook)/webhooksUnsubscribe by id or url/webhooks/{id}Unsubscribe a webhook by id/webhooks/eventsList webhook event types with sample payloadsStart and poll an AI campaign build
POST /campaigns/build accepts the same fields as the dashboard builder and MCP build_ai_campaign. Omit platforms to default to Meta. Poll GET /campaigns/build/{taskId} until status is completed or failed; the campaign lands in review (paused) on the platform.
curl -X POST https://lazyads.ai/api/v1/campaigns/build \
-H "Authorization: Bearer la_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"platforms": ["meta", "tiktok"],
"dailyBudgetUsd": 40,
"objectiveOverride": "OUTCOME_SALES",
"creativeMix": "existing",
"skipCompetitorAnalysis": false,
"confirmNotPolitical": true,
"preferredCreativeIds": ["cr_..."],
"customInstructions": "Avoid medical claims"
}'
# → 201 { "data": { "task_id": "...", "campaign_id": "...", "builds": [...] } }
curl "https://lazyads.ai/api/v1/campaigns/build/TASK_ID?campaignId=CAMPAIGN_ID" \
-H "Authorization: Bearer la_your_api_key"
# → { "data": { "status": "running", "output": { "steps": [...] } } }creativeMix is ai_decide (default), images_only, videos_only, images_and_videos, or existing (reuse the library, no new generation). Other optional fields: preferredPagePostId, socialContentIds, referenceCreativeIds. Live creative performance is on GET /creatives as lifetime_roas, lifetime_spend, and related fields.
Import campaigns you already run
List what is live on each connected account, then link the ones you want. A worker pulls structure and daily stats; trackingEnabled feeds the dashboard and AI analysis, aiManaged lets the optimizer edit (both default per plan and stay off on BYOA).
curl "https://lazyads.ai/api/v1/campaigns/importable?platform=google,meta" \
-H "Authorization: Bearer la_your_api_key"
curl -X POST https://lazyads.ai/api/v1/campaigns/import \
-H "Authorization: Bearer la_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "campaigns": [ { "platform": "google", "platformCampaignId": "123456", "trackingEnabled": true } ] }'Send server-side conversions
POST /events takes a batch of up to 100 events. Reuse the browser pixel's eventId so Meta CAPI deduplicates; set googleConversionActionId to also forward Google Enhanced Conversions. User fields are hashed before forwarding.
curl -X POST https://lazyads.ai/api/v1/events \
-H "Authorization: Bearer la_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"events": [{
"eventName": "Purchase",
"eventId": "order_8841",
"value": 129.00,
"currency": "USD",
"orderId": "8841",
"fbclid": "IwAR...",
"user": { "email": "buyer@example.com" }
}]
}'Errors
Errors return a JSON body with a stable code and the HTTP status:
{
"error": {
"message": "The REST API requires the Growth plan or above. Your API key still works with the Lazy Ads MCP server at https://mcp.lazyads.ai/mcp.",
"code": "PLAN_INSUFFICIENT",
"status": 403
}
}MISSING_AUTH / INVALID_AUTH_FORMAT / INVALID_KEY401 — send Authorization: Bearer la_… with an active keyPLAN_INSUFFICIENT403 — REST needs Growth+; AI endpoints need Starter+ AI accessPERMISSION_DENIED403 — the key was scoped and lacks this endpoint’s scopeCLIENT_ACCESS_DENIED / VIEWER_READ_ONLY403 — agency header without an active grant, or viewer attempted a writeRATE_LIMIT_EXCEEDED429 — wait for Retry-After secondsINVALID_BODY / INVALID_INPUT400 — the first Zod issue is returned in messageNOT_FOUND404 — the resource is not owned by this accountSame actions from your agent
Every write above is also an MCP tool (for example pause_resume_campaign, set_ad_set_budget, import_platform_campaign, build_ai_campaign). If your automation lives in Claude, Cursor, Codex, or Hermes, the MCP server is the shorter path and works on every paid plan.