← 返回
内容创作 Key 中文

LinkedIn

LinkedIn API integration with managed OAuth. Share posts, manage profile, and access LinkedIn features. Use this skill when users want to share content on Li...
通过托管OAuth实现LinkedIn API集成,支持发布动态、管理个人资料并访问LinkedIn功能,适用于用户需要分享内容时使用。
byungkyu
内容创作 clawhub v1.0.9 6 版本 98253.9 Key: 需要
★ 45
Stars
📥 14,406
下载
💾 1,566
安装
6
版本
#latest

概述

LinkedIn

Access the LinkedIn API with managed OAuth authentication. Share posts, manage advertising campaigns, retrieve profile and organization information, upload media, and access the Ad Library.

Quick Start

# Get current user profile
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://api.maton.ai/linkedin/rest/{resource}

Maton proxies requests to api.linkedin.com and automatically injects your OAuth token.

Authentication

All requests require the Maton API key in the Authorization header:

Authorization: Bearer $MATON_API_KEY

Environment Variable: Set your API key as MATON_API_KEY:

export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key

Required Headers

LinkedIn REST API requires the version header:

LinkedIn-Version: 202506

Connection Management

Manage your LinkedIn OAuth connections at https://api.maton.ai.

List Connections

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=linkedin&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'linkedin'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "connection": {
    "connection_id": "{connection_id}",
    "status": "ACTIVE",
    "creation_time": "2026-02-07T08:00:24.372659Z",
    "last_updated_time": "2026-02-07T08:05:16.609085Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "linkedin",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple LinkedIn connections, specify which one to use with the Maton-Connection header:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If you have multiple connections, always include this header to ensure requests go to the intended account.

Security & Permissions

  • Access is scoped to posts, profiles, organizations, images, videos, and analytics within the connected LinkedIn account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call:
  1. State the exact operation (e.g., "Create a DRAFT campaign in ad account 123456789")
  2. Show the user the request body or key parameters
  3. Wait for explicit confirmation before sending the request
  4. For destructive operations (DELETE), additionally confirm the resource cannot be recovered
    • Advertising operations (campaign creation, budget changes, account modifications) carry financial impact. Always confirm budget amounts and targeting criteria with the user before execution.

API Reference

Profile

Get Current User Profile

GET /linkedin/rest/me
LinkedIn-Version: 202506

Example:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "firstName": {
    "localized": {"en_US": "John"},
    "preferredLocale": {"country": "US", "language": "en"}
  },
  "localizedFirstName": "John",
  "lastName": {
    "localized": {"en_US": "Doe"},
    "preferredLocale": {"country": "US", "language": "en"}
  },
  "localizedLastName": "Doe",
  "id": "yrZCpj2Z12",
  "vanityName": "johndoe",
  "localizedHeadline": "Software Engineer at Example Corp",
  "profilePicture": {
    "displayImage": "urn:li:digitalmediaAsset:C4D00AAAAbBCDEFGhiJ"
  }
}

Sharing Posts

Create a Text Post

POST /linkedin/rest/posts
Content-Type: application/json
LinkedIn-Version: 202506

{
  "author": "urn:li:person:{personId}",
  "lifecycleState": "PUBLISHED",
  "visibility": "PUBLIC",
  "commentary": "Hello LinkedIn! This is my first API post.",
  "distribution": {
    "feedDistribution": "MAIN_FEED"
  }
}

Response: 201 Created with x-restli-id header containing the post URN.

Create an Article/URL Share

POST /linkedin/rest/posts
Content-Type: application/json
LinkedIn-Version: 202506

{
  "author": "urn:li:person:{personId}",
  "lifecycleState": "PUBLISHED",
  "visibility": "PUBLIC",
  "commentary": "Check out this great article!",
  "distribution": {
    "feedDistribution": "MAIN_FEED"
  },
  "content": {
    "article": {
      "source": "https://example.com/article",
      "title": "Article Title",
      "description": "Article description here"
    }
  }
}

Create an Image Post

First, initialize the image upload, then upload the image, then create the post.

Step 1: Initialize Image Upload

POST /linkedin/rest/images?action=initializeUpload
Content-Type: application/json
LinkedIn-Version: 202506

{
  "initializeUploadRequest": {
    "owner": "urn:li:person:{personId}"
  }
}

Response:

{
  "value": {
    "uploadUrlExpiresAt": 1770541529250,
    "uploadUrl": "https://www.linkedin.com/dms-uploads/...",
    "image": "urn:li:image:D4D10AQH4GJAjaFCkHQ"
  }
}

Step 2: Upload Image Binary

PUT {uploadUrl from step 1}
Content-Type: image/png

{binary image data}

Step 3: Create Image Post

POST /linkedin/rest/posts
Content-Type: application/json
LinkedIn-Version: 202506

{
  "author": "urn:li:person:{personId}",
  "lifecycleState": "PUBLISHED",
  "visibility": "PUBLIC",
  "commentary": "Check out this image!",
  "distribution": {
    "feedDistribution": "MAIN_FEED"
  },
  "content": {
    "media": {
      "id": "urn:li:image:D4D10AQH4GJAjaFCkHQ",
      "title": "Image Title"
    }
  }
}

Visibility Options

ValueDescription
--------------------
PUBLICViewable by anyone on LinkedIn
CONNECTIONSViewable by 1st-degree connections only

Share Media Categories

ValueDescription
--------------------
NONEText-only post
ARTICLEURL/article share
IMAGEImage post
VIDEOVideo post

Ad Library (Public Data)

The Ad Library API provides access to public advertising data on LinkedIn. These endpoints use the REST API with version headers.

Required Headers for Ad Library

LinkedIn-Version: 202506

Search Ads

GET /linkedin/rest/adLibrary?q=criteria&keyword={keyword}

Query parameters:

  • keyword (string): Search ad content (multiple keywords use AND logic)
  • advertiser (string): Search by advertiser name
  • countries (array): Filter by ISO 3166-1 alpha-2 country codes
  • dateRange (object): Filter by served dates
  • start (integer): Pagination offset
  • count (integer): Results per page (max 25)

Example - Search ads by keyword:

GET /linkedin/rest/adLibrary?q=criteria&keyword=linkedin

Example - Search ads by advertiser:

GET /linkedin/rest/adLibrary?q=criteria&advertiser=microsoft

Response:

{
  "paging": {
    "start": 0,
    "count": 10,
    "total": 11619543,
    "links": [...]
  },
  "elements": [
    {
      "adUrl": "https://www.linkedin.com/ad-library/detail/...",
      "details": {
        "advertiser": {...},
        "adType": "TEXT_AD",
        "targeting": {...},
        "statistics": {
          "firstImpressionDate": 1704067200000,
          "latestImpressionDate": 1706745600000,
          "impressionsFrom": 1000,
          "impressionsTo": 5000
        }
      },
      "isRestricted": false
    }
  ]
}

Search Job Postings

GET /linkedin/rest/jobLibrary?q=criteria&keyword={keyword}

Note: Job Library requires version 202506.

Query parameters:

  • keyword (string): Search job content
  • organization (string): Filter by company name
  • countries (array): Filter by country codes
  • dateRange (object): Filter by posting dates
  • start (integer): Pagination offset
  • count (integer): Results per page (max 24)

Example:

GET /linkedin/rest/jobLibrary?q=criteria&keyword=software&organization=google

Response includes:

  • jobPostingUrl: Link to job listing
  • jobDetails: Title, location, description, salary, benefits
  • statistics: Impression data

Marketing API (Advertising)

The Marketing API provides access to LinkedIn's advertising platform. These endpoints use the versioned REST API.

Required Headers for Marketing API

LinkedIn-Version: 202506

List Ad Accounts

GET /linkedin/rest/adAccounts?q=search

Returns all ad accounts accessible by the authenticated user.

Response:

{
  "paging": {
    "start": 0,
    "count": 10,
    "links": []
  },
  "elements": [
    {
      "id": 123456789,
      "name": "My Ad Account",
      "status": "ACTIVE",
      "type": "BUSINESS",
      "currency": "USD",
      "reference": "urn:li:organization:12345"
    }
  ]
}

Get Ad Account

GET /linkedin/rest/adAccounts/{adAccountId}

Create Ad Account

POST /linkedin/rest/adAccounts
Content-Type: application/json

{
  "name": "New Ad Account",
  "currency": "USD",
  "reference": "urn:li:organization:{orgId}",
  "type": "BUSINESS"
}

Update Ad Account

POST /linkedin/rest/adAccounts/{adAccountId}
Content-Type: application/json
X-RestLi-Method: PARTIAL_UPDATE

{
  "patch": {
    "$set": {
      "name": "Updated Account Name"
    }
  }
}

List Campaign Groups

Campaign groups are nested under ad accounts:

GET /linkedin/rest/adAccounts/{adAccountId}/adCampaignGroups

Create Campaign Group

POST /linkedin/rest/adAccounts/{adAccountId}/adCampaignGroups
Content-Type: application/json

{
  "name": "Q1 2026 Campaigns",
  "status": "DRAFT",
  "runSchedule": {
    "start": 1704067200000,
    "end": 1711929600000
  },
  "totalBudget": {
    "amount": "10000",
    "currencyCode": "USD"
  }
}

Get Campaign Group

GET /linkedin/rest/adAccounts/{adAccountId}/adCampaignGroups/{campaignGroupId}

Update Campaign Group

POST /linkedin/rest/adAccounts/{adAccountId}/adCampaignGroups/{campaignGroupId}
Content-Type: application/json
X-RestLi-Method: PARTIAL_UPDATE

{
  "patch": {
    "$set": {
      "status": "ACTIVE"
    }
  }
}

Delete Campaign Group

> Destructive operation. Deleting a campaign group may be irreversible and will remove all associated data. Confirm the campaign group ID and that no active campaigns depend on it before proceeding.

DELETE /linkedin/rest/adAccounts/{adAccountId}/adCampaignGroups/{campaignGroupId}

List Campaigns

Campaigns are also nested under ad accounts:

GET /linkedin/rest/adAccounts/{adAccountId}/adCampaigns

Create Campaign

POST /linkedin/rest/adAccounts/{adAccountId}/adCampaigns
Content-Type: application/json

{
  "campaignGroup": "urn:li:sponsoredCampaignGroup:123456",
  "name": "Brand Awareness Campaign",
  "status": "DRAFT",
  "type": "SPONSORED_UPDATES",
  "objectiveType": "BRAND_AWARENESS",
  "dailyBudget": {
    "amount": "100",
    "currencyCode": "USD"
  },
  "costType": "CPM",
  "unitCost": {
    "amount": "5",
    "currencyCode": "USD"
  },
  "locale": {
    "country": "US",
    "language": "en"
  }
}

Get Campaign

GET /linkedin/rest/adAccounts/{adAccountId}/adCampaigns/{campaignId}

Update Campaign

POST /linkedin/rest/adAccounts/{adAccountId}/adCampaigns/{campaignId}
Content-Type: application/json
X-RestLi-Method: PARTIAL_UPDATE

{
  "patch": {
    "$set": {
      "status": "ACTIVE"
    }
  }
}

Delete Campaign

> Destructive operation. Deleting a campaign is irreversible and will stop all ad delivery. Confirm the campaign ID and its current status with the user before proceeding.

DELETE /linkedin/rest/adAccounts/{adAccountId}/adCampaigns/{campaignId}

Campaign Status Values

StatusDescription
---------------------
DRAFTCampaign is in draft mode
ACTIVECampaign is running
PAUSEDCampaign is paused
ARCHIVEDCampaign is archived
COMPLETEDCampaign has ended
CANCELEDCampaign was canceled

Campaign Objective Types

ObjectiveDescription
------------------------
BRAND_AWARENESSIncrease brand visibility
WEBSITE_VISITSDrive traffic to website
ENGAGEMENTIncrease post engagement
VIDEO_VIEWSMaximize video views
LEAD_GENERATIONCollect leads via Lead Gen Forms
WEBSITE_CONVERSIONSDrive website conversions
JOB_APPLICANTSAttract job applications

Organizations

List Organization ACLs

Get organizations the authenticated user has access to:

GET /linkedin/rest/organizationAcls?q=roleAssignee
LinkedIn-Version: 202506

Response:

{
  "paging": {
    "start": 0,
    "count": 10,
    "total": 2
  },
  "elements": [
    {
      "role": "ADMINISTRATOR",
      "organization": "urn:li:organization:12345",
      "state": "APPROVED"
    }
  ]
}

Get Organization

GET /linkedin/rest/organizations/{organizationId}
LinkedIn-Version: 202506

Lookup Organization by Vanity Name

GET /linkedin/rest/organizations?q=vanityName&vanityName={vanityName}

Example:

GET /linkedin/rest/organizations?q=vanityName&vanityName=microsoft

Response:

{
  "elements": [
    {
      "vanityName": "microsoft",
      "localizedName": "Microsoft",
      "website": {
        "localized": {"en_US": "https://news.microsoft.com/"}
      }
    }
  ]
}

Get Organization Share Statistics

GET /linkedin/rest/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity={orgUrn}

Example:

GET /linkedin/rest/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:12345

Get Organization Posts

GET /linkedin/rest/posts?q=author&author={orgUrn}

Example:

GET /linkedin/rest/posts?q=author&author=urn:li:organization:12345

Media Upload (REST API)

The REST API provides modern media upload endpoints. All require version header LinkedIn-Version: 202506.

Initialize Image Upload

POST /linkedin/rest/images?action=initializeUpload
Content-Type: application/json
LinkedIn-Version: 202506

{
  "initializeUploadRequest": {
    "owner": "urn:li:person:{personId}"
  }
}

Response:

{
  "value": {
    "uploadUrlExpiresAt": 1770541529250,
    "uploadUrl": "https://www.linkedin.com/dms-uploads/...",
    "image": "urn:li:image:D4D10AQH4GJAjaFCkHQ"
  }
}

Use the uploadUrl to PUT your image binary, then use the image URN in your post.

Create a Video Post

Video uploads are a 4-step process: initialize, upload binary, finalize, then create the post.

> CRITICAL — URL Encoding: The upload URL returned by the initialize step contains URL-encoded characters (e.g., %253D) that get corrupted when passed through shell variables or curl. You MUST use Python urllib for the entire flow — parse the JSON response and use the URL directly in Python without passing it through the shell. This is the only reliable approach.

Complete working example:

python <<'EOF'
import urllib.request, os, json

GATEWAY = 'https://api.maton.ai'
HEADERS = {
    'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
    'Content-Type': 'application/json',
    'LinkedIn-Version': '202506',
    'X-Restli-Protocol-Version': '2.0.0',
}

# Step 0: Get person ID
req = urllib.request.Request(f'{GATEWAY}/linkedin/rest/me')
for k, v in HEADERS.items(): req.add_header(k, v)
person_id = json.load(urllib.request.urlopen(req))['id']
owner = f'urn:li:person:{person_id}'

# Step 1: Initialize upload (via gateway)
file_path = '/path/to/video.mp4'
file_size = os.path.getsize(file_path)

init_data = json.dumps({
    'initializeUploadRequest': {
        'owner': owner,
        'fileSizeBytes': file_size,
        'uploadCaptions': False,
        'uploadThumbnail': False,
    }
}).encode()

req = urllib.request.Request(f'{GATEWAY}/linkedin/rest/videos?action=initializeUpload', data=init_data, method='POST')
for k, v in HEADERS.items(): req.add_header(k, v)
init_resp = json.load(urllib.request.urlopen(req))
upload_url = init_resp['value']['uploadInstructions'][0]['uploadUrl']
video_urn = init_resp['value']['video']

# Step 2: Upload binary DIRECTLY to LinkedIn's pre-signed URL (NOT through the gateway)
# The upload URL points to www.linkedin.com — it is pre-signed and needs NO Authorization header.
# IMPORTANT: Use the URL exactly as returned by json.load() — do NOT pass it through shell variables.
with open(file_path, 'rb') as f:
    video_data = f.read()

upload_req = urllib.request.Request(upload_url, data=video_data, method='PUT')
upload_req.add_header('Content-Type', 'application/octet-stream')
upload_resp = urllib.request.urlopen(upload_req)
etag = upload_resp.headers['etag']

# Step 3: Finalize upload (via gateway)
finalize_data = json.dumps({
    'finalizeUploadRequest': {
        'video': video_urn,
        'uploadToken': '',
        'uploadedPartIds': [etag],
    }
}).encode()

req = urllib.request.Request(f'{GATEWAY}/linkedin/rest/videos?action=finalizeUpload', data=finalize_data, method='POST')
for k, v in HEADERS.items(): req.add_header(k, v)
urllib.request.urlopen(req)

# Step 4: Create post with video (via gateway)
post_data = json.dumps({
    'author': owner,
    'lifecycleState': 'PUBLISHED',
    'visibility': 'PUBLIC',
    'commentary': 'Check out this video!',
    'distribution': {'feedDistribution': 'MAIN_FEED'},
    'content': {'media': {'id': video_urn}},
}).encode()

req = urllib.request.Request(f'{GATEWAY}/linkedin/rest/posts', data=post_data, method='POST')
for k, v in HEADERS.items(): req.add_header(k, v)
resp = urllib.request.urlopen(req)
print(f'Video post created! {resp.headers.get("location")}')
EOF

How it works:

  • Steps 1, 3, 4 go through the gateway (api.maton.ai/linkedin/...) — Maton injects your OAuth token automatically.
  • Step 2 goes directly to LinkedIn's pre-signed upload URL (www.linkedin.com/dms-uploads/...) — no auth header needed, no gateway.
  • The etag from the upload response is required for the finalize step.
  • For large videos (>4MB), LinkedIn returns multiple uploadInstructions — upload each chunk to its respective URL and collect all etags.

Video specifications:

  • Length: 3 seconds to 30 minutes
  • File size: 75KB to 500MB
  • Format: MP4

Initialize Document Upload

POST /linkedin/rest/documents?action=initializeUpload
Content-Type: application/json
LinkedIn-Version: 202506

{
  "initializeUploadRequest": {
    "owner": "urn:li:person:{personId}"
  }
}

Response:

{
  "value": {
    "uploadUrlExpiresAt": 1770541530896,
    "uploadUrl": "https://www.linkedin.com/dms-uploads/...",
    "document": "urn:li:document:D4D10AQHr-e30QZCAjQ"
  }
}

Ad Targeting

> Compliance note: Ad targeting involves sensitive audience attributes (age, gender, location, employers). Ensure all targeting criteria comply with LinkedIn's Advertising Policies and applicable anti-discrimination laws. Do not use protected characteristics for discriminatory exclusion in housing, employment, or credit advertising.

Get Available Targeting Facets

GET /linkedin/rest/adTargetingFacets

Returns all available targeting facets for ad campaigns (31 facets including employers, degrees, skills, locations, industries, etc.).

Response:

{
  "elements": [
    {
      "facetName": "skills",
      "adTargetingFacetUrn": "urn:li:adTargetingFacet:skills",
      "entityTypes": ["SKILL"],
      "availableEntityFinders": ["AD_TARGETING_FACET", "TYPEAHEAD"]
    },
    {
      "facetName": "industries",
      "adTargetingFacetUrn": "urn:li:adTargetingFacet:industries"
    }
  ]
}

Available targeting facets include:

  • skills - Member skills
  • industries - Industry categories
  • titles - Job titles
  • seniorities - Seniority levels
  • degrees - Educational degrees
  • schools - Educational institutions
  • employers / employersPast - Current/past employers
  • locations / geoLocations - Geographic targeting
  • companySize - Company size ranges
  • genders - Gender targeting
  • ageRanges - Age range targeting

Getting Your Person ID

To create posts, you need your LinkedIn person ID. Get it from the /rest/me endpoint:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/linkedin/rest/me')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('LinkedIn-Version', '202506')
result = json.load(urllib.request.urlopen(req))
print(f"Your person URN: urn:li:person:{result['id']}")
EOF

Code Examples

JavaScript - Create Text Post

const personId = 'YOUR_PERSON_ID';

const response = await fetch(
  'https://api.maton.ai/linkedin/rest/posts',
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
      'Content-Type': 'application/json',
      'LinkedIn-Version': '202506'
    },
    body: JSON.stringify({
      author: `urn:li:person:${personId}`,
      lifecycleState: 'PUBLISHED',
      visibility: 'PUBLIC',
      commentary: 'Hello from the API!',
      distribution: {
        feedDistribution: 'MAIN_FEED'
      }
    })
  }
);

Python - Create Text Post

import os
import requests

person_id = 'YOUR_PERSON_ID'

response = requests.post(
    'https://api.maton.ai/linkedin/rest/posts',
    headers={
        'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
        'Content-Type': 'application/json',
        'LinkedIn-Version': '202506'
    },
    json={
        'author': f'urn:li:person:{person_id}',
        'lifecycleState': 'PUBLISHED',
        'visibility': 'PUBLIC',
        'commentary': 'Hello from the API!',
        'distribution': {
            'feedDistribution': 'MAIN_FEED'
        }
    }
)

Rate Limits

Throttle TypeDaily Limit (UTC)
----------------------------------
Member150 requests/day
Application100,000 requests/day

Little Text Format (Commentary Field)

The commentary field in posts uses LinkedIn's "Little Text Format". Reserved characters must be escaped with a backslash or the post content will be truncated.

Reserved Characters (Must Escape)

CharacterEscape As
----------------------
\\\
`\``\\`
{\{
}\}
@\@
[\[
]\]
(\(
)\)
<\<
>\>
#\#
*\*
_\_
~\~

Example

{
  "commentary": "Hello\\! Check out these bullet points:\\n\\n\\* Point 1\\n\\* Point 2\\n\\* More info \\(details inside\\)"
}

Mentions and Hashtags

Use Little Text Format syntax for mentions and hashtags:

  • Mention a person: @Display Name
  • Mention an organization: @Company Name
  • Hashtag (template): {hashtag|\\#|MyTag}
  • Hashtag (simple): #hashtag (single words only)

Python Helper Function

def escape_linkedin_commentary(text):
    """Escape reserved characters for LinkedIn Little Text Format."""
    reserved = ['\\', '|', '{', '}', '@', '[', ']', '(', ')', '<', '>', '#', '*', '_', '~']
    for char in reserved:
        text = text.replace(char, '\\' + char)
    return text

# Usage
commentary = escape_linkedin_commentary("Check this out! Details (inside) #tech")
# Result: "Check this out\\! Details \\(inside\\) \\#tech"

Notes

  • Person IDs are unique per application and not transferable across apps
  • Commentary uses Little Text Format — escape reserved characters (\|{}@[]()<>#*_~) with backslash or content will be truncated
  • The author field must use URN format: urn:li:person:{personId}
  • All posts require lifecycleState: "PUBLISHED"
  • Image uploads are a 3-step process: initialize, upload binary, create post
  • Video uploads are a 4-step process: initialize, upload binary, finalize, create post
  • Media upload URLs (images, videos, documents) point to www.linkedin.com, NOT api.linkedin.com. These are pre-signed URLs that do NOT go through the gateway and do NOT require an Authorization header. You MUST use Python urllib to handle these URLs — do NOT pass them through shell variables or use curl, as the URL contains encoded characters (%253D) that get corrupted by shell expansion.
  • Include LinkedIn-Version: 202506 header for all REST API calls
  • Profile picture URLs may expire; re-fetch if needed

Error Handling

StatusMeaning
-----------------
400Missing LinkedIn connection or invalid request
401Invalid or missing Maton API key
403Insufficient permissions (check OAuth scopes)
404Resource not found
422Invalid request body or URN format
429Rate limited
4xx/5xxPassthrough error from LinkedIn API

Error Response Format

{
  "status": 403,
  "serviceErrorCode": 100,
  "code": "ACCESS_DENIED",
  "message": "Not enough permissions to access resource"
}

Troubleshooting: API Key Issues

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with linkedin. For example:
  • Correct: https://api.maton.ai/linkedin/rest/me
  • Incorrect: https://api.maton.ai/rest/me

OAuth Scopes

ScopeDescription
--------------------
openidOpenID Connect authentication
profileRead basic profile
emailRead email address
w_member_socialCreate, modify, and delete posts
r_organization_socialRead organization posts and statistics
w_organization_socialCreate and manage organization posts
r_adsRead advertising account data
rw_adsCreate and manage ad campaigns, campaign groups, and accounts

Note: Available scopes depend on your LinkedIn OAuth connection. Verify granted scopes at your Maton connection settings before attempting advertising operations.

Resources

版本历史

共 6 个版本

  • v1.0.9 当前
    2026-06-07 05:15
  • v1.0.8
    2026-06-06 05:52
  • v1.0.7
    2026-05-03 02:22 安全 安全
  • v1.0.6
    2026-04-30 06:01
  • v1.0.4
    2026-03-27 23:24 安全
  • v1.0.3
    2026-03-26 21:12

安全检测

腾讯云安全 (Keen)

队列中

腾讯云安全 (Sanbu)

队列中

🔗 相关推荐

developer-tools

API Gateway

byungkyu
通过 Maton 管理的 API 路由连接外部服务;仅在用户指定目标应用、账户和任务后使用;以读取/列...
★ 392 📥 103,022
content-creation

AdMapix

fly0pants
广告情报与应用数据分析助手,支持搜索广告素材、分析应用排名、下载量、收入及市场洞察,用于广告素材和竞品分析。
★ 294 📥 136,395
content-creation

Humanizer

biostartechnology
消除AI写作痕迹,使文本更自然真实。基于维基百科"AI写作特征"指南,识别并修正夸张象征、宣传用语、肤浅-ing分析、模糊归因、破折号滥用、三项排比、AI词汇、负面平行结构及冗长连接词等模式。
★ 857 📥 199,237