Skip to content
Colin Wren

The frustrations of dealing with the LinkedIn API

Software Development, Automation, Technology4 min read

Recently I was working on an extension to my automated resume set up (using HackMyResume and Travis) which was to have a script update my LinkedIn profile on the release of a new resume.

My reasoning behind this need was that while I review and update my Resume about once a month I hardly ever use LinkedIn except to clear out the connection requests from recruiters who offer me work completely out of my skill set.

However while I’m not proactively using LinkedIn I am aware of the value it gives to those conducting interviews, especially when all they have to work with is a one page CV.

There’s been a number of interviews I’ve been in where the person conducting the interview has had a print out of both my CV and my LinkedIn profile so it’s important that both contain similar information.

Automating updates to LinkedIn

Automating the updates would involve getting a diff of the current and new resume.json file and then using that diff to send update requests to the LinkedIn via the public APIs it offers.

There was going to be a potential issue which was that in order to do anything involving user data you need to use a 3 step OAuth flow which would have meant updating an access code every 3 months but for the sake of effortless updates of my profile I was willing to attempt it.

So I went onto LinkedIn’s developer site, created an organisation page (need to register an app), registered my application and created a basic OAuth flow using Postman and Python’s SimpleHTTPServer module to act as the redirect URL.

Unfortunately, once I got the access token and started to use the API I realised due to the permissions model and LinkedIn’s lack of forewarning on their documentation I wasn’t going to achieve what I set out to do.

Editing your profile via LinkedIn’s Profile-Edit-API

LinkedIn has a number of APIs, there’s the Profile-API for getting users profiles and there’s the Profile-Edit-API which can be used to send a patch of the user’s profile to update the content.

In order to use the Profile-Edit-API you need to have the w_compliance permission associated with your app.

The w_compliance permission is gained via LinkedIn’s partner program where an app that promises not to compete with LinkedIn or abuse the API can gain access to more data.

At the time of writing however LinkedIn is no longer accepting new applications to the partner program so the w_compliance permission is completely unobtainable.

Stuck in a help centre loop

It was not very clear at all in the documentation that the partner program was how you gain access to the w_compliance permission or that LinkedIn were not taking new applicants for the partner program.

So I decided to use the help centre on LinkedIn’s documentation to track down how I would gain access to the w_compliance permission.

The first port of call was the FAQs which didn’t really offer much, you’ll find the message about the partner programs being unavailable but at this time I hadn’t realised this was what I needed to get access to the correct permissions.

I then tried the LinkedIn forums where there were a couple of posts from developers asking how to get access to the permission.

I’m not sure if the response came from an automated bot or the person didn’t grasp the question but the responses to the posts were exactly the same, telling the poster to go to the LinkedIn developer website.

So at this point I’ve been on the LinkedIn developer website, gone to the LinkedIn help centre, found a relevant post that then tells me to go back to the LinkedIn developer website — fucking classic!

Of course at no time does the help centre show any form of email or phone number I could have contacted to make enquiries.

Eventually I gave up using LinkedIn’s (un)help(ful) centre and went over to Stack Overflow which after doing broader and broader searches I finally came across this post from 2015 which had been updated to explain that the partner program had been stopped.

If the API doesn’t work, I can automate it right?

Nope, it turns out LinkedIn has a practice of banning people’s accounts if they are found to be using Selenium or similar automation software.

As someone who is looking to use this automation to update my profile it wouldn’t really be valuable to me to have that account then banned!

Making manual updates easier

So with automated updates ruled out I decided to pivot my idea from automatically updating my LinkedIn profile to just making the job of updating my LinkedIn profile easier.

The original concept is still the same, I have a script that generates the diff from the previous and current resume.json but now instead of using the diff to send information via the LinkedIn API I send that diff into a templating engine and produce a HTML webpage that has easy to follow instructions on what to update.

I had originally wanted to generate a HTML email and send this from Travis but it turns out Travis blocks outgoing SMTP connections so I had to settle with uploading it to my site.

output of changes
An example of the change list HTML page
1// some JS objects to compare
2const v1 = {foo: "bar"};
3const v2 = {foo: "baz", bar: "foo"};
5const jsonDiff = require('json-diff');
6const diff = jsonDiff.diff(v1, v2);
8// { foo: { __old: 'bar', __new: 'baz' }, bar__added: "foo" }
An example of how json-diff works
2 "about": {
3 "additions": [],
4 "changes": [],
5 "removals": []
6 },
7 "experience": {
8 "additions": [],
9 "changes": [
10 {
11 "original_position": "Test Automation Engineer - International Gambling Company",
12 "summary": "Working for a international gambling sector client to launch their New Jersey offering. Moved from Development to Test Automation as they grow their global platform for new markets. Developed a regression suite for testing a Kafka based sports data platform with bi-directional traceability in JIRA"
13 }
14 ],
15 "removals": []
16 },
17 "education_certification_courses": {
18 "additions": [],
19 "changes": [],
20 "removals": []
21 },
22 "volunteer": {
23 "additions": [],
24 "changes": [],
25 "removals": []
26 },
27 "skills": {
28 "additions": [],
29 "changes": [],
30 "removals": []
31 },
32 "publications": {
33 "additions": [],
34 "changes": [],
35 "removals": []
36 },
37 "projects": {
38 "additions": [],
39 "changes": [],
40 "removals": []
41 },
42 "honours": {
43 "additions": [],
44 "changes": [],
45 "removals": []
46 },
47 "language": {
48 "additions": [],
49 "changes": [],
50 "removals": []
51 },
52 "organisations": {
53 "additions": [],
54 "changes": [],
55 "removals": []
56 }
An example of the JSON format I used to create the changes list

That’ll do pig, that’ll do

While I can’t deny I’m not happy with how things planned out I’ve at least got myself some means of reminding me to update my LinkedIn profile and I’ve made it semi-easy to update it.

I would like to end this blog by saying that LinkedIn probably has one of the worst developer experiences I’ve had in a long time.

The documentation is extensive with loads of examples, but the simple fact that a lot of the APIs used in those examples require partner program approval and they didn’t think to make it really clear the articles were redundant due to the partner program not being open has probably wasted many hours of developer time.