Documentation API

Référence complète de l'API REST Commissia v1

Introduction

L'API REST Commissia permet d'accéder en lecture seule aux données de votre organisation : commerciaux, affaires, plans de commissionnement, périodes de calcul, résultats et synthèses.

L'API est disponible pour les plans Growth et Scale uniquement. Générez vos clés API depuis Paramètres > API & Webhooks.
ParamètreTypeDescription
Base URLhttps://app.commissia.com/api/v1
Versionv1 (incluse dans l'URL)
FormatJSON (application/json)
MéthodesGET uniquement (lecture seule)

Authentification

Chaque requête doit inclure un header Authorization avec votre clé API au format Bearer token.

Les clés ont le préfixe cc_live_ et sont affichées une seule fois à la création. Elles sont stockées sous forme de hash SHA-256.

Exemple curl
curl -H "Authorization: Bearer cc_live_your_api_key_here" \
  https://app.commissia.com/api/v1/reps

Erreurs d'authentification :

CodeDescription
401Header manquant, format invalide ou clé révoquée
403Plan insuffisant (Growth+ requis)

Pagination

Tous les endpoints de liste supportent la pagination via les paramètres limit et offset.

ParamètreTypeDescription
limitintegerNombre de résultats (1-100, défaut: 50)
offsetintegerDécalage depuis le début (défaut: 0)
Réponse paginée
{
  "data": [ ... ],
  "pagination": {
    "total": 42,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Pour les endpoints de détail (/reps/:id, etc.), la réponse ne contient pas d'objet pagination :

Réponse unitaire
{
  "data": { ... }
}

Erreurs

Les erreurs suivent un format uniforme :

Format d'erreur
{
  "error": {
    "message": "Description du probleme",
    "status": 401
  }
}
Code HTTPSignification
200Succès
401Non authentifié (clé manquante, invalide ou révoquée)
403Interdit (plan insuffisant)
404Ressource non trouvée
429Rate limit dépassé
500Erreur serveur interne

Rate Limiting

Chaque clé API est limitée à 60 requêtes par minute (fenêtre glissante de 60 secondes). Au-delà, l'API retourne un code 429.

Réponse 429
{
  "error": {
    "message": "Rate limit exceeded",
    "status": 429
  }
}

Attendez la fin de la fenêtre (60 secondes max) avant de retenter vos requêtes.

Commerciaux

GET/api/v1/repsLister les commerciaux
GET/api/v1/reps/:idDétail d'un commercial

Paramètres de liste :

ParamètreTypeDescription
searchstringRecherche par nom, prénom ou email
include_inactivebooleanInclure les commerciaux supprimés (défaut: false)
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)
curl - Lister les commerciaux
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/reps?search=dupont"
Réponse
{
  "data": [
    {
      "id": "uuid",
      "first_name": "Jean",
      "last_name": "Dupont",
      "email": "jean.dupont@example.com",
      "external_id": null,
      "start_date": "2025-01-01",
      "end_date": null,
      "is_active": true,
      "created_at": "2025-01-15T10:00:00Z",
      "updated_at": "2025-01-15T10:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Affaires

GET/api/v1/dealsLister les affaires
GET/api/v1/deals/:idDétail d'une affaire

Paramètres de liste :

ParamètreTypeDescription
searchstringRecherche par nom de l'affaire
rep_iduuidFiltrer par commercial
deal_typestringFiltrer par type d'affaire
close_date_fromdateDate de clôture min (YYYY-MM-DD)
close_date_todateDate de clôture max (YYYY-MM-DD)
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)
curl - Affaires d'un commercial sur une période
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/deals?rep_id=uuid&close_date_from=2025-01-01&close_date_to=2025-03-31"
Réponse
{
  "data": [
    {
      "id": "uuid",
      "deal_name": "Acme Corp - Licence annuelle",
      "deal_type": "Nouveau",
      "amount": "15000.00",
      "currency": "EUR",
      "close_date": "2025-02-15",
      "stage": "Gagné",
      "external_id": null,
      "product_category": "SaaS",
      "rep_id": "uuid",
      "crm_source": null,
      "created_at": "2025-02-10T14:30:00Z",
      "updated_at": "2025-02-10T14:30:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Plans de commissionnement

GET/api/v1/plansLister les plans
GET/api/v1/plans/:idDétail d'un plan (avec règles)

Paramètres de liste :

ParamètreTypeDescription
include_inactivebooleanInclure les plans supprimés (défaut: false)
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)
curl - Détail d'un plan
curl -H "Authorization: Bearer cc_live_xxx" \
  https://app.commissia.com/api/v1/plans/uuid
Réponse (détail avec règles)
{
  "data": {
    "id": "uuid",
    "name": "Plan Commercial Q1 2025",
    "description": "Plan standard equipe vente",
    "effective_from": "2025-01-01",
    "effective_to": "2025-03-31",
    "is_active": true,
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z",
    "rules": [
      {
        "id": "uuid",
        "name": "Commission 10%",
        "rule_type": "percentage",
        "priority": 1,
        "conditions": {
          "deal_type": "Nouveau",
          "min_amount": "1000",
          "max_amount": null
        },
        "calculation": {
          "rate": "0.10"
        },
        "is_active": true,
        "created_at": "2025-01-01T00:00:00Z",
        "updated_at": "2025-01-01T00:00:00Z"
      }
    ]
  }
}

Périodes de calcul

GET/api/v1/periodsLister les périodes
GET/api/v1/periods/:idDétail d'une période

Paramètres de liste :

ParamètreTypeDescription
statusstringFiltrer par statut : draft, calculating, review, approved, paid
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)
curl - Périodes approuvées
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/periods?status=approved"
Réponse
{
  "data": [
    {
      "id": "uuid",
      "name": "Janvier 2025",
      "period_start": "2025-01-01",
      "period_end": "2025-01-31",
      "status": "approved",
      "calculated_at": "2025-02-01T09:00:00Z",
      "approved_at": "2025-02-03T14:00:00Z",
      "paid_at": null,
      "payment_notes": null,
      "created_at": "2025-01-31T10:00:00Z",
      "updated_at": "2025-02-03T14:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Résultats de commissions

GET/api/v1/periods/:id/resultsRésultats détaillés d'une période

Chaque résultat représente la commission calculée pour une affaire selon une règle spécifique. Une affaire peut générer plusieurs résultats si plusieurs règles de même priorité s'appliquent. Seul le groupe de priorité la plus haute (chiffre le plus bas) est utilisé.

Paramètres :

ParamètreTypeDescription
rep_iduuidFiltrer par commercial
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)
curl
curl -H "Authorization: Bearer cc_live_xxx" \
  "https://app.commissia.com/api/v1/periods/uuid/results?rep_id=uuid"
Réponse
{
  "data": [
    {
      "id": "uuid",
      "period_id": "uuid",
      "rep_id": "uuid",
      "deal_id": "uuid",
      "rule_id": "uuid",
      "base_amount": "15000.00",
      "commission_amount": "1500.00",
      "calculation_details": {
        "rule_type": "percentage",
        "rate": "0.10",
        "cap_applied": true,
        "uncapped_amount": "2000.00"
      },
      "adjustment_total": "200.00",
      "created_at": "2025-02-01T09:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Les champs cap_applied et uncapped_amount dans calculation_details sont présents lorsqu'un plafond par règle a été appliqué. Le champ adjustment_total est présent lorsque des ajustements manuels existent pour ce résultat spécifique.

Synthèses

GET/api/v1/periods/:id/summariesSynthèses d'une période
GET/api/v1/summariesToutes les synthèses (cross-périodes)

Les synthèses agrègent les commissions par commercial et par période : nombre d'affaires, revenu total et commission totale.

Paramètres /periods/:id/summaries :

ParamètreTypeDescription
rep_iduuidFiltrer par commercial
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)

Paramètres /summaries :

ParamètreTypeDescription
period_iduuidFiltrer par période
rep_iduuidFiltrer par commercial
limitintegerPagination (1-100, défaut: 50)
offsetintegerDécalage (défaut: 0)
curl - Synthèses d'une période
curl -H "Authorization: Bearer cc_live_xxx" \
  https://app.commissia.com/api/v1/periods/uuid/summaries
Réponse
{
  "data": [
    {
      "id": "uuid",
      "period_id": "uuid",
      "rep_id": "uuid",
      "total_deals": 12,
      "total_revenue": "180000.00",
      "total_commission": "18000.00",
      "quota_target": "200000.00",
      "quota_attainment": "0.9000",
      "cap_amount": "20000.00",
      "uncapped_commission": "22000.00",
      "adjustment_total": "500.00",
      "created_at": "2025-02-01T09:00:00Z",
      "updated_at": "2025-02-01T09:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "has_more": false
  }
}

Les champs quota_target et quota_attainment sont présents uniquement lorsqu'un objectif (quota) est défini sur le plan ou par override pour le commercial. L'atteinte est exprimée en ratio (1.0 = 100%).

Les champs cap_amount et uncapped_commission sont présents uniquement lorsqu'un plafond est configuré. total_commission reflète le montant après application du plafond.

Le champ adjustment_total est présent lorsque des ajustements manuels existent pour ce commercial sur cette période. Montant positif = bonus, négatif = déduction. Le total final = total_commission + adjustment_total.

Webhooks

Les webhooks sortants notifient votre serveur en temps réel lorsqu'un événement se produit dans Commissia. Configurez vos endpoints depuis Paramètres > API & Webhooks > Webhooks.

Événements disponibles :

ÉvénementDescription
period.calculatedPériode calculée
period.approvedPériode approuvée
period.paidPériode payée
deal.createdAffaire créée
deal.importedAffaires importées (CSV ou CRM)
rep.createdCommercial créé
rep.updatedCommercial modifié
rep.deletedCommercial supprimé
plan.createdPlan créé
plan.updatedPlan modifié
plan.deletedPlan supprimé
pingTest de connectivité

Format du payload :

Corps de la requete POST
{
  "event": "period.approved",
  "data": {
    "id": "uuid",
    "name": "Janvier 2025",
    "status": "approved"
  },
  "timestamp": "2025-02-03T14:00:00.000Z"
}

Headers envoyés :

HeaderDescription
Content-Typeapplication/json
X-Webhook-SignatureSignature HMAC-SHA256 du corps
X-Webhook-EventNom de l'événement
X-Webhook-Delivery-IdIdentifiant unique de la livraison

Vérification de la signature :

Le header X-Webhook-Signature contient un HMAC-SHA256 du corps brut de la requête, signé avec votre secret webhook. Vérifiez-le pour authentifier les requêtes.

Vérification en Node.js
import { createHmac, timingSafeEqual } from "crypto";

function verifySignature(body: string, signature: string, secret: string): boolean {
  const expected = createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Dans votre handler :
const rawBody = await request.text();
const signature = request.headers.get("X-Webhook-Signature");

if (!verifySignature(rawBody, signature, WEBHOOK_SECRET)) {
  return new Response("Invalid signature", { status: 401 });
}

const payload = JSON.parse(rawBody);

Politique de retry :

Si votre endpoint répond avec un code non-2xx ou ne répond pas dans les 10 secondes, Commissia réessaie automatiquement :

TentativeDélai
2e tentative30 secondes
3e tentative2 minutes

Après 3 tentatives échouées, la livraison est marquée comme failed. Consultez l'historique des livraisons dans l'onglet Livraisons de la page API & Webhooks.