linkedin-member-data-portability — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited linkedin-member-data-portability (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill whenever you implement or review LinkedIn API behavior for Unlinked.
Unlinked uses LinkedIn's Member Data Portability (Member) API product. The purpose is to let a LinkedIn member connect their own professional profile and experience data to an AI assistant through a local MCP server. The API is read-only for this project.
This API product exists for DMA data portability and is currently available only to LinkedIn members located in the European Economic Area and Switzerland. User-facing setup and error messages should say this plainly.
r_dma_portability_self_serve for member self-serve access.r_dma_portability_member and r_dma_portability_3rd_party permissions. Treat 403 responses as likely product/scope/consent problems and explain that clearly.Authorization: Bearer <access_token> to LinkedIn.Every LinkedIn REST call should include:
Authorization: Bearer <access_token>
Linkedin-Version: <YYYYMM>
Content-Type: application/jsonUse the exact header name Linkedin-Version. Make the version configurable where useful. The changelog docs mention 202312, while the current documentation version is 2025-11; verify the latest supported version before changing defaults.
Use the Snapshot API for profile and professional-history data.
GET https://api.linkedin.com/rest/memberSnapshotData?q=criteria
GET https://api.linkedin.com/rest/memberSnapshotData?q=criteria&domain=PROFILEThe optional domain query parameter is case-sensitive. If omitted, LinkedIn may return all domains. Prefer explicit domains for predictable assistant-facing tools.
Important response behavior:
elements contains snapshot records with snapshotDomain and snapshotData.snapshotData is a list of data generated for the requested domain.paging.links entries whose rel is next or prev.paging.total as a complete page count; the docs say offline systems can make it incomplete.Professional-context domains to prioritize:
PROFILE: basic biographical profile information.POSITIONS: job roles, companies, titles, descriptions, locations, and dates.EDUCATION: schools, dates, degrees, and activities.SKILLS: skills added to the member profile.CERTIFICATIONS: certifications on the profile.PROJECTS: projects listed on the profile.LANGUAGES: languages and proficiency.HONORS: honors listed on the profile.COURSES: courses listed on the profile.PUBLICATIONS: publications listed on the profile.PATENTS: patents listed on the profile.ORGANIZATIONS: organizations listed on the profile.VOLUNTEERING_EXPERIENCES: volunteering roles and descriptions.RECOMMENDATIONS: recommendations received and given.Other useful domains include CONNECTIONS, MEMBER_SHARE_INFO, ARTICLES, ALL_COMMENTS, ALL_LIKES, JOB_APPLICATIONS, JOB_POSTINGS, SAVED_JOBS, JOB_SEEKER_PREFERENCES, and PROFILE_SUMMARY. Be thoughtful before exposing broad activity or inbox-like domains by default because they may contain sensitive personal data.
Use the Changelog API for recent post-consent activity events.
GET https://api.linkedin.com/rest/memberChangeLogs?q=memberAndApplication
GET https://api.linkedin.com/rest/memberChangeLogs?q=memberAndApplication&startTime=<epoch_ms>&count=10Behavior to preserve:
startTime is an inclusive epoch-millisecond timestamp.400.count=10; the upper limit is 50.processedAt as the next startTime cursor. If no event is returned, keep the same cursor for the next poll.capturedAt is the recommended event activity time when embedded activity timestamps are missing.id, capturedAt, processedAt, owner, actor, resourceName, resourceId, resourceUri, method, activity, processedActivity, activityId, and activityStatus.method, resourceName, resourceId, and processedActivity.The changelog management API can check whether changelog generation is active:
GET https://api.linkedin.com/rest/memberAuthorizations?q=memberAndApplicationThere is also a documented activation endpoint:
POST https://api.linkedin.com/rest/memberAuthorizations
Content-Type: application/json
{}Unlinked should stay read-only by default. Do not add the POST activation behavior unless the project explicitly decides that this consent-management call is acceptable and documents it as separate from LinkedIn profile data mutation.
LinkedIn error bodies typically contain:
{
"message": "Empty oauth2_access_token",
"serviceErrorCode": 401,
"status": 401
}Map common failures into helpful MCP errors:
400: invalid query, timestamp, count, domain, or request syntax.401: missing, expired, revoked, invalid, or malformed bearer token.403: application lacks product access, scope, or member consent.404: endpoint or restricted API issue.426: API version header is deprecated.429: rate limit; reduce duplicate calls and retry later.500 or 504: LinkedIn-side failure or timeout; include request id headers when available, but never include tokens.McpServer and StdioServerTransport from @modelcontextprotocol/sdk.content and machine-readable structuredContent for profile and changelog tools.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.