Übersicht
Die LeadGrid API ermöglicht es dir, Dossiers zu erstellen und zu verwalten, Phasen zu aktualisieren, Notizen anzuhängen und Daten mit deinen eigenen Tools zu synchronisieren. Jede Anfrage gibt JSON zurück.
Alle Zeitstempel sind ISO 8601 in UTC. Alle Beträge sind ganzzahlig oder dezimal in der kleinsten praktischen Einheit (z. B. Euro, nicht Cent). Die Paginierung verwendet page und per_page Abfrageparameter; Antworten enthalten ein meta Objekt mit der Gesamtanzahl.
Authentifizierung
Jede Anfrage muss einen API-Schlüssel im Authorization-Header tragen. Schlüssel beginnen mit lg_live_ und sind auf eine Organisation beschränkt.
- 1Gehe zu Einstellungen → API und klicke auf API-Schlüssel erstellen.
- 2Wähle die benötigten Scopes (siehe Tabelle unten) und setze optional ein Ablaufdatum. Der vollständige Schlüssel wird einmalig angezeigt, kopiere ihn sofort.
- 3Sende den Schlüssel als Bearer-Token bei jeder Anfrage mit.
curl https://leadgrid.io/api/v1/dossiers \ -H "Authorization: Bearer lg_live_your_key_here"
| Feld | Typ | Beschreibung |
|---|---|---|
| dossiers:read | scope | Dossiers auflisten und abrufen. |
| dossiers:write | scope | Dossiers erstellen, aktualisieren und archivieren. Auch erforderlich, um Phasen zu verschieben. |
| contacts:read | scope | Kontakte auflisten und abrufen sowie ihre Dossierverknüpfungen lesen. |
| contacts:write | scope | Kontakte erstellen, aktualisieren und löschen. Zusätzlich zu dossiers:write erforderlich, um Kontakte mit einem Dossier zu verknüpfen oder die Verknüpfung aufzuheben. |
| flows:read | scope | Flows auflisten und ihre Phasen lesen. |
| notes:read | scope | Notizen zu Dossiers lesen. |
| notes:write | scope | Neue Notizen zu Dossiers hinzufügen. |
Dossiers
Dossiers sind die Entitäten, die du verfolgst, Kandidaten im Recruiting oder Leads im Vertrieb. Jedes Dossier gehört zu genau einem Flow und befindet sich in genau einer Phase.
/dossiersDossiers in deiner Organisation auflisten. Unterstützt Filtern und Paginierung.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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 }
}/dossiersEin neues Dossier erstellen. Wenn flow_id weggelassen wird, wird der Standard-Flow für den angegebenen Typ verwendet; das Dossier startet in der ersten Phase dieses Flows. Übergib optional eine contact_id, um das Dossier mit einem bestehenden Kontakt zu verknüpfen, statt einen neuen anzulegen. Sende application/json für eine einfache Erstellung oder multipart/form-data mit einem 'cv'-Dateifeld, um das Dossier UND einen PDF-Lebenslauf in einem atomaren Aufruf anzuhängen: Wenn der Upload fehlschlägt, wird das Dossier zurückgerollt.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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/:idEin einzelnes Dossier anhand der ID abrufen.
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/:idEine beliebige Teilmenge von Feldern aktualisieren. Das Setzen von current_stage_id verschiebt das Dossier in eine neue Phase und löst einen dossier.stage_changed-Webhook aus.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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/:idArchiviert das Dossier (Soft Delete). Setzt den Status auf 'archived' und löst dossier.deleted aus. Daten bleiben erhalten und können per PATCH wiederhergestellt werden.
curl -X DELETE https://leadgrid.io/api/v1/dossiers/a91c… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"id": "a91c…",
"status": "archived"
}
}/dossiers/:id/cvEinen PDF-Lebenslauf (max. 10 MB) hochladen und an ein vorhandenes Dossier anhängen. Der Upload ersetzt einen eventuell vorhandenen Lebenslauf. Akzeptiert multipart/form-data mit einem 'cv'-Feld oder application/pdf mit den PDF-Bytes als Raw-Body. Löst dossier.updated aus.
# 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"
}
}Kontakte
Kontakte sind die Personen in deinem Netzwerk: Kandidaten, Interessenten, Kunden, Lieferanten und Partner. Ein einzelner Kontakt kann mehrere kinds gleichzeitig haben und mit beliebig vielen Dossiers verknüpft sein.
/contactsKontakte in deiner Organisation auflisten. Unterstützt Filterung nach kind, Pool-Status und Freitextsuche sowie Paginierung.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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 }
}/contactsEinen neuen Kontakt erstellen. full_name ist das einzige Pflichtfeld. Existiert bereits ein Kontakt mit derselben E-Mail-Adresse in deiner Organisation (Groß-/Kleinschreibung wird ignoriert), gibt die API 409 mit einem duplicate_contact-Fehler zurück.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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/:idEinen einzelnen Kontakt anhand der ID abrufen, einschließlich seiner kinds und aggregierter Dossierzahlen.
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/:idBeliebige Felder eines Kontakts teilweise aktualisieren. Sende nur die Schlüssel, die du ändern möchtest.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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/:idDen Kontakt endgültig löschen. Die Verknüpfungen in dossier_contacts werden mitgelöscht, die verknüpften Dossiers selbst bleiben erhalten.
curl -X DELETE https://leadgrid.io/api/v1/contacts/c12a… \ -H "Authorization: Bearer lg_live_your_key"
{
"data": {
"id": "c12a…",
"deleted": true
}
}Dossierverknüpfungen
Eine Dossier-Kontakt-Verknüpfung verbindet einen Kontakt mit einem Dossier und hält fest, welche Rolle die Person bei diesem Deal oder Hire einnimmt (primary, hiring manager, decision maker, champion, gatekeeper, introducer oder other). Ein Dossier kann viele Kontakte haben; ein Kontakt kann auf vielen Dossiers stehen.
/dossiers/:id/contactsDie mit einem Dossier verknüpften Kontakte auflisten, inklusive Rolle und Information, ob es sich um den primären Kontakt handelt.
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/contactsEinen vorhandenen Kontakt mit einer Rolle an ein Dossier knüpfen. Wenn is_primary auf true gesetzt wird, verliert ein vorheriger primärer Kontakt auf diesem Dossier diesen Status.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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_idDie Verknüpfung eines Kontakts mit einem Dossier aufheben. Der Kontakt selbst bleibt bestehen.
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 sind die Pipelines, durch die Dossiers sich bewegen. Jeder Flow hat geordnete Phasen mit optionalen Deadlines und Gewinnwahrscheinlichkeiten.
/flowsFlows in deiner Organisation auflisten. Phasen sind verschachtelt und nach Position geordnet.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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/stagesDie Phasen für einen einzelnen Flow abrufen, sortiert nach Position. Nützlich, wenn du die flow_id bereits kennst und nur die Phasen möchtest.
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 }
}Notizen
Notizen sind die Zeitleiste der Aktualisierungen, die an ein Dossier angehängt sind. Sie sind von ältester bis neuester sortiert und standardmäßig immer intern.
/dossiers/:id/notesNotizen für ein Dossier auflisten, älteste zuerst.
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/notesEine neue Notiz zu einem Dossier hinzufügen. Löst einen note.created-Webhook aus.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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
Konfiguriere einen Webhook-Endpunkt unter Einstellungen → API. LeadGrid sendet eine POST-Anfrage mit einem JSON-Body, wenn eines dieser Events eintritt.
| Feld | Typ | Beschreibung |
|---|---|---|
| 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"
}
}Signaturverifizierung
Jede Webhook-Anfrage enthält einen X-LeadGrid-Signature Header mit einem Zeitstempel und einer HMAC-SHA256-Signatur von `${"timestamp"}.${"body"}` signiert mit dem Geheimnis deines Endpunkts. Verifiziere sie, bevor du dem Payload vertraust.
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),
);
}Fehler & Rate Limits
Fehler verwenden Standard-HTTP-Statuscodes. Der Body enthält immer ein Error-Objekt mit einem stabilen Code und einer lesbaren Nachricht.
{
"error": {
"code": "not_found",
"message": "Dossier not found."
}
}| Feld | Typ | Beschreibung |
|---|---|---|
| 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 und X-RateLimit-Remaining Header, damit du zurückschalten kannst, bevor du das Limit erreichst.