Entwicklung mit einer Transkriptions-API: Die erste Integration
apientwicklertutorial

Entwicklung mit einer Transkriptions-API: Die erste Integration

BMMamane B. MoussaMay 26, 2026Updated July 2, 202610 min read

Summarize this article with:

Die Integration in fünf Schritten

Sie können jeder Backend-Anwendung in weniger als einer Stunde Transkription hinzufügen: API-Schlüssel besorgen, Audio per POST senden (per Datei-Upload oder URL), per Polling abfragen oder bei Fertigstellung einen Webhook empfangen, das Ergebnis abrufen und in das benötigte Format exportieren. Die Muster hier werden anhand der ConvertAudioToText-API gezeigt, aber das Submit-dann-Poll-Muster ist bei jedem asynchronen Transkriptionsanbieter Standard. Wenn Sie noch dabei sind, einen Anbieter auszuwählen, werfen Sie zuerst einen Blick auf den Transkriptions-API-Vergleich 2026.

Die fünf Schritte sind: authentifizieren, einen Job einreichen, das Ergebnis abrufen, Fehler behandeln und exportieren. Jeder Abschnitt unten behandelt einen Schritt mit lauffähigem Code.

Schritt 1: API-Schlüssel erstellen

Der API-Zugang auf ConvertAudioToText erfordert den Business-Tarif. Navigieren Sie im Dashboard zu Settings, dann zu API Keys, und erstellen Sie dort einen neuen Schlüssel. Geben Sie ihm einen aussagekräftigen Namen, der zur Integration passt („production-backend“, „staging-ingest“). Der Schlüssel wird genau einmal angezeigt, kopieren Sie ihn also sofort.

Schlüsselformat: ck_live_ gefolgt von 64 Hexadezimalzeichen. Behandeln Sie ihn wie ein Passwort. Speichern Sie ihn in einer Umgebungsvariable, niemals in der Quellcodeverwaltung.

Jede Anfrage verwendet Authorization: Bearer <key>:

curl https://api.convertaudiototext.com/api/v1/result/some-job-id \
  -H "Authorization: Bearer ck_live_..."

In Node.js:

const headers = { 'Authorization': `Bearer ${process.env.CATT_API_KEY}` };

In Python:

headers = {'Authorization': f'Bearer {os.environ["CATT_API_KEY"]}'}

Schritt 2: Einen Transkriptions-Job einreichen

Der Endpunkt ist POST /api/v1/transcribe. Er gibt sofort HTTP 201 mit einer job_id zurück; die eigentliche Transkription erfolgt asynchron.

Es gibt zwei Übermittlungswege: Datei-Upload und URL. Beide liefern dasselbe Antwortformat zurück.

Datei-Upload

Verwenden Sie dies, wenn sich die Audiodatei lokal befindet oder Sie sie als Multipart-Form-Upload von Ihren Nutzern erhalten.

import FormData from 'form-data';
import { createReadStream } from 'fs';
import fetch from 'node-fetch';

async function submitFileJob(filePath, language = 'en') {
  const form = new FormData();
  form.append('source', 'upload');
  form.append('language', language);
  form.append('file', createReadStream(filePath));

  const res = await fetch('https://api.convertaudiototext.com/api/v1/transcribe', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.CATT_API_KEY}` },
    body: form
  });

  if (!res.ok) throw new Error(`Submit failed: ${res.status}`);
  const { job_id, status } = await res.json();
  return { job_id, status };
}

URL-Übermittlung

Verwenden Sie dies, wenn sich das Audio bereits im Cloud-Speicher befindet (S3, R2, GCS oder eine beliebige öffentliche HTTPS-URL). Der Server lädt mit hoher Bandbreite direkt vom Ursprung herunter, was schneller ist als ein erneuter Upload von Ihrem Rechner.

async function submitURLJob(audioURL, language = 'en') {
  const res = await fetch('https://api.convertaudiototext.com/api/v1/transcribe', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CATT_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      source: 'url',
      input_url: audioURL,
      language: language
    })
  });

  if (!res.ok) throw new Error(`Submit failed: ${res.status}`);
  const { job_id, status } = await res.json();
  return { job_id, status };
}

Beide geben { job_id: "uuid-string", status: "queued" } zurück.

ConvertAudioToText Audio-Upload-Tool
ConvertAudioToText Audio-Upload-Tool

Das Audio-Upload-Tool, das von der API betrieben wird. Dieselbe Job-Pipeline läuft, egal ob Sie die Weboberfläche oder die API nutzen.

Schritt 3: Das Ergebnis abrufen

Ein abgeschlossener Job ist unter GET /api/v1/result/{job_id} verfügbar. Zwei Muster fürs Warten: Polling und Webhooks.

Polling

Fragen Sie alle 5 Sekunden ab, bis status "completed" oder "failed" ist. Der Endpunkt antwortet sofort; die Verzögerung liegt vollständig auf der Transkriptionsseite.

async function pollForResult(jobId, maxWaitMs = 600000) {
  const start = Date.now();

  while (Date.now() - start < maxWaitMs) {
    const res = await fetch(
      `https://api.convertaudiototext.com/api/v1/result/${jobId}`,
      { headers: { 'Authorization': `Bearer ${process.env.CATT_API_KEY}` } }
    );
    const data = await res.json();

    if (data.status === 'completed') return data;
    if (data.status === 'failed') throw new Error(data.error || 'Job failed');

    await new Promise(r => setTimeout(r, 5000));
  }

  throw new Error('Timeout waiting for transcription result');
}

Fragen Sie nicht häufiger als einmal pro Sekunde pro Job ab. Das globale Rate-Limit liegt bei 100 Anfragen pro Minute pro IP, daher wird eine dichte Schleife über viele Jobs dieses Limit auslösen.

Webhooks

Für eine bessere Ressourcennutzung bei Skalierung ersetzen Webhooks das Polling vollständig. Registrieren Sie einmalig eine Webhook-URL:

curl -X POST https://api.convertaudiototext.com/api/v1/dashboard/webhooks \
  -H "Authorization: Bearer $CATT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/transcription",
    "events": ["job.completed", "job.failed"]
  }'

Die Antwort enthält ein secret-Feld. Speichern Sie es. Der Server sendet bei jedem passenden Ereignis einen POST an Ihre URL. Die Payload sieht so aus:

{
  "event": "job.completed",
  "timestamp": "2026-07-01T14:22:05Z",
  "data": {
    "job_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "completed",
    "duration": 1842,
    "result_url": "https://api.convertaudiototext.com/api/v1/result/550e8400-...",
    "completed_at": "2026-07-01T14:22:04Z"
  }
}

Verifizieren Sie jede Zustellung mit HMAC-SHA256. Der Server sendet die Signatur im Header X-Webhook-Signature als sha256=<hex>:

import crypto from 'crypto';

function verifyWebhookSignature(rawBody, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

// In your Express/Fastify handler:
app.post('/webhooks/transcription', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-webhook-signature'];
  if (!verifyWebhookSignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const { event, data } = JSON.parse(req.body);
  if (event === 'job.completed') {
    // fetch full transcript from data.result_url
  }
  res.status(200).end();
});

Webhooks erfordern den Business-Tarif und eine öffentlich erreichbare HTTPS-URL. Einen tieferen Vergleich der beiden Ansätze finden Sie im Leitfaden Webhook vs. Polling für Transkripte.

Schritt 4: Das Ergebnis parsen

In der Antwort eines abgeschlossenen Jobs ist das Transkript unter dem Schlüssel transcript verschachtelt. Die genaue Struktur bestimmt der serverseitige Formatter, aber folgende Felder finden Sie immer:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "language": "en",
  "duration": 1842,
  "filename": "interview.mp3",
  "transcript": {
    "text": "Hello, welcome to the show...",
    "summary": "An interview about...",
    "confidence": 0.97,
    "word_count": 4210,
    "timeline": [
      {
        "speaker": "Speaker 0",
        "text": "Hello, welcome to the show.",
        "start": 0.12,
        "end": 1.87
      }
    ],
    "topics": [...],
    "sentiments": [...]
  }
}

Das Feld text enthält das vollständige, zusammengeführte Transkript. Das Array timeline liefert Ihnen sprecherzugeordnete Äußerungen mit Zeitstempeln. Die Felder summary, topics und sentiments werden bei englischem Audio in Tarifen mit KI-Einblicken befüllt; im Starter-Tarif werden sie entfernt oder sind nicht vorhanden.

Schritt 5: Exportformate

Formatierte Dateien laden Sie herunter über:

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/srt" \
  -H "Authorization: Bearer $CATT_API_KEY" > captions.srt  # SRT for video captions

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/vtt" \
  -H "Authorization: Bearer $CATT_API_KEY" > captions.vtt  # WebVTT

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/txt" \
  -H "Authorization: Bearer $CATT_API_KEY" > transcript.txt  # Plain text with speaker labels

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/json" \
  -H "Authorization: Bearer $CATT_API_KEY" > transcript.json  # Structured JSON

curl "https://api.convertaudiototext.com/api/v1/result/$JOB_ID/docx" \
  -H "Authorization: Bearer $CATT_API_KEY" > transcript.docx  # DOCX

Alle Export-Endpunkte erfordern einen kostenpflichtigen Tarif. Anfragen aus dem kostenlosen Tarif geben HTTP 402 mit einem upgrade_url-Feld zurück. Zum Aufbau von Untertitel-Workflows im großen Maßstab eignen sich die SRT- und VTT-Endpunkte gut für Batch-Pipelines.

Fehlerbehandlung

Drei Fehlerkategorien müssen behandelt werden, jeweils mit einer anderen Wiederherstellungsstrategie.

4xx-Fehler sind Ihr Bug. Falsche Authentifizierung (401), fehlende Pflichtfelder (400), erschöpftes Kontingent (402) oder erreichtes Rate-Limit (429). Wiederholen Sie nichts, ohne die Anfrage zu korrigieren. Lesen Sie bei 429 das Feld retry_after aus dem Antwortkörper.

5xx-Fehler sind vorübergehend. Wiederholen Sie mit exponentiellem Backoff. Die meisten klären sich innerhalb von 30 Sekunden.

Fehler auf Job-Ebene. Ein Job kann erfolgreich eingereicht werden (HTTP 201), aber später während der Verarbeitung fehlschlagen. status wird zu "failed" und error trägt den Grund. Häufige Ursachen: beschädigtes Audio, durchgehend stumme Aufnahmen, nicht unterstützte Codecs. Versuchen Sie den Job nur erneut, wenn die Audioquelle gültig ist.

async function transcribeWithRetry(audioPath, maxAttempts = 3) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      const { job_id } = await submitFileJob(audioPath);
      return await pollForResult(job_id);
    } catch (err) {
      // 4xx: fix the request, do not retry
      if (err.status >= 400 && err.status < 500) throw err;
      // Last attempt: give up
      if (attempt === maxAttempts - 1) throw err;
      // 5xx: wait and try again
      const delayMs = 1000 * Math.pow(2, attempt);
      await new Promise(r => setTimeout(r, delayMs));
    }
  }
}

Rate-Limits

Die Limits, die für authentifizierte API-Anfragen gelten:

EbeneLimitGeltungsbereich
Global100 Anfragen/Min.Pro IP-Adresse
Transkriptions-Jobs10 Einreichungen/Min.Pro authentifiziertem Benutzer
Multipart-Upload (Sign-Aufrufe)1000/Min.Pro IP, eigenes Limit

Das Transkriptions-Job-Limit bedeutet, dass Sie bis zu 10 Jobs pro Minute einreichen können, nicht 10 gleichzeitig; darüber hinausgehende Jobs werden auf dem Server in die Warteschlange gestellt.

Wird eines der Limits erreicht, gibt die API HTTP 429 mit retry_after in Sekunden im Antwortkörper zurück.

Ein vollständiges, lauffähiges Beispiel

import { createReadStream } from 'fs';
import FormData from 'form-data';
import fetch from 'node-fetch';

const API_KEY = process.env.CATT_API_KEY;
const BASE    = 'https://api.convertaudiototext.com/api/v1';

async function submit(filePath, language = 'en') {
  const form = new FormData();
  form.append('source', 'upload');
  form.append('language', language);
  form.append('file', createReadStream(filePath));

  const res = await fetch(`${BASE}/transcribe`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` },
    body: form
  });

  if (!res.ok) throw Object.assign(new Error('Submit failed'), { status: res.status });
  return res.json();
}

async function poll(jobId, maxWaitMs = 600000) {
  const deadline = Date.now() + maxWaitMs;

  while (Date.now() < deadline) {
    const res = await fetch(`${BASE}/result/${jobId}`, {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    });
    const data = await res.json();

    if (data.status === 'completed') return data;
    if (data.status === 'failed') throw new Error(data.error || 'Transcription failed');

    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error('Timeout');
}

export async function transcribeFile(filePath, language = 'en') {
  const { job_id } = await submit(filePath, language);
  const result     = await poll(job_id);
  return result.transcript?.text ?? '';
}

Von hier aus fügen Sie Caching für Transkriptionsergebnisse hinzu, um identische Dateien nicht erneut verarbeiten zu müssen, und wechseln von Polling zu Webhooks, sobald Sie mehr als eine Handvoll gleichzeitiger Jobs haben.

Meine Einschätzung: Das Submit-Poll-Muster ist bei allen großen asynchronen Transkriptionsanbietern gleich, daher lässt sich der Client-Code fast unverändert übernehmen. Die Unterschiede liegen im Format des Authentifizierungs-Headers, in den Feldnamen der Antwort und darin, ob erweiterte Funktionen wie Sprecherkennzeichnungen einen höheren Tarif erfordern. Prüfen Sie jedes Detail gegen die aktuelle Dokumentation des Anbieters, bevor Sie live gehen.

Wenn Sie nur gelegentlich ein sauberes Transkript benötigen, ohne API-Schlüssel oder Tarifstufen verwalten zu müssen, können Sie mit ConvertAudioToText Ihr Transkript kostenlos und ohne Einrichtung hochladen, transkribieren und kopieren.

Häufig gestellte Fragen

Welchen Tarif brauche ich, um die API zu nutzen?

Die Erstellung eines API-Schlüssels auf ConvertAudioToText erfordert den Developer- oder Business-Tarif. Developer umfasst 600 Minuten pro Monat; Business ist unbegrenzt. Prüfen Sie /pricing auf die aktuellen Tarife, bevor Sie einen Kauf tätigen.

Wie hoch ist das Rate-Limit für Transkriptions-Jobs?

Das globale Limit beträgt 100 Anfragen pro Minute pro IP-Adresse. Einreichungen von Transkriptions-Jobs sind zusätzlich auf 10 Jobs pro Minute pro Benutzer begrenzt. Wird eines der Limits erreicht, gibt die API HTTP 429 mit einem Retry-After-Header zurück.

Polling oder Webhooks: Was sollte ich verwenden?

Polling funktioniert für Integrationen mit geringem Volumen oder einmalige Anwendungsfälle und erfordert keinen öffentlichen Endpunkt. Webhooks sind besser, sobald Sie mehrere gleichzeitige Jobs haben: Statt alle paar Sekunden N Jobs abzufragen, erhält Ihr Server einen POST pro abgeschlossenem Job. Webhooks erfordern den Business-Tarif und eine öffentlich erreichbare HTTPS-URL.

Wie überprüfe ich, ob eine Webhook-Payload echt ist?

Jede Webhook-Registrierung gibt eine geheime Zeichenfolge (Secret) zurück. Wenn der Server eine Payload zustellt, berechnet er daraus HMAC-SHA256 des rohen JSON-Bodys mit diesem Secret und sendet das Ergebnis im X-Webhook-Signature-Header als sha256=hex. Berechnen Sie denselben HMAC auf Ihrer Seite neu und vergleichen Sie beide Werte. Lehnen Sie jede Anfrage ab, bei der sie nicht übereinstimmen.

Welche Exportformate unterstützt die API?

Abgeschlossene Jobs lassen sich als SRT, VTT, TXT, JSON, DOCX und PDF über GET /api/v1/result// exportieren. Alle Export-Endpunkte erfordern einen kostenpflichtigen Tarif; Anfragen aus dem kostenlosen Tarif geben HTTP 402 zurück.

Quellen

Try transcription free

Convert any audio or video to clean, unwatermarked text — speaker labels, timestamps, and AI summaries included. First 10 minutes free, no account.

Related Articles