Référence de l’API
Chaque appel ci-dessous a un exemple de requête et de réponse, suivis des états de tâche, des codes d’erreur, des limites et des durées de conservation. Vous débutez ? Commencez par le guide du développeur.
Vue d’ensemble
- URL de base :
https://api.video-to-notes.com. Chaque chemin commence par/api/v1. - Les requêtes et les réponses sont en JSON sur HTTPS. Envoyez
Content-Type: application/jsonavec chaque corps de requête. - Les dates sont des horodatages Unix en secondes (UTC). Les positions dans un enregistrement sont des secondes depuis le début du fichier.
- Les ID et les curseurs sont des chaînes opaques. Conservez-les exactement tels que vous les recevez.
- Chaque réponse d’erreur contient un
request_id. Indiquez-le lorsque vous contactez le support. - Les réponses sont envoyées avec
Cache-Control: no-store; ne les placez pas dans des caches partagés. - Le contrat lisible par machine se trouve dans openapi.json (OpenAPI 3.1) et paid-api.schema.json (JSON Schema).
Authentification
Envoyez votre clé API comme jeton Bearer avec chaque requête API. Les clés commencent par vtn_prod_. Vous créez et révoquez les clés en étant connecté sur le site ; une clé API ne peut gérer ni les clés, ni la facturation, ni le compte.
Authorization: Bearer vtn_prod_...Une clé absente, mal formée, expirée ou révoquée renvoie 401 UNAUTHORIZED. N’envoyez jamais la clé aux URL de stockage signées : elles portent leur propre autorisation. Les exemples curl de cette page utilisent cette petite fonction, qui transmet la clé à curl par l’entrée standard :
# Sends the key through stdin, so it never appears in the process list.
vtn() {
printf 'header = "Authorization: Bearer %s"\n' "$VTN_API_KEY" |
curl -s --config - "$@"
}Compte
GET /api/v1/account
Renvoie la formule, les secondes restantes de la formule, la fin de l’allocation en cours ainsi que les fonctions et limites qui s’appliquent au compte en ce moment. Lisez-le avant d’envoyer un fichier : si eligible ou capabilities.api_admission_enabled vaut false, les nouvelles tâches sont refusées.
vtn "$VTN_API_BASE/api/v1/account"{
"plan": "basic",
"eligible": true,
"remaining_seconds": 64800,
"allowance_expires_at": 1792886400,
"capabilities": {
"api_admission_enabled": true,
"key_creation_enabled": true,
"server_upload_enabled": true,
"long_jobs": true,
"formats": [
"mp4", "m4v", "mov", "webm", "mkv", "ogv", "avi", "wmv", "asf",
"flv", "mpg", "mpeg", "vob", "ts", "mts", "m2ts", "3gp", "3g2",
"mxf", "mp3", "m4a", "aac", "wav", "flac", "ogg", "oga", "opus",
"wma", "amr", "aiff", "aif", "caf", "ac3"
],
"audio_languages": [
"auto", "af", "am", "ar", "hy", "az", "be", "bn", "bs", "bg", "my",
"ca", "zh", "hr", "cs", "da", "nl", "en", "et", "tl", "fi", "fr",
"gl", "ka", "de", "el", "gu", "ha", "he", "hi", "hu", "is", "id",
"it", "ja", "kn", "kk", "km", "ko", "lv", "lt", "mk", "ms", "ml",
"mt", "mr", "mn", "ne", "no", "fa", "pl", "pt", "pa", "ro", "ru",
"sr", "sk", "sl", "es", "sw", "sv", "ta", "te", "th", "tr", "uk",
"uz", "vi"
],
"notes_languages": [
"auto", "af", "am", "ar", "hy", "az", "be", "bn", "bs", "bg", "my",
"ca", "zh", "hr", "cs", "da", "nl", "en", "et", "tl", "fi", "fr",
"gl", "ka", "de", "el", "gu", "ha", "he", "hi", "hu", "is", "id",
"it", "ja", "kn", "kk", "km", "ko", "lv", "lt", "mk", "ms", "ml",
"mt", "mr", "mn", "ne", "no", "fa", "pl", "pt", "pa", "ro", "ru",
"sr", "sk", "sl", "es", "sw", "sv", "ta", "te", "th", "tr", "uk",
"uz", "vi"
],
"download_formats": ["transcript_txt", "notes_md", "notes_html", "notes_pdf"],
"email_opt_in": false,
"limits": {
"max_upload_bytes": 8589934592,
"max_selection_seconds": null,
"active_jobs": 1,
"active_uploads": 1,
"daily_uploads": 10,
"daily_upload_bytes": 21474836480,
"new_requests_per_minute": 12,
"read_requests_per_minute": 60,
"poll_after_seconds": 5,
"result_page_bytes": 1000000,
"result_page_items": 32,
"upload_url_seconds": 900,
"download_url_seconds": 600,
"result_retention_seconds": 86400,
"recovery_retention_seconds": 172800,
"idempotency_retention_seconds": 34560000
}
}
}Envois
Les fichiers sont envoyés en plusieurs parties directement dans le stockage via des URL signées. Un compte peut avoir un seul envoi actif à la fois.
POST /api/v1/uploads
Démarre un envoi. Transmettez la taille exacte du fichier en octets et son extension. La réponse indique part_size et part_count : découpez le fichier en parties de part_size octets ; la dernière peut être plus petite.
vtn -X POST "$VTN_API_BASE/api/v1/uploads" \
-H "Content-Type: application/json" \
-d '{
"byte_size": 1048576,
"extension": "mp4"
}'{
"upload_id": "upload-1",
"state": "created",
"expires_at": 1792807200,
"part_size": 16777216,
"part_count": 1,
"error": null
}POST /api/v1/uploads/{upload_id}/parts
Renvoie des URL d’envoi signées pour 1 à 100 numéros de partie. Chaque URL est valable jusqu’à 15 minutes ; demandez-en une nouvelle quand elle expire ou quand une partie doit être renvoyée.
vtn -X POST "$VTN_API_BASE/api/v1/uploads/upload-1/parts" \
-H "Content-Type: application/json" \
-d '{
"part_numbers": [1]
}'{
"upload_id": "upload-1",
"targets": [
{
"part_number": 1,
"url": "https://example.invalid/signed",
"expires_at": 1792800900
}
]
}PUT {signed part URL}
Envoyez chaque partie sous forme d’octets bruts dans un HTTP PUT vers son URL signée, sans en-tête Authorization. Conservez l’en-tête de réponse ETag exactement tel qu’il est renvoyé, guillemets compris. Chaque URL n’accepte que la taille exacte de sa partie : part_size pour chaque partie sauf la dernière, qui contient les octets restants. Un corps d’une autre longueur est refusé avec HTTP 403.
# PART_URL comes from the parts response; send no Authorization header.
curl -s --upload-file part-0001.bin --dump-header - --output /dev/null \
"$PART_URL" | grep -i '^etag:'POST /api/v1/uploads/{upload_id}/complete
Termine l’envoi. Transmettez chaque numéro de partie avec son ETag. Terminer un envoi ne lance pas le traitement ; créez ensuite une tâche.
vtn -X POST "$VTN_API_BASE/api/v1/uploads/upload-1/complete" \
-H "Content-Type: application/json" \
-d '{
"parts": [
{
"part_number": 1,
"etag": "opaque-etag"
}
]
}'{
"upload_id": "upload-1",
"state": "uploaded",
"expires_at": 1792807200,
"part_size": 16777216,
"part_count": 1,
"error": null
}GET /api/v1/uploads/{upload_id}
Renvoie l’état d’un envoi : created, uploading, uploaded, probing, probed, failed, aborted ou expired.
vtn "$VTN_API_BASE/api/v1/uploads/upload-1"{
"upload_id": "upload-1",
"state": "uploaded",
"expires_at": 1792807200,
"part_size": 16777216,
"part_count": 1,
"error": null
}POST /api/v1/uploads/{upload_id}/abort
Annule un envoi que vous n’utiliserez pas et libère l’emplacement d’envoi du compte. Un nouvel appel est sans risque.
vtn -X POST "$VTN_API_BASE/api/v1/uploads/upload-1/abort" \
-H "Content-Type: application/json" \
-d '{}'Tâches
Une tâche transforme un fichier envoyé en transcription et en notes. Un compte peut exécuter une seule tâche à la fois.
POST /api/v1/jobs
Lance le traitement d’un fichier envoyé. L’en-tête Idempotency-Key est obligatoire : 1 à 128 caractères ASCII imprimables sans espace, nouveau pour chaque tâche. Les champs facultatifs sont range (start_seconds et end_seconds, tous deux requis s’il est présent), audio_language et notes_language. Renvoie 202 avec la tâche à l’état preparing. La même clé avec le même corps renvoie la même tâche ; la même clé avec un autre corps renvoie 409.
vtn -X POST "$VTN_API_BASE/api/v1/jobs" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{
"upload_id": "upload-1",
"range": {
"start_seconds": 5,
"end_seconds": 60
},
"audio_language": null,
"notes_language": "en"
}'{
"job_id": "job-1",
"state": "preparing",
"stage": "probe",
"created_at": 1792800000,
"expires_at": 1792807200,
"result_expires_at": null,
"idempotency_expires_at": 1827360000,
"poll_after_seconds": 5,
"status_url": "/api/v1/jobs/job-1",
"result_url": "/api/v1/jobs/job-1/result",
"completed_units": 0,
"total_units": null,
"charged_seconds": 0,
"result_available": false,
"can_resume": false,
"warnings": [],
"error": null
}GET /api/v1/jobs/{job_id}
Renvoie l’état, l’étape en cours, la progression (completed_units sur total_units), charged_seconds, les avertissements et l’éventuelle erreur. Une tâche en échec renvoie quand même 200 ; lisez son error.
vtn "$VTN_API_BASE/api/v1/jobs/job-1"{
"job_id": "job-1",
"state": "completed",
"stage": "terminal",
"created_at": 1792800000,
"expires_at": 1792807200,
"result_expires_at": 1792886400,
"idempotency_expires_at": 1827360000,
"poll_after_seconds": 5,
"status_url": "/api/v1/jobs/job-1",
"result_url": "/api/v1/jobs/job-1/result",
"completed_units": 8,
"total_units": 8,
"charged_seconds": 1140,
"result_available": true,
"can_resume": false,
"warnings": [],
"error": null
}POST /api/v1/jobs/{job_id}/cancel
Arrête une tâche. Les parties terminées restent disponibles et le temps réservé non utilisé est restitué. Un nouvel appel est sans risque.
vtn -X POST "$VTN_API_BASE/api/v1/jobs/job-1/cancel" \
-H "Content-Type: application/json" \
-d '{}'POST /api/v1/jobs/{job_id}/resume
Reprend une tâche interrompue lorsque son état indique can_resume: true. Cela exige une formule active et revérifie votre temps restant. Les parties déjà traitées ne sont pas facturées à nouveau.
vtn -X POST "$VTN_API_BASE/api/v1/jobs/job-1/resume" \
-H "Content-Type: application/json" \
-d '{}'Résultats
GET /api/v1/jobs/{job_id}/result
Renvoie une page de résultats d’au plus 32 éléments et 1 Mo. Les éléments sont ordonnés et ont un kind : transcript (texte avec segments horodatés), notes (Markdown), gap (audio qui n’a pas pu être traité) ou warning. Passez next_cursor dans le paramètre de requête cursor pour obtenir la page suivante, jusqu’à ce qu’il soit null. Chaque page peut lister jusqu’à quatre liens de téléchargement dans artifacts, valables jusqu’à 10 minutes. Si la tâche est reprise pendant votre lecture, l’API renvoie 409 JOB_CONFLICT ; recommencez à la première page.
vtn --get "$VTN_API_BASE/api/v1/jobs/job-1/result" \
--data-urlencode "cursor=$NEXT_CURSOR" # omit for the first page{
"job_id": "job-1",
"snapshot": "generation-1",
"items": [
{
"index": 0,
"kind": "transcript",
"text": "Welcome to the weekly planning meeting.",
"segments": [
{
"text": "Welcome to the weekly planning meeting.",
"start_seconds": 0,
"end_seconds": 4.2,
"timing_quality": "approximate",
"timing_method": "provider_segment"
}
]
},
{
"index": 0,
"kind": "notes",
"text": "## Summary\n\nThe team agreed on the launch plan.\n\n## Key points\n\n- Launch moves to Monday."
}
],
"next_cursor": "opaque-account-bound-cursor",
"artifacts": [
{
"format": "notes_md",
"url": "https://example.invalid/signed-notes",
"expires_at": 1792800600
}
],
"charged_seconds": 1140,
"partial": false,
"expires_at": 1792886400
}Chaque segment de transcription indique sa timing_quality : aligned, approximate ou unavailable. Les temps approximatifs sont proches de la parole, mais pas précis au mot près.
Les formats de téléchargement sont transcript_txt (TXT), notes_md (Markdown), notes_html (HTML) et notes_pdf (PDF). Les notes longues peuvent être réparties sur plusieurs fichiers ; téléchargez-les dans l’ordre. L’appel du compte liste les formats disponibles actuellement.
États d’une tâche
| État | Signification |
|---|---|
preparing | Le serveur vérifie le fichier et planifie le travail. |
queued | La tâche attend de démarrer. |
processing | L’audio est extrait, transcrit et transformé en notes. |
completed | Terminée. La transcription complète et les notes sont disponibles. |
completed_with_gaps | Terminée, mais une partie de l’audio n’a pas pu être traitée. Voir les éléments gap. |
interrupted | Arrêtée avant la fin. Vérifiez can_resume. |
cancelled | Arrêtée à votre demande. Les parties terminées restent disponibles. |
failed | La tâche n’a pas pu être traitée. Voir error. |
expired | Le contenu n’est plus conservé. |
stage indique l’étape en cours : probe, planning, admission, extraction, transcription, notes, publication et enfin terminal.
Erreurs
Chaque erreur a le même corps JSON. retryable indique si la même requête peut réussir plus tard, et retry_after_seconds combien de temps attendre.
{
"error": {
"code": "RATE_LIMITED",
"message": "Request refused.",
"retryable": true,
"retry_after_seconds": 5
},
"request_id": "request-1"
}| Code | HTTP | Signification | Que faire |
|---|---|---|---|
UNAUTHORIZED | 401 | La clé est absente, mal formée, expirée, révoquée ou destinée à un autre environnement. | Vérifiez la clé ou créez-en une nouvelle. |
FORBIDDEN | 403 | La clé ne peut pas être utilisée pour cette requête. | Gérez les clés et la facturation sur le site. |
NOT_FOUND | 404 | L’envoi ou la tâche n’existe pas ou appartient à un autre compte. | Vérifiez l’ID. |
VALIDATION_ERROR | 400 | Le corps, un en-tête ou un paramètre de requête est invalide. | Corrigez la requête ; ne la répétez pas à l’identique. |
PLAN_REQUIRED | 403 | Le compte n’a pas de formule Basic ou Plus active. | Choisissez une formule, puis réessayez. |
INSUFFICIENT_BALANCE | 403 | Le temps restant de la formule ne couvre pas l’audio sélectionné. | Sélectionnez une plage plus courte ou attendez le renouvellement de vos heures. |
CAPABILITY_DISABLED | 503 | Les nouvelles tâches sont suspendues ou une fonction est désactivée. | Réessayez plus tard ; l’appel du compte indique l’état actuel. |
UNSUPPORTED_MEDIA | 400 | Le format n’est pas pris en charge, ou la taille envoyée diffère de la taille déclarée. | Envoyez un fichier pris en charge avec sa taille exacte. |
MEDIA_TOO_LARGE | 413 | Le fichier dépasse la limite. | Envoyez un fichier de 8 Gio au maximum. |
PROBE_FAILED | 400 | Le fichier n’a pas de piste audio décodable, ou la plage est en dehors du fichier. | Vérifiez le fichier et la plage. Aucun temps n’est facturé. |
IDEMPOTENCY_CONFLICT | 409 | La Idempotency-Key a déjà été utilisée avec d’autres entrées. | Utilisez une nouvelle clé pour une nouvelle tâche. |
IDEMPOTENCY_EXPIRED | 410 | La tâche d’origine de cette clé a expiré. | Ne la répétez pas ; lancez une nouvelle tâche avec une nouvelle clé. |
JOB_CONFLICT | 409 | Un autre envoi ou une autre tâche est actif, l’état n’autorise pas cette action, ou le résultat a changé pendant la pagination. | Attendez la tâche en cours, ou recommencez la pagination à la première page. |
RESULT_EXPIRED | 410 | Le résultat n’est plus conservé. | Enregistrez les résultats avant leur expiration. |
RATE_LIMITED | 429 | Trop de requêtes, ou la limite quotidienne d’envois est atteinte. | Attendez Retry-After, puis réessayez. |
UNAVAILABLE | 503 | Un service est temporairement indisponible. | Réessayez avec des délais croissants. |
Limites
Voici les valeurs par défaut. L’appel du compte renvoie les valeurs qui s’appliquent à votre compte ; fiez-vous à celles-ci.
| Limite | Par défaut | Champ dans capabilities.limits |
|---|---|---|
| Taille de fichier | 8 Gio | max_upload_bytes |
| Audio sélectionné par tâche | Le temps restant de votre formule (null signifie aucun autre plafond) | max_selection_seconds |
| Envois et tâches actifs | Un de chaque par compte | active_uploads, active_jobs |
| Envois par jour UTC | 10 envois, 20 Gio au total | daily_uploads, daily_upload_bytes |
| Nouvelles tâches et reprises | 12 par minute | new_requests_per_minute |
| Autres requêtes | 60 par minute pour l’ensemble des clés | read_requests_per_minute |
| Suivi de l’état | Pas plus d’une fois toutes les 5 secondes | poll_after_seconds |
| Page de résultats | 32 éléments et 1 Mo | result_page_items, result_page_bytes |
| URL d’envoi signée | Valable jusqu’à 15 minutes | upload_url_seconds |
| Lien de téléchargement | Valable jusqu’à 10 minutes | download_url_seconds |
| Échecs d’authentification | 30 par minute par adresse IP ; ensuite, chaque requête depuis cette adresse reçoit 429, même avec une clé valide, jusqu’à la fin de la minute | — |
Conservation
| Données | Conservées pendant |
|---|---|
| Envoi sans tâche | Environ 2 heures |
| Pages de résultats et fichiers à télécharger | Environ 24 heures après la fin de la tâche |
| Récupération de la transcription | Environ 48 heures |
| Enregistrement d’idempotence, sans contenu | 400 jours |
Les valeurs expires_at de chaque réponse font foi ; utilisez-les plutôt que ces valeurs par défaut.
Journal des modifications
La version de l’API fait partie du chemin. Les modifications de v1 sont listées ici avec leur date.
- 2026-10-24 : API v1 disponible pour les formules Basic et Plus.