Référence APIv1

Développe sur tes pipelines LeadGrid.

Crée des dossiers, fais-les progresser dans les étapes, synchronise des notes et réagis aux événements. Une seule API REST, JSON en entrée et en sortie. Disponible avec le plan Growth.

01: Par ici

Aperçu

L'API LeadGrid te permet de créer et gérer des dossiers, de mettre à jour les étapes, d'attacher des notes et de synchroniser des données avec tes propres outils. Chaque requête retourne du JSON.

URL de base
https://leadgrid.io/api/v1
Format
JSON (UTF-8)
Auth
Bearer clé API
Disponibilité
Plan Growth

Tous les horodatages sont en ISO 8601 UTC. Tous les montants sont des entiers ou des décimaux dans la plus petite unité pratique (p. ex. euros, pas centimes). La pagination utilise page et per_page comme paramètres de requête ; les réponses incluent un objet meta avec le nombre total.

02: Sécurité

Authentification

Chaque requête doit comporter une clé API dans l'en-tête Authorization. Les clés commencent par lg_live_ et sont liées à une seule organisation.

  1. 1Rends-toi dans Paramètres → API et clique sur Créer une clé API.
  2. 2Choisis les scopes dont tu as besoin (voir le tableau ci-dessous) et définis éventuellement une date d'expiration. La clé complète est affichée une seule fois . Copie-la immédiatement.
  3. 3Envoie la clé comme token Bearer à chaque requête.
curl
curl https://leadgrid.io/api/v1/dossiers \
  -H "Authorization: Bearer lg_live_your_key_here"
Scopes disponibles
ChampTypeDescription
dossiers:readscopeLister et récupérer des dossiers.
dossiers:writescopeCréer, mettre à jour et archiver des dossiers. Également requis pour déplacer des étapes.
contacts:readscopeLister et récupérer des contacts, et lire leurs liens vers les dossiers.
contacts:writescopeCréer, mettre à jour et supprimer des contacts. Requis en plus de dossiers:write pour lier ou délier des contacts à un dossier.
flows:readscopeLister les flows et lire leurs étapes.
notes:readscopeLire les notes sur les dossiers.
notes:writescopeAjouter de nouvelles notes aux dossiers.
N'expose jamais ta clé dans du code côté client. La clé donne un accès complet à ton organisation ; traite-la comme un mot de passe. Si une clé fuite, supprime-la depuis Paramètres → API et remplace-la immédiatement.
03: Ressources

Dossiers

Les dossiers sont les entités que tu suis, candidats en recrutement ou prospects en vente. Chaque dossier appartient à exactement un flow et se trouve dans exactement une étape.

GET/dossiers

Lister les dossiers de ton organisation. Supporte le filtrage et la pagination.

Paramètres de requête
ChampTypeDescription
typestring'candidate' or 'sales'.
statusstring'active', 'won', 'lost' or 'archived'.
stage_iduuidReturn only dossiers currently in this stage.
pageinteger1-based page number. Default: 1.
per_pageintegerItems per page (max 100). Default: 25.
Exemple de requête
curl "https://leadgrid.io/api/v1/dossiers?type=sales&status=active" \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "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 }
}
POST/dossiers

Créer un nouveau dossier. Si flow_id est omis, le flow par défaut pour le type donné est utilisé ; le dossier démarre à la première étape de ce flow. Passe éventuellement un contact_id pour rattacher le dossier à un Contact existant au lieu d'en créer un nouveau. Envoie application/json pour une création simple, ou multipart/form-data avec un champ 'cv' pour créer le dossier ET joindre un CV PDF en un seul appel atomique : si l'upload échoue, le dossier est annulé.

Corps de la requête
ChampTypeDescription
type*string'candidate' or 'sales'.
name*stringFor candidates: the person's name. For sales: deal or account name.
emailstringPrimary contact email.
phonestringPrimary contact phone.
companystringCandidate: current employer. Sales: target company.
rolestringCandidate: role they're applying for. Sales: role of the contact.
contact_iduuidLink the dossier to an existing Contact instead of creating a new one. Must belong to your organization.
flow_iduuidOverride the default flow. Must belong to your organization.
assigned_touuidUser ID of the member to assign this dossier to.
intake_notesstringDirector/intake notes shown in the dossier drawer.
contact_personstringSales only. Named contact at the target company.
deal_sizenumberSales only. Expected contract value.
deal_currencystringSales only. ISO 4217 currency code (e.g. 'EUR').
cvfile (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.
Exemple de requête
# 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"
Exemple de réponse
{
  "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"
  }
}
GET/dossiers/:id

Récupérer un seul dossier par son ID.

Exemple de requête
curl https://leadgrid.io/api/v1/dossiers/a91c… \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "data": {
    "id": "a91c…",
    "type": "sales",
    "name": "KLM, Cabin crew hiring",
    "deal_size": 62000,
    "current_stage_id": "b77f…"
  }
}
PATCH/dossiers/:id

Mettre à jour un sous-ensemble quelconque de champs. Définir current_stage_id déplace le dossier vers une nouvelle étape et émet un webhook dossier.stage_changed.

Corps de la requête
ChampTypeDescription
namestringRename the dossier.
emailstringUpdate primary contact email.
phonestringUpdate phone.
companystringUpdate company / employer.
rolestringUpdate role.
contact_personstringSales only.
deal_sizenumberSales only.
deal_currencystringSales only.
statusstring'active', 'won', 'lost' or 'archived'.
assigned_touuidReassign to another member. Null to unassign.
intake_notesstringReplace intake notes.
current_stage_iduuidMove to a new stage. Must belong to the dossier's flow.
Exemple de requête
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" }'
Exemple de réponse
{
  "data": {
    "id": "a91c…",
    "current_stage_id": "d8e2…",
    "status": "active"
  }
}
DELETE/dossiers/:id

Archive le dossier (suppression douce). Définit le statut sur 'archived' et émet dossier.deleted. Les données sont conservées et peuvent être restaurées via PATCH.

Exemple de requête
curl -X DELETE https://leadgrid.io/api/v1/dossiers/a91c… \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "data": {
    "id": "a91c…",
    "status": "archived"
  }
}
POST/dossiers/:id/cv

Uploader un CV PDF (max. 10 Mo) et l'attacher à un dossier existant. L'upload remplace tout CV précédent. Accepte multipart/form-data avec un champ 'cv', ou application/pdf avec les octets PDF comme corps brut. Émet dossier.updated.

Exemple de requête
# 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
Exemple de réponse
{
  "data": {
    "id": "a91c…",
    "cv_url": "<org-id>/dossiers/a91c…/cv.pdf"
  }
}
04: Ressources

Contacts

Les Contacts sont les personnes de ton réseau : candidats, prospects, clients, fournisseurs et partenaires. Un même Contact peut porter plusieurs kinds à la fois et être rattaché à un nombre quelconque de dossiers.

GET/contacts

Lister les contacts de ton organisation. Supporte le filtrage par kind, statut de pool et recherche libre, avec pagination.

Paramètres de requête
ChampTypeDescription
kindstringFilter by kind. Repeat the parameter to combine values: 'candidate', 'prospect', 'client', 'supplier' or 'partner'.
poolstring'in_pool' for contacts currently in the talent pool, 'expired' for contacts whose pool window has passed.
searchstringFree-text search over full_name, email, company and role.
pageinteger1-based page number. Default: 1.
per_pageintegerItems per page (max 100). Default: 25.
Exemple de requête
curl "https://leadgrid.io/api/v1/contacts?kind=candidate&kind=client&search=sophie" \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "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 }
}
POST/contacts

Créer un nouveau contact. full_name est le seul champ obligatoire. Si un contact avec la même adresse e-mail existe déjà dans ton organisation (insensible à la casse), l'API retourne 409 avec une erreur duplicate_contact.

Corps de la requête
ChampTypeDescription
full_name*stringThe contact's full name.
emailstringPrimary email. Must be unique per organization (case-insensitive). Returns 409 on conflict.
phonestringPrimary phone number.
linkedin_urlstringPublic LinkedIn profile URL.
companystringCurrent employer or account.
rolestringJob title or role.
citystringCity of residence.
kindstring[]Array of kinds: 'candidate', 'prospect', 'client', 'supplier', 'partner'. Defaults to an empty array.
notesstringFree-form internal notes shown on the contact drawer.
Exemple de requête
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"]
  }'
Exemple de réponse
{
  "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"
  }
}
GET/contacts/:id

Récupérer un seul contact par son ID, avec ses kinds et le nombre agrégé de dossiers associés.

Exemple de requête
curl https://leadgrid.io/api/v1/contacts/c12a… \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "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
  }
}
PATCH/contacts/:id

Mettre à jour partiellement n'importe quel champ d'un contact. N'envoie que les clés que tu veux modifier.

Corps de la requête
ChampTypeDescription
full_namestringRename the contact.
emailstringUpdate primary email. Still subject to the per-org uniqueness check.
phonestringUpdate phone number.
linkedin_urlstringUpdate LinkedIn URL.
companystringUpdate company.
rolestringUpdate role.
citystringUpdate city.
kindstring[]Replace the full kinds array. Send the complete set of kinds you want on the contact.
notesstringReplace internal notes.
Exemple de requête
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" }'
Exemple de réponse
{
  "data": {
    "id": "c12a…",
    "kind": ["candidate", "client"],
    "city": "Rotterdam"
  }
}
DELETE/contacts/:id

Supprimer définitivement le contact. Les liens dans dossier_contacts sont supprimés en cascade, mais les dossiers liés eux-mêmes restent intacts.

Exemple de requête
curl -X DELETE https://leadgrid.io/api/v1/contacts/c12a… \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "data": {
    "id": "c12a…",
    "deleted": true
  }
}

Liens vers les dossiers

Un lien dossier-contact associe un Contact à un dossier et enregistre le rôle qu'il joue sur cette deal ou ce recrutement (primary, hiring manager, decision maker, champion, gatekeeper, introducer ou other). Un dossier peut avoir plusieurs contacts ; un contact peut figurer sur plusieurs dossiers.

GET/dossiers/:id/contacts

Lister les contacts liés à un dossier, avec leur rôle et l'indication s'ils sont le contact principal.

Exemple de requête
curl https://leadgrid.io/api/v1/dossiers/a91c…/contacts \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "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 }
}
POST/dossiers/:id/contacts

Lier un contact existant à un dossier avec un rôle. Mettre is_primary à true rétrograde tout contact principal précédent sur ce dossier.

Corps de la requête
ChampTypeDescription
contact_id*uuidThe contact to link. Must belong to your organization.
role_on_dossier*stringOne of 'primary', 'hiring_manager', 'decision_maker', 'champion', 'gatekeeper', 'introducer' or 'other'.
is_primarybooleanDefault: false. Setting true demotes the previous primary contact on this dossier.
Exemple de requête
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
  }'
Exemple de réponse
{
  "data": {
    "dossier_id": "a91c…",
    "contact_id": "c44b…",
    "role_on_dossier": "decision_maker",
    "is_primary": false
  }
}
DELETE/dossiers/:id/contacts/:contact_id

Délier un contact d'un dossier. Le contact lui-même est conservé.

Exemple de requête
curl -X DELETE https://leadgrid.io/api/v1/dossiers/a91c…/contacts/c44b… \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "data": {
    "dossier_id": "a91c…",
    "contact_id": "c44b…",
    "unlinked": true
  }
}
05: Ressources

Flows

Les flows sont les pipelines par lesquels les dossiers progressent. Chaque flow comporte des étapes ordonnées avec des délais et des probabilités de gain optionnels.

GET/flows

Lister les flows de ton organisation. Les étapes sont imbriquées et ordonnées par position.

Paramètres de requête
ChampTypeDescription
typestringFilter to 'candidate' or 'sales'.
pageintegerPage number. Default: 1.
per_pageintegerItems per page. Default: 25.
Exemple de requête
curl "https://leadgrid.io/api/v1/flows?type=sales" \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "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 }
}
GET/flows/:id/stages

Récupérer les étapes d'un seul flow, triées par position. Utile si tu connais déjà le flow_id et veux uniquement les étapes.

Exemple de requête
curl https://leadgrid.io/api/v1/flows/f01a…/stages \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "data": [
    {
      "id": "s1…",
      "name": "Lead",
      "position": 1,
      "deadline_days": 3,
      "win_probability": 14
    }
  ],
  "meta": { "total": 6, "page": 1, "per_page": 6 }
}
06: Ressources

Notes

Les notes constituent la chronologie des mises à jour attachées à un dossier. Elles sont triées de la plus ancienne à la plus récente et sont toujours internes par défaut.

GET/dossiers/:id/notes

Lister les notes d'un dossier, les plus anciennes en premier.

Exemple de requête
curl https://leadgrid.io/api/v1/dossiers/a91c…/notes \
  -H "Authorization: Bearer lg_live_your_key"
Exemple de réponse
{
  "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 }
}
POST/dossiers/:id/notes

Ajouter une nouvelle note à un dossier. Émet un webhook note.created.

Corps de la requête
ChampTypeDescription
content*stringThe note text. Cannot be empty.
is_internalbooleanDefault: true. Internal notes are not shared.
Exemple de requête
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." }'
Exemple de réponse
{
  "data": {
    "id": "n2…",
    "dossier_id": "a91c…",
    "content": "Followed up by email.",
    "is_internal": true,
    "created_at": "2026-04-15T12:04:10Z"
  }
}
07: Événements

Webhooks

Configure un endpoint webhook dans Paramètres → API. LeadGrid envoie une requête POST avec un corps JSON lorsque l'un de ces événements se produit.

Types d'événements
ChampTypeDescription
dossier.createdeventA new dossier was created (via API, UI or email).
dossier.updatedeventAny field on a dossier changed. Fires alongside stage_changed when applicable.
dossier.stage_changedeventcurrent_stage_id was updated.
dossier.deletedeventDossier was archived (status set to 'archived').
note.createdeventA new note was added to a dossier.
Example payload
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"
  }
}

Vérification de signature

Chaque requête webhook inclut un en-tête X-LeadGrid-Signature contenant un horodatage et une signature HMAC-SHA256 de `${"timestamp"}.${"body"}` signée avec le secret de ton endpoint. Vérifie-la avant de faire confiance au payload.

node.js (verification)
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),
  );
}
08: Référence

Erreurs & limites de débit

Les erreurs utilisent les codes de statut HTTP standard. Le corps contient toujours un objet error avec un code stable et un message lisible.

Error shape
{
  "error": {
    "code": "not_found",
    "message": "Dossier not found."
  }
}
Codes d'erreur courants
ChampTypeDescription
unauthorized401Missing, malformed or invalid API key. Also returned for expired keys.
plan_required402Your organization is on Free or Pro. API access requires Growth.
forbidden403The API key doesn't include the required scope for this action.
not_found404The resource doesn't exist, or doesn't belong to your organization.
invalid_body400Missing required field, unknown value or malformed JSON.
rate_limited429You've exceeded the rate limit for your plan. Retry after the time in the Retry-After header.
internal500Unexpected server error. Safe to retry.
Limite de débit Growth
600 req / min / key
Réponse 429
Retry-After header in seconds
Chaque réponse inclut X-RateLimit-Limit et X-RateLimit-Remaining en-têtes pour que tu puisses ralentir avant d'atteindre la limite.