Référence développeur : API REST et MCP
La référence complète de l'API Sellio : authentification par clé API, découverte des champs, points de terminaison REST, format d'erreur, limite de débit et le serveur MCP pour les agents IA.
Intégrez Sellio via HTTP ou connectez votre agent IA via MCP. Dans les deux cas, c'est la même clé, la même portée de tenant et la même limite de débit. Découvrez les champs de n'importe quel objet et commencez à lire et écrire des enregistrements en quelques minutes.
Authentification
Chaque requête porte une clé API dans l'en-tête Authorization: Bearer. Cette clé identifie le tenant propriétaire, donc tout est automatiquement limité à sa portée. N'exposez jamais la clé dans le navigateur ; utilisez-la uniquement côté serveur. Vous générez et révoquez les clés dans Paramètres → API & développeurs.
curl -H "Authorization: Bearer sk_live_..." \
https://www.selliocrm.com/api/v1/objectsPortées de clé
Lorsque vous générez une clé dans Paramètres → API & développeurs, vous choisissez sa portée. Donnez à chaque intégration uniquement l'accès dont elle a besoin. Les limites s'appliquent de la même façon en REST et en MCP, car les deux surfaces utilisent la même clé et le même contrôle.
- Lecture seule : la clé lit les données mais ne peut pas créer, modifier ni supprimer. Elle bloque POST, PATCH et DELETE en REST et les outils create_record, update_record et delete_record en MCP. Les tentatives d'écriture ou de suppression reçoivent 403 avec { "error": "errors.apiKeyReadOnly" }.
- Limitée à des objets : choisissez les objets auxquels la clé peut accéder. Tout objet hors de la liste renvoie 403 avec { "error": "errors.apiKeyObjectDenied" }. La liste d'objets (GET /api/v1/objects et l'outil list_objects) est déjà filtrée selon la portée, et les activités (/api/v1/activities) comptent comme l'objet activité : la clé n'y accède que si activity fait partie de la portée.
- Autoriser la suppression : par défaut, une clé ne supprime JAMAIS, même avec l'écriture activée. Lors de la génération de la clé, vous pouvez activer la suppression pour permettre DELETE /api/v1/{object}/{id} et l'outil MCP delete_record. Sans cette portée, la suppression renvoie 403 avec { "error": "errors.apiKeyDeleteDenied" }. La suppression est douce : les enregistrements vont dans la corbeille et peuvent être restaurés.
Une clé sans portée définie (par défaut) a un accès complet en lecture et écriture à tous les objets, comme avant. Les clés créées avant ce changement conservent l'accès complet jusqu'à ce que vous génériez une nouvelle clé avec portée.
OAuth et applications connectées
Lorsqu'un système TIERS doit s'intégrer au nom de l'utilisateur (sans que le client colle une clé admin), utilisez le flux OAuth 2.0 Authorization Code avec PKCE. L'utilisateur voit un écran de consentement avec les portées demandées, approuve, et l'application reçoit un jeton d'accès qui ne peut faire que ce qui a été consenti. Les applications sont validées : le développeur enregistre et publie l'application pour obtenir un client_id et un client_secret.
- Redirigez l'utilisateur vers GET /api/oauth/authorize avec client_id, redirect_uri (correspondance exacte avec la liste d'autorisation de l'application), scope, state et PKCE (code_challenge avec code_challenge_method=S256). PKCE est obligatoire.
- L'utilisateur connecté approuve sur l'écran de consentement et le CRM redirige avec code et le même state.
- Sur votre serveur, échangez le code à POST /api/oauth/token (grant_type=authorization_code, avec code_verifier, client_id, client_secret et redirect_uri) contre un jeton d'accès (Bearer, environ 1 heure) et un jeton de rafraîchissement.
- Appelez l'API v1 et le serveur MCP avec Authorization: Bearer at_..., limité au consentement. Renouvelez avec grant_type=refresh_token ; le rafraîchissement est en rotation (l'ancien meurt à l'utilisation) et la réutilisation révoque la famille. Révoquez à POST /api/oauth/revoke.
# 1) Consentement (l'utilisateur approuve → redirect_uri?code=...&state=...)
GET https://www.selliocrm.com/api/oauth/authorize?response_type=code&client_id=app_...&redirect_uri=https://your-app/callback&scope=records:read%20activities:read&state=abc&code_challenge=...&code_challenge_method=S256
# 2) Échanger le code contre des jetons (côté serveur)
curl -X POST https://www.selliocrm.com/api/oauth/token \
-d grant_type=authorization_code -d code=<authcode> -d code_verifier=<verifier> \
-d client_id=app_... -d client_secret=secret_... -d redirect_uri=https://your-app/callback
# → { "access_token": "at_...", "token_type": "Bearer", "expires_in": 3600,
# "refresh_token": "rt_...", "scope": "records:read activities:read" }Portées OAuth : records:read et records:write (tous les objets) ; records:read:contact et records:write:opportunity (par objet) ; activities:read et activities:write ; objects:read (découverte). Elles correspondent aux mêmes contrôles de lecture, écriture et par objet que les clés.
Widgets intégrés (iframe)
Votre application peut intégrer son propre écran (un widget) sur le détail d'un enregistrement ou sur le tableau de bord. Le widget s'exécute dans une iframe en bac à sable, servie depuis votre propre origine sur la liste d'autorisation des applications, et demande la portée widgets:embed. L'administrateur du tenant choisit où chaque widget apparaît dans Applications → Installées.
L'hôte envoie au widget uniquement le contexte d'interface via postMessage (sellio:widget:context, version 1) : recordId, objectApiName, locale, theme et installId. Aucune donnée métier, jeton ou secret ne circule dans ce message. Pour lire ou écrire des données, le widget utilise l'API OAuth avec son propre jeton (les portées accordées à l'installation). Le widget ne peut répondre que sellio:widget:ready (pour recevoir le contexte à nouveau) et sellio:widget:resize avec { height } (pour ajuster sa hauteur, plafonnée) ; tout autre message est ignoré.
Sécurité : l'iframe est en bac à sable et cross-origin, donc le widget ne peut pas accéder au DOM ni aux cookies de l'hôte. L'hôte valide l'origine exacte à chaque postMessage et l'embedUrl est toujours vérifiée par rapport à la liste d'autorisation des applications. Dans votre widget, n'acceptez les messages que lorsque event.origin est l'origine de l'hôte.
window.addEventListener('message', (event) => {
if (event.origin !== 'https://www.selliocrm.com') return; // hôte uniquement
const msg = event.data;
if (!msg || msg.version !== 1) return;
if (msg.type === 'sellio:widget:context') {
const { recordId, objectApiName, locale, theme } = msg.payload;
// données : utilisez l'API OAuth avec VOTRE jeton (ne transite jamais par postMessage)
}
});
parent.postMessage({ type: 'sellio:widget:ready', version: 1 }, 'https://www.selliocrm.com');Découverte des champs
Avant de créer ou de mettre à jour un enregistrement, découvrez les champs de l'objet : ce qui existe, ce qui est obligatoire, et quelles valeurs une liste de sélection accepte. Pas de devinette, et pas besoin d'inspecter un enregistrement existant.
En REST, vous obtenez l'objet et ses champs, avec required, options (pour select) et targetObject (pour lookup) :
GET https://www.selliocrm.com/api/v1/objects/contact
# → {
# "apiName": "contact",
# "label": "Contact",
# "fields": [
# { "apiName": "name", "label": "Name", "type": "text", "required": true },
# { "apiName": "email", "label": "Email", "type": "email", "required": false },
# { "apiName": "source", "label": "Source", "type": "select", "required": true,
# "options": [ { "value": "site", "label": "Website" },
# { "value": "referral", "label": "Referral" } ] },
# { "apiName": "company", "label": "Company", "type": "lookup",
# "required": false, "targetObject": "company" }
# ]
# }En MCP, l'outil describe_object renvoie les mêmes champs à l'agent :
{ "method": "tools/call",
"params": { "name": "describe_object", "arguments": { "object": "contact" } } }API REST v1
Enregistrements de n'importe quel objet, en envoyant et recevant du JSON. {object} est l'apiName (par exemple contact, lead, opportunity) et {id} est l'uuid de l'enregistrement.
- GET /api/v1/objects : lister les objets du tenant.
- GET /api/v1/objects/{object} : champs de l'objet (découverte).
- GET /api/v1/{object} : lister et rechercher des enregistrements.
- GET /api/v1/{object}/{id} : un enregistrement.
- POST /api/v1/{object} : créer un enregistrement.
- POST /api/v1/{object}/bulk : créer en masse (jusqu'à 500 ; succès partiel par élément).
- PATCH /api/v1/{object}/{id} : mettre à jour des champs (partiel).
- PATCH /api/v1/{object}/bulk : mettre à jour en masse ({ updates: [{ id, ...fields }] }).
- DELETE /api/v1/{object}/{id} : supprimer (doux, va dans la corbeille ; nécessite la portée de suppression sur la clé).
Paramètres de liste (GET) : limit (1 à 500, par défaut 50), offset (décalage de pagination, par défaut 0 ; le total sans pagination est dans le champ total), search (recherche par nom, insensible aux accents et à la casse), order (champ avec :asc ou :desc pour trier) et filter. Filtres avancés : répétez filter=field:operator:value pour combiner plusieurs conditions avec un ET logique (il n'y a pas de OU ; jusqu'à 12 par appel). Opérateurs : eq, neq, contains, gt, lt, gte, lte, empty, not_empty (empty et not_empty ne prennent pas de valeur). L'ancienne forme filter=field:value (sans opérateur) signifie toujours l'égalité exacte.
# Liste (limit, offset, search, filter, order)
curl -H "Authorization: Bearer sk_live_..." \
"https://www.selliocrm.com/api/v1/opportunity?limit=20&order=updated_at:desc&filter=stage:won"
# Filtres avancés (ET logique : amount >= 1000 ET stage = won)
curl -H "Authorization: Bearer sk_live_..." \
"https://www.selliocrm.com/api/v1/opportunity?filter=amount:gte:1000&filter=stage:eq:won"
# Un enregistrement
curl -H "Authorization: Bearer sk_live_..." \
https://www.selliocrm.com/api/v1/contact/8f3c...
# Créer
curl -X POST -H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"Ana Souza","email":"ana@acme.com","source":"site"}' \
https://www.selliocrm.com/api/v1/contact
# Création en masse (succès partiel par élément)
curl -X POST -H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"records":[{"name":"Ana"},{"name":"Bruno"}]}' \
https://www.selliocrm.com/api/v1/contact/bulk
# → { "results": [ { "index": 0, "ok": true, "id": "..." } ], "created": 1, "failed": 0 }
# Mise à jour (partielle)
curl -X PATCH -H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"source":"referral"}' \
https://www.selliocrm.com/api/v1/contact/8f3c...
# Suppression (douce, va dans la corbeille ; nécessite la portée de suppression sur la clé)
curl -X DELETE -H "Authorization: Bearer sk_live_..." \
https://www.selliocrm.com/api/v1/contact/8f3c...Format d'erreur
Les erreurs renvoient du JSON sous la forme { "error": "message" } avec le statut HTTP correspondant :
{ "error": "required field: source" } # HTTP 400- 200 et 201 : succès (201 à la création).
- 400 : validation ou règle métier.
- 401 : clé manquante ou invalide.
- 403 : pas d'autorisation (RBAC) pour l'objet, ou bloqué par la portée de la clé (lecture seule, objet hors portée, ou suppression non activée).
- 404 : objet ou enregistrement introuvable (inclut DELETE/PATCH d'un id inexistant).
- 429 : limite de débit dépassée (voir l'en-tête Retry-After).
Serveur MCP (agents IA)
Sellio expose un serveur MCP (Model Context Protocol) natif pour que votre agent IA puisse lire et écrire dans le CRM en toute sécurité. C'est la même clé API, la même limite de débit, les mêmes validations et le même RBAC. L'URL du serveur est https://www.selliocrm.com/api/mcp.
- list_objects : lister les objets du tenant.
- describe_object : les champs d'un objet (obligatoires, types, options).
- list_records : lister et rechercher des enregistrements.
- get_record : un enregistrement par id.
- create_record : créer un enregistrement.
- update_record : mettre à jour des champs.
- delete_record : supprimer (doux, va dans la corbeille) ; nécessite la portée de suppression sur la clé.
Les clients qui prennent en charge le MCP distant via HTTP utilisent l'URL avec l'en-tête Authorization: Bearer. Sur les clients sans HTTP distant natif, utilisez le pont mcp-remote :
{
"mcpServers": {
"sellio-crm": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://www.selliocrm.com/api/mcp",
"--header", "Authorization: Bearer sk_live_..."
]
}
}
}Limite de débit
Chaque clé a une limite par minute (par défaut 120, configurable). Les réponses incluent les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset. En cas de dépassement, l'API renvoie 429 avec Retry-After.
Modèle d'objets
Chaque tenant possède des objets standard (Contact, Company, Lead, Opportunity et autres) et des objets personnalisés no-code. Découvrez-les tous avec GET /api/v1/objects et les champs de chacun avec GET /api/v1/objects/{object} ou avec describe_object. Le schéma est toujours celui de votre tenant.