0
Create Image Post (User)
One script reply has been approved by the moderators Verified

Create an image post on LinkedIn. See the docs here

Created by hugo697 130 days ago Viewed 54 times
0
Submitted by hugo697 Typescript (fetch-only)
Verified 130 days ago
1
type Linkedin = {
2
	token: string
3
	apiVersion: string
4
}
5

6
type Base64 = string
7

8
async function initializeImageUpload(resource: Linkedin, owner: string) {
9
	const endpoint = 'https://api.linkedin.com/rest/images?action=initializeUpload'
10
	const response = await fetch(endpoint, {
11
		method: 'POST',
12
		headers: {
13
			Authorization: `Bearer ${resource.token}`,
14
			'X-Restli-Protocol-Version': '2.0.0',
15
			'Content-Type': 'application/json',
16
			'LinkedIn-Version': `${resource.apiVersion}`
17
		},
18
		body: JSON.stringify({
19
			initializeUploadRequest: {
20
				owner
21
			}
22
		})
23
	})
24

25
	if (!response.ok) {
26
		throw new Error(`HTTP error! status: ${response.status}`)
27
	}
28

29
	const data = await response.json()
30
	return data.value
31
}
32

33
async function uploadImage(uploadUrl: string, image: Base64) {
34
	const buffer = Buffer.from(image, 'base64')
35

36
	const response = await fetch(uploadUrl, {
37
		method: 'PUT',
38
		headers: {
39
			'Content-Type': 'application/octet-stream'
40
		},
41
		body: buffer
42
	})
43

44
	if (!response.ok) {
45
		throw new Error(`HTTP error! status: ${response.status}`)
46
	}
47
}
48

49
export async function main(
50
	resource: Linkedin,
51
	postData: {
52
		author: string
53
		commentary: string
54
		visibility: 'CONNECTIONS' | 'PUBLIC' | 'LOGGED_IN' | 'CONTAINER'
55
		distribution: {
56
			feedDistribution: 'NONE' | 'MAIN_FEED'
57
		}
58
		content: {
59
			media: {
60
				id: string
61
				title?: string
62
				altText?: string
63
			}
64
		}
65
		isReshareDisabledByAuthor: boolean
66
	},
67
	image: Base64
68
) {
69
	// Step 1: Initialize image upload
70
	const uploadData = await initializeImageUpload(resource, postData.author)
71
	const uploadUrl = uploadData.uploadUrl
72
	const imageUrn = uploadData.image
73

74
	// Step 2: Upload the image
75
	await uploadImage(uploadUrl, image)
76

77
	// Step 3: Create post with image
78
	postData.content.media.id = imageUrn
79

80
	const endpoint = 'https://api.linkedin.com/rest/posts'
81

82
	const response = await fetch(endpoint, {
83
		method: 'POST',
84
		headers: {
85
			Authorization: `Bearer ${resource.token}`,
86
			'X-Restli-Protocol-Version': '2.0.0',
87
			'Content-Type': 'application/json',
88
			'LinkedIn-Version': `${resource.apiVersion}`
89
		},
90
		body: JSON.stringify({ ...postData, lifecycleState: 'PUBLISHED' })
91
	})
92

93
	if (!response.ok) {
94
		throw new Error(`HTTP error! status: ${response.status}`)
95
	}
96

97
	const postId = response.headers.get('x-restli-id')
98
	const data = await response.json()
99
	return { ...data, postId }
100
}
101