Documentation
Quickstart, your first enrichment request
Get a Triguna API key, make an authenticated GET request to the person and company endpoints, and read the record that comes back. Two requests, start to finish.
On this page
Two authenticated GET requests are the whole integration. This page gets a record back; the API reference documents every field it can carry.
1. Get an API key
Create a project, then copy the key from Settings → API keys. Keys are scoped per project and
per environment. A test key (tg_test_…) returns shaped sample records and never spends credits;
a live key (tg_live_…) spends credits on every successful call.
TRIGUNA_API_KEY=tg_live_••••••••••••
2. Make your first request
Authentication uses the custom ApiKey header. Both endpoints are GET only and take no request
body.
# Person
curl -H "ApiKey: $TRIGUNA_API_KEY" \
"https://api.triguna.ai/v1/people/profile?profile_id=rokafor&include_contact_info=true"
# Company
curl -H "ApiKey: $TRIGUNA_API_KEY" \
"https://api.triguna.ai/v1/companies/details?company_id=northwind"
3. Read the record
Responses are JSON on success and plain text on error. Do not run failures through your JSON parser.
HTTP/1.1 200 OK
Content-Type: application/json
X-Data-Source: live
X-Fetched-At: 2026-07-31T14:02:11+00:00
X-Data-Age-Seconds: 0
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9
{
"member_urn": "urn:li:member:251749025",
"public_identifier": "williamhgates",
"first_name": "Bill",
"last_name": "Gates",
"headline": "Chair, Gates Foundation",
"experience": [ /* grouped by company, see the reference */ ]
}
The body is the record and nothing else. Where it came from and how old it is travel in headers.
Three things to internalize before you write a parser:
- Every field is nullable. Branch on presence, not on shape.
experience[]is grouped by company and the job title lives on a nestedpositions[]array.experience[0].titleisundefinedfor effectively every record. Read the person reference first.- Store the raw payload alongside whatever you parse today. A stored response lets you pick up unmapped fields later without paying for the call twice.
- Some sections are not populated yet.
network_infoand the email and phone fields insidecontact_infocurrently come back null. See the person reference.
4. Handle the two failures you will actually see
const res = await fetch(url, { headers: { ApiKey: key } });
if (res.status === 429 || res.status === 503) {
// Retry-After is in seconds. Fall back to 5s, give up after ~60s total.
const wait = Number(res.headers.get('Retry-After') ?? 5) * 1000;
await sleep(wait);
return retry();
}
if (res.status === 400) {
// You sent something with no LinkedIn identifier in it, usually a display name.
log.error({ identifier }, 'triguna: unusable identifier');
return null;
}
if (res.status === 404) {
// Parsed fine, but no such profile. Never billed.
log.warn({ identifier }, 'triguna: not found');
return null;
}
if (!res.ok) throw new Error(await res.text()); // plain text, not JSON
Only 429 and 503 are worth retrying. Nothing that fails costs a credit.
Full status-code semantics are in conventions, errors, and limits.
5. Check your balance
curl -H "ApiKey: $TRIGUNA_API_KEY" https://api.triguna.ai/v1/credits
{ "credits": 4820 }
Free to call. Poll it from a dashboard rather than waiting to be surprised by a 402.
Where to go next
- Provenance and freshness: the response headers, and
max_age_days. - Identifiers and slugs: what the endpoints accept.
- Person profile reference: every field the person endpoint returns.
- Company details reference: firmographics and funding.
- Enrich on signup: the most common integration shape.