transcrevo docs

Repetição segura

Idempotency-Key, o campo retryable, espera longa com ?wait=, cancelamento, cursor e os limites que a própria API informa: o que uma integração precisa para se defender sozinha.

Uma integração de transcrição roda sem ninguém olhando: rede pisca, um deploy reinicia o processo no meio de uma chamada, um backlog destrava de uma vez. Esta página é o que a API oferece para nada disso virar áudio cobrado duas vezes ou job perdido.

Repetir a criação sem cobrar duas vezes

O POST /v1/transcripts cria E cobra. Uma resposta que se perde no caminho de volta deixa o cliente sem saber se o job existe, e repetir às cegas cria o segundo. O Idempotency-Key fecha essa janela:

curl https://api.transcrevo.com/v1/transcripts \
  -H "Authorization: Bearer $TRANSCREVO_API_KEY" \
  -H "Idempotency-Key: 8e1f0f1a-3c1a-4a1f-9f0a-2b7d5c9e1234" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/audio.mp3", "speakers": true}'

A mesma chave devolve a mesma transcrição, sem criar nem cobrar outra. A mesma chave com um corpo diferente é 409 idempotency_conflict: é erro do seu lado, não repetição, e devolver o job antigo faria o áudio novo sumir sem aviso.

Escolha a chave pelo que é estável no seu lado. Com upload, chaveie pelo PRIMEIRO uploadId: ele muda a cada nova tentativa de envio, então usar o id da sua mídia daria 409 para sempre depois da primeira vez.

Saber o que vale repetir

Todo erro traz retryable:

{ "error": { "code": "rate_limited", "message": "…", "retryable": true, "requestId": "…" } }
const { error } = await createTranscript(input);
if (error && !error.retryable) throw new Error(`${error.code}: ${error.message} (${error.requestId})`);
// retryable: espera exponencial, ou o Retry-After quando ele vier

Sem esse campo, cada integração mantém a própria tabela de "quais erros valem retry", e a que erra repete para sempre o que jamais vai passar. retryable: true não quer dizer "repita agora": em rate_limited o Retry-After diz quando.

Guarde o requestId (também no header X-Request-Id) no seu log. É por ele que achamos, do nosso lado, o que houve naquela chamada.

Esperar o resultado sem ficar perguntando

GET /v1/transcripts/{id}?wait=30

A resposta é segurada até a transcrição terminar, e volta no instante em que ela termina. Uma requisição no lugar de um laço de polling. O teto é 60 segundos; a espera vencer não é erro (você recebe a transcrição ainda em processing e chama de novo).

Enquanto está processing, a resposta traz Retry-After com o intervalo que vale esperar antes da próxima pergunta.

Para muitos áudios ao mesmo tempo, webhookUrl continua sendo mais barato: uma entrega por job, em vez de uma conexão aberta por job.

Cancelar

POST /v1/transcripts/{id}/cancel

Para uma transcrição que ainda está processing. Ela vira canceled, terminal, e nunca é cobrada; o crédito que ela segurava (reserved no GET /v1/balance) é liberado na hora.

Cancelar é sobre a cobrança, não sobre a máquina: o áudio que já está numa GPU termina o trabalho em curso e o resultado é descartado. Nada dele chega até você nem à sua fatura.

Paginar um histórico longo

GET /v1/transcripts?cursor=<nextCursor>&perPage=100

O cursor não pula nem repete transcrição quando novas chegam durante a paginação, que é justamente o que o offset faz. Ele também não conta o total da conta: total volta null por cursor, porque essa contagem é o custo que ele existe para evitar.

?page= continua funcionando para quem já integrou com ele.

Perguntar os limites em vez de gravá-los no código

GET /v1/limits

Duração máxima por áudio, formatos aceitos, tetos de upload, de chunk e de corpo da requisição, glossário, e quantas transcrições esta conta pode rodar ao mesmo tempo. Ler no início do processo evita descobrir um teto depois de já ter subido o arquivo.

Rajada

Toda resposta de rota limitada traz RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset. Com eles a sua fila desacelera antes de bater no teto, em vez de descobri-lo sendo recusada. Detalhes e códigos em Erros.

On this page