Démarrer avec une clé de test
En quinze minutes, vous créez une session, vous la faites avancer comme si un client ouvrait le lien, et vous lisez ce que l’API en a retenu. Tout se passe en mode test : aucun SMS ne part et rien n’est facturé.
Pas à pas
Section intitulée « Pas à pas »-
Créez une clé de test. Dans le back-office, ouvrez Intégrations et API, et créez une clé de test (en images). Son secret,
vz_test_<préfixe>_…, ne s’affiche qu’une fois : gardez-le dans votre gestionnaire de secrets, puis exportez-le pour la suite.Fenêtre de terminal # Collez le secret de la clé de test, puis Entrée : rien ne s'affiche, rien ne reste dans l'historique.read -rs VIZALIA_API_KEY && export VIZALIA_API_KEY -
Vérifiez la clé.
GET /medécrit la clé utilisée : son espace, ses portées, son mode et son échéance.livemodevautfalsepour une clé de test.Fenêtre de terminal curl https://api.vizalia.ai/v1/me \-H "Authorization: Bearer $VIZALIA_API_KEY" -
Créez une session. Avec
channel: link, rien n’est envoyé : la réponse donnejoin_url, le lien du client. Ouvrez-le sur un téléphone pour voir la page que reçoit le client.Fenêtre de terminal curl https://api.vizalia.ai/v1/sessions \-H "Authorization: Bearer $VIZALIA_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-d '{"channel": "link", "reference": "TEST-1"}'Gardez l’identifiant de la session,
ses_…:export SESSION_ID="ses_…". Si votre outil ouvre le poste conseiller, gardez aussiadvisor_url: elle n’est renvoyée qu’ici (Sessions). L’en-têteIdempotency-Keyrend la requête rejouable sans créer de doublon (Idempotence). -
Abonnez une URL aux événements. Votre serveur reçoit alors un
POSTsigné à chaque étape. Gardez le secretwhsec_…de la réponse : il ne s’affiche qu’une fois, et sert à vérifier la signature.Fenêtre de terminal curl https://api.vizalia.ai/v1/webhook_endpoints \-H "Authorization: Bearer $VIZALIA_API_KEY" \-H "Content-Type: application/json" \-d '{"url": "https://crm.exemple.fr/webhooks/vizalia", "events": ["session.ended", "report.ready"]}'Pas encore d’URL publique en HTTPS ? Passez cette étape :
GET /eventsdonne les mêmes événements, à l’étape 6. -
Faites avancer la session sans téléphone.
simulatejoue le client, une action après l’autre :open(il ouvre le lien),go_live(la vidéo passe),take_photo(une photo est prise), puisend. Chaque étape envoie ses webhooks, comme en production.Fenêtre de terminal for action in open go_live take_photo end; docurl https://api.vizalia.ai/v1/sessions/$SESSION_ID/simulate \-H "Authorization: Bearer $VIZALIA_API_KEY" \-H "Content-Type: application/json" \-d "{\"action\": \"$action\"}"done -
Lisez les événements. Le journal garde les événements des 30 derniers jours, les plus récents d’abord.
Fenêtre de terminal curl "https://api.vizalia.ai/v1/events?session_id=$SESSION_ID" \-H "Authorization: Bearer $VIZALIA_API_KEY" -
Lisez le rapport. Il est prêt quand
report.readyest envoyé, parfois quelques minutes aprèssession.ended; avant, l’API répond409 report_not_ready. Ajoutez?format=pdfpour le PDF.Fenêtre de terminal curl https://api.vizalia.ai/v1/sessions/$SESSION_ID/report \-H "Authorization: Bearer $VIZALIA_API_KEY"
Le parcours en un script
Section intitulée « Le parcours en un script »Le même parcours, des étapes 2 à 6, d’un seul tenant. VIZALIA_API_BASE change l’adresse de l’API si besoin.
#!/usr/bin/env bash# Parcours complet en mode test : clé, session, simulation, événements, rapport.# Prérequis : curl, jq, uuidgen, et une clé de test dans VIZALIA_API_KEY (vz_test_…).set -euo pipefail
API="${VIZALIA_API_BASE:-https://api.vizalia.ai/v1}": "${VIZALIA_API_KEY:?Exportez VIZALIA_API_KEY, une clé vz_test_…}"
# Appelle l'API. Sur une erreur, affiche son code, son détail et son request_id# (RFC 9457), puis arrête le parcours.vizalia() { local methode=$1 chemin=$2 corps=${3:-} reponse statut local options=(-sS -X "$methode" -H "Authorization: Bearer $VIZALIA_API_KEY" -w '\n%{http_code}') if [ -n "$corps" ]; then options+=(-H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" -d "$corps") fi reponse=$(curl "${options[@]}" "$API$chemin") statut=${reponse##*$'\n'} reponse=${reponse%$'\n'*} if [ "$statut" -ge 400 ]; then echo "Erreur $statut sur $methode $chemin : $(jq -r '"\(.code) : \(.detail // .title) (\(.request_id))"' <<<"$reponse" 2>/dev/null || echo "$reponse")" >&2 exit 1 fi printf '%s\n' "$reponse"}
# 1. La clé : espace, portées, mode (livemode vaut false en mode test)vizalia GET /me | jq '{livemode, scopes, space}'
# 2. Une session sans envoi (channel link) : la réponse donne join_urlSESSION_ID=$(vizalia POST /sessions '{"channel": "link", "reference": "TEST-1"}' | jq -r '.id')echo "Session : $SESSION_ID"
# 3. Le client simulé ouvre le lien, la vidéo passe, une photo est prise, l'appel se terminefor action in open go_live take_photo end; do vizalia POST "/sessions/$SESSION_ID/simulate" "{\"action\": \"$action\"}" | jq -r --arg action "$action" '"\($action) → \(.status)"'done
# 4. Les événements envoyés pour cette session, les plus récents d'abordvizalia GET "/events?session_id=$SESSION_ID" | jq -r '.data[].type'
# 5. Le rapport (409 report_not_ready tant que la session n'est pas terminée)vizalia GET "/sessions/$SESSION_ID/report" | jq '{schema_version, generated_at, photos: (.pictures | length)}'// Parcours complet en mode test, Node.js 18 ou plus (fetch intégré).// Prérequis : une clé de test dans VIZALIA_API_KEY (vz_test_…).import { randomUUID } from 'node:crypto';
const API = process.env.VIZALIA_API_BASE ?? 'https://api.vizalia.ai/v1';const CLE = process.env.VIZALIA_API_KEY;if (!CLE) throw new Error('Exportez VIZALIA_API_KEY, une clé vz_test_…');
async function vizalia(methode, chemin, corps, entetes = {}) { const reponse = await fetch(`${API}${chemin}`, { method: methode, headers: { Authorization: `Bearer ${CLE}`, ...(corps ? { 'Content-Type': 'application/json' } : {}), ...entetes, }, body: corps ? JSON.stringify(corps) : undefined, }); const contenu = await reponse.json(); if (!reponse.ok) { // Erreur RFC 9457 : `code` est stable, `request_id` va au support throw new Error(`${reponse.status} ${contenu.code} : ${contenu.detail ?? contenu.title} (${contenu.request_id})`); } return contenu;}
// 1. La clé : espace, portées, modeconst cle = await vizalia('GET', '/me');console.log('Mode test :', cle.livemode === false, '· portées :', cle.scopes.join(', '));
// 2. Une session sans envoi (channel link) : la réponse donne join_urlconst session = await vizalia( 'POST', '/sessions', { channel: 'link', reference: 'TEST-1' }, { 'Idempotency-Key': randomUUID() },);// session.join_url, le lien du client, donne accès à la session : ouvrez-le sur un// téléphone pour voir sa page, mais ne l'écrivez dans aucun journal.console.log('Session :', session.id);
// 3. Le client simulé ouvre le lien, la vidéo passe, une photo est prise, l'appel se terminefor (const action of ['open', 'go_live', 'take_photo', 'end']) { const etat = await vizalia('POST', `/sessions/${session.id}/simulate`, { action }); console.log(`${action} → ${etat.status}`);}
// 4. Les événements envoyés pour cette sessionconst evenements = await vizalia('GET', `/events?session_id=${session.id}`);console.log('Événements :', evenements.data.map((e) => e.type).join(', '));"""Parcours complet en mode test, Python 3.9 ou plus (pip install requests).
Prérequis : une clé de test dans VIZALIA_API_KEY (vz_test_…)."""import osimport uuid
import requests
API = os.environ.get("VIZALIA_API_BASE", "https://api.vizalia.ai/v1")CLE = os.environ["VIZALIA_API_KEY"]
session_http = requests.Session()session_http.headers["Authorization"] = f"Bearer {CLE}"
def vizalia(methode, chemin, corps=None, entetes=None): reponse = session_http.request(methode, API + chemin, json=corps, headers=entetes, timeout=30) contenu = reponse.json() if not reponse.ok: # Erreur RFC 9457 : `code` est stable, `request_id` va au support raise RuntimeError(f"{reponse.status_code} {contenu['code']} : {contenu.get('detail')} ({contenu['request_id']})") return contenu
# 1. La clé : espace, portées, modecle = vizalia("GET", "/me")print("Mode test :", cle["livemode"] is False, "· portées :", ", ".join(cle["scopes"]))
# 2. Une session sans envoi (channel link) : la réponse donne join_urlsession = vizalia( "POST", "/sessions", {"channel": "link", "reference": "TEST-1"}, {"Idempotency-Key": str(uuid.uuid4())},)# session["join_url"], le lien du client, donne accès à la session : ouvrez-le sur un# téléphone pour voir sa page, mais ne l'écrivez dans aucun journal.print("Session :", session["id"])
# 3. Le client simulé ouvre le lien, la vidéo passe, une photo est prise, l'appel se terminefor action in ["open", "go_live", "take_photo", "end"]: etat = vizalia("POST", f"/sessions/{session['id']}/simulate", {"action": action}) print(f"{action} → {etat['status']}")
# 4. Les événements envoyés pour cette sessionevenements = vizalia("GET", f"/events?session_id={session['id']}")print("Événements :", ", ".join(e["type"] for e in evenements["data"]))Avant la production
Section intitulée « Avant la production »Passez à une clé de production vz_<préfixe>_… : rien d’autre ne change. Vérifiez avant :
- la clé de production est dans un gestionnaire de secrets, et n’apparaît ni dans le code, ni dans les journaux, ni dans une URL (Authentification) ;
- chaque webhook est vérifié sur son corps brut, et un doublon est ignoré grâce à
webhook-id; - chaque
POSTporte uneIdempotency-Key, réutilisée seulement pour rejouer la même requête (Idempotence) ; - votre code teste le
codedes erreurs, et attendRetry-Aftersecondes sur un429(Erreurs, Limites) ; - votre code ignore les champs et les événements qu’il ne connaît pas (Compatibilité).
