Failed to create subscription: LinkedIn Developer API real-time notification error

I’m working on enabling real-time notifications from LinkedIn. I can successfully retrieve access tokens, but when I try to create a real-time notification subscription, the API returns the following error. Could someone please help me understand what might be causing this issue?

Error Message { "message": "Failed to create subscription. RestException{_response=RestResponse[headers={Content-Length=13373, content-type=application/x-protobuf2; symbol-table="https://ltx1-app150250.prod.linkedin.com:3778/partner-entities-manager/resources|partner-entities-manager-war--60418946", x-restli-error-response=true, x-restli-protocol-version=2.0.0},cookies=[],status=400,entityLength=13373]}", "status": 400 }

My code is below

def linkedinCallBack(request):
    """Handle LinkedIn OAuth callback."""
    code = request.GET.get('code')
    state = request.GET.get('state')

    if not code or not state:
        return handle_redirect(request, message_key='missing_params')

    try:
        error, state_data = parse_state_json(state)
        if error:
            return handle_redirect(request, message_key='missing_params')

        error, platform = get_social_platform(state_data['platform_id'])
        if error:
            return handle_redirect(request, message=error)

        redirect_uri = request.build_absolute_uri(
            reverse('social:linkedin_callback'))

        # Exchange code for access token
        token_url = 'https://www.linkedin.com/oauth/v2/accessToken'
        data = {
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': redirect_uri,
            'client_id': os.environ.get('LINKEDIN_APP_ID'),
            'client_secret': os.environ.get('LINKEDIN_APP_SECRET'),
        }
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = requests.post(token_url, data=data, headers=headers)

        if response.status_code != 200:
            return handle_redirect(request, message_key='token_failed')

        token_data = response.json()
        access_token = token_data.get('access_token', None)
        refresh_token = token_data.get('refresh_token', None)
        refresh_token_expires_in = token_data.get(
            'refresh_token_expires_in', None)
        expires_in = token_data.get('expires_in', 3600)
        if not access_token:
            return handle_redirect(request, message_key='token_failed')
        LINKEDIN_API_VERSION = os.environ.get('LINKEDIN_API_VERSION')

        org_url = "https://api.linkedin.com/v2/organizationalEntityAcls"
        params = {
            'q': 'roleAssignee',
            'role': 'ADMINISTRATOR',
            'state': 'APPROVED',
            'projection': '(elements*(*,organizationalTarget~(id,localizedName)))'
        }

        headers = {
            'Authorization': f'Bearer {access_token}',
            'X-Restli-Protocol-Version': '2.0.0',
            'LinkedIn-Version': LINKEDIN_API_VERSION
        }

        org_response = requests.get(org_url, headers=headers, params=params)
        app_id = os.environ.get('LINKEDIN_APP_UID')
        developer_urn = f'urn:li:developerApplication:{app_id}'  # Update this
        webhook_url = request.build_absolute_uri(
            reverse('social:linkedin_wehbook'))

        org_data = org_response.json()
        page_names = []
        for org in org_data.get("elements", []):
            page_id = org.get("organizationalTarget~", {}).get("id")
            page_name = org.get("organizationalTarget~",
                                {}).get("localizedName")

            person_urn = org.get("roleAssignee")
            role = org.get("role")
            organization_urn = org.get("organizationalTarget")

            platform_config = {
                "role": role,
                "roleAssignee": person_urn,
                "organizationalTarget": organization_urn
            }

            subscription_key = (
                f"(developerApplication:{urllib.parse.quote(developer_urn)},"
                f"user:{urllib.parse.quote(person_urn)},"
                f"entity:{urllib.parse.quote(organization_urn)},"
                "eventType:ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS)"
            )

            subscription_url = f'https://api.linkedin.com/rest/eventSubscriptions/{subscription_key}'
            subscription_data = json.dumps({'webhook': webhook_url})

            headers['Content-Type'] = 'application/json'
            response = requests.put(
                subscription_url, headers=headers, data=subscription_data)
            response_json = response.json()
            if response.status_code not in (200, 201, 204):
                return handle_redirect(request, message=f'Subscription failed for {page_name}: {response.text}')
            error = save_social_account(
                platform, page_id, page_name, access_token, expires_in, request.user,
                refresh_token=refresh_token, rt_expires_at=refresh_token_expires_in,
                platform_config=platform_config
            )
            if error is not None:
                return handle_redirect(request, message=error)
            page_names.append(page_name)
        return handle_redirect(request, message=f"{platform.name} account(s) connected successfully. {response_json}", message_type='success')

    except Exception as e:
        return handle_redirect(request, message_key='error')

urls.py for webhook url

path('linkedin_wehbook/', views_webhooks.WebhookViewLinkedin.as_view(), name='linkedin_wehbook'),

views_webhooks.py

@method_decorator(csrf_exempt, name='dispatch')
class WebhookViewLinkedin(View):

    def get(self, request, *args, **kwargs):
        # Verification per docs
        challenge = request.GET.get('challengeCode')
        if challenge:
            return JsonResponse({'challengeResponse': challenge})
        return HttpResponseBadRequest('Invalid challenge')

    def post(self, request, *args, **kwargs):
        pass

Notes

  1. The developer urn is taken from the below url Linked in app url
  2. Is there a configuration option available for webhooks, similar to what Meta provides?

Reference

Organization Social Action Notifications

Вернуться на верх