For end users
LinkedIn Marketing API integration
Connects Pectus to LinkedIn Campaign Manager so it can pull ad performance — daily spend, impressions, clicks, leads per campaign.
Approval delay: 1–3 weeks. Marketing Developer Platform access requires manual approval from LinkedIn. Start the application early in the install flow — it’s the gating factor.
Env vars set by this flow:
LINKEDIN_CLIENT_ID=
LINKEDIN_CLIENT_SECRET=
LINKEDIN_REFRESH_TOKEN=
LINKEDIN_ACCESS_TOKEN=
LINKEDIN_AD_ACCOUNT_ID=
The refresh token lasts 365 days, so this is a yearly maintenance step rather than continuous.
1. Apply for Marketing Developer Platform access
This is the slow step. Do it first.
- Go to https://www.linkedin.com/developers/
- Sign in with the LinkedIn account that owns (or has access to) the company’s Campaign Manager
- Click Create app
- Fill in:
- App name:
Pectus Marketing(or similar) - LinkedIn Page: associate with the company’s LinkedIn Page
- App logo: upload (required)
- Privacy policy URL: required
- App name:
- Once the app is created, click into it
- Products tab → Marketing Developer Platform → Request access
- Fill in the use-case form. Be specific about what the app does (read ad performance for the company’s own ad account, no third-party data).
- Submit and wait. LinkedIn reviews within 1–3 weeks. They may ask follow-up questions; respond promptly.
While you wait, you can do steps 2–4 — they don’t depend on approval.
2. Get the OAuth client credentials
In the LinkedIn Developer app:
- Auth tab
- Copy Client ID →
LINKEDIN_CLIENT_ID - Copy Client Secret →
LINKEDIN_CLIENT_SECRET
3. Add an authorized redirect URL
Still in the Auth tab:
- Under OAuth 2.0 settings → Authorized redirect URLs for your app, click Add redirect URL
- For the OAuth Playground flow we’ll use later, add:
https://www.linkedin.com/developers/tools/oauth/redirect - Save
4. Find the Ad Account ID
- Go to https://www.linkedin.com/campaignmanager/accounts
- Click into the relevant account
- The URL contains the Ad Account ID:
The number is the Ad Account ID. Save it ashttps://www.linkedin.com/campaignmanager/accounts/123456789/...LINKEDIN_AD_ACCOUNT_ID.
5. (After approval) Verify Marketing Developer Platform is granted
When LinkedIn approves the request, you’ll get an email. Confirm in the developer console:
- Products tab → Marketing Developer Platform should show as Active
- The available Auth scopes should now include:
r_adsr_ads_reportingr_organization_social(optional — for organic page metrics)
If those scopes aren’t visible, the approval didn’t propagate yet. Wait a few hours and retry.
6. Generate a refresh token
LinkedIn doesn’t have a public OAuth playground like Google’s, but their Developer Tools page provides one specifically for this flow.
- Go to https://www.linkedin.com/developers/tools/oauth/token-generator
- Pick your app from the dropdown
- Scopes: tick
r_adsandr_ads_reporting - Click Request access token
- Sign in with the LinkedIn account that has access to the ad account
- Copy the access token and refresh token that appear
Save:
LINKEDIN_ACCESS_TOKEN(60-day lifetime, will be refreshed)LINKEDIN_REFRESH_TOKEN(365-day lifetime, used to mint new access tokens)
7. Verify
Once your credentials are saved, open the per-app page in the CMS at /apps/linkedin and click Test connection. Pectus runs a small probe call against the API and surfaces the response inline.
Common errors
401 Unauthorized with “ACCESS_TOKEN_EXPIRED” — refresh-token flow needs to run. Pectus normally handles this automatically; if it surfaces, check that LINKEDIN_REFRESH_TOKEN is still valid (365-day lifetime). If expired, redo step 6.
403 Forbidden with “Not enough permissions” — the user that authorized the app doesn’t have access to the ad account in Campaign Manager, OR Marketing Developer Platform isn’t approved yet. Check the Products tab of the developer app — Marketing Developer Platform must show as Active.
429 Too Many Requests — LinkedIn’s rate limits are tighter than Google’s or Meta’s. Pectus’s LinkedIn client uses exponential backoff; if you’re hitting limits during a backfill, run with LINKEDIN_RATE_LIMIT_RPS=1 to slow down.
What LinkedIn actually returns
LinkedIn’s reporting API has a different shape than Google’s or Meta’s:
- Reporting requests are finite: you must specify campaign IDs, date range, and metrics in advance (no
SELECT * FROM...). - Currency is normalized to microcurrency units (multiply by 1e-6 for the actual amount).
- Time granularity options:
DAILY,MONTHLY,YEARLY.DAILYis what Pectus pulls for the panel. - Conversion tracking requires the LinkedIn Insight Tag installed on the marketing site. If it’s not, paid → on-site conversion attribution won’t work but spend / clicks / impressions still come through.
This is documented in apps/linkedin/README.md (the lower-level integration code), not here. This file is just the credential-gathering tutorial.