---
title: "Create a LinkedIn video campaign (ad set)"
method: POST
path: "/api/v1/tools/linkedin_create_video_campaign/execute"
tags: ["LinkedIn Ads"]
---

# Create a LinkedIn video campaign (ad set)

`POST /api/v1/tools/linkedin_create_video_campaign/execute`

## Request

- Base URL: `https://adako.ai`
- URL: `https://adako.ai/api/v1/tools/linkedin_create_video_campaign/execute`
- Auth: HTTP bearer

Builds a video sponsored-content campaign: campaign group (a campaign in Campaign Manager), campaign (ad set), video upload (or an existing video URN), dark post and creative (ad). The campaign starts paused and holds everything back (LinkedIn creates groups and creatives only active or draft).
Use when: the user has a video and an objective that permits it (VIDEO_VIEW, BRAND_AWARENESS, ENGAGEMENT, WEBSITE_VISIT or WEBSITE_CONVERSION; LEAD_GENERATION needs a Lead Gen Form this server cannot attach, so it is refused). Prefer video_urn when the video is already in the account: uploads are the slowest and most fragile step of this chain.
Do not use it for a large file. This server uploads a video in one part; anything LinkedIn wants chunked is refused with instructions to upload once in Campaign Manager and pass the URN instead. That refusal happens after the campaign exists, so pass video_urn when in doubt.
Do not call it twice after a failure — it reports what exists and linkedin_add_creative finishes the job.
Returns every id created. Judge a video campaign with linkedin_get_engagement_metrics, not CTR: a video ad's job is watch time. Nothing delivers until the campaign is resumed. Say that the campaign is paused when you report the result, with the two links the result gives (LinkedIn Campaign Manager and the campaign's page in Adako), and offer "enable all": one linkedin_resume_campaign call, listed in the result as go_live.enable_all, one approval.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `arguments` object, required
    - `ad_account_id` string: LinkedIn ad account id — the numeric id from Campaign Manager, as a string ("506699162"). Omit it to use the primary account; pass it when the user manages several.
    - `name` string, required: Campaign name.
    - `campaign_group_id` string: Existing campaign group id. Omit and a group named after the campaign is created first — prefer reusing one from linkedin_list_campaign_groups.
    - `objective` 'BRAND_AWARENESS' | 'WEBSITE_VISIT' | 'ENGAGEMENT' | 'VIDEO_VIEW' | 'LEAD_GENERATION' | 'WEBSITE_CONVERSION' | 'JOB_APPLICANT', required: Campaign objective. It cannot be changed later — confirm it with linkedin_explain_objectives if unsure. LEAD_GENERATION is refused: its ads need a Lead Gen Form, which this server cannot attach yet.
    - `daily_budget` number, required: Daily budget, a decimal in the account currency (50 means fifty). Must clear the LinkedIn per-currency minimum.
    - `total_budget` number: Optional lifetime ceiling for this campaign.
    - `bid` number: Manual bid, a decimal in the account currency: per click with cost_type CPC, per 1,000 impressions with CPM, per view with CPV. Setting it puts the campaign on manual bidding, where LinkedIn never bids above it. Omit it for LinkedIn's automated bidding, which optimises for the objective and always bills CPM. Text ads need a bid.
    - `cost_type` 'CPM' | 'CPC' | 'CPV': How a manual bid is billed; defaults to what the objective prefers. Only with bid: without one the campaign bids automatically and is billed CPM.
    - `targeting` object, required: Targeting entity URNs per facet, exactly as linkedin_search_targeting returned them (for example locations: ["urn:li:geo:103644278"]). Never free text. locations is required. Entities inside one facet widen the audience (title A or title B); separate facets narrow it (location and title).
      - `locations` string[]
      - `titles` string[]
      - `industries` string[]
      - `seniorities` string[]
      - `staffCountRanges` string[]
      - `skills` string[]
      - `interests` string[]
      - `memberBehaviors` string[]
      - `employers` string[]
      - `degrees` string[]
      - `fieldsOfStudy` string[]
      - `interfaceLocales` string[]
    - `exclude` object: Facets to exclude from the audience.
      - `locations` string[]
      - `titles` string[]
      - `industries` string[]
      - `seniorities` string[]
      - `staffCountRanges` string[]
      - `skills` string[]
      - `interests` string[]
      - `memberBehaviors` string[]
      - `employers` string[]
      - `degrees` string[]
      - `fieldsOfStudy` string[]
      - `interfaceLocales` string[]
    - `start_date` string: YYYY-MM-DD; defaults to today.
    - `end_date` string: YYYY-MM-DD, optional.
    - `language` string: Two-letter language members use LinkedIn in; only they see the ads (default "en"). LinkedIn supports en, ar, zh, cs, da, id, ms, nl, fr, fi, de, it, ja, ko, no, pl, pt, ro, ru, es, sv, th, tl, tr.
    - `country` string: Not where the ads run — that is targeting.locations. Only matters for Chinese: "TW" or "HK" for Traditional, otherwise Simplified. Usually omit.
    - `audience_expansion` boolean: Let LinkedIn deliver to similar members outside the spec. Off by default; only turn it on if the user asked.
    - `audience_network` boolean: Buy impressions on third-party apps and sites too (LinkedIn Audience Network). Off by default. LinkedIn refuses it for text ads, carousels on WEBSITE_VISIT or ENGAGEMENT, and lead generation.
    - `idempotency_key` string: Optional caller-supplied key; identical keys never execute twice.
    - `raw_data` boolean: Return compact JSON only (no markdown). Use when you will compute on the result.
    - `organization_urn` string, required: The company page that authors the post, from linkedin_get_organizations.
    - `video_url` string, uri: The video file. Omit when passing video_urn. Adako hosts no files: the platform downloads this URL itself, from its own servers and often hours later, so it must be a public link straight to the file — not a file on the computer, not a Drive, Dropbox or design-tool share page, not a link that expires or asks for a login. Call check_media first: it repairs the usual share links, checks the file against this platform, and says where to put a file that has no link yet.
    - `video_urn` string: An existing urn:li:video:… already in the account. Preferred over uploading.
    - `headline` string, required: Headline shown under the video.
    - `commentary` string, required: The post text above the video. Sent as plain text: #hashtags and @mentions are not linked.
    - `landing_page_url` string, uri, required: Where the ad sends people.

## Response `200`

The tool ran. A write returns proposal_id and approve_url while the change waits for approval.

- SuccessEnvelope
  - `success` unknown, required
  - `tool` string, required
  - `data` object, required: Machine-readable result.
  - `markdown` string, required: The same result written for a person or a model.
  - `quota` Quota: Task usage for the current billing period.
    - `plan` string
    - `used` integer
    - `limit` integer
    - `period_end` string
    - `upgrade_url` string
  - `proposal_id` string: Present for writes. Nothing changes on the ad platform until it is approved.
  - `approve_url` string: Where a person approves the proposal.
  - `request_id` string, required

## Other responses

- `400`: Invalid arguments, or the ad account could not be resolved.
- `401`: Missing, invalid, revoked or expired API key.
- `402`: Monthly task quota used up, or the plan does not include this tool.
- `403`: The connected ad account lacks the access level this tool needs.
- `404`: Unknown tool name.
- `409`: Not connected, reconnect needed, confirmation required, a proposal already pending or no longer pending, an identical create that failed earlier today (proposal_failed_before), a create that duplicates an approved one (duplicate_create), the ad-account limit of the plan reached (account_limit), or an Idempotency-Key reused with different arguments.
- `429`: Rate limited by Adako or by the ad platform. See Retry-After.
- `500`: Unexpected error inside Adako.
- `502`: The ad platform returned an error.

---

[API](https://skmtc.dev/adako/apis/adako-rest-api.md) · [All operations](https://skmtc.dev/adako/apis/adako-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/adako/apis/adako-rest-api/revisions/59ee60d48a56?raw)
