Overzicht
De LeadGrid API laat je dossiers aanmaken en beheren, fasen bijwerken, notities koppelen en data synchroniseren met je eigen tools. Elk verzoek retourneert JSON.
Alle tijdstempels zijn ISO 8601 in UTC. Alle bedragen zijn integers of decimalen in de kleinst praktische eenheid (bijv. euro's, niet centen). Paginering gebruikt page en per_page queryparameters; responses bevatten een meta object met het totale aantal.
Authenticatie
Elk verzoek moet een API-sleutel bevatten in de Authorization-header. Sleutels beginnen met lg_live_ en zijn gekoppeld aan één organisatie.
- 1Ga naar Instellingen → API en klik op API-sleutel aanmaken.
- 2Kies de scopes die je nodig hebt (zie de tabel hieronder) en stel optioneel een vervaldatum in. De volledige sleutel wordt eenmalig getoond, kopieer hem direct.
- 3Stuur de sleutel als bearer-token mee bij elk verzoek.
curl https://leadgrid.io/api/v1/dossiers \ -H "Authorization: Bearer lg_live_your_key_here"
| Veld | Type | Beschrijving |
|---|---|---|
| dossiers:read | scope | Dossiers weergeven en ophalen. |
| dossiers:write | scope | Dossiers aanmaken, bijwerken en archiveren. Ook vereist om fasen te verplaatsen. |
| contacts:read | scope | Contacten weergeven en ophalen, en hun dossierkoppelingen lezen. |
| contacts:write | scope | Contacten aanmaken, bijwerken en verwijderen. Naast dossiers:write vereist om contacten aan een dossier te koppelen of los te koppelen. |
| flows:read | scope | Flows weergeven en hun fasen lezen. |
| notes:read | scope | Notities bij dossiers lezen. |
| notes:write | scope | Nieuwe notities aan dossiers toevoegen. |
Dossiers
Dossiers zijn de entiteiten die je bijhoudt, kandidaten in recruitment of leads in sales. Elk dossier hoort bij precies één flow en bevindt zich in precies één fase.
/dossiersGeef dossiers in je organisatie weer. Ondersteunt filteren en paginering.
| Veld | Type | Beschrijving |
|---|---|---|
| type | string | 'candidate' or 'sales'. |
| status | string | 'active', 'won', 'lost' or 'archived'. |
| stage_id | uuid | Return only dossiers currently in this stage. |
| page | integer | 1-based page number. Default: 1. |
| per_page | integer | Items per page (max 100). Default: 25. |
curl "https://leadgrid.io/api/v1/dossiers?type=sales&status=active" \ -H "Authorization: Bearer lg_live_your_key"
{
"data": [
{
"id": "6f2b…",
"type": "sales",
"name": "Rabobank, Talent rollout",
"company": "Rabobank",
"contact_person": "Mark de Vries",
"deal_size": 45000,
"deal_currency": "EUR",
"status": "active",
"current_stage_id": "c3e1…",
"assigned_to": "ab12…",
"created_at": "2026-04-10T09:21:14Z"
}
],
"meta": { "total": 34, "page": 1, "per_page": 25 }
}/dossiersMaak een nieuw dossier aan. Als flow_id wordt weggelaten, wordt de standaardflow voor het opgegeven type gebruikt; het dossier start in de eerste fase van die flow. Geef optioneel een contact_id mee om het dossier aan een bestaand Contact te koppelen in plaats van een nieuw Contact aan te maken. Stuur application/json voor een gewone aanmaak, of multipart/form-data met een 'cv'-bestandsveld om het dossier aan te maken én een PDF-cv in één atomaire aanroep te koppelen: als de upload mislukt, wordt het dossier teruggedraaid.
| Veld | Type | Beschrijving |
|---|---|---|
| type* | string | 'candidate' or 'sales'. |
| name* | string | For candidates: the person's name. For sales: deal or account name. |
| string | Primary contact email. | |
| phone | string | Primary contact phone. |
| company | string | Candidate: current employer. Sales: target company. |
| role | string | Candidate: role they're applying for. Sales: role of the contact. |
| contact_id | uuid | Link the dossier to an existing Contact instead of creating a new one. Must belong to your organization. |
| flow_id | uuid | Override the default flow. Must belong to your organization. |
| assigned_to | uuid | User ID of the member to assign this dossier to. |
| intake_notes | string | Director/intake notes shown in the dossier drawer. |
| contact_person | string | Sales only. Named contact at the target company. |
| deal_size | number | Sales only. Expected contract value. |
| deal_currency | string | Sales only. ISO 4217 currency code (e.g. 'EUR'). |
| cv | file (pdf) | multipart/form-data only. Optional PDF CV (max 10 MB). Uploaded and attached in the same call. If the upload fails, the dossier is rolled back. |
# JSON, plain create
curl -X POST https://leadgrid.io/api/v1/dossiers \
-H "Authorization: Bearer lg_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"type": "sales",
"name": "KLM, Cabin crew hiring",
"company": "KLM",
"contact_person": "Pieter van Leeuwen",
"deal_size": 62000,
"deal_currency": "EUR"
}'
# multipart, create + attach CV in one call
curl -X POST https://leadgrid.io/api/v1/dossiers \
-H "Authorization: Bearer lg_live_your_key" \
-F "type=candidate" \
-F "name=Sophie van Dijk" \
-F "role=Senior Frontend Engineer" \
-F "email=sophie@example.com" \
-F "cv=@./resume.pdf"{
"data": {
"id": "a91c…",
"type": "candidate",
"name": "Sophie van Dijk",
"cv_url": "<org-id>/dossiers/a91c…/cv.pdf",
"status": "active",
"current_stage_id": "b77f…",
"created_at": "2026-04-15T12:03:40Z"
}
}/dossiers/:idHaal één dossier op aan de hand van het ID.
curl https://leadgrid.io/api/v1/dossiers/a91c… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"id": "a91c…",
"type": "sales",
"name": "KLM, Cabin crew hiring",
"deal_size": 62000,
"current_stage_id": "b77f…"
}
}/dossiers/:idWerk een willekeurige subset van velden bij. Door current_stage_id in te stellen verplaats je het dossier naar een nieuwe fase en wordt een dossier.stage_changed-webhook verstuurd.
| Veld | Type | Beschrijving |
|---|---|---|
| name | string | Rename the dossier. |
| string | Update primary contact email. | |
| phone | string | Update phone. |
| company | string | Update company / employer. |
| role | string | Update role. |
| contact_person | string | Sales only. |
| deal_size | number | Sales only. |
| deal_currency | string | Sales only. |
| status | string | 'active', 'won', 'lost' or 'archived'. |
| assigned_to | uuid | Reassign to another member. Null to unassign. |
| intake_notes | string | Replace intake notes. |
| current_stage_id | uuid | Move to a new stage. Must belong to the dossier's flow. |
curl -X PATCH https://leadgrid.io/api/v1/dossiers/a91c… \
-H "Authorization: Bearer lg_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "current_stage_id": "d8e2…", "status": "active" }'{
"data": {
"id": "a91c…",
"current_stage_id": "d8e2…",
"status": "active"
}
}/dossiers/:idArchiveert het dossier (soft delete). Zet de status op 'archived' en verstuurt dossier.deleted. Data blijft bewaard en kan worden hersteld via PATCH.
curl -X DELETE https://leadgrid.io/api/v1/dossiers/a91c… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"id": "a91c…",
"status": "archived"
}
}/dossiers/:id/cvUpload een PDF-cv (max. 10 MB) en koppel het aan een bestaand dossier. De upload vervangt een eventueel eerder cv. Accepteert multipart/form-data met een 'cv'-veld, of application/pdf met de PDF-bytes als ruwe body. Verstuurt dossier.updated.
# multipart/form-data curl -X POST https://leadgrid.io/api/v1/dossiers/a91c…/cv \ -H "Authorization: Bearer lg_live_your_key" \ -F "cv=@./resume.pdf" # raw application/pdf curl -X POST https://leadgrid.io/api/v1/dossiers/a91c…/cv \ -H "Authorization: Bearer lg_live_your_key" \ -H "Content-Type: application/pdf" \ --data-binary @./resume.pdf
{
"data": {
"id": "a91c…",
"cv_url": "<org-id>/dossiers/a91c…/cv.pdf"
}
}Contacten
Contacten zijn de mensen in je netwerk: kandidaten, prospects, klanten, leveranciers en partners. Eén Contact kan meerdere kinds tegelijk hebben en kan aan een willekeurig aantal dossiers worden gekoppeld.
/contactsGeef contacten in je organisatie weer. Ondersteunt filteren op kind, poolstatus en vrije zoektekst, plus paginering.
| Veld | Type | Beschrijving |
|---|---|---|
| kind | string | Filter by kind. Repeat the parameter to combine values: 'candidate', 'prospect', 'client', 'supplier' or 'partner'. |
| pool | string | 'in_pool' for contacts currently in the talent pool, 'expired' for contacts whose pool window has passed. |
| search | string | Free-text search over full_name, email, company and role. |
| page | integer | 1-based page number. Default: 1. |
| per_page | integer | Items per page (max 100). Default: 25. |
curl "https://leadgrid.io/api/v1/contacts?kind=candidate&kind=client&search=sophie" \ -H "Authorization: Bearer lg_live_your_key"
{
"data": [
{
"id": "c12a…",
"full_name": "Sophie van Dijk",
"email": "sophie@example.com",
"phone": "+31 6 12345678",
"linkedin_url": "https://linkedin.com/in/sophievandijk",
"company": "Adyen",
"role": "Senior Frontend Engineer",
"city": "Amsterdam",
"kind": ["candidate", "client"],
"notes": null,
"dossier_count": 2,
"created_at": "2026-04-08T11:14:02Z"
}
],
"meta": { "total": 142, "page": 1, "per_page": 25 }
}/contactsMaak een nieuw contact aan. full_name is het enige verplichte veld. Bestaat er al een contact met hetzelfde e-mailadres in je organisatie (hoofdletterongevoelig), dan retourneert de API 409 met een duplicate_contact-fout.
| Veld | Type | Beschrijving |
|---|---|---|
| full_name* | string | The contact's full name. |
| string | Primary email. Must be unique per organization (case-insensitive). Returns 409 on conflict. | |
| phone | string | Primary phone number. |
| linkedin_url | string | Public LinkedIn profile URL. |
| company | string | Current employer or account. |
| role | string | Job title or role. |
| city | string | City of residence. |
| kind | string[] | Array of kinds: 'candidate', 'prospect', 'client', 'supplier', 'partner'. Defaults to an empty array. |
| notes | string | Free-form internal notes shown on the contact drawer. |
curl -X POST https://leadgrid.io/api/v1/contacts \
-H "Authorization: Bearer lg_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"full_name": "Sophie van Dijk",
"email": "sophie@example.com",
"company": "Adyen",
"role": "Senior Frontend Engineer",
"city": "Amsterdam",
"kind": ["candidate"]
}'{
"data": {
"id": "c12a…",
"full_name": "Sophie van Dijk",
"email": "sophie@example.com",
"company": "Adyen",
"role": "Senior Frontend Engineer",
"city": "Amsterdam",
"kind": ["candidate"],
"dossier_count": 0,
"created_at": "2026-04-30T08:21:14Z"
}
}/contacts/:idHaal één contact op aan de hand van het ID, inclusief kinds en geaggregeerde dossieraantallen.
curl https://leadgrid.io/api/v1/contacts/c12a… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"id": "c12a…",
"full_name": "Sophie van Dijk",
"email": "sophie@example.com",
"company": "Adyen",
"role": "Senior Frontend Engineer",
"city": "Amsterdam",
"kind": ["candidate", "client"],
"dossier_count": 2
}
}/contacts/:idWerk een willekeurig veld op een contact gedeeltelijk bij. Stuur alleen de keys die je wilt wijzigen.
| Veld | Type | Beschrijving |
|---|---|---|
| full_name | string | Rename the contact. |
| string | Update primary email. Still subject to the per-org uniqueness check. | |
| phone | string | Update phone number. |
| linkedin_url | string | Update LinkedIn URL. |
| company | string | Update company. |
| role | string | Update role. |
| city | string | Update city. |
| kind | string[] | Replace the full kinds array. Send the complete set of kinds you want on the contact. |
| notes | string | Replace internal notes. |
curl -X PATCH https://leadgrid.io/api/v1/contacts/c12a… \
-H "Authorization: Bearer lg_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "kind": ["candidate", "client"], "city": "Rotterdam" }'{
"data": {
"id": "c12a…",
"kind": ["candidate", "client"],
"city": "Rotterdam"
}
}/contacts/:idVerwijdert het contact definitief. De koppelingen in dossier_contacts worden mee verwijderd, maar de gekoppelde dossiers zelf blijven intact.
curl -X DELETE https://leadgrid.io/api/v1/contacts/c12a… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"id": "c12a…",
"deleted": true
}
}Dossierkoppelingen
Een dossier-contactkoppeling verbindt een Contact met een dossier en legt vast welke rol diegene speelt op die deal of hire (primary, hiring manager, decision maker, champion, gatekeeper, introducer of other). Eén dossier kan meerdere contacten hebben; één contact kan op meerdere dossiers staan.
/dossiers/:id/contactsGeef de contacten weer die aan een dossier zijn gekoppeld, inclusief hun rol en of ze het primaire contact zijn.
curl https://leadgrid.io/api/v1/dossiers/a91c…/contacts \ -H "Authorization: Bearer lg_live_your_key"
{
"data": [
{
"contact_id": "c12a…",
"full_name": "Sophie van Dijk",
"email": "sophie@example.com",
"company": "Adyen",
"role_on_dossier": "primary",
"is_primary": true
},
{
"contact_id": "c44b…",
"full_name": "Mark de Vries",
"email": "mark@rabobank.nl",
"company": "Rabobank",
"role_on_dossier": "decision_maker",
"is_primary": false
}
],
"meta": { "total": 2, "page": 1, "per_page": 25 }
}/dossiers/:id/contactsKoppel een bestaand contact aan een dossier met een rol. Door is_primary op true te zetten degradeer je een eventueel eerder primair contact op dat dossier.
| Veld | Type | Beschrijving |
|---|---|---|
| contact_id* | uuid | The contact to link. Must belong to your organization. |
| role_on_dossier* | string | One of 'primary', 'hiring_manager', 'decision_maker', 'champion', 'gatekeeper', 'introducer' or 'other'. |
| is_primary | boolean | Default: false. Setting true demotes the previous primary contact on this dossier. |
curl -X POST https://leadgrid.io/api/v1/dossiers/a91c…/contacts \
-H "Authorization: Bearer lg_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"contact_id": "c44b…",
"role_on_dossier": "decision_maker",
"is_primary": false
}'{
"data": {
"dossier_id": "a91c…",
"contact_id": "c44b…",
"role_on_dossier": "decision_maker",
"is_primary": false
}
}/dossiers/:id/contacts/:contact_idMaak de koppeling tussen een contact en een dossier ongedaan. Het contact zelf blijft behouden.
curl -X DELETE https://leadgrid.io/api/v1/dossiers/a91c…/contacts/c44b… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"dossier_id": "a91c…",
"contact_id": "c44b…",
"unlinked": true
}
}Flows
Flows zijn de pipelines waar dossiers doorheen bewegen. Elke flow heeft geordende fasen met optionele deadlines en winstkansen.
/flowsGeef flows in je organisatie weer. Fasen zijn genest en geordend op positie.
| Veld | Type | Beschrijving |
|---|---|---|
| type | string | Filter to 'candidate' or 'sales'. |
| page | integer | Page number. Default: 1. |
| per_page | integer | Items per page. Default: 25. |
curl "https://leadgrid.io/api/v1/flows?type=sales" \ -H "Authorization: Bearer lg_live_your_key"
{
"data": [
{
"id": "f01a…",
"name": "Sales Flow",
"type": "sales",
"is_default": true,
"stages": [
{
"id": "s1…",
"name": "Lead",
"position": 1,
"deadline_days": 3,
"win_probability": 14,
"color": "#FF5C35"
},
{
"id": "s2…",
"name": "Discovery",
"position": 2,
"deadline_days": 5,
"win_probability": 29,
"color": "#22C55E"
}
]
}
],
"meta": { "total": 1, "page": 1, "per_page": 25 }
}/flows/:id/stagesHaal de fasen op voor één flow, gesorteerd op positie. Handig als je het flow_id al weet en alleen de fasen wilt.
curl https://leadgrid.io/api/v1/flows/f01a…/stages \ -H "Authorization: Bearer lg_live_your_key"
{
"data": [
{
"id": "s1…",
"name": "Lead",
"position": 1,
"deadline_days": 3,
"win_probability": 14
}
],
"meta": { "total": 6, "page": 1, "per_page": 6 }
}Notities
Notities zijn de tijdlijn van updates die aan een dossier zijn gekoppeld. Ze zijn gesorteerd van oudste naar nieuwste en zijn standaard altijd intern.
/dossiers/:id/notesGeef notities voor een dossier weer, oudste eerst.
curl https://leadgrid.io/api/v1/dossiers/a91c…/notes \ -H "Authorization: Bearer lg_live_your_key"
{
"data": [
{
"id": "n1…",
"dossier_id": "a91c…",
"content": "Had a great first call, strong culture fit.",
"is_internal": true,
"created_at": "2026-04-14T09:12:30Z"
}
],
"meta": { "total": 3, "page": 1, "per_page": 25 }
}/dossiers/:id/notesVoeg een nieuwe notitie toe aan een dossier. Verstuurt een note.created-webhook.
| Veld | Type | Beschrijving |
|---|---|---|
| content* | string | The note text. Cannot be empty. |
| is_internal | boolean | Default: true. Internal notes are not shared. |
curl -X POST https://leadgrid.io/api/v1/dossiers/a91c…/notes \
-H "Authorization: Bearer lg_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "content": "Followed up by email." }'{
"data": {
"id": "n2…",
"dossier_id": "a91c…",
"content": "Followed up by email.",
"is_internal": true,
"created_at": "2026-04-15T12:04:10Z"
}
}Webhooks
Configureer een webhook-endpoint via Instellingen → API. LeadGrid verstuurt een POST-verzoek met een JSON-body wanneer een van deze events plaatsvindt.
| Veld | Type | Beschrijving |
|---|---|---|
| dossier.created | event | A new dossier was created (via API, UI or email). |
| dossier.updated | event | Any field on a dossier changed. Fires alongside stage_changed when applicable. |
| dossier.stage_changed | event | current_stage_id was updated. |
| dossier.deleted | event | Dossier was archived (status set to 'archived'). |
| note.created | event | A new note was added to a dossier. |
POST https://your-app.com/webhooks/leadgrid
Content-Type: application/json
X-LeadGrid-Signature: t=1713178230,v1=3b2c4f…
{
"id": "evt_…",
"type": "dossier.stage_changed",
"created_at": "2026-04-15T12:04:10Z",
"data": {
"id": "a91c…",
"current_stage_id": "d8e2…",
"status": "active"
}
}Handtekeningverificatie
Elk webhook-verzoek bevat een X-LeadGrid-Signature header met een tijdstempel en een HMAC-SHA256-handtekening van `${"timestamp"}.${"body"}` ondertekend met het geheim van je endpoint. Verifieer deze voordat je de payload vertrouwt.
import crypto from "node:crypto";
export function verifyLeadGridSignature(
header: string,
body: string,
secret: string,
) {
const parts = Object.fromEntries(
header.split(",").map((p) => p.split("=")),
);
const { t, v1 } = parts as { t: string; v1: string };
const expected = crypto
.createHmac("sha256", secret)
.update(`${t}.${body}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(v1),
);
}Fouten & limieten
Fouten gebruiken standaard HTTP-statuscodes. De body bevat altijd een error-object met een stabiele code en een leesbare melding.
{
"error": {
"code": "not_found",
"message": "Dossier not found."
}
}| Veld | Type | Beschrijving |
|---|---|---|
| unauthorized | 401 | Missing, malformed or invalid API key. Also returned for expired keys. |
| plan_required | 402 | Your organization is on Free or Pro. API access requires Growth. |
| forbidden | 403 | The API key doesn't include the required scope for this action. |
| not_found | 404 | The resource doesn't exist, or doesn't belong to your organization. |
| invalid_body | 400 | Missing required field, unknown value or malformed JSON. |
| rate_limited | 429 | You've exceeded the rate limit for your plan. Retry after the time in the Retry-After header. |
| internal | 500 | Unexpected server error. Safe to retry. |
X-RateLimit-Limit en X-RateLimit-Remaining headers zodat je terug kunt schakelen voordat je het limiet bereikt.