Documentation

Tout ce qu'il faut pour intégrer Callisto — SMS, OTP, WhatsApp Business et monitoring.

Démarrage rapide #

Intégrez l'envoi de SMS en quelques minutes avec notre API REST simple et puissante.

1

Créer un compte

Inscrivez-vous gratuitement sur Callisto

2

Obtenir une clé API

Générez votre clé dans le tableau de bord

3

Envoyer un SMS ou WhatsApp

Faites votre premier appel API

Authentification #

L'API Callisto utilise l'authentification HTTP Basic. Chaque requête doit inclure un en-tête Authorization contenant vos identifiants encodés en base64.

Vos identifiants

Chaque clé API génère deux valeurs : access_key (identifiant public) et access_secret (à garder confidentiel). Récupérez-les depuis le tableau de bord à /api-keys.

Format de l'en-tête

Concaténez vos identifiants avec un deux-points puis encodez en base64 :

Authorization: Basic <base64(access_key:access_secret)>

Exemple avec cURL

Le drapeau -u de cURL encode automatiquement vos identifiants :

curl -u 'ak_xxx:sk_xxx' https://api.callistosignal.com/v1/sms/balance

URL de base #

https://api.callistosignal.com/v1

Envoyer un SMS #

POST /v1/sms/send

Paramètres

Paramètre Type Requis Description
to string | array Oui Numéro(s) de téléphone du/des destinataire(s) (format international)
message string Oui Contenu du message (max 1600 caractères)
sender_id string Non Identifiant de l'expéditeur (doit être approuvé)
scheduled_at datetime Non Date et heure d'envoi programmé (ISO 8601)

Exemple de requête

// Envoyer un SMS
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/sms/send', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        message: 'Bonjour',
        sender: 'MyApp'
    })
});
const data = await res.json();
// Envoyer un SMS via cURL
$ch = curl_init('https://api.callistosignal.com/v1/sms/send');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'      => '+22507XXXXXXXX',
        'message' => 'Bonjour',
        'sender'  => 'MyApp',
    ]),
]);
$response = curl_exec($ch);
curl_close($ch);
# Envoyer un SMS
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/sms/send \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "+22507XXXXXXXX",
    "message": "Bonjour",
    "sender": "MyApp"
  }'

Réponse

{
  "success": true,
  "data": {
    "id": "msg_abc123xyz",
    "to": ["+22507XXXXXXXX"],
    "status": "queued",
    "credits_used": 1,
    "created_at": "2026-02-01T10:30:00Z"
  }
}

Envoi en masse #

POST /v1/sms/send

Envoyez le même message à plusieurs destinataires en une seule requête.

Exemple de requête

// Envoyer un SMS en masse
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/sms/send', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: ['+22507XXXXXXXX', '+22508XXXXXXXX'],
        message: 'Bonjour à tous',
        sender: 'MyApp'
    })
});
// Envoyer un SMS en masse
$ch = curl_init('https://api.callistosignal.com/v1/sms/send');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'      => ['+22507XXXXXXXX', '+22508XXXXXXXX'],
        'message' => 'Bonjour à tous',
        'sender'  => 'MyApp',
    ]),
]);
$response = curl_exec($ch);
# Envoyer un SMS en masse
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/sms/send \
  -H 'Content-Type: application/json' \
  -d '{
    "to": ["+22507XXXXXXXX", "+22508XXXXXXXX"],
    "message": "Bonjour à tous",
    "sender": "MyApp"
  }'

OTP — Envoyer un code #

POST /v1/otp/send
POST /otp/send

Envoyez un code de vérification unique (OTP) à un destinataire. Le code est généré automatiquement et inséré dans votre message via la variable {code}.

Paramètres

Paramètre Type Requis Description
to string Oui Numéro de téléphone du destinataire (format international)
message string Oui Message contenant {code} (5-500 caractères)
sender string Non Identifiant de l'expéditeur (doit être approuvé). Ignoré pour le canal WhatsApp.
expired_in integer Oui Durée de validité en secondes (60 - 86400)
digit_size integer Non Nombre de caractères du code (4-16, défaut: 6)
type string Non Type de code: digit, alpha, alphanumeric (défaut: digit)
provider string Non Canal de livraison: sms (défaut) ou whatsapp
instanceCode string Conditionnel Code de l'instance WhatsApp à utiliser. Requis lorsque provider = whatsapp.

Exemple de requête

// Envoyer un code OTP
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/otp/send', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        message: 'Votre code de vérification est {code}',
        sender: 'MyApp',
        digit_size: 6,
        expired_in: 300,
        type: 'digit',
        provider: 'sms'
    })
});
const { id, recipient, expires_at } = await res.json();
// Envoyer un code OTP
$ch = curl_init('https://api.callistosignal.com/v1/otp/send');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'         => '+22507XXXXXXXX',
        'message'    => 'Votre code de vérification est {code}',
        'sender'     => 'MyApp',
        'digit_size' => 6,
        'expired_in' => 300,
        'type'       => 'digit',
        'provider'   => 'sms',
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/otp/send \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "+22507XXXXXXXX",
    "message": "Votre code de vérification est {code}",
    "sender": "MyApp",
    "digit_size": 6,
    "expired_in": 300,
    "type": "digit",
    "provider": "sms"
  }'

Réponse

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "provider": "sms",
  "recipient": "+22507XXXXXXXX",
  "expires_at": "2026-04-07T10:35:00Z",
  "expires_in": 300
}

Variante : livraison via WhatsApp

Pour envoyer le code via une instance WhatsApp connectée, ajoutez provider: "whatsapp" et instanceCode. Le champ sender est ignoré dans ce mode.

{
  "to": "+22507XXXXXXXX",
  "message": "Votre code Callisto est {code}",
  "expired_in": 300,
  "digit_size": 6,
  "type": "digit",
  "provider": "whatsapp",
  "instanceCode": "{instanceCode}"
}

Réponse identique, avec "provider": "whatsapp". Renvoie 400 si instanceCode est manquant ou si l'instance n'est pas connectée.

Note : Conservez l'id retourné pour vérifier le code ultérieurement.

OTP — Vérifier un code #

POST /v1/otp/verify
POST /otp/verify

Vérifiez le code OTP saisi par l'utilisateur.

Paramètres

Paramètre Type Requis Description
otp_id string Oui ID de l'OTP retourné lors de l'envoi (UUID)
code string Oui Code saisi par l'utilisateur (4-16 caractères)

Exemple de requête

// Vérifier un code OTP
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/otp/verify', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        otp_id: 'otp_xxxxxx',
        code: '123456'
    })
});
// Vérifier un code OTP
$ch = curl_init('https://api.callistosignal.com/v1/otp/verify');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'otp_id' => 'otp_xxxxxx',
        'code'   => '123456',
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/otp/verify \
  -H 'Content-Type: application/json' \
  -d '{
    "otp_id": "otp_xxxxxx",
    "code": "123456"
  }'

Réponse (succès)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "verified",
  "verified": true,
  "verified_at": "2026-04-07T10:32:15Z"
}

Réponse (échec)

{
  "message": "Invalid OTP code"
}

Codes d'erreur OTP

Code Description
400 Code OTP invalide
404 OTP non trouvé
410 OTP expiré
429 Trop de tentatives de vérification

OTP — Statut #

GET /v1/otps/{id}
GET /otps/{{otp_id}}

Récupérez le statut actuel d'un OTP.

Exemple de requête

// Consulter le statut d'un code OTP
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/otps/otp_xxxxxx', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
// Consulter le statut d'un code OTP
$ch = curl_init('https://api.callistosignal.com/v1/otps/otp_xxxxxx');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  https://api.callistosignal.com/v1/otps/otp_xxxxxx

Réponse

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "recipient": "+22507XXXXXXXX",
  "status": "pending",
  "created_at": "2026-04-07T10:30:00Z",
  "expires_at": "2026-04-07T10:35:00Z",
  "verified_at": null
}

Statuts possibles

Statut Description
pending En attente de vérification
verified Code vérifié avec succès
expired Code expiré

OTP — Liste #

GET /v1/otps
GET /otps

Récupérez la liste des OTP avec pagination.

Paramètres de requête

Paramètre Type Défaut Description
page integer 1 Numéro de page
limit integer 20 Nombre d'éléments par page
started_at date -30 jours Date de début (YYYY-MM-DD)
ended_at date aujourd'hui Date de fin (YYYY-MM-DD)

Exemple de requête

// Lister les codes OTP envoyés
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/otps?limit=50', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
// Lister les codes OTP envoyés
$ch = curl_init('https://api.callistosignal.com/v1/otps?limit=50');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  'https://api.callistosignal.com/v1/otps?limit=50'

Réponse

{
  "items": [
    {
      "id": "3b5d654b-d603-44b6-8f9e-0f24b38eafd0",
      "client_id": "9d8e0eab-6c65-4794-ae22-637445a421bf",
      "client_api_id": "c11e9a92-27eb-430f-949f-40dea00d521d",
      "message_id": "ea01e0ba-02d2-471a-8e23-340b7d570b3e",
      "recipient": "+22507XXXXXXXX",
      "status": "expired",
      "expires_at": "2026-04-07 19:05:12",
      "verified_at": null,
      "attempts": 0,
      "created_at": "2026-04-07 18:06:52",
      "updated_at": "2026-04-07 18:06:52"
    },
    {
      "id": "d5f29dfc-03b5-41da-b371-2d7998896c72",
      "client_id": "9d8e0eab-6c65-4794-ae22-637445a421bf",
      "client_api_id": "c11e9a92-27eb-430f-949f-40dea00d521d",
      "message_id": "ac118655-fe08-4eba-afb1-e4a7a5399a95",
      "recipient": "+22508XXXXXXXX",
      "status": "verified",
      "expires_at": "2026-04-07 18:55:37",
      "verified_at": "2026-04-07 18:52:15",
      "attempts": 1,
      "created_at": "2026-04-07 17:57:17",
      "updated_at": "2026-04-07 18:52:15"
    }
  ],
  "total": 25,
  "per_page": 20,
  "current_page": 1,
  "next": 2,
  "previous": 0,
  "total_pages": 2
}

Connecter une instance #

WhatsApp Business nécessite de pairer une fois un numéro de téléphone via QR code dans le tableau de bord. L'API REST ne prend pas en charge le pairing — elle commence à partir de l'envoi de messages et de la consultation des statuts.

Étapes

  1. Connectez-vous à votre tableau de bord.
  2. Allez dans WhatsApp → Instances → Nouvelle instance.
  3. Nommez l'instance (par exemple "Production" ou "Support").
  4. Scannez le QR code affiché avec WhatsApp Business sur le téléphone qui hébergera l'instance.
  5. Une fois status: connected, vous pouvez envoyer des messages via l'API.
Le pairing se fait uniquement via le tableau de bord. L'API REST commence à partir de l'envoi de messages et de la consultation des statuts.
Créer une instance

Instances #

Consulter la liste de vos instances WhatsApp pairées et leur statut.

Lister les instances

GET /v1/whatsapp/instances
// Lister les instances WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/instances', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
const instances = await res.json();
// Lister les instances WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/instances');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  https://api.callistosignal.com/v1/whatsapp/instances

Réponse (200)

[
  {
    "id": "{instanceCode}",
    "name": "Production",
    "phone_number": "+22507XXXXXXXX",
    "phone_name": "Callisto Demo",
    "status": "connected",
    "billing_status": "active",
    "trial_days_remaining": 0,
    "monthly_fee": 5000,
    "created_at": "2026-04-12T10:34:00Z"
  }
]

Détails d'une instance

GET /v1/whatsapp/{instanceCode}

Paramètre de chemin : instanceCode — UUID de l'instance.

// Consulter une instance WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
const instance = await res.json();
// Consulter une instance WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  https://api.callistosignal.com/v1/whatsapp/{instanceCode}

Réponse (200)

{
  "id": "{instanceCode}",
  "name": "Production",
  "phone_number": "+22507XXXXXXXX",
  "phone_name": "Callisto Demo",
  "status": "connected",
  "billing_status": "active",
  "trial_days_remaining": 0,
  "monthly_fee": 5000,
  "created_at": "2026-04-12T10:34:00Z"
}

Envoyer un message #

Une fois votre instance pairée et connected, envoyez des messages texte ou média via l'API.

Message texte

POST /v1/whatsapp/{instanceCode}/send/text

Paramètres du corps

Paramètre Type Requis Description
tostringOuiNuméro destinataire au format E.164 (ex. +22507XXXXXXXX).
messagestringOuiContenu du message texte.
// Envoyer un message texte WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/text', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        message: 'Bonjour Aïcha'
    })
});
// Envoyer un message texte WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/text');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'      => '+22507XXXXXXXX',
        'message' => 'Bonjour Aïcha',
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/text \
  -H 'Content-Type: application/json' \
  -d '{"to":"+22507XXXXXXXX","message":"Bonjour Aïcha"}'

Réponse (200)

{
  "id": "wmsg_xxxxxx",
  "instance_id": "{instanceCode}",
  "to": "+22507XXXXXXXX",
  "status": "queued"
}

Message média

POST /v1/whatsapp/{instanceCode}/send/media

Paramètres du corps

Paramètre Type Requis Description
tostringOuiNuméro destinataire (E.164).
typestringOuiimage
media_urlstringOuiURL publique du média (http:// ou https://).
captionstringNonLégende affichée avec le média (max 1024 caractères).
filenamestringNonNom du fichier (utile pour document, max 255 caractères).
// Envoyer un média WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/media', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        type: 'image',
        media_url: 'https://example.com/photo.jpg',
        caption: 'Notre nouveau produit'
    })
});
// Envoyer un média WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/media');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'        => '+22507XXXXXXXX',
        'type'      => 'image',
        'media_url' => 'https://example.com/photo.jpg',
        'caption'   => 'Notre nouveau produit',
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/media \
  -H 'Content-Type: application/json' \
  -d '{"to":"+22507XXXXXXXX","type":"image","media_url":"https://example.com/photo.jpg","caption":"Notre nouveau produit"}'

Réponse (200)

{
  "id": "wmsg_xxxxxx",
  "instance_id": "{instanceCode}",
  "to": "+22507XXXXXXXX",
  "status": "queued"
}

Message boutons

POST /v1/whatsapp/{instanceCode}/send/buttons

Paramètres du corps

Paramètre Type Requis Description
tostringOuiNuméro destinataire (E.164).
bodystringOuiTexte principal du message (max 1024 caractères).
buttonsarrayOui1 à 3 boutons {id, title}. title ≤ 20 caractères, id ≤ 256 caractères.
headerstringNonEn-tête optionnel (≤ 60 caractères).
footerstringNonPied de message optionnel (≤ 60 caractères).
scheduled_atdatetimeNonDifférer l'envoi (YYYY-MM-DD HH:MM:SS).
// Envoyer un message à boutons WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/buttons', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        body: 'Confirmez-vous votre commande ?',
        header: 'Commande #1234',
        footer: 'Répondez à tout moment.',
        buttons: [
            { id: 'yes', title: 'Oui' },
            { id: 'no', title: 'Non' },
            { id: 'later', title: 'Plus tard' }
        ]
    })
});
// Envoyer un message à boutons WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/buttons');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'      => '+22507XXXXXXXX',
        'body'    => 'Confirmez-vous votre commande ?',
        'header'  => 'Commande #1234',
        'footer'  => 'Répondez à tout moment.',
        'buttons' => [
            ['id' => 'yes', 'title' => 'Oui'],
            ['id' => 'no', 'title' => 'Non'],
            ['id' => 'later', 'title' => 'Plus tard'],
        ],
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/buttons \
  -H 'Content-Type: application/json' \
  -d '{"to":"+22507XXXXXXXX","body":"Confirmez-vous ?","buttons":[{"id":"yes","title":"Oui"},{"id":"no","title":"Non"}]}'

Réponse (200)

{
  "id": "wmsg_xxxxxx",
  "instance_id": "{instanceCode}",
  "recipient": "+22507XXXXXXXX",
  "message_type": "buttons",
  "status": "queued",
  "scheduled": false
}

Message localisation

POST /v1/whatsapp/{instanceCode}/send/location

Paramètres du corps

Paramètre Type Requis Description
tostringOuiNuméro destinataire (E.164).
latitudenumberOuiLatitude entre -90 et 90.
longitudenumberOuiLongitude entre -180 et 180.
namestringNonNom du lieu (≤ 255 caractères).
addressstringNonAdresse postale (≤ 1024 caractères).
scheduled_atdatetimeNonDifférer l'envoi.
// Envoyer une localisation WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/location', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        latitude: 5.3599517,
        longitude: -4.0082563,
        name: 'Plateau, Abidjan',
        address: 'Boulevard de la République, Abidjan'
    })
});
// Envoyer une localisation WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/location');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'        => '+22507XXXXXXXX',
        'latitude'  => 5.3599517,
        'longitude' => -4.0082563,
        'name'      => 'Plateau, Abidjan',
        'address'   => 'Boulevard de la République, Abidjan',
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/location \
  -H 'Content-Type: application/json' \
  -d '{"to":"+22507XXXXXXXX","latitude":5.3599517,"longitude":-4.0082563,"name":"Plateau, Abidjan"}'

Réponse (200)

{
  "id": "wmsg_xxxxxx",
  "instance_id": "{instanceCode}",
  "recipient": "+22507XXXXXXXX",
  "message_type": "location",
  "status": "queued",
  "scheduled": false
}

Message liste

POST /v1/whatsapp/{instanceCode}/send/list

Paramètres du corps

Paramètre Type Requis Description
tostringOuiNuméro destinataire (E.164).
bodystringOuiTexte principal (max 1024 caractères).
button_textstringOuiLibellé du bouton qui ouvre la liste (≤ 20 caractères).
sectionsarrayOui1 à 10 sections {title, rows}. Total des rows ≤ 10. Chaque ligne {id, title, description?} avec title ≤ 24 et description ≤ 72.
headerstringNonEn-tête optionnel (≤ 60 caractères).
footerstringNonPied de message optionnel (≤ 60 caractères).
scheduled_atdatetimeNonDifférer l'envoi.
// Envoyer un menu liste WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/list', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + credentials
    },
    body: JSON.stringify({
        to: '+22507XXXXXXXX',
        body: 'Sélectionnez une option dans le menu.',
        button_text: 'Voir le menu',
        header: 'Notre catalogue',
        sections: [
            {
                title: 'Plats',
                rows: [
                    { id: 'plat-1', title: 'Attiéké poisson', description: 'Avec sauce piment' },
                    { id: 'plat-2', title: 'Garba' }
                ]
            },
            {
                title: 'Boissons',
                rows: [
                    { id: 'bsn-1', title: 'Bissap' },
                    { id: 'bsn-2', title: 'Gnamakoudji' }
                ]
            }
        ]
    })
});
// Envoyer un menu liste WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/list');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'to'          => '+22507XXXXXXXX',
        'body'        => 'Sélectionnez une option dans le menu.',
        'button_text' => 'Voir le menu',
        'header'      => 'Notre catalogue',
        'sections'    => [
            [
                'title' => 'Plats',
                'rows'  => [
                    ['id' => 'plat-1', 'title' => 'Attiéké poisson', 'description' => 'Avec sauce piment'],
                    ['id' => 'plat-2', 'title' => 'Garba'],
                ],
            ],
            [
                'title' => 'Boissons',
                'rows'  => [
                    ['id' => 'bsn-1', 'title' => 'Bissap'],
                    ['id' => 'bsn-2', 'title' => 'Gnamakoudji'],
                ],
            ],
        ],
    ]),
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  -X POST https://api.callistosignal.com/v1/whatsapp/{instanceCode}/send/list \
  -H 'Content-Type: application/json' \
  -d '{"to":"+22507XXXXXXXX","body":"Choisir une option","button_text":"Menu","sections":[{"title":"Plats","rows":[{"id":"a","title":"Garba"}]}]}'

Réponse (200)

{
  "id": "wmsg_xxxxxx",
  "instance_id": "{instanceCode}",
  "recipient": "+22507XXXXXXXX",
  "message_type": "list",
  "status": "queued",
  "scheduled": false
}

Messages WhatsApp #

Lister les messages envoyés depuis une instance, ou consulter le statut d'un message individuel.

Lister les messages d'une instance

GET /v1/whatsapp/{instanceCode}/messages

Paramètres de requête

Paramètre Type Défaut Description
limitint50Nombre maximum d'éléments (max 200).
cursorstringCurseur de pagination (retourné dans next_cursor).
// Lister les messages WhatsApp d'une instance
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/messages?limit=50', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
// Lister les messages WhatsApp d'une instance
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/{instanceCode}/messages?limit=50');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  'https://api.callistosignal.com/v1/whatsapp/{instanceCode}/messages?limit=50'

Réponse (200)

{
  "data": [
    {
      "id": "wmsg_xxxxxx",
      "to": "+22507XXXXXXXX",
      "body": "Bonjour Aïcha",
      "media_type": null,
      "status": "delivered",
      "sent_at": "2026-05-14T10:34:00Z",
      "delivered_at": "2026-05-14T10:34:02Z",
      "read_at": null,
      "error_code": null,
      "error_message": null
    }
  ],
  "next_cursor": null
}

Statut d'un message

GET /v1/whatsapp/messages/{messageId}

Paramètre de chemin : messageId — identifiant du message (ex. wmsg_xxxxxx).

// Consulter le statut d'un message WhatsApp
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/whatsapp/messages/wmsg_xxxxxx', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
// Consulter le statut d'un message WhatsApp
$ch = curl_init('https://api.callistosignal.com/v1/whatsapp/messages/wmsg_xxxxxx');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  https://api.callistosignal.com/v1/whatsapp/messages/wmsg_xxxxxx

Réponse (200)

{
  "id": "wmsg_xxxxxx",
  "to": "+22507XXXXXXXX",
  "body": "Bonjour Aïcha",
  "media_type": null,
  "status": "delivered",
  "sent_at": "2026-05-14T10:34:00Z",
  "delivered_at": "2026-05-14T10:34:02Z",
  "read_at": null,
  "error_code": null,
  "error_message": null
}

Valeurs possibles pour status : queued, sent, delivered, read, failed.

URL Monitor #

Vérifiez périodiquement la disponibilité de vos endpoints HTTP/HTTPS. Callisto interroge l'URL à l'intervalle configuré et déclenche une alerte email dès qu'elle devient lente ou inaccessible.

Configuration

  1. Connectez-vous à votre tableau de bord.
  2. Allez dans Monitoring → UpTime → Nouveau moniteur.
  3. Renseignez l'URL cible, la méthode HTTP (GET par défaut), l'intervalle (≥ 60 s) et le délai de timeout.
  4. Optionnel : codes de statut attendus (ex. 200, 204), en-têtes requis.
  5. Adresse email d'alerte (par défaut celle du compte).

Notifications : alertes email automatiques en cas d'incident (downtime, code de statut inattendu, latence dépassée).

Tarification : inclus gratuitement avec votre compte Callisto.

API publique à venir — pour l'instant configurez via le tableau de bord.

Heartbeat Monitor #

Surveillez vos cron jobs et tâches planifiées. Vos jobs envoient un ping HTTP à une URL unique à la fin de chaque exécution&nbsp;; Callisto vous alerte par email si le ping n'arrive pas dans l'intervalle attendu.

Configuration

  1. Allez dans Monitoring → Heartbeats → Nouveau heartbeat.
  2. Nommez le heartbeat (ex. "Backup nuit", "Sync inventaire").
  3. Définissez l'intervalle attendu (ex. 5 min) et le délai de grâce (ex. 1 min).
  4. Copiez l'URL de ping générée — elle est de la forme https://ping.callistosignal.com/<uuid>.
  5. Ajoutez un appel HTTP à cette URL à la fin de votre cron job.

Intégration

curl -fsS https://ping.callistosignal.com/<uuid>
*/5 * * * * /usr/bin/php /path/to/job.php && curl -fsS https://ping.callistosignal.com/<uuid>

                                    // À la fin de votre job :
                                    file_get_contents('https://ping.callistosignal.com/<uuid>');
                                

Notifications : alertes email si aucun ping reçu dans intervalle + grâce.

Tarification : inclus gratuitement.

API publique pour gérer les heartbeats à venir — pour l'instant configurez via le tableau de bord.

Webhook Capture #

Inspectez en temps réel les requêtes HTTP entrantes pour déboguer vos intégrations tierces. Chaque webhook reçoit une URL unique&nbsp;; tous les en-têtes, le corps et les paramètres de requête sont enregistrés.

Configuration

  1. Allez dans Monitoring → Webhooks → Nouveau webhook.
  2. Nommez le webhook (ex. "Stripe test", "Hub2 staging").
  3. Copiez l'URL générée — de la forme https://webhook.callistosignal.com/hook/<token> (token = 32 caractères hexadécimaux).
  4. Configurez ce webhook chez le service tiers que vous voulez tester (Stripe, Hub2, etc.).
  5. Les requêtes apparaissent en direct dans le tableau de bord, avec en-têtes, corps et paramètres de requête enregistrés.

Méthodes acceptées : GET, POST, PUT, PATCH, DELETE.

Affichage : chaque requête entrante est visible immédiatement dans le tableau de bord avec son timestamp, ses en-têtes, son corps et ses paramètres de requête.

Tarification : inclus gratuitement.

API publique pour lister les requêtes capturées à venir — pour l'instant consultez via le tableau de bord.

Vérifier le solde #

GET /v1/sms/balance
// Consulter le solde du compte
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/sms/balance', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
// Consulter le solde du compte
$ch = curl_init('https://api.callistosignal.com/v1/sms/balance');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  https://api.callistosignal.com/v1/sms/balance

Statut d'un message #

GET /v1/sms/{id}
// Consulter le statut d'un message
const credentials = btoa('ACCESS_KEY:ACCESS_SECRET');
const res = await fetch('https://api.callistosignal.com/v1/sms/msg_xxxxxx', {
    headers: { 'Authorization': 'Basic ' + credentials }
});
// Consulter le statut d'un message
$ch = curl_init('https://api.callistosignal.com/v1/sms/msg_xxxxxx');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'ACCESS_KEY:ACCESS_SECRET',
]);
$response = curl_exec($ch);
curl -u 'ACCESS_KEY:ACCESS_SECRET' \
  https://api.callistosignal.com/v1/sms/msg_xxxxxx

Statuts possibles

Statut Description
queued Le message est en file d'attente
sent Le message a été envoyé à l'opérateur
delivered Le message a été livré au destinataire
failed L'envoi du message a échoué

Codes d'erreur #

Code Description
400 Requête invalide - vérifiez les paramètres
401 Non autorisé - clé API invalide ou manquante
402 Crédits insuffisants
404 Ressource non trouvée
429 Limite de requêtes dépassée
500 Erreur serveur interne

Limites de requêtes #

Pour garantir la stabilité du service, les limites suivantes s'appliquent :

  • 100 requêtes/minute pour les endpoints d'envoi de SMS
  • 1000 requêtes/minute pour les endpoints de lecture
  • 10 000 SMS/jour par défaut (contactez-nous pour augmenter)

Les en-têtes de réponse incluent des informations sur vos limites actuelles :

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1706789400