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 nested positions[] array. experience[0].title is undefined for 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_info and the email and phone fields inside contact_info currently 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