LinkedIn is the world’s largest professional network on the internet. You can use LinkedIn to find the right job or internship, connect and strengthen professional relationships, and learn the skills you need to succeed in your career. LinkedIn provides an API interface that enables its partners and developers build, run, and grow sustainable businesses on the platform. An API, or Application Programming Interface, is a way of communication between various software components. It is a method in which applications give access to their data in a structured way, without the need of interacting with the user interface. Linkedin’s APIs are grouped and organized by their business lines covering Consumer, Compliance, Learning, Marketing, Sales, and Talent Solutions.
In this article, you will learn how to get your credentials, authenticate the API using OAuth 2.0 and share content from your personal profile.
Navigate to the company creation page, Select Create a Company Page. Click on Company and enter the details and click on Create Page.
You will be asked to provide the following details for you company page:
Name of your company.
Company URL
Company Website
Industry
Company Size
Logo
Tagline - A short description of your company.
Once you have provided all these details, your LinkedIn company page has been created now.
Create the LinkedIn app
Navigate to the developer portal, click on My Apps select Create App and enter the following details for your application:
Application name
Linkedin Page - The LinkedIn Company Page you select will be associated with your app
An optional Privacy policy URL.
Application logo
Agree to the terms and click on Create App
To verify your application click on the verify button.
Click Generate URL copy the verification URL provided and click the I’m done button.
Go to the verification url you just copied, here you will be asked to verify the application for your company page.Click on verify and you will now have successfully created a LinkedIn company page and also created an app to interact with LinkedIn using the REST APIs.
Add Products to the LinkedIn Applcation
Once you have created the LinkedIn App, you need to define what are the products that you are going to use with your app. Based on this, your app will be provided with the necessary permissions that you need. There are three products available to choose from:
Share on LinkedIn - This allows you to post content from your profile.
Sign In with LinkedIn - This allows you to use LinkedIn social sign on your webpage.
Marketing Developer Platform - Allows you to post content from your page. This product requires additional access. You will receive a form for this. Fill up the form and wait for approval. Click on the View Access Form and fill it up with relevant details.
Set-Up the Callback/Redirect URL
The callback url is the URL that OAuth invokes after the authentication process. OAuth redirects back to this URL and appends additional parameters to it, including an access code which will be exchanged for an access_token.
Consuming LinkedIn API with python
Now comes the interesting bit, writing python code that interacts with the API. Under the OAuth 2.0 scopes card in the auth tab of your application you can see the levels of access your app has in my case that is:
Therefore this article will only cover the above scopes which lets you:
Fetch your OAuth credentials from the auth tab of your application.
Leaving passwords in code is obviously terrible idea, as it’s lying there in plaintext for anyone to see and you’re also running risk of accidentally pushing it to git repo. A little better option would be to store it in environment variables. Create a .env file and populate it with your credentials as follows:
Now that we have the credentials in place lets begin interacting with the LinkedIn APIs
Install python dependencies
To write code that interacts with REST APIs, you need to make HTTP Requests to the various API endpoints.In python the requests library allows you to send HTTP/1.1 requests extremely easily. It abstracts the complexities of making requests behind a beautiful, simple API so that you can focus on interacting with services and consuming data in your application.
To install requests :
$ python -m pip install requests
Also to read the environment variables created above we need the python-dotenv library that facilitates reading key-value pairs from a .env file and set them as environment variables
Install it with:
The LinkedIn API uses OAuth 2.0 for user authorization and API authentication. Applications must be authorized and authenticated before they can fetch data from LinkedIn or get access to member data.
Request an Authorization Code
To request an authorization code, you must direct the member’s browser to LinkedIn’s OAuth 2.0 authorization page, where the member either accepts or denies your application’s permission request.
GET https://www.linkedin.com/oauth/v2/authorization
Sample request with python
def generate_CSRF_token():
return secrets.token_urlsafe(32)
def parse_redirect_uri(redirect_response):
"""
Extract the authorization code from the redirect uri.
""" url = urlparse(redirect_response)
url = parse_qs(url.query)
return url["code"][0]
def request_authorization_code(url: str, client_id: str, redirect_uri: str):
csrf_token = generate_CSRF_token()
params = {
"response_type": "code",
"client_id": client_id,
"redirect_uri": redirect_uri,
"state": csrf_token,
"scope": "r_liteprofile,r_emailaddress,w_member_social",
}
with requests.session() as s:
response = s.get(url=url, params=params)
OAuthURL = response.url
webbrowser.open_new_tab(OAuthURL)
print(
f"""
Copy the URL of where you have been redirected to:\n """ )
# Get the authorization code from the callback url input redirect_response = input("Paste the redirect URL here:")
auth_code = parse_redirect_uri(redirect_response)
return auth_code
This is a bit chunky but here we are basically building a GET request to the authorization endpoint with the following parameters:
response_type (string) - The value of this field should always be: code
client_id (string) - The API Key value generated when you registered your application.
redirect_uri (string) - The URI your users are sent back to after authorization. This value must match one of the Redirect URLs defined in your application configuration.
state (string) - A unique string value of your choice that is hard to guess.
scope (string) - URL-encoded, space-delimited list of member permissions your application is requesting on behalf of the user.
The state request parameter string is generated in the generate_CSRF_token() function that uses the secrets module to generate a random URL-safe text string, containing 32 bytes random bytes.
Using the webbrowser module we open the authorizatio url we just built in a new window of your default browser basically making a GET request with the above parameters. This directs to LinkedIn’s OAuth 2.0 authorization page, where the member either accepts or denies your application’s permission request.
By providing valid LinkedIn credentials and clicking Allow, the member approves your application’s request to access their member data and interact with LinkedIn on their behalf.
This approval instructs LinkedIn to redirect the member to the redirect URL that you defined in your redirect_uri parameter.
Attached to the redirect_uri are two important URL arguments that you need to read from the request:
code - The OAuth 2.0 authorization code.
state - A value used to test for possible CSRF attacks.
I’ve setup a simple HTTP server with python that servers a simple HTML page on the redirect url and using ngrok exposed this web server running on my machine to LinkedIn. You dont need to do this.
This is beyond the scope of the article and is completely optional. The python script then reads the redirect url as input and filters out the Authorization code. You will thus need to copy this url and paste it after the prompt Copy the URL of where you have been redirected to:
In our case the url is:
The next step is to get an access token for your application using the authorization code from the previous step.
To generate an access token, issue a HTTP POST request against the accessToken url with a Content-Type header of x-www-form-urlencoded and the following parameters in the request body:
POST https://www.linkedin.com/oauth/v2/accessToken
Define the file path to our .env file load it and read the environment variables.
Obtain an Authorization Code
Obtain an Access Token
Run the encapsulating main() function
Make Authenticated Requests
Once you’ve obtained an access token, you can start making authenticated API requests on behalf of the member by including an Authorization header in the HTTP call to LinkedIn’s API.
Get User LinkedIn profile information
The Profile API returns a member’s LinkedIn profile, based on the access token.
Make a HTTP GET request to the endpoint url:
There are multiple ways to share content with your LinkedIn network. You can create shares using text, URLs, and images. In this article i have selected to share an article from my dev.to account. Your application may post shares in the context of a specific member or organization. Use a URN in the owner field to associate the share with an organization or authenticated member. The valid URN formats are urn:li:person:{id}.
You will need the permission w_member_social to create shares on behalf of a member, or w_organization_social to create shares on behalf of an organization.
POST https://api.linkedin.com/v2/shares
Request body schema
owner - Owner of the share
text - Text of the share
content - Referenced content such as articles and images
distribution - Distribution target for the share
Create an Atricle Share
Sample Request Body
{
"content": {
"contentEntities": [
{
"entityLocation": "https://dev.to/danchei99/getting-started-with-fast-api-and-docker-part-1-54oo",
"thumbnails": [
{
"resolvedUrl": "https://res.cloudinary.com/practicaldev/image/fetch/s--k24egrxV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aifzgpakwlbxzukgaaj.png" }
]
}
],
"title": "Getting Started with Fast API and Docker" },
"distribution": {
"linkedInDistributionTarget": {}
},
"owner": "urn:li:person:<person_id>",
"text": {
"text": "Learn more about APIs and Docker by reading the Blog!" }
}
Sample request with python
def share_article(access_token: str, profile_id: str):
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
}
payload = {
"content": {
"contentEntities": [
{
"entityLocation": "https://dev.to/danchei99/getting-started-with-fast-api-and-docker-part-1-54oo",
"thumbnails": [
{
"resolvedUrl": "https://res.cloudinary.com/practicaldev/image/fetch/s--k24egrxV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aifzgpakwlbxzukgaaj.png" }
],
}
],
"title": "Getting Started with Fast API and Docker",
},
"distribution": {"linkedInDistributionTarget": {}},
"owner": f"urn:li:person:{profile_id}",
"text": {"text": "Learn more about APIs and Docker by reading the Blog!"},
}
with requests.session() as s:
response = s.post(url=SHARE_URL, headers=headers, json=payload)
return response.json()
Sample Response
A successful share request returns a JSON response:
{
"owner":"urn:li:person:uvoFu7gji4",
"activity":"urn:li:activity:6956317238383509504",
"edited":false,
"created":{
"actor":"urn:li:person:uvoFu7gji4",
"time":1658515271742
},
"text":{
"text":"Learn more about APIs and Docker by reading the Blog!" },
"lastModified":{
"actor":"urn:li:person:uvoFu7gji4",
"time":1658515271742
},
"id":"6956317237402046465",
"distribution":{
"linkedInDistributionTarget":{
"visibleToGuest":true }
},
"content":{
"title":"Getting Started with Fast API and Docker",
"contentEntities":[
{
"thumbnails":[
{
"imageSpecificContent":{
},
"resolvedUrl":"https://res.cloudinary.com/practicaldev/image/fetch/s--k24egrxV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aifzgpakwlbxzukgaaj.png" }
],
"title":"Getting Started with Fast API and Docker",
"entityLocation":"https://dev.to/danchei99/getting-started-with-fast-api-and-docker-part-1-54oo" }
],
"shareMediaCategory":"ARTICLE" }
}
Once the request is successful, the content will be shared from your personal profile and it will appear in the feed as follows:
Full Code
Here is the complete code:
importosimportsecretsimportstringimportwebbrowserfrompathlibimport Path
fromurllib.parseimport parse_qs, urlparse
importrequestsfromdotenvimport load_dotenv, set_key
AUTHORIZATION_URL = "https://www.linkedin.com/oauth/v2/authorization"ACCESS_TOKEN_URL = "https://www.linkedin.com/oauth/v2/accessToken"USER_PROFILE_URL = "https://api.linkedin.com/v2/me"SHARE_URL = "https://api.linkedin.com/v2/shares"def generate_CSRF_token():
return secrets.token_urlsafe(32)
def parse_redirect_uri(redirect_response):
"""
Extract the authorization code from the redirect uri.
""" url = urlparse(redirect_response)
url = parse_qs(url.query)
return url["code"][0]
def request_authorization_code(client_id: str, redirect_uri: str):
csrf_token = generate_CSRF_token()
params = {
"response_type": "code",
"client_id": client_id,
"redirect_uri": redirect_uri,
"state": csrf_token,
"scope": "r_liteprofile,r_emailaddress,w_member_social",
}
with requests.session() as s:
response = s.get(AUTHORIZATION_URL, params=params)
OAuthURL = response.url
webbrowser.open_new_tab(OAuthURL)
print(
f"""
Copy the URL of where you have been redirected to:\n """ )
redirect_response = input("Paste the redirect URL here:")
"""
Extract the authorization code from the redirect uri.
""" auth_code = parse_redirect_uri(redirect_response)
return auth_code
def authorize(client_id: str, redirect_url: str, env_path: Path):
authorization_code = os.environ.get("AUTHORIZATION_CODE", None)
ifnot authorization_code:
authorization_code = request_authorization_code(
AUTHORIZATION_URL, client_id, redirect_url
)
set_key(env_path, "AUTHORIZATION_CODE", authorization_code)
return authorization_code
def get_access_token(
auth_code: str, redirect_uri: str, client_id: str, client_secret: str
):
# Request body parameters params = {
"grant_type": "authorization_code",
"code": auth_code,
"redirect_uri": redirect_uri,
"client_id": client_id,
"client_secret": client_secret,
}
with requests.session() as s:
response = s.post(url=ACCESS_TOKEN_URL, params=params)
return response.json()["access_token"]
def get_linkedin_profile(access_token: str):
# Request header header = {"Authorization": f"Bearer {access_token}"}
with requests.session() as s:
response = s.get(USER_PROFILE_URL, headers=header)
# return response.json()["id"]return response.json()
def share_article(access_token: str, profile_id: str):
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
}
payload = {
"content": {
"contentEntities": [
{
"entityLocation": "https://dev.to/danchei99/getting-started-with-fast-api-and-docker-part-1-54oo",
"thumbnails": [
{
"resolvedUrl": "https://res.cloudinary.com/practicaldev/image/fetch/s--k24egrxV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8aifzgpakwlbxzukgaaj.png" }
],
}
],
"title": "Getting Started with Fast API and Docker",
},
"distribution": {"linkedInDistributionTarget": {}},
"owner": f"urn:li:person:{profile_id}",
"text": {"text": "Learn more about APIs and Docker by reading the Blog!"},
}
with requests.session() as s:
response = s.post(url=SHARE_URL, headers=headers, json=payload)
return response.json()
def main():
env_path = Path.cwd() / ".env" load_dotenv(env_path)
client_id, client_secret, redirect_url = (
os.environ.get("CLIENT_ID", None),
os.environ.get("CLIENT_SECRET", None),
os.environ.get("REDIRECT_URL", None),
)
authorization_code = authorize(client_id, redirect_url, env_path)
access_token = get_access_token(
authorization_code, redirect_url, client_id, client_secret
)
user_profile = get_linkedin_profile(access_token)
person_id = user_profile["id"]
share_response = share_article(access_token, person_id)
if __name__ == "__main__":
main()
Limitations of LinkedIn APIs
Starting on May 12, 2015, LinkedIn limited the open APIs to only support the following uses:
Enabling members to share professional content to their LinkedIn network from across the Web leveraging our Share API.
Enabling companies to share professional content to LinkedIn with our Company API.
The use of all other APIs was restricted to those developers approved by LinkedIn requiring developers to become members of one of their partnership programs which means having to reach out to your LinkedIn Relationship Manager or Business Development contact to get this and you will need to meet certain criteria and sign an API agreement with data restrictions in order to use this integration.
Conclusion
In this article, we have focused on how to use the LinkedIn REST APIs and share content from a personal profile. LinkedIn is a powerful platform to share content with your social network. Ensuring your content receives the professional audience it deserves.
This enables you:
Get your content in front of an audience of millions of professionals.
Drive traffic to your site and grow your member base.
Benefit from having your content shared across multiple professional networks worldwide.
Resources
To understand LinkedIn Apis better, i recommend looking at the following resource: