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

# Create a LinkedIn text ad campaign (ad set)

`POST /api/v1/tools/linkedin_create_text_campaign/execute`

## Request

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

Creates a TEXT_AD campaign (an ad set in Campaign Manager) — the small desktop-sidebar unit with a 25-character headline and a 75-character description. Campaign group (campaign), campaign and creative (ad); the campaign starts paused and holds everything back.
Use when: the user has no company page to post from (text ads need none), or wants a cheap desktop-only test of a message before committing to sponsored content. CPCs are far lower than feed placements and so are click volumes.
Do not use it as the main channel for a serious campaign: text ads do not appear on mobile at all, which is most of LinkedIn's traffic. Say that before recommending it.
Do not exceed 25 characters of headline or 75 of description — LinkedIn truncates silently and the ad reads as an accident.
Do not call it without a bid: LinkedIn text ads only bid manually (CPC or CPM), and a manual campaign without a bid never delivers. If the user has no figure, get LinkedIn's suggested range from linkedin_forecast_campaign_supply with campaign_type TEXT_AD and ask. Text ads run with BRAND_AWARENESS, WEBSITE_VISIT or WEBSITE_CONVERSION, never on the Audience Network.
Returns the campaign and creative ids. 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.
    - `headline` string, required: Headline, at most 25 characters.
    - `description` string, required: Description, at most 75 characters.
    - `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)
