← Toutes les intégrations

🛠️

CRM custom — API Rosa v1.0

Documentation technique pour brancher Rosa à un CRM maison ou un SI propriétaire (Brokin, Modulr, Wizio, ou tout backend exposant des endpoints HTTP). À destination des développeurs et IT internes.

Vue d'ensemble

Vous exposez 2 endpoints HTTP côté CRM. Rosa les appelle :

  • POST votre URL outbound → Rosa pousse call.completed à la fin de chaque appel
  • GET votre URL lookup → Rosa interroge à l'arrivée d'un appel pour identifier le client

Les deux endpoints partagent une clé API (Bearer + HMAC). Vous renseignez les 3 champs (URL POST, URL GET, clé) dans Paramètres → CRM → Configuration manuelle.

Endpoint 1 — POST call.completed (outbound)

Appelé à la fin de chaque appel (~1-2 min après le raccrochage, le temps de l'analyse). Timeout côté Rosa : 5 s. Non bloquant — si vous ne répondez pas en 5 s, on log mais on continue.

Request

POST {votre_url_outbound}
Content-Type: application/json
User-Agent: RosaBot/1.0 (+https://www.rosa-ia.com)
X-Rosa-Contract-Version: 1.0
Authorization: Bearer {votre_cle_api}
X-Rosa-Signature: hmac_sha256(body, votre_cle_api)  [hex]

{
  "version": "1.0",
  "event": "call.completed",
  "rosa_call_id": "abc-123",
  "artisan_id": "uuid-...",
  "occurred_at": "2026-05-26T10:30:00.000Z",
  "call": {
    "duration_seconds": 142,
    "started_at": "2026-05-26T10:27:38.000Z",
    "ended_at": "2026-05-26T10:30:00.000Z",
    "outcome": "service_provided" | "appointment" | "info_only" | "...",
    "dashboard_url": "https://www.rosa-ia.com/dashboard/calls/abc-123"
  },
  "caller": {
    "phone": "+33612345678" | null,
    "name": "Jean Dupont" | null,
    "email": "jean@example.com" | null,
    "address": "12 rue des Lilas, 75011 Paris" | null
  },
  "intent": "devis_auto" | "sinistre" | "carte_tp" | "rdv" | "info" | "...",
  "urgency": "normal" | "urgent" | "emergency",
  "summary": "Résumé court rédigé par l'analyzer (~2-4 lignes)",
  "need_description": "Description longue du besoin si capturée" | null,
  "appointment": {
    "date": "2026-05-28T14:00:00Z" | null,
    "preference_text": "mardi après-midi" | null,
    "status": "confirmed" | "proposed" | null
  },
  "proposed_price": {
    "min": 45 | null,
    "max": 65 | null,
    "currency": "EUR"
  },
  "tags": {
    "is_existing_client": false,
    "has_appointment": true
  }
}

Response attendue

  • 2xx = OK. Le body peut être n'importe quoi, on ne le parse pas.
  • 4xx / 5xx = échec. Rosa log l'erreur dans calls.crm_push_error, visible dans le dashboard.

Idempotence : utilisez rosa_call_idcomme clé d'unicité côté CRM pour résister aux éventuels retries.

Endpoint 2 — GET lookup (inbound)

Appelé à l'arrivée de chaque appel, pour savoir si le numéro est connu. Timeout côté Rosa : 2 s. Si vous ne répondez pas en 2 s, Rosa décroche sans contexte CRM (dégradation silencieuse — l'appel n'est pas bloqué).

Request

GET {votre_url_lookup}?phone=%2B33612345678
User-Agent: RosaBot/1.0
X-Rosa-Contract-Version: 1.0
Authorization: Bearer {votre_cle_api}

Response — client connu (200)

HTTP/1.1 200 OK
Content-Type: application/json

{
  "client": {
    "name": "Jean Dupont",
    "email": "jean@example.com",
    "address": "12 rue des Lilas, 75011 Paris",
    "since": "2023-04-15",
    "tags": ["VIP", "fidèle"],
    "notes": "Préfère être contacté l'après-midi."
  },
  "contracts": [
    {
      "id": "C-12345",
      "product": "Auto Peugeot 308",
      "company": "AXA",
      "status": "actif",
      "policy_number": "AXA-789-456",
      "premium": "62 €/mois",
      "next_renewal": "2027-04-15",
      "notes": "Tous risques + assistance 0 km"
    },
    {
      "product": "MRH",
      "company": "Generali",
      "status": "actif"
    }
  ],
  "recent_interactions": [
    {
      "date": "2026-04-12",
      "type": "email",
      "summary": "A demandé une attestation tiers-payant — envoyée."
    }
  ]
}

Response — client inconnu (404)

HTTP/1.1 404 Not Found

Tous les champs sont optionnels. Renvoyez ce que vous avez. Rosa adapte intelligemment son discours selon les champs présents.

Sécurité — HMAC signature

Pour vérifier qu'un POST vient bien de Rosa (et pas d'un attaquant qui aurait découvert votre URL), validez la signature HMAC-SHA256 :

# Pseudo-code Node.js
const crypto = require('crypto');
const expected = crypto
  .createHmac('sha256', VOTRE_CLE_API)
  .update(rawBody, 'utf8')
  .digest('hex');

if (expected !== req.headers['x-rosa-signature']) {
  return res.status(401).end('Invalid signature');
}

Exemple cURL — tester votre endpoint

# Test POST outbound
curl -X POST https://votre-crm.fr/webhooks/rosa \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "X-Rosa-Contract-Version: 1.0" \
  -d '{
    "version": "1.0",
    "event": "call.completed",
    "rosa_call_id": "test-curl",
    "artisan_id": "test",
    "occurred_at": "2026-05-26T10:30:00Z",
    "call": { "duration_seconds": 60, "outcome": "info_only",
              "dashboard_url": "https://www.rosa-ia.com/...", ... },
    "caller": { "phone": "+33600000000", "name": "Test Rosa", ... },
    "intent": "info",
    "urgency": "normal",
    "summary": "Test cURL",
    "tags": { "is_existing_client": false, "has_appointment": false }
  }'

# Test GET lookup
curl -G https://votre-crm.fr/api/rosa/clients \
  -H "Authorization: Bearer YOUR_KEY" \
  --data-urlencode "phone=+33612345678"

Auto-test depuis le dashboard

Une fois vos URLs renseignées, cliquez sur 🧪 Tester le webhook et 🧪 Tester le lookup dans le dashboard. Rosa envoie un payload factice avec un flag _test: true que vous pouvez détecter côté CRM pour ne pas polluer vos données.

Versioning du contrat

La version actuelle est 1.0. Toute évolution incompatible se fera en bumping la version (header X-Rosa-Contract-Version) — et on annoncera 30 jours à l'avance. Les ajouts compatibles (nouveaux champs optionnels) se feront sur la même version.

Besoin d'un dev d'appoint ?

Si votre IT manque de bande passante, on peut câbler le pont avec votre CRM pour vous — contactez-nous.