Référence de l’API de démonstration
Cette page décrit l’API telle qu’elle est conçue aujourd’hui : authentification, idempotence, pagination, erreurs, points d’accès et webhooks. C’est une version de démonstration. Tous les exemples sont fictifs.
Mis à jour le
Statut de cette référence
Il s’agit d’une proposition de conception, susceptible d’évoluer sans préavis. Aucune API de production n’est ouverte à ce jour.
Tant qu’aucun fournisseur n’est configuré, les appels, commandes de numéros et SMS sont des simulations. Les réponses portent alors le champ simulated: true.
Adresse de base et authentification
Toutes les requêtes passent par la base https://api.example.test/v1, en HTTPS. Authentifiez-vous avec une clé d’API dans l’en-tête Authorization, au schéma Bearer.
Une clé est limitée à un projet et à un environnement. Elle ne doit jamais figurer dans un code exécuté côté navigateur ni dans une URL.
Authorization: Bearer tq_test_EXEMPLE
Content-Type: application/jsonIdempotence
Toute requête POST exige un en-tête Idempotency-Key contenant un identifiant unique, par exemple un UUID. Sans lui, l’API répond 400 invalid_request.
Si vous renvoyez la même clé avec le même corps, l’API rejoue la réponse d’origine et ne crée rien de plus : un double clic ou une nouvelle tentative réseau reste sans effet. Si vous renvoyez la même clé avec un corps différent, l’API répond 409 idempotency_conflict.
Générez une clé neuve pour chaque nouvelle opération. Si une réponse n’est jamais arrivée, rejouez la requête avec la même clé plutôt qu’avec une nouvelle.
Pagination par curseur
Les listes acceptent limit et cursor. La réponse contient le tableau data et next_cursor. Pour lire la page suivante, passez la valeur de next_cursor dans cursor. Quand next_cursor est nul, la liste est terminée.
Un curseur est opaque : ne le décodez pas et ne le construisez pas vous-même.
{
"data": [],
"next_cursor": null
}Quotas et limites de débit
L’API limite le débit des requêtes. Au-delà de la limite, elle répond 429 rate_limited avec un en-tête Retry-After indiquant, en secondes, le temps d’attente avant de réessayer.
Les limites applicables à votre projet dépendent de votre contrat. Aucun chiffre n’est publié sur cette page.
HTTP/1.1 429 Too Many Requests
Retry-After: 2
Content-Type: application/json
{ "error": { "code": "rate_limited", "message": "Trop de requêtes. Réessayez après le délai indiqué.", "request_id": "req_EXEMPLE_001" } }Format des erreurs
Toute erreur renvoie un objet error avec trois champs : code (stable, à utiliser dans votre logique), message (destiné à une personne, susceptible de changer) et request_id (à communiquer à l’assistance).
{
"error": {
"code": "invalid_request",
"message": "Le champ « to » doit être un numéro au format E.164.",
"request_id": "req_EXEMPLE_002"
}
}| HTTP | code | Signification | Action conseillée |
|---|---|---|---|
| 400 | invalid_request | Requête mal formée : champ manquant ou invalide, Idempotency-Key absente sur un POST. | Corrigez la requête. |
| 401 | unauthorized | Clé absente, invalide ou révoquée. | Vérifiez la clé et l’en-tête Authorization. |
| 403 | forbidden | La clé n’a pas le droit d’accéder à cette ressource ou à ce projet. | Utilisez une clé disposant des droits. |
| 404 | not_found | Ressource inexistante ou hors de votre périmètre. | Vérifiez l’identifiant. |
| 409 | idempotency_conflict | Même Idempotency-Key utilisée avec un corps différent. | Générez une nouvelle clé. |
| 429 | rate_limited | Débit trop élevé. | Attendez la durée de Retry-After. |
GET /numbers
Liste les numéros de votre compte.
- limit : nombre d’éléments par page (facultatif).
- cursor : curseur de la page suivante (facultatif).
- Chaque numéro porte id, e164, country, type, capabilities (voice, sms), project_id et status.
{
"data": [
{
"id": "num_EXEMPLE_001",
"e164": "+33199001234",
"country": "FR",
"type": "local",
"capabilities": ["voice", "sms"],
"project_id": "prj_EXEMPLE_A",
"status": "active"
}
],
"next_cursor": "cur_EXEMPLE_002"
}GET /numbers/search
Cherche des numéros dans le stock. La disponibilité réelle dépend du pays, du fournisseur retenu et du contrat.
- country : pays au format ISO à deux lettres, par exemple FR.
- type : type de numéro, par exemple local.
- Chaque résultat porte e164, country, type, capabilities et documents_required, la liste des justificatifs à fournir avant activation.
{
"data": [
{
"e164": "+33199001234",
"country": "FR",
"type": "local",
"capabilities": ["voice", "sms"],
"documents_required": ["proof_of_address"]
}
]
}POST /number-orders
Passe une commande de numéro. En-tête Idempotency-Key obligatoire. La commande reste en attente de validation des justificatifs et des conditions.
- e164 : numéro à commander, issu d’une recherche (obligatoire).
- project_id : projet de rattachement (obligatoire).
{
"id": "ord_EXEMPLE_001",
"status": "pending_validation",
"simulated": true
}POST /calls
Lance un appel sortant entre deux numéros. En-tête Idempotency-Key obligatoire.
- from : numéro appelant, en E.164 (obligatoire).
- to : numéro appelé, en E.164 (obligatoire).
- project_id : projet concerné (obligatoire).
- flow_id : scénario d’appel à appliquer (facultatif).
{
"id": "call_EXEMPLE_001",
"status": "ringing",
"simulated": true
}GET /calls
Liste le journal des appels, avec pagination par curseur. Les durées sont en secondes. La durée de conversation et la durée facturable sont deux champs distincts : elles peuvent différer selon le contrat.
- limit et cursor : pagination (facultatifs).
- Chaque appel porte id, direction, status, duration_seconds, billable_seconds et project_id.
{
"data": [
{
"id": "call_EXEMPLE_001",
"direction": "outbound",
"status": "completed",
"duration_seconds": 42,
"billable_seconds": 42,
"project_id": "prj_EXEMPLE_A"
}
],
"next_cursor": null
}POST /messages
Envoie ou programme un SMS. En-tête Idempotency-Key obligatoire. Un texte long est découpé en segments, chacun comptant pour la consommation.
- from : expéditeur (obligatoire).
- to : destinataire, en E.164 (obligatoire).
- text : contenu du message (obligatoire).
- nature : transactional ou marketing (obligatoire).
- scheduled_at : date et heure d’envoi programmé (facultatif).
- timezone : fuseau horaire de scheduled_at (facultatif, à fournir avec scheduled_at).
- La réponse indique segments et encoding (GSM-7 ou UCS-2).
{
"id": "msg_EXEMPLE_001",
"status": "queued",
"segments": 1,
"encoding": "GSM-7",
"simulated": true
}GET /usage
Renvoie les quantités consommées sur une période. La réponse porte des quantités et des unités, jamais de montants.
- from et to : bornes de la période, au format AAAA-MM-JJ.
- group_by : day, number, project, country ou service.
- provisional vaut true quand des événements peuvent encore arriver en retard.
- Un appel peut générer plusieurs lignes de consommation selon le contrat.
{
"data": [
{ "key": "2026-10-01", "service": "voice", "direction": "outbound", "unit": "second", "quantity": 5400 },
{ "key": "2026-10-01", "service": "sms", "direction": "outbound", "unit": "segment", "quantity": 120 }
],
"provisional": false
}Statuts
| Objet | Statuts | Remarque |
|---|---|---|
| Appel | ringing, connected, completed, failed | failed n’indique pas la cause. Ne la déduisez pas. |
| SMS | queued, sent, delivered, undelivered, unknown | delivered ne veut pas dire lu. unknown peut rester définitif. |
| Commande de numéro | pending_validation | Le numéro n’est utilisable qu’après activation (événement number.activated). |
Webhooks
Vous pouvez recevoir des événements sur une adresse HTTPS de votre choix. Chaque livraison porte un en-tête Telqio-Signature de la forme t=<horodatage unix>,v1=<signature hexadécimale>.
La signature est un HMAC-SHA256 du texte « t, point, corps brut » avec le secret du point de terminaison. Rejetez toute livraison dont l’horodatage s’écarte de plus de 300 secondes, et dédupliquez sur l’identifiant d’événement id.
Événements : call.ringing, call.connected, call.completed, call.failed, message.sent, message.delivered, message.undelivered et number.activated. Les nouvelles tentatives de livraison suivent une politique bornée, visible dans la console. L’ordre d’arrivée n’est pas garanti.
Le guide « Vérifier un webhook signé » donne le code complet en Node.js.
POST /webhook HTTP/1.1
Telqio-Signature: t=1794096000,v1=<signature_hexadecimale>
Content-Type: application/json
{
"id": "evt_EXEMPLE_001",
"type": "call.completed",
"created": 1794096000,
"data": { "call_id": "call_EXEMPLE_001", "status": "completed" }
}Ce que cette référence n’est pas
- Ce n’est pas un engagement de service : aucune disponibilité, aucun délai ni aucune capacité n’est promis.
- Ce n’est pas une API ouverte : aucune clé réelle n’existe et aucune communication n’est émise.
- Les capacités réelles dépendront du pays, du fournisseur retenu et du contrat. Pour votre périmètre, demandez un devis.
Questions fréquentes
Puis-je utiliser cette API en production ?
Non. Il s’agit d’une version de démonstration. Aucune API de production n’est ouverte et le contrat d’interface peut encore changer.
Pourquoi les réponses contiennent-elles simulated: true ?
Parce qu’aucun fournisseur n’est configuré. Les appels, SMS et commandes de numéros sont simulés, et aucune communication réelle n’est émise.