A API de explicadores
Crie explicadores narrados e visuais a partir do seu próprio código e depois compartilhe, incorpore ou delete esses explicadores, e leia a narração deles como texto. São seis endpoints, uma chave de API e JSON na entrada e na saída.
A API está em beta. Para usá-la, solicite acesso à API.
Conceitos básicos
Todos os endpoints ficam sob uma única URL base e respondem em JSON.
https://scrimba.com/api/v1Toda requisição envia a sua chave de API como bearer token:
Authorization: Bearer scr_live_…O corpo de uma requisição é application/json, ou multipart/form-data quando leva arquivos. As datas nas respostas são strings ISO 8601 em UTC. Os ids são strings opacas. Uma resposta de erro também é JSON; veja Erros.
A versão fica no caminho. Novos campos podem ser adicionados às respostas sem mudança de versão; dentro da v1, nenhum campo é removido ou renomeado.
Chaves de API
Uma chave pertence a uma conta do Scrimba. Tudo o que a chave cria pertence a essa conta, sai da cota mensal dela e aparece no site nessa conta.
- Faça login em scrimba.com. No menu do seu perfil, abra Settings e depois a seção API keys.
- Escolha Create API key e dê um nome a ela, por exemplo o nome do servidor que vai guardá-la.
- Copie o segredo do diálogo. Ele começa com scr_live_ e aparece uma única vez: o Scrimba guarda apenas um hash dele.
A API está em beta. Uma conta precisa de acesso à API para que o diálogo de chaves abra. Enquanto o Scrimba não habilitar a conta, o diálogo e toda chamada à API respondem 403 api_not_enabled.
Mantenha o segredo no seu servidor, nunca em um navegador ou em um app que você distribui. Para encerrar uma chave, escolha Revoke na linha dela, na mesma seção. Uma chave revogada responde 401 a partir daí e não pode ser restaurada; crie uma nova no lugar. Uma conta tem no máximo 20 chaves ativas, e todas compartilham os limites da conta.
Os exemplos abaixo usam duas variáveis de shell:
export SCRIMBA=https://scrimba.com
export SCRIMBA_KEY=scr_live_your_secret_hereInício rápido
Crie um explicador, espere ele terminar e depois compartilhe o link. A chamada de criação responde na hora; o explicador é gerado em segundo plano, e a página dele é renderizada ao vivo enquanto ele é construído.
const base = 'https://scrimba.com/api/v1'
const headers = {Authorization: `Bearer ${process.env.SCRIMBA_KEY}`}
const created = await fetch(`${base}/explainers`, {
method: 'POST',
headers: {...headers, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID()},
body: JSON.stringify({prompt: 'Explain how the Node.js event loop schedules work', privacy: 'unlisted'})
})
if (!created.ok) throw new Error((await created.json()).error.message)
let explainer = await created.json()
while (explainer.status === 'generating') {
await new Promise(resolve => setTimeout(resolve, 5000))
explainer = await (await fetch(`${base}/explainers/${explainer.id}`, {headers})).json()
}
console.log(explainer.status, explainer.url)Um explicador curto fica pronto em menos de um minuto. Um longo pode levar alguns minutos. Faça polling a cada 5 segundos, mais ou menos.
GET /api/v1/me
A conta por trás da chave, a própria chave, o plano e o uso mensal da conta, e os nomes que o endpoint de criação aceita.
curl -s "$SCRIMBA/api/v1/me" -H "Authorization: Bearer $SCRIMBA_KEY"{
"account": {"id": "u1a2b3c", "alias": "acme", "name": "Acme Learning"},
"key": {"id": "ak9x", "name": "server", "prefix": "scr_live_abc123", "created_at": "2026-10-09T10:12:00.000Z"},
"tier": {"name": "pro", "requests_per_minute": 120, "concurrent_generations": 3, "explainers_per_month": 100},
"explainers": {"used": 12, "remaining": 88, "resets_at": "2026-11-01T00:00:00.000Z"},
"teachers": ["eli5", "standard", "per", "tom", "lol", "professor", "tldr"],
"modes": ["landscape", "portrait", "square"],
"privacy": ["private", "unlisted", "public"]
}key.prefix é o início do segredo, o suficiente para diferenciar as chaves. tier.explainers_per_month é o limite mensal da conta: o número do tier, ou um que o Scrimba definiu para a conta. explainers.resets_at é quando a contagem mensal recomeça.
POST /api/v1/explainers
Cria um explicador e inicia a geração dele. Responde 201 com o objeto do explicador assim que o explicador passa a existir; nesse momento, status é generating.
Campos
| Campo | Valores | Padrão |
|---|---|---|
prompt | O que explicar, como uma string de até 12.000 caracteres. Obrigatório, a menos que a requisição tenha um anexo. | |
mode | landscape (16:9), portrait (9:16), square (1:1). O formato dos slides. | landscape |
privacy | private (somente a sua conta), unlisted (qualquer pessoa com o link), public (listado no site). | private |
language | Um código ISO 639-1, como en ou pt-BR. A narração e o texto visível ficam nesse idioma, seja qual for o idioma do prompt. Uma região, como em pt-BR, seleciona esse dialeto. | O idioma do prompt |
teacher | eli5, standard, per, tom, lol, professor, tldr. A voz e o estilo da explicação. | eli5 |
watermark | true ou false. false exige uma conta Pro. | true |
attachments | Partes de arquivo multipart, até 5. Veja Anexos. | |
cite_attachments | true ou false. Com true, a narração cita as partes dos seus anexos de texto das quais ela ensina, e a transcrição carrega essas citações. | false |
Um campo que você omite, ou envia como null, assume o valor padrão. Um campo que você envia precisa ter um valor: language: false é recusado, assim como privacy: false.
JSON
curl -s "$SCRIMBA/api/v1/explainers" \
-H "Authorization: Bearer $SCRIMBA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4821-explainer" \
-d '{
"prompt": "Explain how HTTP caching headers decide what a browser keeps",
"mode": "landscape",
"privacy": "unlisted",
"language": "en",
"teacher": "standard"
}'Multipart, com anexos
Envie um corpo multipart/form-data. Os campos de texto são os mesmos. Adicione cada arquivo como uma parte chamada attachments. O prompt é opcional quando há pelo menos um anexo.
curl -s "$SCRIMBA/api/v1/explainers" \
-H "Authorization: Bearer $SCRIMBA_KEY" \
-F "prompt=Walk through this diagram and the code behind it" \
-F "mode=portrait" \
-F "[email protected]" \
-F "[email protected]"Idempotência
Envie um header Idempotency-Key, uma string sua de 1 a 200 caracteres imprimíveis, uma para cada explicador que você pretende criar. Se uma requisição for interrompida antes de você ler a resposta, repita-a com a mesma chave de API e o mesmo header: a API responde com o explicador que já criou, com 200 em vez de 201, e não cria um segundo. Duas requisições que chegam juntas com o mesmo header criam um único explicador. O header é lembrado por chave de API; um explicador deletado libera o header dele.
Resposta
{
"id": "guide0abc123",
"url": "https://scrimba.com/explain/guide0abc123",
"status": "generating",
"error": null,
"title": "Explain how HTTP caching headers decide what a browser keeps",
"description": null,
"mode": "landscape",
"privacy": "unlisted",
"language": null,
"created_at": "2026-10-09T10:15:02.000Z",
"finished_at": null,
"video_url": null,
"embed": "<iframe src=\"https://scrimba.com/explain/guide0abc123\" …></iframe>",
"attachments": [],
"duration_ms": 0
}Abra ou compartilhe url na hora. A página mostra o explicador sendo construído e o reproduz quando ele fica pronto.
Uma criação recusada não cria nada e não gasta nada. Uma criação além da cota do mês responde 429 quota_exceeded, e uma criação feita enquanto a conta já tem em andamento todas as gerações que o plano permite responde 429 too_many_running; as duas respostas trazem Retry-After.
GET /api/v1/explainers/:id
Um explicador que a conta criou pela API, com o status atual.
curl -s "$SCRIMBA/api/v1/explainers/guide0abc123" -H "Authorization: Bearer $SCRIMBA_KEY"status passa de generating para ready ou failed e não muda mais. Quando é ready, finished_at, language e duration_ms são preenchidos. Quando é failed, error diz o motivo, a página em url informa que o explicador falhou, e o explicador não conta na cota do mês: o crédito volta. Uma geração que para sem terminar, por exemplo em um reinício do servidor, é informada como failed depois de dez minutos.
Um explicador criado no site, ou criado pela API por outra conta, responde 404.
GET /api/v1/explainers/:id/transcript
A narração de um explicador pronto: uma entrada por trecho falado, em ordem de reprodução, com as partes dos seus anexos que cada trecho cita. A narração aponta para o slide como sempre; uma citação diz de onde vêm as palavras dela.
Enquanto o explicador está gerando, e quando ele falhou, a resposta é 409 not_ready. Um explicador criado no site, ou criado pela API por outra conta, responde 404.
curl -s "$SCRIMBA/api/v1/explainers/guide0abc123/transcript" -H "Authorization: Bearer $SCRIMBA_KEY"{
"id": "guide0abc123",
"attachments": [{"ref": 1, "name": "server.ts", "type": "text/plain"}],
"entries": [
{
"index": 3,
"slide": 2,
"title": "Checking the token",
"text": "The handler reads the token from the header, then compares it to the stored secret.",
"references": [
{
"text": "reads the token from the header",
"text_start": 12,
"text_end": 43,
"attachment": 1,
"offset": 412,
"length": 39,
"lines": [10, 10],
"cited_text": "const token = req.headers.authorization"
}
]
}
]
}| Campo | Tipo | Significado |
|---|---|---|
attachments | array | A mesma lista que o objeto explicador carrega, então uma chamada basta. |
entries[].index | number | A posição da entrada na narração, a partir de 0. |
entries[].slide | number | O slide mostrado enquanto a entrada toca, a partir de 0. |
entries[].title | string ou null | O rótulo de narração que o explicador deu ao trecho. |
entries[].text | string | As palavras faladas, como a transcrição da página as mostra. |
entries[].references | array | As partes dos seus anexos que a entrada cita, na ordem em que a narração as lista. Vazio quando a entrada não cita nenhuma. |
references[].text | string | As palavras de text que a citação sustenta. |
references[].text_start, text_end | number ou null | Onde essas palavras estão em text: o índice do primeiro caractere e o índice depois do último. Null quando a narração não fala as palavras exatamente como a citação as dá. |
references[].attachment | number | O ref do arquivo citado em attachments. |
references[].offset, length | number | A parte citada do arquivo: o primeiro caractere dela e quantos caracteres tem. |
references[].lines | array | A primeira e a última linha da parte citada, contadas a partir de 1. |
references[].cited_text | string | A parte citada em si. |
As citações vêm de cite_attachments: true na criação; Citações mostra como usá-las. Sem ele, toda lista references fica vazia. Só arquivos de texto e código são citados, nunca imagens ou PDFs.
Um arquivo de texto é lido até 30.000 caracteres, e offset conta dentro do que foi lido. Uma citação cuja parte citada não é encontrada no arquivo é deixada de fora.
GET /api/v1/explainers
Os explicadores que a conta criou pela API, do mais novo para o mais antigo, em páginas. Explicadores criados no site não aparecem na lista.
| Parâmetro de query | Valores | Padrão |
|---|---|---|
limit | Linhas por página, de 1 a 100. | 25 |
cursor | O next_cursor da página anterior. | A primeira página |
curl -s "$SCRIMBA/api/v1/explainers?limit=25" -H "Authorization: Bearer $SCRIMBA_KEY"
# {"explainers": [{…}, {…}], "next_cursor": "guide0abc123"}
curl -s "$SCRIMBA/api/v1/explainers?limit=25&cursor=guide0abc123" -H "Authorization: Bearer $SCRIMBA_KEY"
# {"explainers": [{…}], "next_cursor": null}Cada linha é um objeto de explicador sem duration_ms. next_cursor é null na última página. Um cursor continua válido depois que o explicador dele é deletado; um cursor que nunca correspondeu a um dos explicadores da conta criados pela API responde 400 invalid_cursor.
DELETE /api/v1/explainers/:id
Deleta um explicador que a conta criou pela API, junto com o vídeo exportado dele, se houver. A página e o link do explicador deixam de funcionar, e o explicador responde 404 a partir daí. O crédito dele não é devolvido.
curl -s -X DELETE "$SCRIMBA/api/v1/explainers/guide0abc123" -H "Authorization: Bearer $SCRIMBA_KEY"
# {"deleted": "guide0abc123"}O objeto do explicador
O que POST, GET e a lista respondem para um explicador.
| Campo | Tipo | Significado |
|---|---|---|
id | string | O id do explicador, usado nos caminhos acima. |
url | string | A página do explicador. Quem pode abri-la depende do valor de privacy. |
status | string | generating, ready ou failed. |
error | objeto ou null | {"code": "generation_failed", "message": "…"} quando status é failed; caso contrário, null. |
title | string | O título do explicador: o prompt ou, quando não há prompt, um nome tirado dos anexos. |
description | string ou null | Uma sinopse curta, preenchida quando o explicador fica pronto. |
mode | string | landscape, portrait ou square. |
privacy | string | private, unlisted ou public. |
language | string ou null | O idioma da narração como uma tag, por exemplo en-us. null até o explicador ficar pronto. |
created_at | string | Quando o explicador foi criado. |
finished_at | string ou null | Quando a geração terminou; null enquanto ela roda ou depois que ela falhou. |
video_url | string ou null | Um MP4 do explicador. Preenchido apenas quando existe uma exportação de vídeo e o explicador é unlisted ou public. |
embed | string ou null | Um trecho <iframe> para as suas próprias páginas. Preenchido apenas quando o explicador é unlisted ou public: um iframe de um explicador private mostra a tela de login para todo mundo, menos para você. |
attachments | array | Os arquivos enviados com a requisição, na ordem de envio: {"ref": 1, "name": "server.ts", "type": "text/plain"}. ref é o número pelo qual o explicador conhece o arquivo. |
duration_ms | número | A duração da reprodução em milissegundos; 0 até o explicador ficar pronto. Somente em POST e GET, não na lista. |
Anexos
Uma requisição pode levar até 5 arquivos, como partes multipart chamadas attachments. O explicador lê esses arquivos como contexto e pode mostrar imagens deles.
| Tipo | Aceito como | Limite |
|---|---|---|
| Imagens | png, jpeg, gif, webp | 5 MB e 30 megapixels cada |
| PDFs | application/pdf | 5 MB cada |
| Texto e código | Qualquer tipo text/*, ou um nome terminado em txt, md, log, env, conf, cfg, ini, js, jsx, ts, tsx, py, json, imba, html, css | 30.000 caracteres cada |
| Jupyter notebooks | Um nome terminado em .ipynb | Armazenado como markdown e medido como texto: 30.000 caracteres |
Uma imagem ou um PDF é avaliado pelos seus bytes, seja qual for o content type que a parte declara. Qualquer outro arquivo segue o tipo declarado, ou os seus bytes quando a parte não declara nenhum tipo ou declara application/octet-stream. Um arquivo de outro tipo responde 415 unsupported_attachment, e um arquivo acima do limite responde 413 too_large; as duas respostas nomeiam o arquivo. Uma requisição recusada não armazena nada.
O corpo inteiro da requisição tem no máximo 32 MB. Um corpo JSON tem no máximo 256 KB.
Limites
| Limite | Gratuito | Pro |
|---|---|---|
| Explicadores por mês, por conta | 5 | 100 |
| Gerações em andamento ao mesmo tempo, por conta | 1 | 3 |
| Requisições por minuto, somando todas as chaves da conta | 30 | 120 |
| watermark: false | Não | Sim |
Pro é a assinatura Scrimba Pro da conta. O Scrimba pode dar a uma conta um limite mensal próprio, inclusive 0; GET /api/v1/me e uma resposta quota_exceeded informam o limite que vale.
A contagem mensal é zerada no primeiro dia do mês, em UTC; GET /api/v1/me informa o horário exato. Só contam os explicadores que são de fato criados, e um explicador que falha devolve o crédito. Uma requisição recusada não gasta nada.
Uma recusa por limite é um 429 com um header Retry-After em segundos. Espere esse tempo em vez de tentar de novo na hora.
Erros
Todo erro responde JSON com o mesmo formato, com um status HTTP que indica o tipo e um código que indica a causa:
{"error": {"code": "invalid_prompt", "message": "The prompt is over 12000 characters"}}| Status | Código | Significado |
|---|---|---|
| 400 | invalid_prompt, invalid_mode, invalid_privacy, invalid_language, invalid_teacher, invalid_watermark, invalid_cite_attachments, too_many_attachments, invalid_json, invalid_multipart, invalid_idempotency_key, invalid_limit, invalid_cursor | Um campo, um header ou o corpo está errado. A mensagem diz qual. |
| 401 | unauthorized | O bearer token está ausente, é desconhecido ou foi revogado. |
| 403 | api_not_enabled | A conta ainda não está habilitada para a API. |
| 403 | pro_required | watermark: false em uma conta sem Pro. |
| 404 | not_found | Não há explicador com esse id nesta conta, ou ele foi deletado. |
| 409 | not_ready | A transcrição de um explicador que ainda está gerando, ou que falhou. |
| 413 | too_large | Um corpo JSON tem mais de 256 KB, um corpo multipart tem mais de 32 MB, uma imagem ou um PDF tem mais de 5 MB ou 30 megapixels, ou um arquivo de texto tem mais de 30.000 caracteres. A mensagem nomeia o arquivo. |
| 415 | unsupported_attachment, unsupported_media_type | Um arquivo de um tipo que um explicador não aceita, ou um corpo que não é nem JSON nem multipart. |
| 429 | rate_limited | A conta passou do limite de requisições por minuto, ou há imagens demais sendo enviadas no site inteiro. Espere o Retry-After. |
| 429 | too_many_running | A conta já tem em andamento todas as gerações que o plano permite. Espere o Retry-After, ou que uma delas termine. |
| 429 | quota_exceeded | Os explicadores do mês acabaram. A mensagem diz quando a contagem é zerada. |
| 503 | busy | O servidor está com uploads demais neste momento. Tente de novo daqui a pouco. |
| 500 | internal | Uma falha do lado do Scrimba. Tente de novo mais tarde; se continuar, entre em contato com o Scrimba informando o horário e o id do explicador, se você tiver um. |
Descreve a API de explicadores tal como estava em 20 de outubro de 2026.

