Documentation API
L’API Techtuel convertit un fichier audio ou vidéo en texte. Deux appels suffisent : vous soumettez une URL, puis vous récupérez la transcription. Tout est en JSON, sur HTTPS, avec une authentification par clé.
- URL de base
- https://api.techtuel.com/v1
- Format
- JSON · UTF-8
- Authentification
- Clé API (Bearer)
Authentification
Chaque requête doit inclure votre clé API dans l’en-tête Authorization. Les clés sont préfixées par txl_. Gardez-les secrètes : une clé donne accès à votre quota.
Authorization: Bearer txl_your_secret_keyDémarrage rapide
Un seul appel. Envoyez une source — URL publique (YouTube, podcast, MP3) ou fichier téléversé via POST /uploads — et récupérez la transcription dans la même réponse. Pas d’identifiant de job, pas de boucle d’attente.
curl -X POST https://api.techtuel.com/v1/transcribe \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "source_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }'
{ "status": "completed", "transcript": "..." }Un long audio ne tient pas dans une requête HTTP. Si la transcription tourne encore au bout de 30 secondes (ajustable via ?wait=, jusqu’à 120), vous recevez un 202 et un id de job à la place — le job continue, et GET /transcriptions/{id} le récupère une fois terminé. Ajoutez-y ?format=srt pour télécharger les sous-titres. Chaque endpoint est détaillé ci-dessous.
Référence API
Tous les endpoints publics, générés depuis le schéma de l'API — ils correspondent donc toujours à ce que le service expose réellement.
Transcriptions
Soumettre un audio à transcrire et récupérer le résultat.
Transcribe and wait for the result
Submit a source and receive the finished transcript in the SAME response — no job id, no polling loop. Returns **200** with `transcript` (and `segments`) once the transcription completes, which is immediate when the source is already in the shared cache. Long audio does not fit in one HTTP request. When the transcription is still running after the wait window (default 30s, `?wait=` up to 120s), the response is **202** with the job `id` and `status: "processing"` — the job keeps running, and GET /transcriptions/{id} retrieves it exactly as with the asynchronous API. Treat 202 as "not finished yet", never as a failure. A job that fails within the window returns **200** with `status: "failed"` and `error` set: the request succeeded, the transcription did not.
Paramètres de requête
| Champ | Type | Description |
|---|---|---|
| wait | integer | Seconds to wait before falling back to 202 (default 30, max 120) |
Corps de la requête
| Champ | Type | Description |
|---|---|---|
| audio_url | string | |
| preferred_language | string | PreferredLanguage is the ISO 639-1 code the caller wants the transcript in. Omit it to get the language actually spoken in the audio. It is a PREFERENCE, not a guarantee: when the transcript cannot be translated the original is returned rather than an error, and the response's `language` field always states what was really produced. |
| source_url | string | |
| upload_id | string |
curl -X POST https://api.techtuel.com/v1/transcribe \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://example.com/episode.mp3",
"preferred_language": "fr",
"source_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"upload_id": "up_abc123"
}'{
"api_key_id": "key_abc123",
"created_at": "2026-07-21T09:30:00Z",
"detected_language": "it",
"error": "string",
"id": "job_abc123",
"language": "fr",
"minutes": 12.5,
"segments": [
{
"start_seconds": 12.5,
"text": "Bonjour et bienvenue dans cet"
}
],
"source_kind": "url",
"source_url": "https://youtu.be/dQw4w9WgXcQ",
"status": "processing",
"title": "Le 6-9 de France Inter",
"transcript": "string",
"translated": true
}- 400
- Bad Request
- 401
- Unauthorized
- 402
- Refused: `reason` says which — `quota_exceeded` or `payment_failed`
Transcribe a local file in one call
Send the audio/video file itself and receive the finished transcript in the SAME response — no upload slot, no polling loop. This is the one-call form of the three-step upload flow (POST /uploads → PUT → POST /transcribe). Send `multipart/form-data` with the bytes in a `file` part; `Content-Type` of that part decides the accepted format. Limited to 100 MiB per request, well below what POST /uploads accepts (200 MiB audio, 1 GiB video): here the bytes travel through the API, whereas a presigned upload goes straight to storage. A larger file gets **413** naming the presigned flow — use it, it is not a downgrade but the shape that works for big files. Wait semantics are identical to POST /transcribe: **200** once the transcription completes, **202** with the job `id` when it is still running after the wait window (default 30s, `?wait=` up to 120s). Upload time counts against that window, so a large file is likelier to answer 202 — the job keeps running and GET /transcriptions/{id} retrieves it.
Paramètres de requête
| Champ | Type | Description |
|---|---|---|
| wait | integer | Seconds to wait before falling back to 202 (default 30, max 120) |
curl -X POST https://api.techtuel.com/v1/transcribe/file \
-H "Authorization: Bearer txl_your_api_key" \
-F file=@/path/to/episode.mp3 \
-F preferred_language=fr{
"api_key_id": "key_abc123",
"created_at": "2026-07-21T09:30:00Z",
"detected_language": "it",
"error": "string",
"id": "job_abc123",
"language": "fr",
"minutes": 12.5,
"segments": [
{
"start_seconds": 12.5,
"text": "Bonjour et bienvenue dans cet"
}
],
"source_kind": "url",
"source_url": "https://youtu.be/dQw4w9WgXcQ",
"status": "processing",
"title": "Le 6-9 de France Inter",
"transcript": "string",
"translated": true
}- 400
- Missing file part or unsupported format
- 401
- Unauthorized
- 402
- Refused: `reason` says which — `quota_exceeded` or `payment_failed`
- 413
- File exceeds the inline limit — use POST /uploads
- 503
- Uploads not configured
Lister les transcriptions
Retourne les jobs de transcription du compte authentifié, du plus récent au plus ancien, page par page. Utilisez ?page= (à partir de 1) et ?per_page= (20 par défaut, 100 au maximum) ; la réponse porte `total` et `has_more` pour permettre à un client d'enchaîner la page suivante. Les lignes n'incluent PAS le transcript complet — seulement `preview_segments`.
Paramètres de requête
| Champ | Type | Description |
|---|---|---|
| api_key_id | string | Restrict to jobs submitted by this API key id |
| page | integer | 1-based page number |
| per_page | integer | Jobs per page (1-100) |
curl -X GET https://api.techtuel.com/v1/transcriptions \
-H "Authorization: Bearer txl_your_api_key"{
"has_more": true,
"jobs": [
{
"api_key_id": "key_abc123",
"created_at": "2026-07-21T09:30:00Z",
"error": "string",
"has_transcript": true,
"id": "job_abc123",
"minutes": 12.5,
"preview_segments": [],
"source_kind": "url",
"source_url": "https://youtu.be/dQw4w9WgXcQ",
"status": "processing",
"title": "Le 6-9 de France Inter"
}
],
"page": 1,
"per_page": 10,
"total": 47
}- 401
- Unauthorized
Créer une transcription
Soumet un audio à transcrire. Répond immédiatement avec un job en cours de traitement ; interrogez ensuite l'endpoint de récupération, ou appuyez-vous sur un webhook pour être notifié du résultat.
source_url pour une URL résolue par le worker (audio/vidéo direct, page de podcast ou YouTube), ou upload_id pour un fichier envoyé via POST /uploads. audio_url est un alias historique de source_url ; préférez source_url dans du code neuf. Si une URL et un upload_id sont envoyés ensemble, upload_id l'emporte.Corps de la requête
| Champ | Type | Description |
|---|---|---|
| audio_urlau choix | string | |
| preferred_language | string | PreferredLanguage is the ISO 639-1 code the caller wants the transcript in. Omit it to get the language actually spoken in the audio. It is a PREFERENCE, not a guarantee: when the transcript cannot be translated the original is returned rather than an error, and the response's `language` field always states what was really produced. |
| source_urlau choix | string | |
| upload_idau choix | string |
Exactement une source est requise
curl -X POST https://api.techtuel.com/v1/transcriptions \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"source_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"preferred_language": "fr"
}'{
"api_key_id": "key_abc123",
"created_at": "2026-07-21T09:30:00Z",
"detected_language": "it",
"error": "string",
"id": "job_abc123",
"language": "fr",
"minutes": 12.5,
"segments": [
{
"start_seconds": 12.5,
"text": "Bonjour et bienvenue dans cet"
}
],
"source_kind": "url",
"source_url": "https://youtu.be/dQw4w9WgXcQ",
"status": "processing",
"title": "Le 6-9 de France Inter",
"transcript": "string",
"translated": true
}- 400
- Bad Request
- 401
- Unauthorized
- 402
- Refused: `reason` says which — `quota_exceeded` (the period's allowance is spent; it refills on renewal) or `payment_failed` (the subscription is unpaid; update the payment method)
Récupérer une transcription
Récupère un job de transcription par son id. La réponse par défaut est l'enveloppe JSON du job (statut + texte assemblé). Passez ?format= pour télécharger le transcript dans un format horodaté une fois le job terminé : `txt` (texte brut), `json` (texte + segments horodatés), `srt` (sous-titres SubRip), `vtt` (sous-titres WebVTT).
Paramètres de chemin
| Champ | Type | Description |
|---|---|---|
| idrequis | string | Job id |
Paramètres de requête
| Champ | Type | Description |
|---|---|---|
| format | string | Output formattxt · json · srt · vtt |
curl -X GET https://api.techtuel.com/v1/transcriptions/job_abc123 \
-H "Authorization: Bearer txl_your_api_key"{
"api_key_id": "key_abc123",
"created_at": "2026-07-21T09:30:00Z",
"detected_language": "it",
"error": "string",
"id": "job_abc123",
"language": "fr",
"minutes": 12.5,
"segments": [
{
"start_seconds": 12.5,
"text": "Bonjour et bienvenue dans cet"
}
],
"source_kind": "url",
"source_url": "https://youtu.be/dQw4w9WgXcQ",
"status": "processing",
"title": "Le 6-9 de France Inter",
"transcript": "string",
"translated": true
}- 401
- Unauthorized
- 404
- Not Found
- 409
- Conflict
- 422
- Unprocessable Entity
Supprimer une transcription
Retire de l'historique de l'appelant une transcription terminée (réussie ou en échec). Le transcript lui-même reste dans le cache de sources partagé : resoumettre la même source plus tard reste servi sans re-transcrire. Un job encore en cours ne peut pas être supprimé — attendez qu'il se termine.
Paramètres de chemin
| Champ | Type | Description |
|---|---|---|
| idrequis | string | Job id |
curl -X DELETE https://api.techtuel.com/v1/transcriptions/job_abc123 \
-H "Authorization: Bearer txl_your_api_key""string"- 404
- Not Found
Relancer une transcription en échec
Remet en file une transcription en échec sur le MÊME job, afin que l'historique conserve une ligne par source au lieu d'en accumuler une par tentative. Seuls les jobs en échec peuvent être relancés, et la relance est soumise au quota mensuel.
Paramètres de chemin
| Champ | Type | Description |
|---|---|---|
| idrequis | string | Job id |
curl -X POST https://api.techtuel.com/v1/transcriptions/job_abc123/retry \
-H "Authorization: Bearer txl_your_api_key"{
"api_key_id": "key_abc123",
"created_at": "2026-07-21T09:30:00Z",
"detected_language": "it",
"error": "string",
"id": "job_abc123",
"language": "fr",
"minutes": 12.5,
"segments": [
{
"start_seconds": 12.5,
"text": "Bonjour et bienvenue dans cet"
}
],
"source_kind": "url",
"source_url": "https://youtu.be/dQw4w9WgXcQ",
"status": "processing",
"title": "Le 6-9 de France Inter",
"transcript": "string",
"translated": true
}- 402
- Refused: `reason` is `quota_exceeded` or `payment_failed`
- 404
- Not Found
Extraction web
Transformer n'importe quelle page web publique en texte propre et structuré : titre, métadonnées et contenu lisible, sans navigation ni publicité.
Extract clean, structured text from a web page
Fetches a public web page, strips navigation/ads/boilerplate, and returns its title, metadata and readable text — both flattened and split into positioned segments. Synchronous: no job id, no polling. Costs 1 credit; a page already in the global cache is free.
Corps de la requête
| Champ | Type | Description |
|---|---|---|
| url | string |
curl -X POST https://api.techtuel.com/v1/v1/extract \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/article"
}'{
"author": "string",
"cached": false,
"charCount": 0,
"creditsCharged": 0,
"description": "string",
"extractedAt": "string",
"imageUrl": "string",
"segments": [
{
"charLength": 0,
"charOffset": 0,
"sectionTitle": "string",
"text": "string"
}
],
"siteName": "string",
"sourceId": "string",
"sourceType": "webpage",
"text": "string",
"title": "string",
"url": "string"
}- 400
- invalid or disallowed url
- 402
- monthly credit allowance exhausted
- 404
- page not found
- 422
- page yielded no readable content (paywall, JS-only app, or no prose)
- 502
- page could not be fetched
- 503
- site is rate limiting us; retry later
Envois de fichiers
Transcrire un fichier local : demander un emplacement, envoyer les octets, puis créer un job depuis l'id retourné.
Créer un emplacement d'envoi de fichier
Retourne une URL PUT présignée. Envoyez le fichier audio/vidéo directement sur `put_url` avec exactement les `size_bytes` déclarés, puis appelez POST /transcriptions avec l'`upload_id` retourné. `content_type` et `size_bytes` sont signés dans l'URL : le stockage rejette un envoi qui ne correspond pas. Les limites de taille dépendent du médium : 25 Mio pour l'audio, 200 Mio pour la vidéo.
PUT sur le put_url retourné avec exactement les content_type et size_bytes déclarés (les deux sont signés dans l'URL — toute divergence est rejetée), puis appelez POST /transcriptions avec l'upload_id retourné.Corps de la requête
| Champ | Type | Description |
|---|---|---|
| content_typerequis | string | |
| size_bytesrequis | integer | |
| filename | string |
curl -X POST https://api.techtuel.com/v1/uploads \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"content_type": "audio/mpeg",
"filename": "episode.mp3",
"size_bytes": 18400000
}'{
"expires_at": "2026-06-04T12:15:00Z",
"put_url": "https://s3.fr-par.scw.cloud/...",
"upload_id": "up_abc123"
}- 400
- Missing/unsupported content_type or size_bytes
- 401
- Unauthorized
- 413
- File exceeds the size limit
- 503
- Uploads not configured
Clés API
Gérer les clés `txl_` qui authentifient chaque appel.
Lister les clés API
Liste les clés API de l'utilisateur authentifié. Le hash du jeton et le secret brut ne sont jamais retournés — uniquement les métadonnées (id, nom, préfixe, 4 derniers caractères, dates).
curl -X GET https://api.techtuel.com/v1/keys \
-H "Authorization: Bearer txl_your_api_key"{
"keys": [
{
"created_at": "2026-06-05T10:00:00Z",
"id": "key_abc123",
"last4": "a1b2",
"last_used_at": "2026-06-05T12:30:00Z",
"name": "production server",
"prefix": "txl_"
}
]
}- 401
- Unauthorized
Créer une clé API
Génère une nouvelle clé API pour l'utilisateur authentifié. Le jeton brut n'est retourné qu'une seule fois, dans le champ `token` — conservez-le immédiatement, il ne pourra plus jamais être récupéré. Accessible uniquement depuis une session web connectée (une clé API ne peut pas en générer une autre).
Corps de la requête
| Champ | Type | Description |
|---|---|---|
| name | string |
curl -X POST https://api.techtuel.com/v1/keys \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "production server"
}'{
"created_at": "2026-06-05T10:00:00Z",
"id": "key_abc123",
"last4": "a1b2",
"last_used_at": "2026-06-05T12:30:00Z",
"name": "production server",
"prefix": "txl_",
"token": "txl_a1b2c3d4e5f6..."
}- 400
- Bad Request
- 401
- Unauthorized
- 403
- Authenticated with an API key, not a session
Révoquer une clé API
Révoque définitivement une des clés API de l'utilisateur authentifié. Idempotent : révoquer une clé inconnue ou déjà révoquée retourne quand même 204. Accessible uniquement depuis une session web connectée.
Paramètres de chemin
| Champ | Type | Description |
|---|---|---|
| idrequis | string | Key id |
curl -X DELETE https://api.techtuel.com/v1/keys/key_abc123 \
-H "Authorization: Bearer txl_your_api_key"- 401
- Unauthorized
- 403
- Authenticated with an API key, not a session
Facturation & usage
Grilles tarifaires, cycle de vie de l'abonnement et quota restant.
Démarrer un paiement (abonnement ou crédits)
Retourne l'URL d'une page de paiement hébergée pour le plan demandé. Redirigez l'utilisateur vers cette URL pour souscrire ou acheter des crédits.
Corps de la requête
| Champ | Type | Description |
|---|---|---|
| string | ||
| name | string | Name is the customer's display name, forwarded to the PSP so the customer record and its invoices are not anonymous. Optional: Lungor ignores it, Mollie uses it when creating the customer. |
| plan | string | |
| success_url | string |
curl -X POST https://api.techtuel.com/v1/billing/checkout \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"email": "dev@example.com",
"name": "Ada Lovelace",
"plan": "pro",
"success_url": "https://app.example.com/billing/return"
}'{
"checkout_url": "string"
}- 400
- Bad Request
- 401
- Unauthorized
- 409
- Already subscribed
- 503
- Billing not configured
Lister les grilles tarifaires
Retourne les plans publics (Free, Pro, Max) avec leurs allocations mensuelles et leur prix, pour la page tarifs et le choix de montée en gamme. Un plan n'est souscriptible que si `purchasable` vaut true. Aucune authentification requise.
curl -X GET https://api.techtuel.com/v1/billing/plans \
-H "Authorization: Bearer txl_your_api_key"{
"plans": [
{
"credits": 2000,
"currency": "EUR",
"name": "pro",
"price_cents": 900,
"purchasable": true,
"rate_per_min": 120
}
]
}Résilier votre abonnement
Interrompt les prélèvements à venir. L'accès continue jusqu'à la fin de la période déjà payée — le mois entamé n'est ni remboursé, ni révoqué. Idempotent : résilier sans abonnement actif réussit quand même.
curl -X DELETE https://api.techtuel.com/v1/billing/subscription \
-H "Authorization: Bearer txl_your_api_key"{
"access_until": "2026-08-24T09:00:00Z",
"active": true,
"status": "canceled"
}- 401
- Unauthorized
- 502
- Payment provider refused the cancellation
- 503
- Billing not configured
Move your subscription to another tier
Changes the tier of an active subscription. The new allowance applies immediately; the new price applies from the next renewal — the month already paid is neither re-charged nor refunded. Refused when the subscription is unpaid or cancelled.
Corps de la requête
| Champ | Type | Description |
|---|---|---|
| plan | string | Plan is the tier to move to, by name. |
curl -X POST https://api.techtuel.com/v1/billing/upgrade \
-H "Authorization: Bearer txl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"plan": "max"
}'{
"allowance_from": "now",
"charged_from": "2026-08-24T09:00:00Z",
"plan": "max"
}- 400
- Unknown or unsellable plan, or nothing to upgrade
- 401
- Unauthorized
- 409
- Subscription cannot be upgraded (unpaid or cancelled)
- 503
- Billing not configured
Consulter l'usage et le quota
Retourne le statut d'abonnement de l'appelant et sa consommation de transcription sur le mois en cours.
curl -X GET https://api.techtuel.com/v1/usage \
-H "Authorization: Bearer txl_your_api_key"{
"access_ends_at": "2026-08-03T00:00:00Z",
"active": true,
"billing_state": "healthy",
"credits_limit": 2000,
"credits_used": 84,
"plan": "pro",
"rate_per_min": 120,
"renews_at": "2026-08-18T00:00:00Z",
"status": "active"
}- 401
- Unauthorized
- 503
- Billing not configured
Compte
Opérations au niveau du compte.
Supprimer votre compte
Résilie l'abonnement de l'appelant auprès du prestataire de paiement et purge ses données transcript-api (clés API, jobs, usage). Irréversible.
curl -X DELETE https://api.techtuel.com/v1/account \
-H "Authorization: Bearer txl_your_api_key"- 401
- Unauthorized
- 500
- Internal Server Error
- 502
- Subscription cancellation failed; nothing was deleted
Erreurs
Toutes les erreurs renvoient le même format, avec un message lisible. Aucune surprise : le code HTTP et le message disent exactement ce qui s’est passé.
{ "message": "source_url or upload_id required" }| Code | Signification |
|---|---|
| 400 | Requête invalide. Ni source_url ni upload_id fourni, ou URL mal formée, non http(s), ou pointant vers une adresse interdite. |
| 401 | Non authentifié. Clé API absente, mal formée ou révoquée. |
| 402 | Crédits insuffisants. Solde épuisé ou quota mensuel dépassé. Consultez GET /usage. |
| 403 | Interdit. Opération réservée à une session connectée : la création et la révocation de clés API ne sont pas accessibles via une clé API. |
| 404 | Introuvable. Aucun job ne correspond à cet identifiant. |
| 409 | Job non terminé. Un format horodaté a été demandé sur une transcription qui n’est pas encore completed. |
| 422 | Format indisponible. Aucun segment horodaté n’existe pour ce transcript : srt et vtt sont impossibles, utilisez txt ou json. |
| 429 | Trop de requêtes. Limite de débit par clé dépassée — le plafond dépend de votre offre (voir Limites). L’en-tête Retry-After indique le délai d’attente. |
| 500 | Erreur interne. Incident côté serveur. La requête peut être rejouée. |
| 503 | Service indisponible. Une dépendance est momentanément inaccessible (facturation, stockage). Réessayez avec un backoff. |
Limites
Dépasser l’une de ces limites ne renvoie pas toujours une erreur HTTP : une source trop longue est acceptée puis le job termine en failed, avec la raison dans le champ error et les crédits réservés intégralement remboursés.
| Durée maximale par transcription | 120 minutes |
| Quota mensuel (crédits) | Gratuit 100 · Pro 2 000 · Max 10 000 |
| Coût en crédits | 2 / minute d’audio · 1 par vidéo sous-titrée |
| Débit par clé API | Gratuit 12 req/min · Pro et Max 120 req/min |
| Taille maximale d’un fichier audio téléversé | 200 Mio — soit les 2 h complètes jusqu’à 232 kbit/s |
| Taille maximale d’une vidéo téléversée | 1 Gio — environ 30 min en 1080p (4 Mbit/s) |
| Vidéo plus longue que 30 min | Par URL — seule la durée maximale s’applique |
| Validité d’une URL de téléversement | 30 minutes |
| Conservation d’un fichier téléversé | 7 jours |
| Jobs renvoyés par GET /transcriptions | 100 max |
| Formats audio téléversables | mp3 m4a wav ogg opus aac flac webm |
| Formats vidéo téléversables | mp4 mpeg webm mov mkv |
| Sources non supportées | flux en direct |