Skip to content

Commit 519c5ab

Browse files
authored
docs: 📚 added create posts example using Share on LinkedIn (#14)
1 parent 85b7349 commit 519c5ab

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

examples/README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,24 @@ This directory contains examples showing how to use the LinkedIn API Python clie
44

55
### Steps to Run
66

7-
1. Navigate inside the `/examples` directory
8-
2. Create a `.env` file that contains the following variables that will be used when running the examples. Only some of these variables may actually be needed to run a particular script. Check the specific example comments on more specific requirements (e.g. required scopes for the access token).
7+
1. Activate virtual environment: `pipenv shell`
8+
2. Navigate inside the `/examples` directory
9+
3. Create a `.env` file that contains the following variables that will be used when running the examples. Only some of these variables may actually be needed to run a particular script. Check the specific example comments on more specific requirements (e.g. required scopes for the access token).
910
```sh
1011
ACCESS_TOKEN="your_valid_access_token"
1112
CLIENT_ID="your_app_client_id"
1213
CLIENT_SECRET="your_app_client_secret"
1314
OAUTH2_REDIRECT_URL="your_app_oauth2_redirect_url"
1415
```
15-
3. Execute the desired example script: `python3 {script filename}`. For example: `python3 get-profile.ts`
16+
4. Execute the desired example script: `python3 {script filename}`. For example: `python3 get_profile.py`
17+
18+
### Example Notes
19+
20+
| Example filename | Description |
21+
|---|---|
22+
| `oauth_member_auth_redirect.py` | Demonstrates the member oauth redirect flow (authorization code flow) to obtain a 3-legged access token. |
23+
| `oauth_2legged.py` | Obtains a 2-legged access token and performs introspection. |
24+
| `get_profile.py` | Uses Sign In With LinkedIn v1 to fetch member profile. Also demonstrates use of field projections and decoration. |
25+
| `create_posts.py` | Uses Sign In With LinkedIn v1 and Share on LinkedIn to create posts. |
26+
| `crud_ad_accounts.py` | Performs create, get, finder, partial update, and delete requests on ad accounts. |
27+
| `batch_get_campaign_groups_query_tunneling.py` | Demonstrates a request that requires query tunneling, which is performed automatically by the client. |

examples/create_posts.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""
2+
Example calls to create a post on LinkedIn. This requires a member-based token with the following
3+
scopes (r_liteprofile, w_member_social), which is provided by the Sign in with LinkedIn and Share on LinkedIn
4+
API products.
5+
6+
The steps include:
7+
1. Fetching the authenticated member's profile to obtain the member's identifier (a person URN)
8+
2. Create a post using /ugcPosts endpoint (legacy) or /posts endpoint (new)
9+
10+
To view these posts, go to linkedin.com and click Me > Posts & Activity.
11+
12+
BEWARE: This will make an actual post to the main feed which is visible to anyone.
13+
"""
14+
15+
import os, sys
16+
17+
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
18+
from dotenv import load_dotenv, find_dotenv
19+
20+
load_dotenv(find_dotenv())
21+
22+
from linkedin_api.clients.restli.client import RestliClient
23+
import json
24+
25+
ACCESS_TOKEN = os.getenv("ACCESS_TOKEN")
26+
if ACCESS_TOKEN is None:
27+
raise Exception(
28+
'A valid access token must be defined in the /examples/.env file under the variable name "ACCESS_TOKEN"'
29+
)
30+
31+
ME_RESOURCE = "/me"
32+
UGC_POSTS_RESOURCE = "/ugcPosts"
33+
POSTS_RESOURCE = "/posts"
34+
API_VERSION = "202302"
35+
36+
restli_client = RestliClient()
37+
restli_client.session.hooks["response"].append(lambda r: r.raise_for_status())
38+
39+
"""
40+
Calling the /me endpoint to get the authenticated user's person URN
41+
"""
42+
me_response = restli_client.get(resource_path=ME_RESOURCE, access_token=ACCESS_TOKEN)
43+
print(f"Successfully fetched profile: {json.dumps(me_response.entity)}")
44+
45+
46+
"""
47+
Calling the legacy /ugcPosts API to create a text post on behalf of the authenticated member
48+
"""
49+
ugc_posts_create_response = restli_client.create(
50+
resource_path=UGC_POSTS_RESOURCE,
51+
entity={
52+
"author": f"urn:li:person:{me_response.entity['id']}",
53+
"lifecycleState": "PUBLISHED",
54+
"specificContent": {
55+
"com.linkedin.ugc.ShareContent": {
56+
"shareCommentary": {
57+
"text": "Sample text post created with /ugcPosts API"
58+
},
59+
"shareMediaCategory": "NONE",
60+
}
61+
},
62+
"visibility": {"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"},
63+
},
64+
access_token=ACCESS_TOKEN,
65+
)
66+
print(
67+
f"Successfully created post using /ugcPosts: {ugc_posts_create_response.entity_id}"
68+
)
69+
70+
71+
"""
72+
Calling the newer, more streamlined (and versioned) /posts API to create a text post on behalf
73+
of the authenticated member
74+
"""
75+
posts_create_response = restli_client.create(
76+
resource_path=POSTS_RESOURCE,
77+
entity={
78+
"author": f"urn:li:person:{me_response.entity['id']}",
79+
"lifecycleState": "PUBLISHED",
80+
"visibility": "PUBLIC",
81+
"commentary": "Sample text post created with /posts API",
82+
"distribution": {
83+
"feedDistribution": "MAIN_FEED",
84+
"targetEntities": [],
85+
"thirdPartyDistributionChannels": [],
86+
},
87+
},
88+
version_string=API_VERSION,
89+
access_token=ACCESS_TOKEN,
90+
)
91+
print(f"Successfully created post using /posts: {posts_create_response.entity_id}")

0 commit comments

Comments
 (0)