Intégration & API

Intégration & API

Documentation API

Numéros, appels, click-to-call, webphone WebRTC, enregistrement et événements temps réel — le guide développeur pour intégrer la voix Kavkom dans votre application.

Introduction

L’API Kavkom permet d’ajouter des fonctionnalités téléphoniques à votre produit : commander des numéros et des lignes, lancer et superviser des appels, intégrer un téléphone directement dans le navigateur et recevoir les événements d’appel en temps réel.

Les briques de l’API

BriqueBaseRôle
API Billingclient.kavkom.comCommander des extensions, aussi appelées lignes, et des numéros DID.
API PBXapi.kavkom.comLister les extensions, lancer des appels, raccrocher des appels.
WebSocketlive.kavkom.comRecevoir l’état des appels entrants et sortants en temps réel.
WebhooksVotre endpoint HTTPSRecevoir les appels en direct et les CDR sur une URL de votre système.

URLs de base & conventions

Toutes les requêtes et réponses sont en JSON. Envoyez systématiquement les en-têtes Content-Type: application/json et Accept: application/json.

APIURL de baseEnveloppe de réponse
Billinghttps://client.kavkom.com{ "status": "success", "return": { … } }
PBXhttps://api.kavkom.com{ "data": { … }, "success": true, "message": "…" }
WebSocketwss://live.kavkom.comMessages JSON { "event": "…", "data": { … } }

Authentification

Jeton API X-API-TOKEN & domain_uuid

Les API Billing et PBX utilisent un jeton API placé dans l’en-tête X-API-TOKEN, ainsi qu’un domain_uuid qui identifie le domaine client.

X-API-TOKEN: <votre-jeton-api>
  • Le jeton est rattaché à un ou plusieurs domaines et à une liste de routes autorisées.
  • domain_uuid est un UUID v4. Il est transmis en query string pour un GET et dans le corps JSON pour un POST.
  • Un jeton non autorisé pour la route demandée, ou non lié au domain_uuid, est rejeté.

Créer une clé API

Voici comment créer une clé API :

  1. Connectez-vous sur l’interface applicative Kavkom avec un compte administrateur, puis accédez aux réglages avancés en cliquant sur la roue dentée en bas à gauche (1).
  2. Cliquez sur l’onglet Paramètres API (2), puis sur le bouton Ajouter un Token (3).
  3. Renseignez le nom du Token (1), activez l’autorisation d’accès au domaine et conservez le domain_uuid (2).
  4. Sélectionnez les objets à autoriser dans la liste à droite (3), puis sauvegardez en cliquant sur Créer (4).
  5. Une fois revenu sur la liste des Tokens API, copiez et conservez la clé en cliquant sur le bouton Copier dans la colonne Actions.

Jetons d’accès pour le WebSocket

La connexion WebSocket /calls utilise un access token de courte durée, obtenu via un refresh token côté serveur.

  1. Obtenez un refresh token avec un jeton Bearer protégé côté serveur.
  2. Échangez-le contre un access token avec le scope calls et les extensions autorisées.
POST https://live.kavkom.com/api/auth/acquire-access
Authorization: Bearer <refresh-token>
Content-Type: application/json

{
  "userUuid": "<user-uuid>",
  "extensions": [1001],
  "scope": "calls",
  "application": "mon-app"
}

Réponse :

{ "token": "<access-token>", "expiresAt": "<date-ISO>" }
EndpointRôle
POST /api/auth/acquire-accessObtenir un access token à partir du refresh token.
POST /api/auth/verify-accessVérifier et éventuellement prolonger un access token.
POST /api/auth/revoke-accessRévoquer un access token.
POST /api/auth/revoke-refreshRévoquer le refresh token.
Sécurité. Ne jamais exposer le jeton API côté navigateur. Le jeton reste sur votre backend. Le front-end demande à votre serveur les données nécessaires, et votre serveur appelle l’API Kavkom.

Commander des ressources – API Billing

Les extensions et les numéros se commandent via le système de facturation, qui crée la commande, gère la facturation puis provisionne automatiquement la ressource sur le PBX. On ne crée pas d’extension directement sur le PBX.

Commander une ligne / extension

POST https://client.kavkom.com/api.php avec route=order et type=line

ChampRequisDescription
routeouiDoit valoir order.
typeouiDoit valoir line.
domain_uuidouiUUID v4 du domaine client.
optionsouiCarte nom d'option → quantité, par exemple { "starter": 2 }.
curl -X POST "https://client.kavkom.com/api.php" \
  -H "X-API-TOKEN: <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "route": "order",
    "type": "line",
    "domain_uuid": "ddcfeb62-110f-4bd7-b7a9-965e1a78295f",
    "options": { "starter": 2 }
  }'

Réponse de succès :

{ "invoiceid": 10231, "order_number": "0123456789" }

Commander un numéro DID

La commande est enregistrée puis, lorsque l’identité du client est validée, un numéro est attribué depuis le stock et provisionné sur le PBX avec un routage vers l’extension choisie.

POST https://client.kavkom.com/api.php avec route=order et type=did

ChampRequisDescription
routeouiDoit valoir order.
typeouiDoit valoir did.
domain_uuidouiUUID v4 du domaine client.
countryouiPays disponible dans le catalogue DID.
locationouiVille ou localité disponible.
extensionouiExtension vers laquelle router les appels entrants.
descriptionnonLibellé libre stocké avec la commande.
identiynonIdentifiant d’enregistrement d’identité. L’orthographe du paramètre est bien identiy.
curl -X POST "https://client.kavkom.com/api.php" \
  -H "X-API-TOKEN: <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "route": "order",
    "type": "did",
    "domain_uuid": "ddcfeb62-110f-4bd7-b7a9-965e1a78295f",
    "country": "FR",
    "location": "Paris",
    "extension": "901",
    "description": "Ligne commerciale"
  }'
{
  "status": "success",
  "return": { "id": 152, "accepted": true }
}
Identité KYC. Si le pays ou la localité n’est pas disponible, ou si l’identité n’est pas validée, la réponse est { "status": "error", "message": "…" }. Le provisioning instantané n’est donc pas garanti dans tous les cas.

Lister les commandes de numéros

GET https://client.kavkom.com/api.php avec route=order et type=didlist

Paramètre requis : domain_uuid. Paramètres optionnels : orderby avec order_date ou accept_date, et asc.

Gérer les appels – API PBX

Lister les extensions

Retourne les extensions configurées d’un domaine, avec pagination. Une variante allégée existe : GET /api/pbx/v1/extension/list_limited.

GET https://api.kavkom.com/api/pbx/v1/extension/list

ParamètreRequisDescription
domain_uuidouiUUID v4 du domaine.
limitnonEnregistrements par page, de 1 à 5000. Défaut : 15.
pagenonNuméro de page.
filter[search_query]nonTexte de filtre, par exemple un numéro d’extension.
sort[0]nonColonne : extension, effective_caller_id_number, outbound_caller_id_name, description.
sort[1]nonSens : ASC ou DESC.
with_usernon1 pour inclure l’utilisateur lié, 0 pour l’omettre.
curl -X GET "https://api.kavkom.com/api/pbx/v1/extension/list?domain_uuid=ddcfeb62-110f-4bd7-b7a9-965e1a78295f" \
  -H "X-API-TOKEN: <token>" \
  -H "Accept: application/json"
{
  "data": [
    {
      "extension_uuid": "48b0d200-2b31-4211-a3d7-b41f87abbcbb",
      "domain_uuid": "ddcfeb62-110f-4bd7-b7a9-965e1a78295f",
      "extension": "901",
      "password": "aB3xY9zK",
      "user_context": "client.kavkom.com",
      "enabled": "true"
    }
  ],
  "success": true,
  "message": "Action completed successfully"
}

Lancer un appel, ou click-to-call

Origine un appel : le PBX appelle d’abord l’extension source, puis la met en relation avec la destination. L’appel est enregistré automatiquement et son call_uuid est renvoyé.

POST https://api.kavkom.com/api/pbx/v1/active_call/call

ParamètreRequisDescription
domain_uuidouiUUID v4 du domaine.
srcouiExtension source. Doit exister sur le domaine.
destinationouiNuméro à appeler : extension interne, numéro externe ou URI SIP.
auto_answernon"true" pour décrocher automatiquement la source.
ignore_earlynonRaccrocher après la mise en relation et ignorer l’early media.
src_cid_numbernonCaller ID affiché sur la jambe source.
curl -X POST "https://api.kavkom.com/api/pbx/v1/active_call/call" \
  -H "X-API-TOKEN: <token>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "domain_uuid": "ddcfeb62-110f-4bd7-b7a9-965e1a78295f",
    "src": "901",
    "destination": "33612345678",
    "auto_answer": "true"
  }'
{
  "success": true,
  "message": "Action completed successfully",
  "call_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "recording": "+OK"
}
Idéal pour un bouton Appeler : l’extension de l’agent, src, sonne d’abord, puis est mise en relation avec le client.

Raccrocher un appel

POST https://api.kavkom.com/api/pbx/v1/active_call/kill

Corps attendu : domain_uuid et call_uuid, le call_uuid étant renvoyé par l’origination.

Enregistrer une extension en SIP

Une fois l’extension commandée et provisionnée, tout appareil SIP ou softphone peut s’enregistrer sur le PBX. L’enregistrement, ou REGISTER, indique au switch où joindre l’utilisateur. Il est requis avant d’émettre ou de recevoir un appel.

Identifiants

Réglage SIPValeurChamp source
Username / Auth userLe numéro d’extension, ex. 901extension
Password / SecretLe secret SIPpassword
Domain / Realm / serveur SIPLe nom de domaine, ex. client.kavkom.comuser_context
TransportUDP, TCP ou TLS. Préférez TLS.Réglage appareil
Port5060 UDP/TCP ou 5061 TLSRéglage appareil
Le realm SIP doit correspondre au user_context de l’extension. C’est ainsi que le PBX détermine le domaine de l’appareil.

Déroulé de l’enregistrement

  1. L’appareil envoie un REGISTER au registrar avec username@domain.
  2. Le PBX répond 401 Unauthorized avec un challenge digest.
  3. L’appareil renvoie REGISTER avec le digest calculé.
  4. En cas de succès, le switch renvoie 200 OK et stocke le contact.
SIP Username : 901
Password     : aB3xY9zK
SIP Domain   : client.kavkom.com
Registrar    : client.kavkom.com
Transport    : TLS
Port         : 5061
Expiry       : 3600
Dépannage. Un 403 Forbidden sur le REGISTER signifie généralement un mauvais mot de passe ou un realm différent de user_context. Derrière un NAT, activez un keep-alive pour rester joignable.

Construire une application webphone WebRTC avec SIP.js

Cette section montre comment intégrer un téléphone directement dans le navigateur à partir des identifiants d’une extension. La référence d’implémentation utilise SIP.js et son assistant SimpleUser.

Prérequis

ÉlémentDétail
Jeton APIAutorisé sur votre domaine et sur l’endpoint de liste des extensions.
domain_uuidUUID v4 du domaine client.
Extension provisionnéeUne extension doit déjà exister.
Navigateur moderneAccès micro requis ; la page doit être servie en HTTPS.

Étape 1 – Récupérer les identifiants SIP côté serveur

Appelez l’endpoint de liste des extensions pour lire les trois valeurs nécessaires à l’enregistrement : extension, password et user_context, qui correspond au domaine ou realm. Vérifiez que l’extension est enabled: "true".

Étape 2 & 3 – Enregistrer et appeler depuis le navigateur

import { Web } from "sip.js";

// 1) Récupérer les identifiants depuis VOTRE backend.
// Ne jamais appeler l'API Kavkom avec le jeton directement depuis le navigateur.
const { extension, password, user_context: domain } = await fetch(
  "/api/mon-backend/sip-credentials"
).then((r) => r.json());

// 2) Construire le client SIP à partir de ces valeurs.
const sipTarget = (number) => `sip:${number}@${domain}`;
const simpleUser = new Web.SimpleUser(`wss://${domain}/`, {
  aor: sipTarget(extension),
  media: { remote: { audio: document.querySelector("#remoteAudio") } },
  userAgentOptions: {
    authorizationUsername: extension,
    authorizationPassword: password,
  },
  delegate: {
    onServerConnect: () => simpleUser.register(),
    onCallReceived: () => simpleUser.answer(),
  },
});

// 3) Connexion + enregistrement, puis appels.
await simpleUser.connect(); // déclenche onServerConnect -> register()
// await simpleUser.call(sipTarget("33612345678"));
// await simpleUser.hangup();

Pendant un appel, le client peut gérer la mise en attente, le micro, le transfert et le clavier DTMF.

Variante – Originer depuis le serveur

Plutôt que de laisser le client composer, vous pouvez démarrer l’appel depuis votre backend avec l’endpoint d’origination. C’est utile pour un bouton click-to-call où l’extension de l’utilisateur doit sonner en premier.

La connexion échoue immédiatement

Le domaine est faux : il doit être égal à user_context et joignable en wss://<domain>/. La page doit être en HTTPS.

L’extension s’enregistre puis se déconnecte

Vérifiez le mot de passe et assurez-vous que le realm correspond à user_context.

Il n’y a pas de son

La permission micro a probablement été refusée, ou aucun élément <audio> n’est lié au média distant.

Impossible d’appeler

Vérifiez que l’extension est enabled: "true" et que le format de destination est correct.

Événements d’appel en temps réel – WebSocket

Le WebSocket /calls pousse l’état des appels en temps réel pour les extensions demandées.

Connexion

WSS wss://live.kavkom.com/calls?t=<access-token>&ext=1001

ParamètreDescription
tAccess token obtenu via acquire-access avec le scope calls.
extListe d’extensions séparées par des virgules, par exemple 1001 ou 1001,1002.
  • t manquant : le serveur répond 406, « &t parameter is missing ».
  • ext manquant : 406, « &ext parameter is missing ».
  • Token invalide ou expiré : connexion rejetée avec 401 ou Invalid token.

Messages reçus

ÉvénementDescription
callMise à jour de l’état d’un appel : ringing, active, held, finished.
pingBattement de cœur ; le client doit répondre par pong.
errorMessage d’erreur dans data.message.

Charge utile d’un événement call

{
  "event": "call",
  "data": {
    "callUuid": "abc-123",
    "state": "active",
    "direction": "inbound",
    "number": "380501234567",
    "presenceId": "1001@contact.example.kavkom.com",
    "createdEpoch": 1710763200,
    "answeredEpoch": 1710763205,
    "duration": 120
  }
}

Ping / Pong

Le serveur envoie ping avec data: { sentStamp, expiresInSec }. Le client doit renvoyer un pong de même structure.

{ "event": "pong", "data": { "sentStamp": 1710763200000, "expiresInSec": 60 } }

Exemple client JavaScript

const ws = new WebSocket(
  `wss://live.kavkom.com/calls?t=${token}&ext=1001`
);

ws.onmessage = (msg) => {
  const { event, data } = JSON.parse(msg.data);
  if (event === "call") console.log(data.state, data.direction, data.number);
  if (event === "ping") ws.send(JSON.stringify({ event: "pong", data }));
};

Webhooks – push des appels & CDR

Depuis l’interface Kavkom, dans Advanced → Integrations → Webhook, configurez une URL vers laquelle Kavkom enverra les événements d’appel. Ce mécanisme est utile pour le screen-pop, le log dans un CRM, le déclenchement de workflows ou les tableaux de bord temps réel.

Paramètres de configuration

ChampDescription
EndpointURL HTTPS de votre serveur. Un bouton de test permet de la valider.
HeadersEn-têtes personnalisés, par exemple Authorization: Bearer ….
VariablesVariables personnalisées ajoutées au payload.
Types d’appelsAppels entrants en direct, appels sortants en direct, et/ou CDR après la fin de l’appel.
MappingCorrespondance des champs Kavkom vers ceux attendus par votre système.

Exemple de payload reçu

POST /webhooks/calls HTTP/1.1
Authorization: Bearer <votre-cle>
Content-Type: application/json

{
  "event": "cdr",
  "callUuid": "a1b2c3d4-...-ef1234567890",
  "direction": "outbound",
  "number": "33612345678",
  "state": "finished",
  "duration": 120
}
Connecteurs natifs. Sans écrire de code, vous pouvez aussi brancher HubSpot, Salesforce, Pipedrive, Zoho ou Fireberry depuis le même écran d’intégrations.
Bon à savoir. Les webhooks Kavkom poussent des événements vers votre endpoint. La réponse HTTP de votre serveur ne pilote pas le déroulé de l’appel : le contrôle d’appel se fait via les endpoints REST et le client SIP.

Référence des endpoints

Méthode & cheminAPIRôle
POST /api.php (route=order, type=line)BillingCommander une ligne / extension.
POST /api.php (route=order, type=did)BillingCommander un numéro DID.
GET /api.php (route=order, type=didlist)BillingLister les commandes DID.
GET /api/pbx/v1/extension/listPBXLister les extensions.
GET /api/pbx/v1/extension/list_limitedPBXListe allégée des extensions.
POST /api/pbx/v1/active_call/callPBXLancer un appel.
POST /api/pbx/v1/active_call/killPBXRaccrocher un appel.
POST /api/auth/acquire-accessAuthObtenir un access token WebSocket.
POST /api/auth/verify-accessAuthVérifier ou prolonger le token.
POST /api/auth/revoke-accessAuthRévoquer l’access token.
WSS /calls?t=&ext=WebSocketFlux d’événements d’appel.

Codes d’erreur & dépannage

Forme des erreurs

API Billing :

{ "status": "error", "message": "Fields required: domain_uuid, options" }

API PBX :

{
  "error": true,
  "message": "Model is not valid",
  "validationErrors": { "extension": "The extension field is required." }
}
CasSignification / action
422 + « src invalid »L’extension source n’existe pas sur ce domaine.
422 + texte switch -ERR …L’appel a été refusé par le switch.
Jeton refuséLe jeton n’est pas autorisé pour la route, ou non lié au domain_uuid fourni.
406 WebSocketParamètre t ou ext manquant.
401 WebSocketToken invalide ou expiré.
403 SIP REGISTERMauvais mot de passe ou realm différent de user_context.

Glossaire

TermeDéfinition
DIDDirect Inward Dialing : numéro de téléphone joignable directement.
Extension / lignePoste téléphonique sur le PBX, identifié par un numéro court, par exemple 901.
domain_uuidUUID v4 identifiant le client, ou tenant, sur la plateforme.
CDRCall Detail Record : métadonnées d’un appel terminé.
IVRServeur vocal interactif, ou menu à touches.
SIPProtocole d’ouverture de session pour la voix sur IP.
WebRTCTechnologie de communication temps réel dans le navigateur.
BridgeMise en relation de deux jambes d’appel.
Sommaire