Aller au contenu

Cinq façons de nous décrire votre API. Un seul modèle en sortie.

Serveur MCP, OpenAPI, GraphQL, connecteur prêt à l'emploi ou saisie manuelle : tout aboutit au même catalogue, et rien n'est exposé sans coche.

Exemple
# Signaler un évènement : Nodium vérifie et range, sans rien envoyercurl https://nodium.io/api/v1/templates/outbound \ -H "Authorization: Bearer nod_••••••••" \ -H "Content-Type: application/json" \ -d '{ "externalId": "order-2481-shipped", "eventType": "order.shipped", "phone": "+33 6 00 00 00 00", "templateName": "order_shipped", "payload": { "reference": "2481" } }'
200 · scheduled
{ "event": { "externalId": "order-2481-shipped", "eventType": "order.shipped", "status": "scheduled", "skipReason": null, "estimatedCostUsd": null }, "duplicate": false, "caller": "machine", "skipReasons": []}

Le parcours d'intégration

Six gestes, de la clé au premier évènement. Aucun ne rend visible ce que personne n'a coché.

  1. Créer une clé d'API

    Dans la console : Le compte › Avancé › Clés d'API. La clé n'est montrée qu'une fois, agit au nom de son créateur et porte un rôle plafonné par le sien.

    Authorization: Bearer nod_…
  2. Brancher votre logiciel

    Choisissez l'une des cinq sources et déposez son authentification : elle est chiffrée et ne ressort jamais d'une lecture.

  3. Tester la connexion

    Un échec revient avec un diagnostic lisible, pas une erreur. Une adresse qui mène à un réseau privé est refusée.

  4. Décrire le catalogue

    Automatique pour un serveur MCP et une description OpenAPI, à la main pour les autres : objets, champs, opérations.

    POST /api/v1/connectors/:id/discover
  5. Cocher ce qui est permis

    La découverte écrit tout à « non ». Votre client confirme ; une écriture naît éteinte et exige l'accord d'un humain.

  6. Signaler vos évènements

    Votre logiciel annonce un fait ; Nodium vérifie le contact, son accord, le modèle et le canal, estime le coût et range. Vos webhooks vous tiennent au courant.

    POST /api/v1/templates/outbound

Les cinq sources

Ce que chacune demande, et ce qu'elle sait faire seule.

  • Connecteur prêt à l'emploi

    Le domaine de votre boutique Shopify et un jeton.

    Déjà cartographiéLe plus rapide
  • Serveur MCP

    L'adresse de votre point de terminaison MCP.

    Découverte automatiqueLe plus fidèle
  • Description OpenAPI

    L'adresse du fichier OpenAPI lui-même, pas celle de la page de documentation.

    Découverte automatiqueLa longue traîne
  • Schéma GraphQL

    L'adresse du point de terminaison, celle qui reçoit les requêtes.

    Catalogue à la mainObligatoire pour Shopify
  • Saisie manuelle

    Rien à publier : vos objets se décrivent une ligne par champ.

    Catalogue à la mainSans API

Pourquoi nous commençons par MCP

  1. Parce que les descriptions d'outils portent le sens et pas seulement la forme. C'est la faiblesse d'une description OpenAPI : elle dit comment appeler, sans dire ce que l'appel veut dire.
  2. Parce que le schéma d'entrée d'un outil MCP est déjà du JSON Schema, donc exactement notre format. Il est recopié tel quel : aucune conversion, donc aucune perte.
  3. Parce que la liste des outils est une découverte vivante. Vous ajoutez un outil, une nouvelle découverte l'ajoute — sans jamais décocher ce que votre client avait confirmé, ni renommer ce qu'il avait renommé.
Les annotations de risque ne décident rien.Un outil qui s'annonce sans risque mais dont le nom dit « annuler » ou « supprimer » reste traité comme une écriture. Un verbe que nous ne connaissons pas est traité comme une écriture. Une annotation pré-trie la liste ; elle n'allume jamais rien toute seule.

La découverte propose, votre client confirme. Tout ce qui est trouvé est écrit à « non » : aucun champ n'est visible, aucune opération n'est appelable tant qu'on ne l'a pas cochée. L'écran arrive pré-coché sur une poignée de champs, écriture éteinte, et l'on peut passer à la suite sans rien toucher.

  • Le champ qui sert de référence, et ceux qui identifient un client final.
  • Les champs sensibles, jamais proposés exposés, et masqués dans les journaux.
  • Les opérations autorisées, et celles qui exigent l'accord d'un humain.
  • Une lecture devenue écriture à la découverte suivante est éteinte d'office : personne n'avait accepté celle-là.

Trois familles d'appel

À l'exécution, tout se ramène à ces trois-là.

  1. search

    Chercher

    Retrouver l'objet dont parle la conversation, à partir d'un numéro, d'une adresse électronique ou d'une référence.

  2. read

    Relire

    Lire à nouveau un objet déjà rattaché, pour répondre sur son état actuel et non sur un souvenir.

  3. execute

    Exécuter

    Agir chez vous. Allumé opération par opération, avec une clé anti-doublon obligatoire : un appel rejoué n'encaisse jamais deux fois.

    Éteint par défaut

Appeler Nodium depuis votre logiciel

Votre système n'a pas de session : il s'annonce avec une clé d'API et signale un évènement — une commande expédiée, une échéance qui approche. Nodium vérifie le contact, son consentement, l'existence d'un modèle approuvé, le canal, puis estime le coût. Cet appel n'envoie rien : il décide.

  • Deux fois le même évènement ne part qu'une fois : l'appel est idempotent sur l'identifiant que vous fournissez, et rejoue la décision d'origine.
  • Une clé présentée et mauvaise est refusée sur-le-champ. Jamais de repli discret sur une session : une clé expirée doit se voir tout de suite.
  • Un refus dit tout ce qui manquait, pas seulement la première raison.
  • Le coût est estimé avant l'envoi. Un tarif inconnu se dit « inconnu », jamais « gratuit ».
Exemple
# HTTP 200 : l'évènement est rangé, rien n'est envoyé{ "event": { "externalId": "order-2482-shipped", "status": "skipped", "skipReason": "no_consent" }, "duplicate": false, "caller": "machine", "skipReasons": ["no_consent", "template_not_approved"]}

Être prévenu : les webhooks

Un abonnement, créé dans la console ou par l'API, reçoit en POST les évènements qu'il a choisis. Chaque livraison est signée ; répondez par un code 2xx.

Les évènements

  • message.received
  • message.sent
  • approval.requested
  • approval.decided
  • mission.closed
  • dossier.changed
  • timer.fired

Sans réponse 2xx, la livraison est reprise : six essais au plus, après 1 min, 5 min, 30 min, 2 h puis 12 h.

Le secret de signature n'est rendu qu'une fois, à la création de l'abonnement. La signature porte l'heure d'envoi et un HMAC-SHA256 de l'heure et du corps.

Exemple
import { createHmac, timingSafeEqual } from 'node:crypto'// Refuser toute livraison dont la signature ne correspond pasexport function isFromNodium(header, rawBody, secret) { const sig = Object.fromEntries(header.split(',').map(p => p.split('='))) const expected = createHmac('sha256', secret) .update(`${sig.t}.${rawBody}`) .digest('hex') return sig.v1?.length === expected.length && timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected))}

Référence rapide

Ce qui vaut pour chaque appel, dans les deux sens.

Appeler l'API de Nodium

Adresse
https://nodium.io/api/v1/…Une route qui change de forme passera sous v2 sans casser v1.
Authentification
Authorization: Bearer nod_…Une clé agit au nom de son créateur, avec un rôle plafonné par le sien ; tout est journalisé en son nom.
Cloisonnement
La clé désigne son espace. Une ressource d'un autre espace répond 404, jamais 403.
Débit
600 appels par minute et par clé ; au-delà, 429 avec le délai à attendre.
Idempotence
Un évènement se rejoue sur son externalId, un envoi de message sur son idempotencyKey : la même clé rend le même résultat.
Erreurs
Du JSON avec statusCode et statusMessage : un message en français affichable tel quel, et un code quand un programme doit réagir autrement.
Pagination
Par curseur, jamais par numéro de page : une file bouge sous les doigts.

Quand Nodium appelle votre API

Cinq façons de s'authentifier, celles que les API emploient réellement : aucune authentification, un jeton présenté en « Authorization: Bearer », une clé dans un en-tête que vous nommez, un couple identifiant et mot de passe, ou un jeton OAuth 2 collé à la main.

OAuth 2 n'est pas encore une autorisation déléguée.Un jeton OAuth 2 est présenté comme un jeton ordinaire et n'est pas renouvelé : quand il expire, il faut le remplacer. Il n'existe pas de bouton « Autoriser Nodium », et nous préférons l'écrire ici que le laisser découvrir en production.

Ce que nous faisons de vos secrets

  • Le secret d'authentification est chiffré et ne ressort jamais. Une lecture dit seulement s'il y en a un.
  • Une clé posée dans un champ qui n'est pas prévu pour elle est refusée, avec l'indication de l'endroit où la mettre.
  • Rien ne franchit la cloison d'un espace. Un identifiant qui appartient à quelqu'un d'autre répond « introuvable », jamais « interdit ».
  • Une adresse qui pointe vers un réseau privé est refusée au moment du test de connexion.
  • Les champs marqués sensibles sont masqués dans les journaux d'appel.

Ce que nous ne savons pas encore faire

La liste est courte et tenue à jour. Une limite écrite coûte moins cher qu'une limite découverte.

  • La découverte automatique n'existe que pour les serveurs MCP et les descriptions OpenAPI. Un schéma GraphQL se teste, mais son catalogue se décrit à la main.
  • Le transport MCP ancien, à deux adresses, n'est pas géré.
  • Aucun renouvellement de jeton OAuth 2.
  • Chaque appel MCP rouvre une poignée de main : un peu plus lent, mais rien à réparer quand votre serveur redémarre.
  • Une donnée sensible logée dans un champ que personne n'a marqué comme tel est journalisée en clair. La découverte propose le marquage, votre client le complète.

Branchez votre API

Enregistrer une source, la tester, puis découvrir son catalogue — trois gestes, depuis un écran.