Stitchflow
LinkedIn Ads logo

LinkedIn Ads User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 18, 2026

Summary and recommendation

LinkedIn Ads exposes user management through the `/rest/adAccountUsers` collection under the Marketing API, authenticated via OAuth 2.0 with the `rw_ads` scope for write operations and `r_ads` for reads.

All requests must include a `LinkedIn-Version: YYYYMM` header;

omitting it risks deprecated behavior.

The API supports GET, POST, PATCH, DELETE, and a `bulkCreate` action, but has no SCIM 2.0 endpoint and no webhook support for user events - polling is the only change-detection mechanism available.

Integrating LinkedIn Ads into an identity graph requires treating it as a poll-only, URN-keyed system with no email-based lookup path in the Marketing API.

API quick reference

Has user APIYes
Auth methodOAuth 2.0
Base URLOfficial docs
SCIM availableNo
SCIM plan requiredN/A

Authentication

Auth method: OAuth 2.0

Setup steps

  1. Register an application at https://www.linkedin.com/developers/apps and obtain a Client ID and Client Secret.
  2. Request the required OAuth 2.0 scopes (e.g., rw_ads, r_ads_reporting) during app configuration.
  3. Redirect the user to LinkedIn's authorization endpoint: https://www.linkedin.com/oauth/v2/authorization with response_type=code, client_id, redirect_uri, scope, and state parameters.
  4. Exchange the returned authorization code for an access token via POST to https://www.linkedin.com/oauth/v2/accessToken.
  5. Include the access token in all API requests as a Bearer token in the Authorization header.
  6. For server-to-server flows, use the 2-legged OAuth (client credentials) flow if your app is approved for it.

Required scopes

Scope Description Required for
r_ads Read ad account data including account users and roles. GET operations on adAccounts and adAccountUsers
rw_ads Read and write ad account data including creating and updating account users. POST, PATCH, DELETE operations on adAccountUsers
r_ads_reporting Read ad performance reporting data. Analytics and reporting endpoints (not user management)
r_organization_social Read organization data; sometimes required for organization-linked ad accounts. Fetching organization-linked account context

User object / data model

Field Type Description On create On update Notes
user URN string LinkedIn member URN identifying the user (e.g., urn:li:person:{id}). required immutable Must be a valid LinkedIn member URN.
account URN string Ad account URN the user is being associated with (e.g., urn:li:sponsoredAccount:{id}). required immutable Composite key with user URN.
role enum string Role assigned to the user on the ad account. Values: ACCOUNT_BILLING_ADMIN, ACCOUNT_MANAGER, CAMPAIGN_MANAGER, CREATIVE_MANAGER, VIEWER. required updatable Only one role per user per account is supported.
changeAuditStamps.created.time long (epoch ms) Timestamp when the user association was created. system-set immutable Read-only.
changeAuditStamps.lastModified.time long (epoch ms) Timestamp of the last modification to the user record. system-set system-set Read-only.

Core endpoints

List users on an ad account

  • Method: GET
  • URL: https://api.linkedin.com/rest/adAccountUsers?q=accounts&accounts=List(urn:li:sponsoredAccount:{id})
  • Watch out for: The accounts parameter must be URL-encoded. Multiple accounts can be passed as a comma-separated list inside List().

Request example

GET /rest/adAccountUsers?q=accounts&accounts=List(urn%3Ali%3AsponsoredAccount%3A123456)
Authorization: Bearer {access_token}
LinkedIn-Version: 202406

Response example

{
  "elements": [
    {
      "user": "urn:li:person:abc123",
      "account": "urn:li:sponsoredAccount:123456",
      "role": "CAMPAIGN_MANAGER"
    }
  ],
  "paging": {"start":0,"count":10,"total":1}
}

Get a specific ad account user

  • Method: GET
  • URL: https://api.linkedin.com/rest/adAccountUsers/(account:urn:li:sponsoredAccount:{id},user:urn:li:person:{personId})
  • Watch out for: The compound key in the URL path must be fully URL-encoded.

Request example

GET /rest/adAccountUsers/(account:urn%3Ali%3AsponsoredAccount%3A123456,user:urn%3Ali%3Aperson%3Aabc123)
Authorization: Bearer {access_token}
LinkedIn-Version: 202406

Response example

{
  "user": "urn:li:person:abc123",
  "account": "urn:li:sponsoredAccount:123456",
  "role": "CAMPAIGN_MANAGER"
}

Add a user to an ad account

  • Method: POST
  • URL: https://api.linkedin.com/rest/adAccountUsers
  • Watch out for: The user must have an existing LinkedIn account and must have previously accepted a connection or have a valid member URN resolvable by your app. You cannot invite net-new LinkedIn members via this API.

Request example

POST /rest/adAccountUsers
Authorization: Bearer {access_token}
LinkedIn-Version: 202406
Content-Type: application/json

{"account":"urn:li:sponsoredAccount:123456","user":"urn:li:person:abc123","role":"CAMPAIGN_MANAGER"}

Response example

HTTP 201 Created
X-RestLi-Id: (account:urn%3Ali%3AsponsoredAccount%3A123456,user:urn%3Ali%3Aperson%3Aabc123)

Update a user's role on an ad account

  • Method: PATCH
  • URL: https://api.linkedin.com/rest/adAccountUsers/(account:urn:li:sponsoredAccount:{id},user:urn:li:person:{personId})
  • Watch out for: LinkedIn REST API PATCH uses the JSON Patch-like $set syntax, not standard JSON Merge Patch.

Request example

PATCH /rest/adAccountUsers/(account:urn%3Ali%3AsponsoredAccount%3A123456,user:urn%3Ali%3Aperson%3Aabc123)
Authorization: Bearer {access_token}
LinkedIn-Version: 202406
Content-Type: application/json

{"patch":{"$set":{"role":"ACCOUNT_MANAGER"}}}

Response example

HTTP 204 No Content

Remove a user from an ad account

  • Method: DELETE
  • URL: https://api.linkedin.com/rest/adAccountUsers/(account:urn:li:sponsoredAccount:{id},user:urn:li:person:{personId})
  • Watch out for: Deleting the last ACCOUNT_BILLING_ADMIN will fail. Ensure at least one billing admin remains.

Request example

DELETE /rest/adAccountUsers/(account:urn%3Ali%3AsponsoredAccount%3A123456,user:urn%3Ali%3Aperson%3Aabc123)
Authorization: Bearer {access_token}
LinkedIn-Version: 202406

Response example

HTTP 204 No Content

List ad accounts accessible to the authenticated user

  • Method: GET
  • URL: https://api.linkedin.com/rest/adAccounts?q=search
  • Watch out for: Only accounts the authenticated user has access to are returned. Use this to discover account URNs before managing users.

Request example

GET /rest/adAccounts?q=search&search=(status:(values:List(ACTIVE)))
Authorization: Bearer {access_token}
LinkedIn-Version: 202406

Response example

{
  "elements": [
    {
      "id": 123456,
      "name": "My Ad Account",
      "status": "ACTIVE",
      "type": "BUSINESS"
    }
  ]
}

Batch create ad account users

  • Method: POST
  • URL: https://api.linkedin.com/rest/adAccountUsers?action=bulkCreate
  • Watch out for: Bulk operations return per-element status codes. Partial failures are possible; check each element's status individually.

Request example

POST /rest/adAccountUsers?action=bulkCreate
Authorization: Bearer {access_token}
LinkedIn-Version: 202406
Content-Type: application/json

{"elements":[{"account":"urn:li:sponsoredAccount:123456","user":"urn:li:person:abc123","role":"VIEWER"}]}

Response example

HTTP 200 OK
{
  "results": {
    "0": {"status": 201}
  },
  "errors": {}
}

Rate limits, pagination, and events

  • Rate limits: LinkedIn Marketing APIs enforce daily and per-minute rate limits per application. Limits vary by endpoint category and are enforced at the application level, not per user.
  • Rate-limit headers: Yes
  • Retry-After header: No
  • Rate-limit notes: LinkedIn returns X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on responses. A 429 status code is returned when limits are exceeded. The official docs do not explicitly document a Retry-After header for Marketing APIs.
  • Pagination method: offset
  • Default page size: 10
  • Max page size: 100
  • Pagination pointer: start / count
Plan Limit Concurrent
Standard Marketing API access 500 calls/day per app for most endpoints; some endpoints have per-minute limits (e.g., 100 calls/minute) 0
  • Webhooks available: No
  • Webhook notes: LinkedIn Marketing APIs do not offer native webhook support for ad account user events as of the current documentation.
  • Alternative event strategy: Poll the adAccountUsers endpoint periodically to detect changes in user membership or roles.

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: N/A
  • Endpoint: Not documented

Limitations:

  • LinkedIn Ads does not expose a SCIM 2.0 endpoint for ad account user management.
  • LinkedIn's enterprise SSO/SCIM (for LinkedIn.com employee accounts) is separate from LinkedIn Ads account user management and does not apply to ad account roles.
  • No IdP connectors (Okta, Entra ID, etc.) are available for LinkedIn Ads ad account user provisioning via SCIM.

Common scenarios

Three core automation scenarios are supported by the API.

First, provisioning: POST to /rest/adAccountUsers with the target account URN, the user's urn:li:person:{id} URN, and the desired role enum

but the member URN must be known in advance, as there is no Marketing API endpoint to resolve a user by email address.

Second, role updates: PATCH to the compound key (account:urn:li:sponsoredAccount:{id},user:urn:li:person:{personId}) using LinkedIn's $set patch syntax, not standard JSON Merge Patch.

Third, cross-account auditing: paginate GET /rest/adAccountUsers per account using start and count parameters (max page size 100), but note that each paginated request counts against the 500 calls/day application-level rate limit

plan pagination budgets carefully across large account portfolios.

Bulk provisioning via ?action=bulkCreate is available but returns per-element status codes;

partial failures are possible and must be checked individually.

Provision a new user as Campaign Manager on an ad account

  1. Obtain the target ad account URN by calling GET /rest/adAccounts?q=search and locating the account by name or ID.
  2. Obtain the LinkedIn member URN for the user (urn:li:person:{id}) via the Profile API or from a prior OAuth flow where the user authenticated.
  3. Call POST /rest/adAccountUsers with the account URN, user URN, and role: CAMPAIGN_MANAGER.
  4. Verify the 201 Created response and store the compound key for future updates or removal.

Watch out for: If the member URN is unknown, there is no Marketing API endpoint to look up a user by email. The user must authenticate via OAuth to expose their URN, or you must use the People Search API (requires separate approval).

Update a user's role from Viewer to Account Manager

  1. Construct the compound key: (account:urn:li:sponsoredAccount:{id},user:urn:li:person:{personId}).
  2. Call PATCH /rest/adAccountUsers/(compound-key) with body {"patch":{"$set":{"role":"ACCOUNT_MANAGER"}}}.
  3. Confirm 204 No Content response.
  4. Optionally call GET on the same compound key to verify the updated role.

Watch out for: Use the $set patch syntax specific to LinkedIn's REST framework. Standard JSON Merge Patch format will be rejected.

Audit all users across multiple ad accounts

  1. Call GET /rest/adAccounts?q=search to retrieve all accessible ad account URNs.
  2. For each account URN, call GET /rest/adAccountUsers?q=accounts&accounts=List(urn:li:sponsoredAccount:{id}) with pagination (start, count).
  3. Iterate through paging.total to collect all users, incrementing start by count until all records are retrieved.
  4. Aggregate results by account and role for reporting.

Watch out for: Each paginated request counts against your daily rate limit. For accounts with many users, plan pagination carefully to avoid exhausting the 500 calls/day limit across all operations.

Why building this yourself is a trap

The most significant integration trap is URN resolution: there is no Marketing API endpoint to look up a LinkedIn member URN by email, meaning any identity graph that stores users by email must either require users to complete an OAuth flow to expose their URN or obtain separate approval for the People Search API.

A second trap is the compound key URL-encoding requirement - urn:li:sponsoredAccount:123456 must be percent-encoded in path parameters, and malformed keys return opaque errors. OAuth access tokens expire after 60 days in 3-legged flows; refresh token handling (365-day validity) must be implemented explicitly or automations will silently fail.

Finally, Marketing API production access requires LinkedIn application review and approval; sandbox access is limited, which constrains pre-production testing of provisioning workflows.

Automate LinkedIn Ads workflows without one-off scripts

Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 18, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste