API · version 2026-08-31

# API et webhooks.

Lisez et écrivez les contacts, sociétés, rendez-vous, deals et leads de votre espace, et recevez ses événements dès qu'ils arrivent. Zapier, Make, n8n, votre site ou votre outil de BI s'y branchent avec une clé, sans attendre une intégration.

URL de base

`https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/api-v1`

Authentification

`Authorization: Bearer lmk_live_…`

Format

REST et JSON, en UTF-8

Limite

120 requêtes par 10 secondes et par clé

Formules

Entreprise Plus et Premium

Spécification

[OpenAPI 3.1, openapi.json](https://www.uggo.app/openapi.json)

## Démarrer en trois étapes

### 1. Créer une clé

Un administrateur de l'espace la crée dans Réglages, API et MCP, et lui donne le nom de l'outil qui s'en servira. Cochez « Autoriser l'écriture » si l'outil doit créer ou modifier des fiches. La clé ne s'affiche qu'une fois : rangez-la dans le coffre de votre outil, jamais dans le code d'une page web.

### 2. Vérifier la clé

`GET /` renvoie la version de l'API, les chemins en lecture et les opérations d'écriture. Une erreur `401` : la clé est mal copiée ou révoquée.

Vérifier la clé

```bash
curl https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/api-v1 \
  -H "Authorization: Bearer lmk_live_…"
```

### 3. Lire et écrire

Chaque ressource se liste, se lit par son identifiant et, pour la plupart, se crée (`POST`) et se modifie (`PATCH`). La réponse d'une écriture est l'objet créé ou modifié.

Lister les contacts

```bash
curl "https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/api-v1/contacts?limit=50" \
  -H "Authorization: Bearer lmk_live_…"
```

Créer un contact

```bash
curl -X POST https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/api-v1/contacts \
  -H "Authorization: Bearer lmk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Camille",
    "last_name": "Martin",
    "phone": "+33612345678",
    "custom_fields": { "call_status": "to_call" }
  }'
```

## Authentification

Chaque requête porte la clé dans l'en-tête `Authorization: Bearer lmk_live_…`, jamais dans l'adresse. Une clé appartient à un espace et ne voit que lui.

- Deux scopes : `read`, toujours présent, et `write`, choisi à la création, pour `POST` et `PATCH`. Une clé ne change pas de scopes : créez-en une autre.
- Jusqu'à 10 clés actives par espace, une par outil, chacune nommée : en révoquer une ne coupe pas les autres.
- uggo ne garde qu'une empreinte de la clé (SHA-256) : une clé perdue se remplace, elle ne se retrouve pas.
- La révocation, depuis les Réglages, prend effet à la requête suivante.

## Pagination et synchronisation

Les listes vont de la fiche la plus récente à la plus ancienne, par pages, avec un curseur : une fiche ajoutée pendant la lecture ne décale pas les pages suivantes.

Une page de contacts

```json
{
  "object": "list",
  "data": [
    { "id": "8f0c…", "first_name": "Camille", "last_name": "Martin", "…": "…" }
  ],
  "has_more": true,
  "next_cursor": "eyJj…"
}
```

| Paramètre | Défaut | Description |
| --- | --- | --- |
| `limit` | 50 | Taille de la page, de 1 à 200. |
| `cursor` | aucun | `next_cursor` de la page précédente (opaque). |
| `updated_since` | aucun | Ne renvoie que les lignes modifiées depuis cette date (ISO 8601), pour une synchronisation incrémentale. |

Pour synchroniser un outil, gardez la date de votre dernière lecture et passez-la dans `updated_since` ; suivez `next_cursor` tant que `has_more` vaut `true`.

Ce qui a changé depuis le 1er octobre

```bash
curl "https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/api-v1/contacts?updated_since=2026-10-01T00:00:00Z&limit=200" \
  -H "Authorization: Bearer lmk_live_…"
```

## Erreurs

Toute erreur renvoie le même JSON : `code`, stable, à tester dans votre code ; `message`, ce qui ne va pas ; `hint`, ce qu'il faut faire pour corriger.

Réponse 401

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Clé API inconnue ou révoquée.",
    "hint": "Envoie l'en-tête `Authorization: Bearer lmk_live_…` avec une clé active, créée dans uggo : Réglages, API."
  }
}
```

| HTTP | Code | Quand |
| --- | --- | --- |
| 400 | `invalid_request` | Un paramètre ou un champ est invalide : `limit`, `cursor`, `updated_since`, uuid, champ inconnu ou mal typé. |
| 401 | `unauthorized` | La clé est absente, inconnue ou révoquée. |
| 403 | `forbidden` | La clé n'a pas le scope `write`, requis pour POST et PATCH. |
| 403 | `plan_gated` | La formule de l'espace ne comprend pas l'API, ou elle écrit une fiche d'objet sans le Builder. |
| 404 | `not_found` | Ressource ou objet introuvable dans l'espace de la clé. |
| 405 | `method_not_allowed` | Méthode non prise en charge, ou écriture sur une ressource en lecture seule (appels). L'en-tête `Allow` liste les méthodes possibles. |
| 409 | `already_exists` | Un lead a déjà été poussé avec cet `external_id`. |
| 422 | `invalid_reference` | `company_id`, `mission_id`, `contact_id` ou `stage_id` n'appartient pas à l'espace. |
| 422 | `invalid_custom_fields` | Une valeur est refusée par le catalogue des champs (`GET /fields`), ou un champ obligatoire manque à la création. |
| 422 | `invalid_data` | Une clé hors du catalogue de l'objet, ou une valeur au mauvais type. |
| 429 | `rate_limited` | Plus de 120 requêtes en 10 secondes pour cette clé : réessayez après `Retry-After` secondes. |
| 500 | `internal_error` | Erreur de notre côté : réessayez, puis écrivez au support avec l'heure de la requête si elle persiste. |

## Référence

Toutes les opérations, par ressource. La même description existe au format OpenAPI 3.1, à importer dans Postman, Insomnia ou un agent IA : [openapi.json](https://www.uggo.app/openapi.json).

Les champs sont ceux de uggo, sans donnée technique ni identifiant de fournisseur. Un champ inconnu ou non modifiable renvoie `400` ; `custom_fields` est fusionné en `PATCH`, `null` efface une clé.

### Point d'entrée

Pour vérifier une clé : la réponse donne la version de l'API, les chemins en lecture et les opérations d'écriture.

#### Point d'entrée de l'API

GET `/`

Vérifie la clé et renvoie la version de l'API, les chemins en lecture et les opérations d'écriture.

### Contacts

Les prospects de l'espace et leurs notes. Le statut de prospection est dans `custom_fields.call_status`.

#### Lister les contacts

GET `/contacts`

Liste les contacts de l'espace de la clé, du plus récent au plus ancien, par pages de 50 (jusqu'à 200) avec un curseur. `updated_since` ne renvoie que les lignes modifiées depuis une date.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

#### Créer un contact

POST `/contacts` scope `write`

Crée un contact (scope `write`) ; au moins un de first_name, last_name, email, phone ou mobile. `custom_fields.call_status` accepte : nouveau, to_call, not_reachable, callback, called, interested, booked, refused, wrong_number, dnc, mv_timing, mv_cible, no_follow_up.

Corps JSON : les champs acceptés en écriture.

#### Lire un contact

GET `/contacts/{id}`

Renvoie un contact de l'espace de la clé par son identifiant.

#### Modifier un contact

PATCH `/contacts/{id}` scope `write`

Modifie les champs envoyés d'un contact (scope `write`) ; les autres restent tels quels, `null` efface une valeur. Renvoie l'objet modifié.

Corps JSON : les champs acceptés en écriture.

#### Lister les notes d'un contact

GET `/contacts/{id}/notes`

Renvoie les notes d'un contact, de la plus récente à la plus ancienne, jusqu'à `limit` (200 au plus), en une seule page.

`limit` : Taille de la page, de 1 à 200.

#### Ajouter une note à un contact

POST `/contacts/{id}/notes` scope `write`

Ajoute une note à un contact (scope `write`), avec `source` = `api`. Le corps ne contient que `content`.

Corps JSON : les champs acceptés en écriture.

### Champs d'un contact, en lecture (19)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `first_name` | texte | Prénom. |
| `last_name` | texte | Nom. |
| `email` | e-mail | Adresse e-mail. |
| `phone` | texte | Téléphone fixe ou principal, de préférence au format E.164 (+33…). |
| `mobile` | texte | Téléphone portable, de préférence au format E.164. |
| `job_title` | texte | Poste. |
| `linkedin_url` | URL | URL du profil LinkedIn. |
| `source` | texte | Provenance du contact (texte libre : salon, import, site…). |
| `tags` | liste de texte | Étiquettes libres. |
| `custom_fields` | objet | Champs personnalisés de l'espace, par clé (catalogue : GET /fields). Fusionnés en PATCH : une clé absente est gardée, `null` l'efface. `call_status` porte le statut de prospection d'un contact. |
| `company_id` | uuid | Société de rattachement (GET /companies). |
| `mission_id` | uuid | Mission ou campagne de rattachement. |
| `callback_at` | date et heure | Rappel planifié (ISO 8601). |
| `last_call_at` | date et heure | Dernier appel. |
| `last_activity_at` | date et heure | Dernière activité. |
| `nrp_count` | entier | Appels sans réponse d'affilée (NRP). |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |

### Champs d'un contact, en écriture (13)

| Champ | Type | Description |
| --- | --- | --- |
| `first_name` | texte | Prénom. |
| `last_name` | texte | Nom. |
| `email` | e-mail | Adresse e-mail. |
| `phone` | texte | Téléphone fixe ou principal, de préférence au format E.164 (+33…). |
| `mobile` | texte | Téléphone portable, de préférence au format E.164. |
| `job_title` | texte | Poste. |
| `linkedin_url` | URL | URL du profil LinkedIn. |
| `source` | texte | Provenance du contact (texte libre : salon, import, site…). |
| `tags` | liste de texte | Étiquettes libres. |
| `custom_fields` | objet | Champs personnalisés de l'espace, par clé (catalogue : GET /fields). Fusionnés en PATCH : une clé absente est gardée, `null` l'efface. `call_status` porte le statut de prospection d'un contact. |
| `company_id` | uuid | Société de rattachement (GET /companies). |
| `mission_id` | uuid | Mission ou campagne de rattachement. |
| `callback_at` | date et heure | Rappel planifié (ISO 8601). |

### Champs d'une note, en lecture (6)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `contact_id` | uuid | Contact de la note. |
| `content` | texte | Texte de la note. |
| `source` | texte | Origine (`api` pour une note créée par l'API). |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |

### Champs d'une note, en écriture (1)

| Champ | Type | Description |
| --- | --- | --- |
| `content` | texte, requis | Texte de la note. |

### Sociétés

Les sociétés de l'espace, avec SIREN, code NAF, effectif et domaine.

#### Lister les sociétés

GET `/companies`

Liste les sociétés de l'espace de la clé, du plus récent au plus ancien, par pages de 50 (jusqu'à 200) avec un curseur. `updated_since` ne renvoie que les lignes modifiées depuis une date.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

#### Créer un société

POST `/companies` scope `write`

Crée un société dans l'espace de la clé (scope `write`). Renvoie l'objet créé.

Corps JSON : les champs acceptés en écriture.

#### Lire un société

GET `/companies/{id}`

Renvoie un société de l'espace de la clé par son identifiant.

#### Modifier un société

PATCH `/companies/{id}` scope `write`

Modifie les champs envoyés d'un société (scope `write`) ; les autres restent tels quels, `null` efface une valeur. Renvoie l'objet modifié.

Corps JSON : les champs acceptés en écriture.

### Champs d'une société, en lecture (16)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `name` | texte | Raison sociale ou nom d'usage. |
| `siren` | texte | SIREN (9 chiffres). |
| `naf_code` | texte | Code NAF ou APE. |
| `industry` | texte | Secteur. |
| `size` | texte | Tranche d'effectif. |
| `city` | texte | Ville. |
| `domain` | texte | Nom de domaine (exemple.fr). |
| `website` | URL | Site web. |
| `phone` | texte | Standard. |
| `generic_email` | texte | Adresse e-mail générique (contact@…). |
| `tags` | liste de texte | Étiquettes libres. |
| `custom_fields` | objet | Champs personnalisés de l'espace, par clé (catalogue : GET /fields). Fusionnés en PATCH : une clé absente est gardée, `null` l'efface. `call_status` porte le statut de prospection d'un contact. |
| `mission_id` | uuid | Mission ou campagne de rattachement. |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |

### Champs d'une société, en écriture (13)

| Champ | Type | Description |
| --- | --- | --- |
| `name` | texte | Raison sociale ou nom d'usage. |
| `siren` | texte | SIREN (9 chiffres). |
| `naf_code` | texte | Code NAF ou APE. |
| `industry` | texte | Secteur. |
| `size` | texte | Tranche d'effectif. |
| `city` | texte | Ville. |
| `domain` | texte | Nom de domaine (exemple.fr). |
| `website` | URL | Site web. |
| `phone` | texte | Standard. |
| `generic_email` | texte | Adresse e-mail générique (contact@…). |
| `tags` | liste de texte | Étiquettes libres. |
| `custom_fields` | objet | Champs personnalisés de l'espace, par clé (catalogue : GET /fields). Fusionnés en PATCH : une clé absente est gardée, `null` l'efface. `call_status` porte le statut de prospection d'un contact. |
| `mission_id` | uuid | Mission ou campagne de rattachement. |

### Appels

Les appels passés et reçus, en lecture seule : ils naissent de la téléphonie. La transcription n'est rendue que sur le détail d'un appel.

#### Lister les appels

GET `/calls`

Liste les appels de l'espace de la clé, du plus récent au plus ancien, par pages de 50 (jusqu'à 200) avec un curseur. `updated_since` ne renvoie que les lignes modifiées depuis une date.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

#### Lire un appel

GET `/calls/{id}`

Renvoie un appel de l'espace de la clé par son identifiant, avec les champs du détail.

### Champs d'un appel, en lecture (14)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `contact_id` | uuid | Contact appelé ou appelant. |
| `direction` | texte | Sens de l'appel. Valeurs : `inbound`, `outbound`. |
| `remote_number` | texte | Numéro du correspondant. |
| `started_at` | date et heure | Début de l'appel. |
| `duration_sec` | entier | Durée en secondes. |
| `status` | texte | Statut téléphonique (répondu, sans réponse…). |
| `outcome` | texte | Résultat noté par le commercial. |
| `summary` | texte | Résumé rédigé par Hunter. |
| `recording_url` | URL | Lien de l'enregistrement. |
| `mission_id` | uuid | Mission ou campagne. |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |
| `transcript` | texte | Transcription de l'appel. |

### Rendez-vous

Les rendez-vous, appelés découvertes dans un espace Entreprise. Un changement de statut est tracé dans l'historique.

#### Lister les rendez-vous

GET `/meetings`

Liste les rendez-vous de l'espace de la clé, du plus récent au plus ancien, par pages de 50 (jusqu'à 200) avec un curseur. `updated_since` ne renvoie que les lignes modifiées depuis une date.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

#### Créer un rendez-vous

POST `/meetings` scope `write`

Crée un rendez-vous ou une découverte (scope `write`) : `scheduled_at` requis ; `company_name`, ou un contact ou une société rattachés ; `mission_id` requis hors espace Entreprise. Statut `booked` par défaut.

Corps JSON : les champs acceptés en écriture.

#### Lire un rendez-vous

GET `/meetings/{id}`

Renvoie un rendez-vous de l'espace de la clé par son identifiant.

#### Modifier un rendez-vous

PATCH `/meetings/{id}` scope `write`

Modifie les champs envoyés d'un rendez-vous (scope `write`) ; les autres restent tels quels, `null` efface une valeur. Renvoie l'objet modifié.

Corps JSON : les champs acceptés en écriture.

### Champs d'un rendez-vous, en lecture (20)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `scheduled_at` | date et heure | Date et heure du rendez-vous (ISO 8601). Requis à la création. |
| `status` | texte | Statut du rendez-vous. Valeurs : `booked`, `validated`, `paid`, `rescheduled`, `no_show`, `cancelled`, `rejected`. |
| `company_name` | texte | Société du rendez-vous (requis sans crm_contact_id ni crm_company_id rattaché à une société). |
| `contact_name` | texte | Nom de la personne rencontrée. |
| `contact_email` | e-mail | E-mail de la personne rencontrée. |
| `contact_phone` | texte | Téléphone de la personne rencontrée. |
| `notes` | texte | Notes. |
| `report` | texte | Compte rendu du rendez-vous. |
| `crm_contact_id` | uuid | Contact rencontré ; société et coordonnées en sont déduites. |
| `crm_company_id` | uuid | Société rencontrée. |
| `mission_id` | uuid | Mission du client ; requise hors espace Entreprise. |
| `origin` | texte | Espace Entreprise : origine de la découverte. Valeurs : `outbound`, `inbound`. |
| `assigned_user_id` | uuid | Espace Entreprise : closer attribué (membre actif de l'espace). |
| `sdr_user_id` | uuid | Membre qui a posé le rendez-vous. |
| `held_auto` | booléen | Validé automatiquement à J+5. |
| `invite_prospect` | booléen | Invite le contact à l'événement d'agenda. |
| `calendar_event_id` | texte | Événement d'agenda lié. |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |

### Champs d'un rendez-vous, en écriture (13)

| Champ | Type | Description |
| --- | --- | --- |
| `company_name` | texte | Société du rendez-vous (requis sans crm_contact_id ni crm_company_id rattaché à une société). |
| `contact_name` | texte | Nom de la personne rencontrée. |
| `contact_email` | e-mail | E-mail de la personne rencontrée. |
| `contact_phone` | texte | Téléphone de la personne rencontrée. |
| `scheduled_at` | date et heure | Date et heure du rendez-vous (ISO 8601). Requis à la création. |
| `status` | texte | Statut du rendez-vous. Valeurs : `booked`, `validated`, `paid`, `rescheduled`, `no_show`, `cancelled`, `rejected`. |
| `notes` | texte | Notes. |
| `crm_contact_id` | uuid | Contact rencontré ; société et coordonnées en sont déduites. |
| `crm_company_id` | uuid | Société rencontrée. |
| `mission_id` | uuid | Mission du client ; requise hors espace Entreprise. |
| `origin` | texte | Espace Entreprise : origine de la découverte. Valeurs : `outbound`, `inbound`. |
| `assigned_user_id` | uuid | Espace Entreprise : closer attribué (membre actif de l'espace). |
| `invite_prospect` | booléen | Invite le contact à l'événement d'agenda. |

### Deals

Le pipeline, appelé opportunités dans un espace Entreprise. Changer d'étape pose ou retire `won_at`, `lost_at` et `lost_reason` comme dans l'app.

#### Lister les deals

GET `/deals`

Liste les deals de l'espace de la clé, du plus récent au plus ancien, par pages de 50 (jusqu'à 200) avec un curseur. `updated_since` ne renvoie que les lignes modifiées depuis une date.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

#### Créer un deal

POST `/deals` scope `write`

Crée un deal (scope `write`) sur la première étape ouverte du pipeline, ou sur `stage_id`. Sans `title`, le titre vient de la société ou du contact.

Corps JSON : les champs acceptés en écriture.

#### Lire un deal

GET `/deals/{id}`

Renvoie un deal de l'espace de la clé par son identifiant.

#### Modifier un deal

PATCH `/deals/{id}` scope `write`

Modifie les champs envoyés d'un deal (scope `write`) ; les autres restent tels quels, `null` efface une valeur. Renvoie l'objet modifié.

Corps JSON : les champs acceptés en écriture.

### Champs d'un deal, en lecture (16)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `title` | texte | Titre du deal. |
| `amount` | nombre | Montant. |
| `currency` | texte | Devise (EUR…). |
| `probability` | nombre | Probabilité de gain, de 0 à 100. |
| `stage_id` | uuid | Étape du pipeline ; won_at, lost_at et lost_reason suivent le type d'étape. |
| `contact_id` | uuid | Contact du deal (création seulement). |
| `company_id` | uuid | Société du deal (création seulement ; déduite du contact sinon). |
| `notes` | texte | Notes. |
| `expected_close_date` | date et heure | Date de signature attendue. |
| `won_at` | date et heure | Gagné le. |
| `lost_at` | date et heure | Perdu le. |
| `lost_reason` | texte | Motif de perte. |
| `custom_fields` | objet | Champs personnalisés de l'espace, par clé (catalogue : GET /fields). Fusionnés en PATCH : une clé absente est gardée, `null` l'efface. `call_status` porte le statut de prospection d'un contact. |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |

### Champs d'un deal, en écriture (10)

| Champ | Type | Description |
| --- | --- | --- |
| `title` | texte | Titre du deal. |
| `amount` | nombre | Montant. |
| `probability` | nombre | Probabilité de gain, de 0 à 100. |
| `notes` | texte | Notes. |
| `expected_close_date` | date et heure | Date de signature attendue. |
| `stage_id` | uuid | Étape du pipeline ; won_at, lost_at et lost_reason suivent le type d'étape. |
| `lost_reason` | texte | Motif de perte. |
| `custom_fields` | objet | Champs personnalisés de l'espace, par clé (catalogue : GET /fields). Fusionnés en PATCH : une clé absente est gardée, `null` l'efface. `call_status` porte le statut de prospection d'un contact. |
| `contact_id` | uuid | Contact du deal (création seulement). |
| `company_id` | uuid | Société du deal (création seulement ; déduite du contact sinon). |

### Leads entrants

Les leads poussés par un site ou un outil no-code arrivent dans le bac de réception, comme une réponse de formulaire : aucune fiche n'est créée avant qualification.

#### Lister les leads entrants

GET `/leads`

Liste les leads entrants de l'espace de la clé, du plus récent au plus ancien, par pages de 50 (jusqu'à 200) avec un curseur. `updated_since` ne renvoie que les lignes modifiées depuis une date.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

#### Créer un lead

POST `/leads` scope `write`

Pousse un lead entrant dans le bac de réception (scope `write`), comme une réponse de formulaire : aucune fiche n'est touchée avant qualification. `identity.email` ou `identity.phone_e164` requis ; `external_id` est unique par espace.

Corps JSON : les champs acceptés en écriture.

#### Lire un lead

GET `/leads/{id}`

Renvoie un lead de l'espace de la clé par son identifiant.

### Champs d'un lead, en lecture (21)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `source` | texte | Origine du lead (`api`, `form`, `signup`…). |
| `form_id` | uuid | Formulaire public d'origine. |
| `status` | texte | État dans le bac de réception. |
| `score` | nombre | Score de qualification. |
| `identity` | objet | Identité du prospect ; `email` ou `phone_e164` requis. |
| `identity.email` | e-mail | E-mail. |
| `identity.phone_e164` | texte | Téléphone au format E.164 (+33612345678). |
| `identity.first_name` | texte | Prénom. |
| `identity.last_name` | texte | Nom. |
| `identity.company` | texte | Société. |
| `identity.job_title` | texte | Poste. |
| `identity.website` | texte | Site web de la société. |
| `payload` | objet | Réponses ou données brutes du formulaire d'origine. |
| `utm` | objet | Paramètres UTM de la visite (utm_source, utm_campaign…). |
| `referrer` | texte | Page d'origine. |
| `contact_id` | uuid | Contact créé ou rapproché. |
| `company_id` | uuid | Société créée ou rapprochée. |
| `owner_id` | uuid | Membre actif de l'espace à qui confier le lead. |
| `created_at` | date et heure | Création. |
| `handled_at` | date et heure | Traité le. |

### Champs d'un lead, en écriture (15)

| Champ | Type | Description |
| --- | --- | --- |
| `identity` | objet, requis | Identité du prospect ; `email` ou `phone_e164` requis. |
| `identity.email` | e-mail | E-mail. |
| `identity.phone_e164` | texte | Téléphone au format E.164 (+33612345678). |
| `identity.first_name` | texte | Prénom. |
| `identity.last_name` | texte | Nom. |
| `identity.company` | texte | Société. |
| `identity.job_title` | texte | Poste. |
| `identity.website` | texte | Site web de la société. |
| `payload` | objet | Réponses ou données brutes du formulaire d'origine. |
| `utm` | objet | Paramètres UTM de la visite (utm_source, utm_campaign…). |
| `referrer` | texte | Page d'origine. |
| `external_source` | texte | Système d'origine (site, Typeform…). |
| `external_id` | texte | Identifiant dans le système d'origine ; unique par espace. |
| `owner_id` | uuid | Membre actif de l'espace à qui confier le lead. |
| `score` | nombre | Score de qualification. |

### Champs et objets personnalisés

Le catalogue des champs de l'espace (les clés à envoyer dans `custom_fields`) et les objets créés avec le Builder (Contrats, Projets…), adressés par leur slug.

#### Lister les champs personnalisés

GET `/fields`

Renvoie le catalogue des champs personnalisés des contacts, sociétés et deals : clés à envoyer dans `custom_fields`, types et choix.

#### Lister les objets personnalisés

GET `/objects`

Renvoie les objets personnalisés de l'espace (Contrats, Projets…) et leurs champs.

#### Lire un objet personnalisé

GET `/objects/{slug}`

Renvoie un objet personnalisé et ses champs, par son slug.

#### Lister les fiches d'un objet

GET `/objects/{slug}/records`

Liste les fiches actives d'un objet personnalisé, avec la même pagination que les autres listes ; `q` cherche dans le titre, `archived=true` inclut les archivées.

Pagination : `limit`, `cursor`, `updated_since` (voir Pagination).

`q` : Recherche dans le titre des fiches.

`archived` : true inclut les fiches archivées.

#### Créer une fiche d'objet

POST `/objects/{slug}/records` scope `write`

Crée une fiche d'objet personnalisé (scope `write`, formule avec le Builder). `data` n'accepte que les clés du catalogue de l'objet.

Corps JSON : les champs acceptés en écriture.

#### Lire une fiche d'objet

GET `/objects/{slug}/records/{record_id}`

Renvoie une fiche d'objet personnalisé par son identifiant.

#### Modifier une fiche d'objet

PATCH `/objects/{slug}/records/{record_id}` scope `write`

Modifie une fiche d'objet personnalisé (scope `write`, formule avec le Builder) : `data` est fusionné, `archived` archive ou restaure.

Corps JSON : les champs acceptés en écriture.

### Champs d'un champ du catalogue, en lecture (8)

| Champ | Type | Description |
| --- | --- | --- |
| `objet` | texte | Fiche du champ : contact, company, deal, ou obj:<id> pour un objet personnalisé. |
| `cle` | texte | Clé à envoyer dans custom_fields ou data. |
| `libelle` | texte | Libellé affiché. |
| `type` | texte | Type du champ (texte, nombre, date, choix…). |
| `obligatoire` | booléen | Requis à la création. |
| `choix` | liste d'objets | Choix possibles d'une liste ; s'envoient par id (ou par libellé). |
| `plusieurs` | booléen | Plusieurs choix possibles. |
| `aide` | texte | Texte d'aide. |

### Champs d'une fiche d'objet, en lecture (9)

| Champ | Type | Description |
| --- | --- | --- |
| `id` | uuid | Identifiant (uuid). |
| `object` | texte | Slug de l'objet. |
| `title` | texte | Valeur du champ titre. |
| `data` | objet | Valeurs, par clé de champ. |
| `owner_id` | uuid | Responsable de la fiche. |
| `created_by` | uuid | Auteur ; null pour une création par clé API. |
| `created_at` | date et heure | Création. |
| `updated_at` | date et heure | Dernière modification. |
| `archived_at` | date et heure | Archivée le ; null si active. |

### Champs d'une fiche d'objet, en écriture (2)

| Champ | Type | Description |
| --- | --- | --- |
| `data` | objet, requis | Valeurs par clé du catalogue de l'objet ; le champ titre est requis. |
| `owner_id` | uuid | Responsable (membre actif de l'espace). |

## Webhooks

uggo envoie les événements de l'espace à vos adresses, en POST JSON, dans la minute. Un administrateur les ajoute dans Réglages, API et MCP, Webhooks sortants, et choisit les événements de chaque adresse (aucun choisi : tous). Un webhook Zapier, Make ou n8n se branche tel quel.

### Événements

| Événement | Quand |
| --- | --- |
| `meeting.created` | Un rendez-vous est créé, dans uggo ou par l'API. |
| `meeting.updated` | Le statut d'un rendez-vous change ; `previous_status` donne l'ancien. |
| `meeting.assigned` | Un closer est attribué ou changé sur une découverte (espace Entreprise). |
| `contact.status_changed` | Le statut de prospection d'un contact (`custom_fields.call_status`) change. |
| `callback.created` | Un rappel est planifié ou déplacé (`callback_at`). |
| `deal.created` | Un deal est créé ; `meeting_id` quand il naît d'une découverte tenue. |
| `deal.stage_changed` | Un deal change d'étape, gagné et perdu compris ; `stage_label` donne le nom de l'étape. |
| `call.completed` | Un appel est enregistré. Durée et résumé arrivent ensuite : relisez `GET /calls/{id}`. |
| `lead.created` | Un lead entrant arrive (formulaire public, API, inscription), avec ses réponses. |
| `booking.created` | Un prospect prend un rendez-vous en ligne. |
| `booking.rescheduled` | Un prospect replanifie un rendez-vous pris en ligne. |
| `booking.cancelled` | Un prospect annule un rendez-vous pris en ligne. |
| `record.created` | Une fiche d'objet personnalisé est créée : la fiche, l'objet et ses champs (clé, libellé, type, valeur). |
| `record.updated` | Une fiche d'objet change ; `changed` liste les champs modifiés. Une écriture sans changement n'envoie rien. |
| `record.archived` | Une fiche d'objet est archivée. |

S'y ajoutent `automation.triggered`, envoyé par l'action « Envoyer à un webhook » d'une automatisation du Builder à l'adresse qu'elle choisit, et `ping`, le test lancé depuis les Réglages.

### Format d'un envoi

Requête reçue par votre adresse

```http
POST https://votre-outil.example/webhooks/uggo
Content-Type: application/json
x-uggo-event: meeting.created
x-uggo-delivery: 5b1e…
x-uggo-signature: t=1793109600,v1=3f9a…

{
  "id": "5b1e…",
  "event": "meeting.created",
  "created_at": "2026-10-27T14:00:00Z",
  "attempt": 1,
  "data": { "…": "…" }
}
```

### Vérifier la signature

Chaque adresse a son secret `whsec_…`, affiché dans les Réglages. `v1` est le HMAC-SHA256 de `<t>.<corps brut>` avec ce secret. Recalculez-le sur le corps reçu, avant tout traitement, et refusez un envoi dont `t` a plus de 5 minutes : un envoi rejoué ne passe pas.

Vérification en Node.js

```js
import crypto from "node:crypto";

// header : en-tête x-uggo-signature ; body : le corps brut, avant JSON.parse ;
// secret : le whsec_… de l'adresse, affiché dans Réglages.
export function signatureValide(header, body, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((part) => part.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // plus de 5 minutes : rejeu
  const attendu = crypto.createHmac("sha256", secret).update(`${t}.${body}`).digest("hex");
  return v1.length === attendu.length && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(attendu));
}
```

### Relances

- Une réponse `2xx` en moins de 8 secondes vaut livraison. Sinon, uggo réessaie après 1 minute, 5 minutes, 30 minutes puis 2 heures, et abandonne à la 5e tentative.
- Après 20 échecs d'affilée, l'adresse est désactivée ; elle se réactive dans les Réglages, où s'affichent ses 20 derniers envois.
- L'ordre est gardé pour une même adresse. Une relance porte le même `id` : dédupliquez sur `id` pour traiter chaque événement une fois.

## Serveur MCP

Pour piloter l'espace depuis Claude, ChatGPT, Gemini ou tout client MCP. Le jeton de l'espace se trouve dans Réglages, API et MCP ; il passe dans l'en-tête Authorization, ou à la fin de l'adresse pour les clients sans en-têtes.

Adresse du serveur (Streamable HTTP, JSON-RPC 2.0)

```http
https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/crm-mcp
Authorization: Bearer <jeton>

https://iwmtiwjknbwymbajbzaz.supabase.co/functions/v1/crm-mcp/<jeton>
```

Ses outils cherchent et lisent les prospects, notent un appel, créent rappels, tâches, deals et rendez-vous, gèrent les listes d'appel, importent des contacts, lisent objectifs et KPI, et fournissent les données d'un rapport d'activité.

## Une question sur l'API ?

Un endpoint qui manque, une intégration à monter : écrivez à [support@uggo.app](mailto:support@uggo.app). L'API, les webhooks et le serveur MCP sont compris dans les formules Entreprise Plus et Premium : [voir les tarifs](https://www.uggo.app/tarifs).

---

- Page : https://www.uggo.app/developpeurs
- Toutes les pages : https://www.uggo.app/sitemap.xml
- uggo pour les agents : https://www.uggo.app/llms.txt
