• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
foxdark410

foxdark410

linkedin-mdp-api

Public
Like
linkedin-mdp-api
Home
Code
2
README.md
H
main.ts
Environment variables
3
Branches
1
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
…
Viewing readonly version of main branch: v12
View latest version
README.md

LinkedIn DMA → MAC / JSON Resume / RenderCV (Val Town HTTP val)

This project provides a single Val Town HTTP val that reads your LinkedIn DMA (Member Data Portability) snapshot and exports it into several developer‑friendly CV formats:

  • MAC (Manfred Awesomic CV) JSON
  • JSON Resume JSON
  • RenderCV YAML (downloadable file)
  • Raw debug views of LinkedIn memberSnapshotData domains

The val is stateless: LinkedIn is the only data source, and all outputs are pure transformations of the exported snapshot.


Supported Formats & Specs

MAC (Manfred Awesomic CV)

  • Format repo: https://github.com/getmanfred/mac
  • This val builds a MAC-like JSON document with:
    • settings.language
    • aboutMe.profile (title, summary, images)
    • experience.jobs and experience.projects
    • knowledge.hardSkills, knowledge.studies, knowledge.courses, knowledge.certifications, knowledge.languages

JSON Resume

  • Schema: https://jsonresume.org/schema/
  • Reference schema repo: https://github.com/jsonresume/resume-schema
  • This val fills the core sections:
    • basics (name, label, summary, image)
    • work
    • education
    • skills
    • languages
    • projects
    • certificates

RenderCV

  • YAML input structure: https://docs.rendercv.com/user_guide/yaml_input_structure/
  • Project repo: https://github.com/rendercv/rendercv
  • This val builds a cv model compatible with RenderCV and returns it as a downloadable rendercv.yaml file:
    • cv.name
    • cv.sections.experience
    • cv.sections.education
    • cv.sections.projects

LinkedIn DMA / Portability API

This val uses LinkedIn’s Member Data Portability (DMA) APIs and the memberSnapshotData endpoint. These APIs are subject to important limitations and eligibility rules.

Official documentation

  • Member portability APIs overview (LinkedIn Help):
    https://www.linkedin.com/help/linkedin/answer/a6214075
  • Member Data Portability (Member) – Microsoft Learn:
    https://learn.microsoft.com/en-us/linkedin/dma/member-data-portability/member-data-portability-member/
  • Portability API terms:
    https://www.linkedin.com/legal/l/portability-api-terms

Geographic and product limitations

  • The DMA Member Data Portability APIs are designed to comply with the EU Digital Markets Act (DMA) and are available only to members located in the European Economic Area (EEA) and Switzerland (or other regions explicitly listed by LinkedIn at the time of use).
  • Outside these regions, members may not be able to authorize or use the Member Data Portability APIs at all.

Data completeness limitations

The data returned by memberSnapshotData does not replicate the LinkedIn UI exactly:

  • Many profile views in the UI are assembled from multiple internal systems and include presentation logic that is not visible through the DMA APIs.
  • The profile data returned by the DMA APIs is typically in one primary language only. If you maintain multiple language versions of your profile, only the primary language may appear.
  • Some profile elements and relationships (for example, how skills are attached to specific positions) may not be exposed as structured data.
  • Availability of domains depends on the member’s activity and privacy settings. For some domains you may receive empty arrays or null even though the domain exists.

Design your downstream processing with these constraints in mind: the val provides a best-effort mapping of what LinkedIn exposes, not a pixel‑perfect reconstruction of the UI profile.


Architecture Overview

1. Token handling

The val expects a LinkedIn DMA access token (Member Data Portability API). It does not implement the OAuth flow itself. You can obtain a token via:

  • LinkedIn’s official OAuth Token Generator in the Developer Portal, or
  • Your own OAuth 2.0 client configured for the Member Data Portability product (for example, scope r_dma_portability_3rd_party or r_dma_portability_self_serve, depending on your setup).

Token lookup order for every request:

  1. Authorization: Bearer <token> HTTP header
  2. ?token=<token> query parameter
  3. Val Town environment variable token

If no token is found, the val returns HTTP 401.

2. LinkedIn API usage

All profile data is fetched from this endpoint:

GET https://api.linkedin.com/rest/memberSnapshotData?q=criteria&domain=<DOMAIN> LinkedIn-Version: 202312 Authorization: Bearer <token>

The val wraps this in a helper fetchRawDomain(token, domain) that returns the snapshotData array for the domain (or null in case of 404 / no data).

3. Aggregation layer (LIFullProfile)

To avoid repeated HTTP calls per format, the val aggregates multiple domains into a single in‑memory structure:

  • PROFILE – core profile (headline, summary, first and last name)
  • SKILLS – list of skills
  • POSITIONS – work experience
  • EDUCATION – education history
  • PROJECTS – project entries
  • CERTIFICATIONS – certifications
  • COURSES – courses
  • LANGUAGES – languages and proficiencies
  • RICH_MEDIA – log of uploaded images (profile photos, background photos, etc.)

This aggregate is returned directly by /profile and is also used as input for MAC, JSON Resume, and RenderCV mappers.

4. Rich media (profile & background images)

The RICH_MEDIA domain acts as an activity log. The val scans it to determine:

  • Profile photo – latest entry whose Date/Time text contains "profile photo".
  • Profile background photo – latest entry whose Date/Time text contains "profile background photo".

These URLs are then stored in:

  • MAC: aboutMe.profile.imageUrl, aboutMe.profile.bannerUrl.
  • JSON Resume: basics.image.

HTTP Endpoints

All endpoints are GET and share the same token rules described above.

GET /profile

Returns the aggregated LIFullProfile JSON object:

  • profile, skills, positions, education
  • projects, certifications, courses, languages
  • richMedia

Use this for debugging, inspection, or building your own mappings.

Example:

curl "https://<your-val>.web.val.run/profile" -H "Authorization: Bearer <LINKEDIN_TOKEN>"

GET /mac

Returns a MAC-format JSON document derived from LIFullProfile.

Key mappings:

  • aboutMe.profile.title ← PROFILE.Headline
  • aboutMe.profile.description ← PROFILE.Summary
  • aboutMe.profile.imageUrl / bannerUrl ← RICH_MEDIA inference
  • experience.jobs ← POSITIONS
  • experience.projects ← PROJECTS
  • knowledge.hardSkills ← SKILLS
  • knowledge.studies ← EDUCATION
  • knowledge.courses ← COURSES
  • knowledge.certifications ← CERTIFICATIONS
  • knowledge.languages ← LANGUAGES

Example:

curl "https://<your-val>.web.val.run/mac" -H "Authorization: Bearer <LINKEDIN_TOKEN>" > mac.json

GET /jsonresume

Returns a JSON Resume object.

Populated sections:

  • basics
    • name = "First Name Last Name"
    • label = LinkedIn headline
    • image = profile photo URL
    • summary = LinkedIn summary
  • work from POSITIONS
  • education from EDUCATION
  • skills – a single entry with keyword list derived from SKILLS
  • languages from LANGUAGES
  • projects from PROJECTS
  • certificates from CERTIFICATIONS

Example:

curl "https://<your-val>.web.val.run/jsonresume" -H "Authorization: Bearer <LINKEDIN_TOKEN>" > resume.json

You can then use any JSON Resume tooling (themes, renderers, HTML/PDF converters) on resume.json.

GET /rendercv

Returns a RenderCV model encoded as YAML and forces a file download named rendercv.yaml.

  • The val maps LIFullProfile into a cv object with:
    • cv.name – full name
    • cv.sections.experience – from POSITIONS
    • cv.sections.education – from EDUCATION
    • cv.sections.projects – from PROJECTS
  • The object is converted to YAML using the yaml package and served with headers:
    • Content-Type: text/yaml; charset=utf-8
    • Content-Disposition: attachment; filename="rendercv.yaml"

Example:

curl -L "https://<your-val>.web.val.run/rendercv" -H "Authorization: Bearer <LINKEDIN_TOKEN>" -o rendercv.yaml

This rendercv.yaml file can be passed to the RenderCV CLI to generate a nicely formatted CV.

GET /debug

Debug endpoint for raw memberSnapshotData.

Supported modes:

  • GET /debug (no domains parameter or empty):

    • Fetches a default set of domains: PROFILE, PROFILE_SUMMARY, PROJECTS, SKILLS, POSITIONS, EDUCATION, CERTIFICATIONS, COURSES, LANGUAGES, RICH_MEDIA.
  • GET /debug?domains=all:

    • Fetches all known domains listed in the code’s KNOWN_DOMAINS array (profile, positions, education, rich media, connections, inbox, etc.). Note that some of these may be empty or unavailable for a given account.
  • GET /debug?domains=PROJECTS,SKILLS,LANGUAGES:

    • Fetches exactly the specified comma-separated domains.

Response shape:

{ "requested_domains": ["PROFILE", "PROJECTS"], "data": { "PROFILE": [/* raw snapshotData */], "PROJECTS": [/* raw snapshotData */] } }

Example:

curl "https://<your-val>.web.val.run/debug?domains=RICH_MEDIA" -H "Authorization: Bearer <LINKEDIN_TOKEN>"

Use this endpoint to explore what LinkedIn actually returns for your account before adjusting mappings.


Deployment on Val Town

  1. Create a new HTTP val on https://val.town.
  2. Paste the TypeScript code (the export default async function handler(req: Request) implementation).
  3. In the val’s Settings → Environment Variables, set:
    • token = <your LinkedIn DMA access token> (optional but convenient).
  4. Visit the val’s URL with one of the endpoints, for example:
    • https://<your-val>.web.val.run/mac
    • https://<your-val>.web.val.run/jsonresume
    • https://<your-val>.web.val.run/rendercv

If you do not set token as an environment variable, always pass the token either as Authorization: Bearer header or as ?token=... in the query string.


Caveats & Recommendations

  • The val cannot override LinkedIn’s data export policies or limitations. It only reshapes what the DMA API provides.
  • Expect differences between what you see in the LinkedIn UI and what appears in the exported data (missing languages, missing links between objects, or missing sections entirely).
  • Before relying on the data for automation or large-scale processing, inspect several responses from /debug and /profile for your account to understand exactly which domains and fields are available.
FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
AboutAlternativesPricingBlogNewsletterCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.