API reference
GET /v1/people/profile: person field reference
Every field the Triguna person endpoint returns: identity, location, network info, experience, education, skills, generic sections, and contact info, with parsing notes.
On this page
GET /v1/people/profile returns a person record: identity, location, network counts, work
history, education, skills, badges, verification, and optionally contact details.
Endpoint
GET https://api.triguna.ai/v1/people/profile
curl -H "ApiKey: $TRIGUNA_API_KEY" \
"https://api.triguna.ai/v1/people/profile?profile_id=rokafor\
&include_network_info=true&include_contact_info=true\
&get_verification_details=true"
Query parameters
| Parameter | Type | Notes |
|---|---|---|
| profile_id | string · required | A vanity slug, or any full LinkedIn profile URL. The slug is extracted for you. |
| include_network_info | boolean | Ungates network_info. |
| include_contact_info | boolean | Ungates contact_info. |
| get_verification_details | boolean | Ungates verifications. |
| max_age_days | number | Accept a stored copy up to this many days old. 0 means live. Capped by platform policy, currently 7. |
| bypass_cache | boolean | Force a fresh upstream fetch, skipping our store and the provider cache. |
The three flags gate whole response sections. Omit them and those objects come back null, which
is a common cause of “the API dropped a field” reports.
You can pass a bare slug or a full URL. See identifiers and slugs.
Response headers
Provenance and rate-limit state travel in headers, not in the body:
X-Data-Source: live | store | stale_fallback
X-Fetched-At: 2026-07-31T14:02:11+00:00
X-Data-Age-Seconds: 0
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9
Full detail in provenance and freshness.
What is not populated yet
Upstream does not expose everything this format can carry. These come back empty today and are back-fillable later, because the raw payload is stored on every call:
| Field | Today | Why |
|---|---|---|
| network_info | null | Follower and connection counts come from a separate upstream endpoint. On the roadmap. |
| contact_info.email_address | null | Not exposed by the current provider. |
| contact_info.phone_numbers | [] | Not exposed by the current provider. |
| contact_info.websites | [] | Not exposed by the current provider. |
| contact_info.twitter_handles | [] | Not exposed by the current provider. |
Everything else below is mapped and returned: identity, URNs, grouped experience[] with nested
positions[], education, skills, all ten generic sections, and contact_info.birth_date.
Top-level fields
| Field | Type | Notes |
|---|---|---|
| member_urn | string | Stable member URN. The durable identity key, so store this. |
| entity_urn | string | Alternate URN form. |
| public_identifier | string | The vanity slug. Users can change it; not a stable key. |
| first_name, last_name | string | |
| headline | string | |
| summary | string | The About section; can be long. |
| industry | string | Display name, not an id. |
| profile_photo_url | string | CDN URL; expires. |
| background_photo_url | string | Profile banner image, CDN URL; expires. |
| profile_url | string | Canonical profile URL. |
| websites | string[] | Often contains only the profile URL itself, not personal sites. For real websites use contact_info.websites. |
| is_memorialized | boolean | Memorialized account. |
| location | object | See nested objects below. |
| network_info | object | Requires include_network_info. |
| badges | object | |
| verifications | object | Requires get_verification_details. |
| contact_info | object | Requires include_contact_info. |
| experience[] | array | Grouped by company. Read the notes before parsing. |
| education[] | array | |
| skills[] | string[] | Plain strings, not objects. |
| certifications[], courses[], honors[], languages[], organizations[], patents[], projects[], publications[], test_scores[], volunteer_experiences[] | array | All share one common item shape. See generic sections. |
Nested objects
{
"location": { "name": "Lisbon, Portugal", "city": "Lisbon",
"country": "Portugal", "country_code": "PT" },
"network_info": { "followers_count": 18400, "connections_count": 500,
"custom_action": { "url": "https://example.com/",
"label": "Visit my website",
"control_name": "ca_website_view",
"open_externally": true } },
"badges": { "premium": true, "creator": true, "influencer": false,
"top_voice": false, "open_to_work": false, "is_hiring": true },
"verifications":{ "is_verified": true, "joined_date": "June 2014",
"sections": [{ "title": "Workplace", "items": [] }] }
}
network_info.custom_actionis the optional custom button on the profile.verifications.joined_dateis a human-readable string such as"June 2014", not an ISO date. Parse accordingly, or store it as text.verifications.sections[]has the shape{ title, items }, butitemswas empty in every sample checked.
experience[]
The single most important thing about this endpoint: experience[] is grouped by company, and
the job title lives on a nested positions[] array, not on the group. Someone promoted twice at
one employer produces one group entry with three positions. Reading experience[0].title returns
undefined for effectively every record.
{
"experience": [
{
"company_name": "Northwind Systems",
"company_id": "1035",
"company_url": "https://example.com/company/northwind",
"company_industry": "Software Development",
"company_employee_count_range": { "start": 101, "end": 500 },
"workplace_type": null,
"date_range": {
"start": { "year": 2023, "month": 11, "day": null, "iso": "2023-11" },
"end": null
},
"positions": [
{
"title": "Staff Platform Engineer",
"description": "Own the retrieval path and its SLOs.",
"location_name": "Lisbon, PT",
"employment_type": "Full-time",
"date_range": {
"start": { "year": 2025, "month": 4, "day": null, "iso": "2025-04" },
"end": null
}
},
{
"title": "Senior Platform Engineer",
"date_range": {
"start": { "year": 2023, "month": 11, "day": null, "iso": "2023-11" },
"end": { "year": 2025, "month": 4, "day": null, "iso": "2025-04" }
}
}
]
}
]
}
Reading the current title correctly:
const currentTitle = record.experience?.[0]?.positions?.[0]?.title ?? null;
- Group fields:
company_name,company_id,company_url,company_logo_url,company_industry,company_employee_count_range,workplace_type,date_range,positions[]. - Position fields: everything above except
positions, plustitle,description,location_name,employment_type. - Ordering.
experience[0]is the current or most recent role, andpositions[0]within it is the most recent position. - Current role. Indicated by an absent or null
date_range.end. company_idis the reliable identity. Display names drift, so comparecompany_idwhen detecting job changes, because comparing names produces false positives.- There is no company website field on
experience[]. Call/companies/detailsfor that. company_employee_count_rangeis an object{ start, end }, consistently.employment_typeobserved values:Full-time,Part-time,Contract,Internship,Self-employed,Freelance,Permanent Full-time, andnull.workplace_type(remote/hybrid/onsite) exists but was unpopulated in every sample checked. Do not build a remote-work filter on it.
Date objects
Dates are objects, not strings, and carry redundant representations:
{ "year": 2018, "month": 3, "day": null, "iso": "2018-03" }
isois a partial ISO string such as"2018-03", not a full date. Feeding it to a strict date parser fails.dayis routinely null andmonthcan be too.- An absent
date_range.endmeans “present”. - The company endpoint’s date objects carry no
isokey.
education[]
| Field | Type | Notes |
|---|---|---|
| school_name | string | The institution name. |
| school_id | string | School id. |
| school_url | string | School page URL. |
| school_logo_url | string | CDN URL. |
| company_id | string | Also present; mirrors school_id for schools with company pages. |
| degree | string | For example "Bachelor of Science". |
| field_of_study | string | |
| grade | string | |
| activities | string | Free text. |
| description | string | Free text. |
| date_range | object | Same shape as above. |
There is no school, institution, or school_logo key. Use school_name and
school_logo_url.
skills[]
A plain array of strings, not objects:
{ "skills": ["Distributed Systems", "Go", "Postgres", "Observability"] }
Generic sections
certifications, courses, honors, languages, organizations, patents, projects,
publications, test_scores, and volunteer_experiences all share one identical item shape.
One parser handles all ten.
| Field | Type | Notes |
|---|---|---|
| name | string | |
| title | string | |
| description | string | |
| url | string | |
| image_url | string | |
| company | string | Issuing or associated organization. |
| company_id | string | Company id for that organization. |
| position_held | string | |
| date_range | object | Standard date range. |
languages[] adds one field: proficiency. There are no section-specific keys such as
authority, issuer, publisher, role, or cause. Whichever section you read, the shape
above is what you get.
contact_info
Only populated when include_contact_info=true.
| Field | Type | Notes |
|---|---|---|
| email_address | string | Frequently null; exposed for only some records. |
| websites | array | Objects: { url, type, label }. type values include PORTFOLIO, COMPANY. url may lack a scheme, so normalize before linking. |
| twitter_handles | string[] | |
| phone_numbers | array | Present but empty in every sample checked; element shape unverified. |
| birth_date | object | Partial-date shape. |
| address | string | Free text. |
{
"contact_info": {
"email_address": null,
"websites": [],
"twitter_handles": [],
"phone_numbers": [],
"birth_date": { "year": 1955, "month": 10, "day": 28 },
"address": null
}
}