profile = "social-media/publish-post@2.0" provider = "linkedin" """ Publish Share to LinkedIn For text-only posts, links, and images (up to 200MB per image). """ map PublishPost { set { // FIXME: New posts API doesn't support content scraping: https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/posts-api?view=li-lms-2023-02&tabs=curl#article-post-creation-sample-request // AND title is required, so this is a poor attempt to provide at least something content = input.link ? {article: { source: input.link, title: input.title || input.link }} : undefined media = Array.isArray(input.media) ? input.media : [] text = input.text } // FIXME: Workaround for https://github.com/superfaceai/one-sdk-js/issues/215 images = call foreach(index of Array(media.length).fill().map((_, i) => i)) UploadImage(media = input.media, index = index, accessToken = parameters.accessToken, profileId = input.profileId) set if (Array.isArray(images) && images.length > 0) { // append the link to the post text = input.link ? `${text || ''} ${input.link}`.trim() : text content = undefined // FIXME: Avoid SDK's "fun" feature of merging objects implicitly } set if (Array.isArray(images) && images.length === 1) { content = {media: images[0]} } // multiple images are special case // https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/multiimage-post-api?view=li-lms-2023-02&tabs=http#create-multiimage-content set if (Array.isArray(images) && images.length > 1) { content = { multiImage: { images: images, } } } // https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/posts-api?view=li-lms-2023-02&tabs=http#create-a-post http POST "/rest/posts" { request "application/json" { headers { "Authorization" = `Bearer ${parameters.accessToken}`, "LinkedIn-Version" = "202302", "X-Restli-Protocol-Version" = "2.0.0", "Accept" = "application/json", } body { author = input.profileId, commentary = text || "", visibility = "PUBLIC", lifecycleState = "PUBLISHED", distribution = { feedDistribution: "MAIN_FEED", targetEntities: [], thirdPartyDistributionChannels: [] }, content = content, } } response 201 "application/json" { urn = headers["x-restli-id"] return map result { postId = urn, url = `https://www.linkedin.com/feed/update/${urn}`, } } response { error = call MapError(statusCode = statusCode, body = body) map error error } } } // https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/images-api?view=li-lms-2023-02&tabs=http#uploading-an-image operation UploadImage { mediaItem = args.media[args.index] set { uploadPath = undefined assetUrn = undefined } // 1. register upload http POST "/rest/images" { security none request { query { action = "initializeUpload", } headers { "X-RestLi-Protocol-Version" = "2.0.0", "Authorization" = `Bearer ${args.accessToken}`, "LinkedIn-Version" = "202302", "Accept" = "application/json", } body { initializeUploadRequest = { owner: args.profileId, } } } response 200 "application/json" { uploadPath = body.value.uploadUrl.replace('https://www.linkedin.com/', '') // no URL parsing for you assetUrn = body.value.image } response { error = call MapError(statusCode = statusCode, body = body) fail error } } // 2. upload the image // https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/vector-asset-api?view=li-lms-2023-02&tabs=http#upload-the-image http PUT "www" "/{uploadPath}" { request "application/octet-stream" { headers { "Authorization" = `Bearer ${args.accessToken}`, } body = mediaItem.contents } response 201 { return { id = assetUrn, altText = mediaItem.altText, } } // Error responses from this endpoint have empty body response 400 { fail { title = "Bad Request", detail = "Media upload resulted in Bad Request error." } } response 401 { fail { title = "Unauthorized", detail = "Media upload resulted in Unauthorized error. The access token is either invalid, or expired." } } } } // https://docs.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/share-api?tabs=http#common-creation-errors operation MapError { statusCode = args.statusCode title = `Unknown response: HTTP ${statusCode}` body = args.body detail = body.message set if (statusCode === 400) { title = "Bad Request" } set if (statusCode === 401) { title = "Unauthorized" } set if (statusCode === 403) { title = "Forbidden" } set if (statusCode === 404) { title = "Not Found" } set if (statusCode === 422) { title = "Conflict" } set if (statusCode === 429) { title = "Too Many Requests" } set if (statusCode === 500) { title = "Server Error" } return { title = title, detail = detail, original = body, } }