Oui, une seule clé et une seule URL de base suffisent pour le texte, l'image, la voix, la transcription, les embeddings, la vidéo et les décisions Jev. Tu changes le chemin de l'endpoint et le champ model, rien d'autre.
Pour le vérifier, j'ai fait un vrai test : un appel de chat, une image en qualité minimale, un clip de voix, des embeddings, une transcription de ce clip et une décision Jev. Tout est passé par la même clé, pour 26,549 crédits au total, soit environ 9 F. La vidéo, je ne l'ai pas générée : je te donne le flux et le prix par seconde.
En bref
- Tchavi, une passerelle d'API IA compatible OpenAI que tu paies en mobile money, sert six types d'appels avec une seule clé : chat, image, audio (voix et transcription), embeddings, vidéo et décisions Jev. Base URL :
https://tchavi.com/api/v1. - Ce qui change d'un type à l'autre : le chemin (
/chat/completions,/images/generations,/audio/speech…) et le modèle. L'en-têteAuthorizationreste le même. - La vidéo est asynchrone : tu envoies une demande, tu reçois un identifiant de tâche, puis tu interroges
/v1/jobs/:idjusqu'à ce que la vidéo soit prête. - Mesuré en octobre 2026, à travers Tchavi : 26,549 crédits pour les six appels, soit environ 9 F à 3 crédits pour 1 F.
- Tchavi n'est pas moins cher qu'un appel direct à chaque fournisseur : tu y gagnes une clé, un solde et un journal, et le paiement en mobile money.
Le principe : un en-tête, six chemins
Tous les appels ci-dessous partent de ce petit assistant Node (version 20 ou plus). Il lit la clé dans une variable d'environnement et lit l'en-tête x-credits-used de chaque réponse.
const BASE = 'https://tchavi.com/api/v1';
const headers = { Authorization: `Bearer ${process.env.TCHAVI_API_KEY}` };
async function post(path, body) {
const res = await fetch(`${BASE}${path}`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
console.log(path, res.status, 'crédits :', res.headers.get('x-credits-used'));
return res;
}
La doc des principes explique le reste : le format est celui d'OpenAI, et chaque réponse porte X-Credits-Used, X-Credits-Remaining et X-Request-Id.
Ce sont les tarifs publics ; certains modèles bénéficient en ce moment d'une remise, et la page de chaque modèle affiche le prix facturé du moment.
Texte : le chat
Endpoint : POST /v1/chat/completions (doc). Modèle du test : GPT-5 Mini, à 0,55 crédit par 1 000 tokens d'entrée et 4,4 par 1 000 tokens de sortie.
const res = await post('/chat/completions', {
model: 'gpt-5-mini',
messages: [
{
role: 'user',
content: "Explique en deux phrases ce qu'est une boutique en ligne à Cotonou.",
},
],
max_completion_tokens: 400,
});
const data = await res.json();
console.log(data.choices[0].message.content);
Mesuré : 23 tokens en entrée, 59 en sortie, 0,273 crédit. Le calcul se vérifie : 23 × 0,55 / 1 000 + 59 × 4,4 / 1 000 = 0,27225, arrondi une fois au millième supérieur.
Image : la qualité la plus basse
Endpoint : POST /v1/images/generations (doc). Modèle du test : GPT Image 1 Mini, à 11 crédits l'image en qualité low.
import { writeFileSync } from 'node:fs';
const res = await post('/images/generations', {
model: 'gpt-image-1-mini',
prompt: 'Un étal de mangues sur un marché de Cotonou, lumière du matin',
size: '1024x1024',
quality: 'low',
});
const data = await res.json();
writeFileSync('mangues.png', Buffer.from(data.data[0].b64_json, 'base64'));
Mesuré : 11 crédits, soit le tarif de la qualité low. Si tu omets quality, c'est la qualité high qui est facturée : 77 crédits sur ce modèle. Pour un test, pense à la préciser.
Voix : de la synthèse à la transcription
Deux endpoints dans la doc audio. La synthèse vocale facture par tranche de 1 000 caractères ; la transcription facture à la minute entamée.
Synthèse : POST /v1/audio/speech, avec TTS Standard (tts-1) à 32 crédits par 1 000 caractères. La réponse est le fichier audio brut.
const text = 'Bonjour, votre commande est prête. Le livreur arrive dans dix minutes.';
const res = await post('/audio/speech', { model: 'tts-1', input: text, voice: 'nova' });
const mp3 = Buffer.from(await res.arrayBuffer());
writeFileSync('commande.mp3', mp3);
Mesuré : 70 caractères, 2,24 crédits (70 × 32 / 1 000), un mp3 d'environ 69 Ko.
Transcription : POST /v1/audio/transcriptions, en multipart/form-data, avec Whisper à 13 crédits par minute entamée.
const form = new FormData();
form.append('model', 'whisper-1');
form.append('language', 'fr');
form.append('file', new Blob([mp3], { type: 'audio/mpeg' }), 'commande.mp3');
const res = await fetch(`${BASE}/audio/transcriptions`, {
method: 'POST',
headers, // pas de Content-Type : fetch ajoute la frontière multipart
body: form,
});
console.log((await res.json()).text, res.headers.get('x-credits-used'));
Mesuré sur le clip que je venais de générer : 13 crédits pour une durée mesurée de 0,07 minute. Un clip de quatre secondes est donc facturé comme une minute pleine. La transcription était juste, avec un détail : elle se terminait par « et… », absent du texte d'origine. Relis toujours la fin d'une transcription automatique.
Embeddings : les vecteurs
Endpoint : POST /v1/embeddings (doc). Modèle : Embedding Small, à 0,044 crédit par 1 000 tokens.
const res = await post('/embeddings', {
model: 'text-embedding-3-small',
input: 'Livraison à Cotonou',
});
const data = await res.json();
console.log(data.data[0].embedding.length); // 1536
Mesuré : 6 tokens, 1 536 dimensions, 0,001 crédit. Le calcul brut donne 0,000264, mais le total est arrondi au millième de crédit supérieur, donc 0,001. Pour un petit appel, ce plancher compte : pour vectoriser un catalogue, ce sont les gros volumes qui comptent.
Décisions Jev : des réponses typées
Endpoint : POST /v1/decisions (doc). Au lieu de demander du JSON à un modèle de chat, tu déclares des questions et tu reçois des réponses typées avec leurs probabilités. Modèle : Jev 1.13, à 0,09 crédit par 1 000 tokens d'entrée.
const res = await post('/decisions', {
model: 'jev-1.13',
state: "Le client écrit : « Ma clé API ne marche plus depuis que je l'ai renouvelée. »",
questions: {
team: {
type: 'choice',
instructions: 'Quelle équipe doit traiter cela ?',
criteria: { billing: 'paiements ou crédits', technical: 'API, clés' },
},
urgency: {
type: 'score',
instructions: "Quel est le niveau d'urgence ?",
criteria: ['pas urgent', 'normal', 'urgent', 'critique'],
},
},
});
console.log((await res.json()).answers);
Mesuré : l'équipe technical avec une probabilité de 1, et une urgence à 1,6 sur l'échelle 0 à 3 (confiance 0,6), pour 0,035 crédit. Les modèles de décision ne fonctionnent que sur cet endpoint : envoyer jev-1.13 à /v1/chat/completions renvoie une erreur 400.
Vidéo : soumettre, puis interroger
La génération de vidéo est asynchrone, parce qu'un rendu prend du temps. Deux endpoints : POST /v1/videos/generations (doc) et GET /v1/jobs/:id (doc des tâches).
Le flux :
- Tu envoies la demande. La réponse arrive tout de suite avec un
202et unidde tâche. - Tu interroges
GET /v1/jobs/:id. L'état passe dependingàprocessing, puis àcompletedoufailed. - À
completed, la réponse contientoutput.video_url. La vidéo est supprimée 24 heures après sa génération : télécharge-la. - À
failed, les crédits débités sont remboursés automatiquement.
const submit = await post('/videos/generations', {
model: 'veo-3.1-lite',
prompt: 'Un livreur à moto traverse un marché de Cotonou au lever du jour',
duration: 4,
resolution: '720p',
generate_audio: false,
});
const job = await submit.json();
let task;
do {
await new Promise((r) => setTimeout(r, 5000));
task = await (await fetch(`${BASE}/jobs/${job.id}`, { headers })).json();
} while (task.status === 'pending' || task.status === 'processing');
console.log(task.status, task.output?.video_url);
Je n'ai pas généré de vidéo pour cet article. Le tarif est par seconde de sortie. Pour Veo 3.1 Lite, il est de 66 crédits par seconde en 720p sans audio, et 110 avec audio : une vidéo de 4 secondes sans audio revient donc à 264 crédits, soit 88 F. Les durées acceptées vont de 4 à 8 secondes.
Le total, appel par appel
| Appel | Modèle | Crédits mesurés |
|---|---|---|
| Chat (23 tokens in, 59 out) | gpt-5-mini | 0,273 |
Image (1024×1024, low) | gpt-image-1-mini | 11 |
| Voix (70 caractères) | tts-1 | 2,24 |
| Embeddings (6 tokens) | text-embedding-3-small | 0,001 |
| Transcription (clip de 4 s) | whisper-1 | 13 |
| Décision Jev (2 questions) | jev-1.13 | 0,035 |
| Total | 26,549 |
À 3 crédits pour 1 F, cela fait environ 8,85 F pour six appels de six natures différentes. Les deux appels les plus chers, l'image et la transcription, sont aussi ceux dont le tarif est un forfait par unité : une image, une minute. Mesuré en octobre 2026, à travers Tchavi, sur une instance de test aux tarifs publics.
Ce que ça change, et ce que ça ne change pas
Ce que tu y gagnes : une clé à protéger, un solde à surveiller, un journal où tout apparaît, et un seul format de réponse d'erreur. Pour une boutique qui envoie une confirmation vocale, une miniature de produit et une réponse WhatsApp, c'est un seul compte à recharger en mobile money.
Ce que tu n'y gagnes pas : un prix de token inférieur à celui des fournisseurs, ni une API identique pour tous les modèles. Chaque modèle garde ses paramètres : un paramètre qu'il n'accepte pas renvoie une erreur 400 qui le nomme. Pour une comparaison générale, lis Passerelle d'API IA : à quoi ça sert, et quand en avoir besoin.
FAQ
Une seule clé suffit-elle pour le texte, l'image, la voix et la vidéo ?
Oui. Tu envoies la même clé dans l'en-tête Authorization pour tous les endpoints. Seuls le chemin et le champ model changent.
Comment fonctionne la génération de vidéo par API ?
Elle est asynchrone. Tu soumets la demande, tu reçois un identifiant de tâche, puis tu interroges GET /v1/jobs/:id jusqu'à completed ou failed. La vidéo est supprimée 24 heures après sa génération.
Combien coûte un appel d'image, de voix ou de transcription ?
Cela dépend du modèle. En octobre 2026, une image en qualité basse a coûté 11 crédits, 70 caractères de voix 2,24 crédits et une transcription 13 crédits. La page de chaque modèle donne le prix du moment.
Dois-je changer de SDK pour passer du texte à l'image ?
Non, si tu utilises un SDK compatible OpenAI avec la base https://tchavi.com/api/v1. Les exemples de cet article utilisent simplement fetch.
Que se passe-t-il si une vidéo échoue ?
Les crédits débités sont remboursés automatiquement, et la tâche indique failed avec un code d'erreur.
Peut-on utiliser les embeddings avec les mêmes crédits ?
Oui. Tous les appels débitent le même solde de crédits, et chaque réponse indique son coût dans X-Credits-Used.
Crée ton compte et recharge 1 000 F
Cet article fait partie de la série « Construire un SaaS IA depuis l'Afrique francophone ». Tchavi est une passerelle d'API IA compatible OpenAI : une seule clé donne accès à plus de 100 modèles de texte, d'image, d'audio et de vidéo, et tu la paies en mobile money, sans carte bancaire (pays et opérateurs). Plus de guides sur le blog. Pour suivre les prochains : LinkedIn et X.