[Python] LinkedIn API: Authorization Error When Posting on Behalf of Organization

Discussão em 'Python' iniciado por Stack, Abril 27, 2025.

  1. Stack

    Stack Membro Participativo

    I’m developing an application that integrates with the LinkedIn API to post content on behalf of our organization. Despite being listed as a super admin and having the following OAuth 2.0 scopes:

    [​IMG] • w_organization_social • rw_organization_admin • r_organization_social 

    I’m encountering the following error when attempting to create a post:

    com.linkedin.content.common.exception.BadRequestResponseException: denied by [resource: organizationUgcAuthorizations => responseStatus: DENIED]

    'description' ='Write to post is denied due to lack of permission'
    'input' ={}
    'code' ='AUTH_DELEGATION_DENIED'


    Additionally, the error code returned is AUTH_DELEGATION_DENIED, with the description: “Write to post is denied due to lack of permission.”

    Steps Taken:

    1. Confirmed that my LinkedIn application has the necessary scopes mentioned above.
    2. Verified that I’m listed as a super admin for the organization.
    3. Ensured that the access token is valid and includes the required scopes.
    4. Attempted to post using the endpoint: https://api.linkedin.com/v2/ugcPosts. 


    Are there additional permissions or configurations required to post on behalf of an organization using the LinkedIn API? Any insights or suggestions would be greatly appreciated.

    Code :

    organization_url = urn:li:eek:rganization:<company_id>

    ⸻

    def post_it(self, title: str, content: str, image_url: str = None, scheduled_time: datetime.datetime = None):
    if not self.access_token or not self.organization_urn:
    raise Exception("Access token and organization URN must be set before posting content.")

    post_data = {
    "author": self.organization_urn,
    "lifecycleState": "PUBLISHED",
    "specificContent": {
    "com.linkedin.ugc.ShareContent": {
    "shareCommentary": {
    "text": f"{title}\n\n{content}"
    },
    "shareMediaCategory": "NONE"
    }
    },
    "visibility": {
    "com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"
    }
    }

    if image_url:
    # First register the media asset
    media_register_data = {
    "registerUploadRequest": {
    "recipes": ["urn:li:digitalmediaRecipe:feedshare-image"],
    "owner": self.organization_urn,
    "serviceRelationships": [{
    "relationshipType": "OWNER",
    "identifier": "urn:li:userGeneratedContent"
    }]
    }
    }

    # Register the media asset
    media_register_response = self.client.action(
    resource_path="/assets",
    action_name="registerUpload",
    action_params=media_register_data,
    access_token=self.access_token
    )

    # Get the upload URL and asset URN
    upload_url = media_register_response.value.get('uploadMechanism').get('com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest').get('uploadUrl')
    asset_urn = media_register_response.value.get('asset')

    # Upload the image to the provided URL
    image_data = requests.get(image_url).content
    upload_response = requests.put(
    upload_url,
    data=image_data,
    headers={"Content-Type": "image/jpeg"}
    )

    if upload_response.status_code != 201:
    raise Exception(f"Failed to upload image: {upload_response.text}")

    # Update post data with the media asset
    post_data["specificContent"]["com.linkedin.ugc.ShareContent"]["shareMediaCategory"] = "IMAGE"
    post_data["specificContent"]["com.linkedin.ugc.ShareContent"]["media"] = [{
    "status": "READY",
    "description": {
    "text": content
    },
    "media": asset_urn,
    "title": {
    "text": title or content[:100]
    }
    }]

    if scheduled_time:
    post_data["lifecycleState"] = "DRAFT"
    post_data["scheduledTime"] = int(scheduled_time.timestamp() * 1000)

    response = self.client.create(
    resource_path="/ugcPosts",
    entity=post_data,
    access_token=self.access_token
    )

    return response

    Continue reading...

Compartilhe esta Página