Ads

LinkedIn Ads

Create and boost LinkedIn campaigns with B2B targeting, every creative format, matched audiences, bid and delivery forecasts and the public ad library.

A linkedinads connection runs LinkedIn's Marketing API. You can create sponsored content from scratch in any of LinkedIn's formats, boost Company Page posts, target by industry, company size, seniority, job function, title and skill, build matched audiences, forecast delivery before you spend, and read firmographic breakdowns of who saw an ad.

#Before you start

Three things have to be in place on LinkedIn:

  • An ad account. Pozy uses its numeric sponsored account id, which GET /v1/ads/accounts lists.
  • A Company Page linked to that ad account. New ads go out in the Page's name as Direct Sponsored Content, so they do not show up in the Page's own feed.
  • A Page role for whoever connected LinkedIn: Administrator, or Direct Sponsored Content Poster. Without one of them LinkedIn refuses with 403.

LinkedIn reviews every ad, so new campaigns sit in DRAFT and review before they deliver.

#Connect

Call GET /v1/connect/linkedin/ads with the profileId. When the profile already has a connected LinkedIn account, the ads connection reuses its token and no consent screen appears. Otherwise the response carries an authUrl.

The standard LinkedIn connection asks for every ads permission: reading ad accounts, managing campaigns, reporting, conversions and lead form responses. An account connected before one of these was requested must reconnect. Missing conversion access returns 403 with linkedin_reconnect_required; missing lead access returns 400 with ads_connection_required.

#How LinkedIn's levels map

Pozy LinkedIn Id on the created ad
Campaign Campaign group platformCampaignId
Ad set (adSetId) Campaign: bidding, targeting, schedule, budget platformAdSetId
Ad Creative platformAdId

#Create a campaign

POST /v1/ads/create creates the Direct Sponsored Content post, then the campaign group, campaign and creative around it.

curl -X POST https://api.pozy.ai/v1/ads/create \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: li-ops-guide-q4" \
  -d '{
    "accountId": "66b2e19d8c3f5a7e9d0b1c5a",
    "adAccountId": "512345678",
    "organizationId": "10293847",
    "name": "Ops leaders - guide download",
    "goal": "traffic",
    "budgetAmount": 60,
    "budgetType": "daily",
    "headline": "The 2027 field ops playbook",
    "body": "How 40 operations teams cut dispatch time by a third. Free guide.",
    "imageUrl": "https://cdn.example.com/ops-guide-1200x627.png",
    "linkUrl": "https://example.com/guide",
    "callToAction": "DOWNLOAD",
    "status": "PAUSED",
    "targeting": {
      "countries": ["US", "CA"],
      "seniorities": ["6", "7"],
      "jobFunctions": ["18"],
      "companySizes": ["D", "E", "F"]
    },
    "platformSpecificData": { "costType": "CPC" }
  }'

Field rules:

  • headline is required, plus exactly one of imageUrl or video: { url }. body is the intro text.
  • organizationId names the authoring Page, as a number or urn:li:organization:N. It is optional when the Page is connected to Pozy or owns the ad account.
  • goal: "traffic" needs linkUrl. Buttons accept LEARN_MORE, SIGN_UP, DOWNLOAD, SUBSCRIBE, REGISTER, JOIN, ATTEND, REQUEST_DEMO, VIEW_QUOTE, APPLY, SEE_MORE, SHOP_NOW and BUY_NOW.
  • A video upload blocks while LinkedIn transcodes it, usually 10 to 30 seconds.
  • status: "PAUSED" pauses only the top level the call creates: a new campaign group, a new campaign (kept in draft) or the new creative.

#Goals

goal On create On boost Notes
engagement, traffic, awareness Yes Yes
lead_generation Yes Yes Needs leadGenFormId (Lead forms)
video_views Yes Yes Needs a video
job_applicants Yes – Needs the jobs format
conversions – Yes Boost only

#Reuse an existing campaign or group

Send adSetId (a LinkedIn campaign id) to add a new creative under that campaign: bidding, targeting, schedule and budget are inherited, so sending any of them returns 400. Send existingCampaignId (a campaign group id) to create a new campaign in that group with its own settings. The two are mutually exclusive. If a create fails, Pozy cleans up only what it created and never touches the parent.

#Creative formats

One key inside platformSpecificData selects the format. Formats exclude each other and the top-level imageUrl and video.

Format Key Goals Notes
Single image or link (article, newsletter) none engagement, traffic, awareness, lead_generation imageUrl + linkUrl
Single video none (video) all base goals plus video_views MP4 H.264/AAC, 3 s to 30 min, 75 KB to 500 MB
Carousel carousel base goals 2 to 10 cards, each with a landing URL (or the ad's linkUrl)
Document document base goals PDF, PPT or DOC up to 100 MB, swipeable in the feed
Event event base goals Promotes an existing LinkedIn Event by urn
Text ad textAd base goals Right rail. Headline 25 characters, description 75, optional 100 x 100 logo
Spotlight spotlight traffic, awareness Personalized with the viewer's photo
Follower follower engagement, awareness Drives Page follows
Jobs jobs job_applicants Shows the Page's live job postings
Conversation conversation base goals A message tree in LinkedIn messaging: up to 25 messages, 5 buttons each, 500 characters per message
Thought leader thoughtLeader base goals Sponsors an existing Company Page post (urn:li:share:N or urn:li:ugcPost:N) under a campaign you control

Conversation ads need a sender approved for the ad account in Campaign Manager, or they fail with SINMAIL_SENDER_NOT_APPROVED. Thought leader and boost only work on posts authored by the Company Page; LinkedIn rejects personal-profile posts.

#Bidding and budgets

Bidding fields go in platformSpecificData on create and boost:

Field Values
costType CPM (default), CPC, CPV. Required with unitCost.
unitCost Manual bid in whole currency units. Omit for automated bidding.
optimizationTargetType LinkedIn's value, such as MAX_CLICK or TARGET_COST_PER_CLICK
creativeSelection OPTIMIZED (default) or ROUND_ROBIN
audienceExpansionEnabled, offsiteDeliveryEnabled, connectedTelevisionOnly Switches for where and to whom the ads deliver

LinkedIn requires at least $10 a day per campaign, and $100 lifetime on an inactive campaign. Bidding cannot be changed after create through Pozy.

#Forecast before you spend

Call Answers
POST /v1/ads/targeting/bid-pricing The suggested bid and the bid and daily budget LinkedIn accepts for a targeting spec. dailyBudgetLimits.min is the real minimum for that audience.
POST /v1/ads/targeting/supply-forecast Projected impressions, clicks and spend over a future window (timeRangeStart, timeRangeEnd in Unix milliseconds) for a dailyBudget or totalBudget
POST /v1/ads/targeting/reach-estimate Audience size for the spec

Send objectiveType (for example WEBSITE_VISIT) on the forecast: LinkedIn rejects it without one. Read each series by its metricType; the CUSTOM granularity is the total over your window. On accounts that are not LinkedIn, the planning calls return { "available": false } with 200, so a multi-network UI can call them unconditionally.

#Targeting

LinkedIn targets by location and professional facets. Send them in a nested targeting object:

Field Values
countries, regions ISO codes, or urn:li:geo:* keys from the search
industries, seniorities, jobFunctions, jobTitles, skills Id fragments or full URNs from the search
companySizes A (1), B (2 to 10), C (11 to 50), D (51 to 200), E (201 to 500), F (501 to 1,000), G (1,001 to 5,000), H (5,001 to 10,000), I (10,001+)
interests, behaviors [{ "id": "urn:..." }] from the search
audienceInclude, audienceExclude Matched audience segment ids
ageMin, ageMax, gender, languages Rounded to LinkedIn's age buckets (18-24, 25-34, 35-54, 55+)

jobTitles cannot be combined with seniorities or jobFunctions. Cities, ZIP codes, radius and income are not available on LinkedIn. PUT /v1/ads/{adId} with targeting updates the live campaign facet by facet. See Targeting for the lookup dimensions.

#Matched audiences

POST /v1/ads/audiences builds four LinkedIn audience types: contact lists (customer_list), company lists (company_list, up to 300,000 rows), engagement retargeting (engagement) and website retargeting (website_retargeting, fed by the Insight Tag). Contact list uploads replace the list rather than adding to it. Details and limits are on Audiences.

#Lead gen forms and conversions

LinkedIn lead forms are created, listed and archived through the lead form endpoints, and responses are kept for 90 days. LinkedIn sends no lead webhook, so poll for new leads. Server-side conversions use conversion rules. Both are covered on Lead forms and Conversions.

#Manage running ads

Job Call Notes
Pause or resume PUT /v1/ads/campaigns/{campaignId}/status (group), /ad-sets/{adSetId}/status (campaign), /{adId}/status (creative) A creative still in DRAFT cannot be paused before approval.
Change the budget PUT /v1/ads/{adId} with budget The budget belongs to the LinkedIn campaign that holds the ad, so every creative in that campaign shares it.
Swap media PUT /v1/ads/{adId} with creative and a new imageUrl or videoUrl Pozy creates a new creative and pauses the old one. Text-only edits return 400.
Rename PUT /v1/ads/ad-sets/{adSetId} with name Creatives cannot be renamed.
Duplicate POST /v1/ads/campaigns/{campaignId}/duplicate with platform: "linkedin" Copies the group, its campaigns and creatives. statusOption defaults to PAUSED.
Delete DELETE on the ad, ad set or campaign Campaigns and groups move to PENDING_DELETION and stay readable for reporting.

#Reporting

Spend, impressions, clicks, CPC and CPM roll up on GET /v1/ads/tree. Firmographic breakdowns come from GET /v1/ads/{adId}/analytics or GET /v1/ads/campaigns/{campaignId}/analytics with breakdowns:

Dimension Shows
job_title, job_function, seniority Who the viewers are
industry, company, company_size Where they work
country, region Where they are

Each row carries LinkedIn's URN in value and a readable name. Breakdowns cover the whole range (LinkedIn does not split them by day), lag 12 to 24 hours and omit segments with fewer than 3 events. Each dimension costs one extra call to LinkedIn, so ask only for the ones you show.

#Ad library

GET /v1/ads/library?platform=linkedin&accountId=...&q=... searches LinkedIn's public archive of ads served since June 2023, by keyword (q), advertiser, countries and a since / until window. Pages hold at most 25 ads. EU ads also carry impression ranges and targeting disclosures.

#Limits and errors

Error Cause Fix
403 with LinkedIn's message The connected person has no suitable Page role, or the Page is not linked to the ad account Grant the role, or link the Page to the ad account, on LinkedIn.
400 with both adSetId and existingCampaignId They exclude each other Send one.
400 on platformSpecificData An unknown key, or two format keys Send one format key and the bidding keys above.
400 mutually_exclusive_fields jobTitles with seniorities or jobFunctions Keep one side.
422 with INVALID_URN_TYPE Boosting a personal-profile post Boost a post the Company Page authored.
422 mentioning sponsorship authorization The Page post is not approved for sponsorship The author approves it in LinkedIn's sponsorship settings.
501 on name for an ad Creatives cannot be renamed Rename the campaign instead.

#Endpoints

Endpoint What it does
GET /v1/connect/{platform}/ads Connect ads for a platform
GET /v1/ads/accounts List ad accounts
POST /v1/ads/create Create standalone ad
POST /v1/ads/boost Boost post as ad
GET /v1/ads/tree Get campaign tree
GET /v1/ads/{adId} Get ad details
PUT /v1/ads/{adId} Update ad
PUT /v1/ads/{adId}/status Pause or resume a single ad
PUT /v1/ads/ad-sets/{adSetId} Update an ad set
PUT /v1/ads/ad-sets/{adSetId}/status Pause or resume a single ad set
PUT /v1/ads/campaigns/{campaignId}/status Pause or resume a campaign
POST /v1/ads/campaigns/{campaignId}/duplicate Duplicate a campaign
DELETE /v1/ads/{adId} Cancel an ad
DELETE /v1/ads/ad-sets/{adSetId} Delete an ad set
DELETE /v1/ads/campaigns/{campaignId} Delete a campaign
GET /v1/ads/targeting/search Search targeting options
POST /v1/ads/targeting/reach-estimate Estimate audience reach
POST /v1/ads/targeting/bid-pricing Suggested bid and budget bounds
POST /v1/ads/targeting/supply-forecast Forecast ad delivery
POST /v1/ads/audiences Create custom audience
POST /v1/ads/audiences/{audienceId}/users Add users to audience
POST /v1/ads/audiences/{audienceId}/companies Replace audience companies
GET /v1/ads/audiences List custom audiences
GET /v1/ads/{adId}/analytics Get ad analytics
GET /v1/ads/campaigns/{campaignId}/analytics Get campaign analytics
GET /v1/ads/library Search the public Ad Library