Lesson 02 · outer fringe
Exactly two entity types can act in this API. Everything else is something you point at. This is the direct answer to your opening question.
≈14 min · pinned to li-lms-2026-08
Across the whole ads surface, every field that means somebody — as opposed to something — accepts one of exactly two URN namespaces:
urn:li:person:{id} // a member
urn:li:organization:{id} // a company page or showcase page
That is the whole cast. There is no "agency" entity, no "brand" entity, no "team". An agency managing fifty clients is modelled as a set of person URNs holding roles on fifty ad accounts. Internalise this early: your multi-tenant model has no LinkedIn-side counterpart. Tenancy is your invention and lives entirely in your database.
Why this matters for you specifically
You are building a platform where many customers connect many accounts. LinkedIn will never tell you "these three ad accounts belong to customer Acme." It will tell you "the person who authenticated has a role on these three accounts." Your tenancy boundary must be derived from OAuth token → person → accounts, and re-derived whenever access changes. Nothing in the ads schema encodes it for you.
Here is where most integrations go wrong. Three separate fields all take a person-or-organization URN, and they answer three genuinely different questions. Sitting at three different levels of the spine you learned in Lesson 01.
| Field | Lives on | Answers | Accepts |
|---|---|---|---|
| reference | Ad Account | Who is this account for? The entity on whose behalf the account advertises. | person organization |
| associatedEntity | Campaign | Who benefits from this campaign? The intended beneficiary. | person organization |
| contentAuthor | Creative content | Whose name is on the ad? Who the member sees as having posted it. | person organization |
In the common case all three are the same organization, which is exactly why the distinction is easy to miss and expensive to discover. They diverge in real scenarios:
associatedEntity is not universally optional: it is required once the campaign uses Sponsored Content, Dynamic Ads, or Lead Gen Forms — which is nearly always. Treat it as required and you will be right more often than the schema suggests.
Now the other half. A creative's content field is a tagged union — the URN namespace tells the server what kind of thing it is. Lesson 01 promised you a field that accepts six namespaces; here it is, and the important structure is not the list but the three shapes hiding in it.
The post exists independently, in the organic content world. Sponsoring it does not move or copy it.
urn:li:share:{id} // older post entity
urn:li:ugcPost:{id} // user-generated content post
Single image, video, article, carousel and document ads all take this shape. The format differs; the mechanism is identical — a creative pointing at a post.
The promoted thing is not a post at all. LinkedIn renders an ad about it.
urn:li:event:{id} // Event Ads — 202505+; also carries a post
urn:li:adInMailContent:{id} // Message / Conversation Ads
Job Ads belong here too — the promoted object is a job posting, and the servingHoldReasons vocabulary has dedicated entries (JOB_POSTING_ON_HOLD, JOB_POSTING_INVALID) for when that external object stops being valid. That is the tell for this shape: the promoted thing has its own lifecycle that can break your ad.
Nothing is being pointed at. The creative is the content, assembled at render time from the organization's page plus the viewing member's own profile.
followerAd // "Follow {org}" — personalised with the viewer's name
spotlightAd // product/service/event spotlight → landing page
jobAd // dynamic job ad
textAd // right rail / top of page
These are the Dynamic Ads family (campaign type: DYNAMIC) plus Text Ads. There is no post, so there is nothing for the customer's social team to have created first, and nothing to reuse across creatives.
The modelling consequence
If you store promotable_object_id as a nullable foreign key to a posts table, Shape 3 breaks it (nothing to point at) and Shape 2 breaks it differently (points at a non-post). The union is irreducible — model it as a discriminated union keyed on the URN namespace, exactly as LinkedIn does. Any attempt to flatten it will leak.
Since the post and the creative are separate objects, creating an ad from new material is normally two calls. inlineContent collapses them into one — you pass the post body inside the creative payload and LinkedIn creates both. The docs' stated motive is bluntly practical: "in order to reduce the number of user calls."
Useful, and a trap for your retry logic. A failed inline create may have produced a post and no creative. There is no idempotency key (Lesson 01), so your reconciliation has to be able to find orphaned posts.
Direct Sponsored Content (DSC) is a sponsored post that never appears on the organization's page. It exists only as an ad.
This is the feature that lets an advertiser run twelve headline variants at a niche audience without turning their company page into a testing ground. On the creative it surfaces as a read-only boolean:
directSponsoredContent: boolean // read-only, default false
Read-only matters: you do not set this flag. It is derived from how the post was created. Publish to the page first and sponsor it after → false. Create it as an ad-only post → true. The decision is made upstream, in the content graph, and the ads API merely reports it.
DSC is also where the two permission systems collide. Creating it requires either:
| System | Requirement |
|---|---|
| Ad account roles | Scope r_ads or rw_ads, with a role above VIEWER |
| Organization roles | Role DIRECT_SPONSORED_CONTENT_POSTER or ADMINISTRATOR on the page |
Two independent access-control systems, one action. A customer can hold every ad-account role and still be unable to author DSC, because page roles are administered separately by whoever runs their LinkedIn page. Expect this support ticket.
graph TD P["urn:li:person"]:::actor O["urn:li:organization"]:::actor A["Ad Account"]:::spine C["Campaign"]:::spine R["Creative"]:::spine S1["share / ugcPost"]:::prom S2["event / adInMailContent
job posting"]:::prom S3["followerAd · spotlightAd
jobAd · textAd"]:::prom P -->|"reference"| A O -->|"reference"| A A --> C --> R O -->|"associatedEntity"| C P -->|"contentAuthor"| S1 O -->|"contentAuthor"| S1 R -->|"content"| S1 R -->|"content"| S2 R -->|"content"| S3 O -.->|"rendered from
page + viewer profile"| S3 classDef actor fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d classDef spine fill:#dbeafe,stroke:#1d4ed8,color:#172554 classDef prom fill:#fef3c7,stroke:#d97706,color:#78350f
Green acts. Blue is the spend spine. Amber is promotable. Note that green never touches blue's lower half directly — an actor authors content, and the spine merely points at it. That separation is what makes the same post sponsorable by several creatives at once.
Interleaved with Lesson 01 on purpose — several answers require the spine, not just this lesson.
Exercise 1 · recognition
For each URN namespace, click the role it plays.
Exercise 2 · recall
Name the field that answers each question.
Exercise 3 · bug hunt
Two payloads, one clean. Click the offending line, or "No bug here".
A · POST /rest/adAccounts
{ "name": "Acme Corp — managed by us", "type": "ENTERPRISE", "currency": "EUR", "reference": "urn:li:organization:2414183"}
B · POST /rest/adAccounts/{id}/adCampaigns
{ "account": "urn:li:sponsoredAccount:5168", "campaignGroup": "urn:li:sponsoredCampaignGroup:6088", "associatedEntity": "urn:li:organization:2414183", "type": "SPONSORED_UPDATES", "costType": "CPM"}
C · POST /rest/adAccounts/{id}/adCreatives — an Event Ad
{ "campaign": "urn:li:sponsoredCampaign:301", "intendedStatus": "ACTIVE", "directSponsoredContent": true, "content": { "eventAd": { "event": "urn:li:event:6802" } }}
Exercise 4 · free recall
Write, from memory: a customer asks why their ad shows the CEO's name instead of the company's. Which field is wrong, and which two other fields will people wrongly suspect?
Next
Lesson 03 — targetingCriteria: the AND/OR construct that decides who sees the ad. It is conjunctive normal form with a few illegal combinations, and once you see the CNF it stops being fiddly. It is also the prerequisite for Lesson 04, Matched Audiences.
Sources: Create and Manage Creatives, Create and Manage Campaigns (§ Direct Sponsored Content), Create and Manage Ad Accounts, version li-lms-2026-08.