This page describes the reviewed public contracts. Availability depends on the deployed Bily version, workspace connection, advertiser permissions, and exact campaign profile. A documented schema or a connected social account does not establish that every campaign type has passed a live advertiser test. Check the current support response and MCP catalog before constructing a write.
Confirm the workspace and advertiser
- Call
GET /contextand select the exact workspace URL. - Read
GET /platform/{resourceUrl}/supportand the selected account’s assets. Use an advertiser account, rather than a Google manager account, for campaign creation. - Read
GET /platform/{resourceUrl}/action-jobs/capabilitiesfor the action IDs that can be saved in a draft. In MCP, search for the exact intent and inspect its current input schema, preconditions, and verification steps. - Complete the required platform permissions, billing, Page or identity access, and any product-account links before saving a launch draft.
sourceAuthority, supply both dataSourceAdAccountId and dataSourceConnectorId; an account name alone is insufficient.
Save and review an immutable draft
CallPOST /platform/{resourceUrl}/action-drafts, or bily.actions.saveAdDraft(...), with a stable idempotencyKey, supported capabilityId values, and the exact action bodies. A draft contains 1–100 actions and expires after seven days while unpublished.
For example, after confirming that update-asset is available for this Meta campaign, an MCP execution can save a pause for review:
GET /platform/{resourceUrl}/action-drafts/{jobId} or bily.actions.readAdDraft({ storeUrl, draftId }). Review the actual action bodies as well as their display summaries: advertiser, target IDs, children, copy, destination, budget, and any warnings. Review labels do not authorize or validate the underlying action.
Keep the returned draft id. If a save response is lost or save confirmation fails, retry the identical save with its original key and body to recover the same staged draft. Do not create a new key to work around an uncertain save. Saving is separate from publication.
Publish selected drafts together
For one reviewed draft, callPOST /platform/{resourceUrl}/action-jobs/{jobId}/start or bily.actions.publishAdDraft({ storeUrl, draftId }).
For several drafts:
- Select 2–100 distinct, unpublished draft IDs from the same user and workspace.
- Call
POST /platform/{resourceUrl}/action-drafts/batch, orbily.actions.prepareAdDraftBatch({ storeUrl, draftIds, idempotencyKey }). - Read and approve the returned batch draft, including every source draft and warning.
- Publish the batch’s returned
idthrough the same explicitstartoperation.
GET /platform/{resourceUrl}/action-drafts or listAdDrafts. Follow every opaque cursor until it is null, and deduplicate by draft id. A bounded first page is not a complete history; large legacy histories can require Load more. Do not edit, decode, or reuse a cursor in another workspace or identity.
Review a native budget before changing it
Meta campaign/ad-set budgets and Google campaign budgets require a fresh native budget review. Both increases and decreases follow the same guard contract.- Call
POST /platform/{resourceUrl}/actions/read-asset-budgetorbily.actions.readAssetBudget(...)with the selected advertiser, exactsourceAuthority, andpayload: { version: 1, assetType, assetId }. Meta ad sets also requireparentAssetId; Google selects a campaign. - Inspect
result.canEdit. If it isfalse, showresult.reasonand resolve it before constructing an action. For an inherited Meta budget, select its owning campaign. - Show the current amount, currency, daily/lifetime cadence, native owner, and complete affected scope. Google shared budgets require review of every
affectedCampaignIdsentry. - Approve an absolute target amount in the account currency.
amountUnitsuses exact integer strings; divide byunitsPerCurrencyfor display. Do not assume cents or change a percentage without first resolving its absolute target. - Copy the returned
budgetGuardunchanged into anupdate-assetdraft. Put onlybudgetandbudgetTypeinupdates; do not combine a budget change with a rename or status change. - For Meta, omit top-level
sourceAuthority: the returned guard contains its exact source. For Google, also supply the exact top-levelsourceAuthoritypair. The URL suppliesresourceUrl; do not add it to the action body. - Review and publish the draft. Bily rereads the owner before dispatch and verifies the live amount afterward. A changed baseline requires a new review and draft.
Verify every action and recover safely
After publication, pollGET /platform/{resourceUrl}/action-jobs/{jobId} or bily.actions.getAdActionJob({ storeUrl, jobId }). Retain the same job ID if a client execution times out or the browser closes. A 202, queued, or running response does not establish completion.
BUDGET_REVIEW_REQUIRED needs a new live quote. BUDGET_OWNER_BUSY needs the existing owner’s job reconciled. BUDGET_UPDATE_REJECTED needs corrected native requirements and a new review. BUDGET_VERIFY_REQUIRED must be reconciled without replay. BUDGET_JOB_STEP_LIMIT requires splitting the reviewed job into fewer actions.
Dismissal removes a saved change from the review list. It does not reverse an accepted platform change or stop already dispatched work. Keep request IDs and job IDs for support; avoid logging complete creative bodies or transport URLs.
Generate or upload creative before a launch
A saved image in Bily’s creative library is separate from a published ad. Generating or uploading it does not activate a campaign. For generation, select a completed creative analysis, refresh the workspace’s brand context and current offers, and callPOST /creative-intelligence/{storeUrl}/generate or bily.creative.generateStatic(...). Use a stable key and the reviewed aspect ratio. Poll the returned generation ID until status is ready; only then use its authenticated mediaUrl. A website uses its eligible brand context; a Shopify product reference must belong to the selected store.
For a local file, reserve an upload with its exact name, content type, and byte length, transfer its bytes to the returned customer upload URL using an authenticated write-capable Bily API connection, then read/finalize the upload. An OAuth MCP connection alone does not authenticate the byte-transfer endpoint. Supported formats are JPEG, PNG, WebP, MP4, MOV, and WebM, bounded at 15 MiB per image or 95 MiB per video. Bily validates the actual media. A ready upload can still need its analysis scheduled or retried.
Respect each record’s retention or pinned state. A library item does not prove that the target advertiser has a matching native image, authorized identity, or supported ad format. Stage any required platform image upload, publish and verify it, then select the resulting native asset in the launch draft.
Check the supported campaign profile
The following boundaries describe the reviewed contracts. Query the deployed catalog and support response for availability in your workspace. Connected-platform permissions, native account eligibility, and live verification are required in addition to a valid input schema.
New fixed-profile builders create paused native resources. Some older low-level shell routes accept explicit active status; do not use them to bypass a launch review. Configured active status is also distinct from effective delivery. On platforms where archival maps to native removal, treat it as destructive rather than as a reversible pause.
Continue with API error handling and MCP safety.