API de Correção de Redação (ENEM)
API REST do Workfuse para enviar redações e receber a correção no padrão ENEM
(5 competências, nota 0–1000, comentários e marcações de gramática). A correção é
assíncrona: você envia a redação, recebe um id, e consulta o resultado (ou
recebe um webhook quando ficar pronta).
Explore e teste os endpoints direto no navegador: API_BASE/public/v1/doc.
O contrato OpenAPI cru está em API_BASE/public/v1/openapi.
API_BASE é a URL da API Workfuse do seu ambiente (ex.: https://api.workfuse.com).
Todos os caminhos abaixo são relativos a API_BASE/public/v1/correction.
Autenticação
Toda requisição usa uma API key no header Authorization, no formato Bearer:
Authorization: Bearer wf_sua_chave_aqui
A chave é gerada no painel (Configurações → API Keys), tem escopo por módulo
(precisa do módulo correction) e identifica a sua instituição — você só acessa
as redações enviadas com a sua chave. Detalhes em Autenticação.
Enviar uma redação
POST /essays
curl -X POST "API_BASE/public/v1/correction/essays" \
-H "Authorization: Bearer wf_sua_chave_aqui" \
-H "Content-Type: application/json" \
-d '{
"userId": "aluno-123",
"proposedTheme": "Os desafios da mobilidade urbana no Brasil",
"content": "Texto completo da redação do aluno...",
"motivationalTexts": [
{ "title": "Texto motivador 1", "content": "..." }
],
"externalId": "redacao-42"
}'
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
userId | string | sim | Id do aluno no seu sistema (você correlaciona). |
proposedTheme | string | sim | Tema proposto da redação. |
content | string | sim | Texto da redação (até 50.000 caracteres). |
motivationalTexts | array | sim | Textos motivadores: { title, content?, images? }. Pode ser []. |
title | string | não | Título da redação. |
externalId | string | não | Seu id de referência (eco na consulta). |
Resposta 201 — a correção foi enfileirada:
{ "id": "clz...", "processStatus": "PENDING" }
Guarde o id para consultar o resultado.
Código executável (Node, sem dependências): submit-essay — envia a redação e faz polling até concluir.
Consultar uma redação
GET /essays/:id
curl "API_BASE/public/v1/correction/essays/clz..." \
-H "Authorization: Bearer wf_sua_chave_aqui"
Enquanto processa, enemFeedback vem null. Quando conclui (processStatus: SUCCESS),
vem a correção completa:
{
"id": "clz...",
"userId": "aluno-123",
"externalId": "redacao-42",
"proposedTheme": "Os desafios da mobilidade urbana no Brasil",
"content": "Texto completo...",
"contentWithGrammarFeedback": "Texto com <span data-content=\"...\">marcações</span>...",
"status": "DONE",
"processStatus": "SUCCESS",
"processErrorMessage": null,
"enemFeedback": {
"competence1Score": 160, "competence1Comment": "...",
"competence2Score": 120, "competence2Comment": "...",
"competence3Score": 160, "competence3Comment": "...",
"competence4Score": 160, "competence4Comment": "...",
"competence5Score": 120, "competence5Comment": "...",
"overallScore": 720,
"overallComment": "...",
"isScoreZeroed": false,
"preliminaryCheckComment": null,
"grammarFeedback": [
{
"message": "Esta conjunção deve ser separada por vírgula.",
"shortMessage": "Separe com vírgulas",
"replacements": ["presentes, mas"],
"offset": 43,
"length": 13
}
]
},
"createdAt": "2026-06-10T20:24:05.734Z",
"updatedAt": "2026-06-10T20:25:12.132Z"
}
Notas do enemFeedback:
- Cada competência (C1–C5) tem nota (0/40/80/120/160/200) + comentário;
overallScoreé a soma (0–1000). isScoreZeroed: truequando a redação foi zerada (fuga ao tema, gênero incorreto, etc.) —preliminaryCheckCommentexplica.contentWithGrammarFeedbacké o texto com marcações de gramática em HTML (<span data-content="...">);grammarFeedback[]traz os mesmos itens comoffset/lengthsobre o texto cru.
Listar redações
GET /essays — paginado, escopado à instituição da sua chave.
curl "API_BASE/public/v1/correction/essays?page=1&pageSize=20" \
-H "Authorization: Bearer wf_sua_chave_aqui"
{ "data": [ { "id": "clz...", "processStatus": "SUCCESS", "...": "..." } ],
"pagination": { "page": 1, "pageSize": 20, "pages": 3, "items": 47 } }
Ciclo de vida (processStatus)
PENDING → PROCESSING → SUCCESS
↘ ERROR (processErrorMessage explica)
status é o estado de alto nível para o aluno: SENT (enviada) → DONE (corrigida).
Receber o resultado por webhook
Em vez de fazer polling no GET, registre um webhook (no painel) para receber um
POST assinado quando a correção concluir (essay.corrected) ou falhar
(essay.failed). Veja Webhooks — exemplo de receiver:
nodejs-webhook.
Erros
| HTTP | Quando |
|---|---|
400 | Corpo inválido (campo faltando / fora do limite). |
401 | API key ausente ou inválida. |
403 | A chave não tem o módulo correction no escopo. |
404 | Redação não encontrada (ou de outra instituição). |
500 | Erro interno. |