Webhooks
Em vez de esperar uma Assembly terminar e sua requisição de API responder, você também pode configurar um Webhook, também conhecido como Assembly Notification. O sistema envia uma requisição POST para uma URL de sua escolha contendo um relatório completo assim que uma Assembly termina.
Por que usar Webhooks?
Ao optar por usar Webhooks, você proporciona uma experiência mais fluida aos seus usuários finais, já que eles só precisam esperar os uploads de arquivos terminarem antes de fechar a janela do navegador. Sem uploads de arquivos, eles poderiam até fechar a janela do navegador imediatamente.
Como ativar Webhooks?
Você ativa webhooks adicionando notify_url às suas Assembly Instructions no seu
Template, no mesmo nível JSON que steps:
{
"steps": {
// …
},
"notify_url": "https://example.com/transloadit_pingback"
}
Quando você então executa seu Template, a Transloadit vai informar seu back-end assim que todo o
processamento tiver acontecido, enviando uma requisição POST para a URL definida contendo todo o
json de status da Assembly.
Se você não quer que seus usuários/programa esperem pela codificação, isso muitas vezes também
envolve definir uma flag. No caso do Uppy (English), defina o parâmetro waitForEncoding como false. Em muitos
SDKs de back-end, esperar pela codificação envolve consultar explicitamente o Assembly Status,
então basta não fazer isso.
Seu back-end precisa responder com um cabeçalho 200, caso contrário a Transloadit assume que a
Notification falhou e a repete algumas vezes com backoff exponencial.
Personalize o payload da Notification
Por padrão, as requisições de webhook incluem o
Assembly Status JSON completo. Se suas Assemblies
produzem muitos resultados, você pode reduzir o tamanho do payload com notification_payload.
Adicione-o junto de notify_url:
{
"steps": {
// …
},
"notify_url": "https://example.com/transloadit_pingback",
"notification_payload": ["without_results", "without_upload_meta_data"]
}
notification_payloadArray<without_params | without_result_meta_data | without_results | without_upload_meta_data | without_uploads>Controla o tamanho do payload enviado nas Assembly Notifications (tanto a notificação inicial quanto os reenvios de notificação). Um array vazio (padrão) envia o status completo da Assembly. Adicione
"without_params"para remover os campos JSON brutos das instruções da Assembly (params,templateemerged_params). Adicione"without_upload_meta_data"para removermetados arquivos emuploads. Adicione"without_result_meta_data"para removermetados arquivos emresults. Adicione"without_uploads"para removeruploadspor completo. Adicione"without_results"para removerresultspor completo. A filtragem é aplicada antes da serialização, portanto usar essas opções reduz o uso de memória e ajuda a evitar falhas de payload grande demais ou de OOM em Assemblies grandes.
Você pode combinar vários valores no mesmo array. Isso também vale quando você reenvia notificações a partir da página da Assembly.
Como é essa requisição POST?
Essa requisição POST multipart contém um campo chamado transloadit, que contém o
Assembly Status JSON completo. Você encontra um exemplo disso na nossa
documentação de resposta da API (English). Ela também contém um campo
signature. Verifique-o com o Auth Secret pertencente
à Auth Key usada para a Assembly original antes de confiar no payload. A verificação deve usar
exatamente a string do campo transloadit, antes de fazer o parse ou reserializar seu JSON.
Exemplo de código
Vamos supor que você tenha realmente especificado "notify_url": "https://example.com/transloadit_pingback" e
que o servidor back-end que receberia os POSTs ali fosse escrito em Node.js.
Este exemplo mostra como verificar assinaturas de webhook recebidas da Transloadit, o que é diferente de gerar assinaturas para requisições de API. Para criar Assemblies com geração automática de assinatura, use nossos SDKs (English). Se você quiser ver como a verificação de assinatura funciona nos bastidores, você pode consultar o código-fonte dos utilitários de assinatura.
Este exemplo usa Node.js 24 ou mais recente, seu parser multipart integrado e o verificador oficial de assinatura. Instale suas dependências:
yarn add @transloadit/utils@4.7.1 zod@3.25.76
Use um projeto ES module ("type": "module" em package.json) e salve o seguinte como
notification-backend-node.ts:
import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'
import { verifyWebhookSignature } from '@transloadit/utils'
import { z } from 'zod'
const authSecret = process.env.AUTH_SECRET
if (!authSecret) throw new Error('Set AUTH_SECRET to the secret used for the original Assembly')
const port = Number(process.argv[2] ?? '3020')
if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error('Invalid port')
const maxBodyBytes = 1024 * 1024
const notificationSchema = z.object({ assembly_id: z.string().regex(/^[a-f0-9]{32}$/u) })
function respond(res: ServerResponse, status: number, message: string): void {
res.writeHead(status, { 'Content-Type': 'text/plain; charset=utf-8', Connection: 'close' })
res.end(message)
}
async function receive(req: IncomingMessage, res: ServerResponse, secret: string): Promise<void> {
if (req.url !== '/transloadit_pingback' || req.method !== 'POST') {
return respond(res, 404, 'Not found')
}
const contentType = req.headers['content-type'] ?? ''
if (contentType.split(';')[0].trim().toLowerCase() !== 'multipart/form-data') {
return respond(res, 415, 'Expected multipart form data')
}
const chunks: Buffer[] = []
let bytes = 0
// Keep the socket open long enough to send 413 when rejecting a streaming request.
for await (const chunk of req.iterator({ destroyOnReturn: false })) {
if (!Buffer.isBuffer(chunk)) throw new Error('Expected a binary request stream')
bytes += chunk.length
if (bytes > maxBodyBytes) return respond(res, 413, 'Notification too large')
chunks.push(chunk)
}
let assemblyId: string
try {
const form = await new Request('http://localhost/transloadit_pingback', {
method: 'POST',
headers: { 'Content-Type': contentType },
body: Buffer.concat(chunks),
}).formData()
const payload = form.get('transloadit')
const signature = form.get('signature')
if (
form.getAll('transloadit').length !== 1 ||
form.getAll('signature').length !== 1 ||
typeof payload !== 'string' ||
typeof signature !== 'string'
) {
return respond(res, 400, 'Expected one payload and one signature')
}
if (!(await verifyWebhookSignature({ rawBody: payload, signatureHeader: signature, authSecret: secret }))) {
return respond(res, 403, 'Invalid signature')
}
assemblyId = notificationSchema.parse(JSON.parse(payload)).assembly_id
} catch {
return respond(res, 400, 'Invalid notification')
}
console.log(`Verified notification for Assembly ${assemblyId}`)
respond(res, 200, 'Accepted')
}
const server = createServer({ requestTimeout: 30_000 }, (req, res) => {
receive(req, res, authSecret).catch(() => respond(res, 500, 'Unable to accept notification'))
})
server.listen(port, '127.0.0.1', () => {
const address = server.address()
if (address && typeof address !== 'string') {
console.log(`Server started, listening on http://127.0.0.1:${address.port}`)
}
})
Esta demonstração de verificação registra apenas o Assembly ID. Ela aceita payloads que omitem uploads ou
results e limita a requisição inteira a 1 MiB. Ajuste esse limite conforme os payloads que você
espera ou use notification_payload para reduzir o tamanho deles.
Antes de usar isso em produção, verifique se a Assembly pertence à operação e ao Workspace que você
espera, valide os campos que sua aplicação consome e armazene de forma durável ou enfileire a
notificação verificada antes de retornar 200. Trate notificações repetidas de forma idempotente.
Uma assinatura válida não torna uma notificação nova, e esta demonstração de log também não persiste
resultados. Mantenha o Auth Secret no lado do servidor e coloque o endpoint atrás do seu proxy
reverso HTTPS.
Execute o servidor com o Auth Secret fornecido pelo seu ambiente:
$ env AUTH_SECRET=******** node notification-backend-node.ts 3020
Server started, listening on http://127.0.0.1:3020
Testando o exemplo de código localmente
Ao testar localmente atrás de um NAT, use o Cloudflare Tunnel, o ngrok ou o pacote oficial @transloadit/notify-url-relay via npx -y @transloadit/notify-url-relay; diferentemente dos túneis, o relay consulta o Assembly Status público e encaminha as notificações finais para o seu handler local notify_url.
Recomendado (relay oficial), em uma nova aba:
$ TRANSLOADIT_SECRET=******** npx -y @transloadit/notify-url-relay \
--notifyUrl "http://127.0.0.1:3020/transloadit_pingback" \
--log-level info
notify-url-relay [ NOTICE] Listening on http://localhost:8888, forwarding to https://api2.transloadit.com, notifying http://127.0.0.1:3020/transloadit_pingback
Ao usar o relay, aponte o endpoint Transloadit do seu app/SDK para http://127.0.0.1:8888.
Agora você pode criar um Template e colar as seguintes Instructions:
{
"notify_url": "http://127.0.0.1:3020/transloadit_pingback",
"steps": {
":original": {
"robot": "/upload/handle"
},
"faces_detected": {
"use": ":original",
"robot": "/image/facedetect",
"crop": true,
"faces": "max-confidence",
"crop_padding": "10%",
"format": "preserve"
}
}
}
Se você preferir um túnel, use o Cloudflare Tunnel ou o ngrok.
No momento em que escrevemos, o ngrok parece ter problemas com faixas da AWS. Se esse for o seu caso, uma alternativa para testar é o Cloudflare Tunnel ou o pacote oficial @transloadit/notify-url-relay.
Agora você está pronto para testar direto no navegador. As Instructions que usamos detectam um rosto, então, para resultados ideais, faça upload da foto de uma pessoa usando a área de testes do Template Editor. Você pode usar o recurso Webcam do Uppy se não tiver uma imagem disponível.
Seu script Node.js deve informar que recebeu a Assembly Notification com sucesso quando a Assembly for concluída:
Verified notification for Assembly 0123456789abcdef0123456789abcdef
O Assembly ID na sua saída vai corresponder à Assembly que você criou.
Além disso, você verá um registro da notificação na página da Assembly, onde também pode reenviá-la manualmente para testes adicionais.
O código de exemplo acima mostra como verificar assinaturas de webhook em Node.js. Para criar Assemblies com geração automática de assinatura (em vez de verificar webhooks recebidos), veja os exemplos de SDK na documentação de Signature Authentication (English).