Visão geral
A API do OnBriefing verifica se vídeos publicados por creators no TikTok, Instagram e YouTube cumprem o briefing de uma campanha. Você cria a campanha com o briefing, envia as URLs dos vídeos e recebe um laudo por vídeo, com um veredito e uma linha por regra, cada uma com evidência.
https://onbriefing.com/api/v1- Corpo das requisições e respostas em JSON (
Content-Type: application/json), UTF-8. - Datas em ISO 8601, UTC, por exemplo
2026-10-09T14:30:00.000Z. - IDs são strings opacas. Não presuma formato nem tamanho.
- Campos novos podem ser adicionados às respostas a qualquer momento; ignore os que não conhecer.
- A análise é assíncrona: o envio responde na hora, o laudo fica pronto em minutos.
Autenticação
Toda chamada exige uma chave de API no header Authorization, no formato Bearer. As chaves começam com obk_.
Authorization: Bearer obk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxComo obter uma chave
- Crie uma conta em onbriefing.com/cadastro (10 vídeos grátis, sem cartão) ou entre na sua. Toda conta pode gerar chaves de API.
- No painel, abra Configurações → Chaves de API → Gerar chave e dê um nome (por exemplo,
integração-produção). - Copie o valor na hora: ele aparece uma única vez. O OnBriefing guarda só um hash da chave e não consegue mostrá-la de novo.
Escopo e segurança
- A chave pertence à organização e dá acesso a todas as campanhas e verificações dela.
- Recursos de outra organização respondem
404, como se não existissem. - Guarde a chave como segredo do servidor (variável de ambiente ou cofre). Nunca a use em código que roda no navegador ou no app do usuário.
- Uma chave revogada no painel para de funcionar imediatamente. Para trocar sem downtime, gere a nova, faça o deploy e só então revogue a antiga.
Início rápido
Do zero ao primeiro laudo em três chamadas.
1. Crie a campanha
curl -X POST https://onbriefing.com/api/v1/campaigns \
-H "Authorization: Bearer $ONBRIEFING_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Verão 2026: lançamento",
"brand": "Marca X",
"rulesText": "O vídeo deve ter no mínimo 30s, mostrar o produto em uso, citar o cupom VERAO26 na fala e usar #MarcaXVerao e #publi na legenda. Não pode citar concorrentes."
}'Guarde o id da resposta.
2. Envie os vídeos
curl -X POST https://onbriefing.com/api/v1/campaigns/$CAMPAIGN_ID/verifications \
-H "Authorization: Bearer $ONBRIEFING_KEY" \
-H "Content-Type: application/json" \
-d '{ "urls": ["https://www.tiktok.com/@creator/video/7300000000000000001"] }'Cada URL com status: "queued" traz o id da verificação.
3. Busque o laudo
curl https://onbriefing.com/api/v1/verifications/$VERIFICATION_ID \
-H "Authorization: Bearer $ONBRIEFING_KEY"Quando status for COMPLETED, o laudo está em verdict, summary e findings. Em produção, troque a consulta pelo webhook.
Exemplo completo em Node.js
const BASE = "https://onbriefing.com/api/v1";
const headers = {
Authorization: `Bearer ${process.env.ONBRIEFING_KEY}`,
"Content-Type": "application/json",
};
async function api(path, init = {}) {
const res = await fetch(BASE + path, { ...init, headers });
const body = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${body.error}`);
return body;
}
const campaign = await api("/campaigns", {
method: "POST",
body: JSON.stringify({ name: "Pilot", brand: "Brand X", rulesText: BRIEF }),
});
const { outcomes } = await api(`/campaigns/${campaign.id}/verifications`, {
method: "POST",
body: JSON.stringify({ urls: VIDEO_URLS }),
});
const ids = outcomes.filter((o) => o.status === "queued").map((o) => o.id);
async function waitFor(id) {
for (;;) {
const v = await api(`/verifications/${id}`);
if (v.status === "COMPLETED" || v.status === "FAILED") return v;
await new Promise((r) => setTimeout(r, 30_000));
}
}
const reports = await Promise.all(ids.map(waitFor));Exemplo em Python
import os, time, requests
BASE = "https://onbriefing.com/api/v1"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['ONBRIEFING_KEY']}"
campaign = s.post(f"{BASE}/campaigns", json={
"name": "Pilot", "brand": "Brand X", "rulesText": BRIEF,
}).json()
outcomes = s.post(f"{BASE}/campaigns/{campaign['id']}/verifications",
json={"urls": VIDEO_URLS}).json()["outcomes"]
for o in outcomes:
if o["status"] != "queued":
continue
while True:
v = s.get(f"{BASE}/verifications/{o['id']}").json()
if v["status"] in ("COMPLETED", "FAILED"):
print(v["videoUrl"], v["status"], v["verdict"])
break
time.sleep(30)Conceitos
| Campo | Tipo | Descrição |
|---|---|---|
| Campanha | Campaign | Nome, marca e o briefing (rulesText). Agrupa as verificações. |
| Briefing | rulesText | O texto que você já manda aos creators, em linguagem livre. O OnBriefing separa as regras sozinho e marca as que não dá para conferir por vídeo. |
| Verificação | Verification | A análise de uma URL de vídeo dentro de uma campanha. |
| Laudo | verdict + findings | O resultado: veredito geral, resumo e uma linha por regra, com evidência. |
| Achado | Finding | O resultado de uma regra: status, severidade, justificativa, confiança e evidências. |
O briefing é congelado no envio
Cada verificação guarda o briefing que valia no momento em que a URL foi enviada. Editar a campanha depois afeta só os próximos envios; laudos já emitidos continuam explicáveis contra a régua original.
Ciclo de vida de uma verificação
QUEUED → DOWNLOADING → TRANSCRIBING → ANALYZING → COMPLETED
↘ FAILEDCOMPLETED e FAILED são estados finais. Quando a plataforma de vídeo limita o acesso temporariamente, a verificação espera e tenta de novo sozinha, e pode ficar alguns minutos a mais em QUEUED ou DOWNLOADING.
Criar campanha
Corpo
| Campo | Tipo | Descrição |
|---|---|---|
| name | string | Obrigatório. Nome da campanha; não pode ser vazio. |
| brand | string | null | Opcional. Marca anunciante. |
| rulesText | string | Obrigatório. Briefing em texto livre, com pelo menos 20 caracteres. |
POST /api/v1/campaigns
{
"name": "Verão 2026: lançamento",
"brand": "Marca X",
"rulesText": "O vídeo deve ter no mínimo 30s, mostrar o produto em uso e citar o cupom VERAO26."
}{
"id": "cm8x1a2b3c4d5e6f7g8h9i0j",
"orgId": "cm7o...",
"name": "Verão 2026: lançamento",
"brand": "Marca X",
"rulesText": "O vídeo deve ter no mínimo 30s, mostrar o produto em uso e citar o cupom VERAO26.",
"active": true,
"archivedAt": null,
"hasWebhook": false,
"webhookUrl": null,
"createdAt": "2026-10-09T14:00:00.000Z",
"updatedAt": "2026-10-09T14:00:00.000Z"
}Erros: 400 se o corpo não for JSON ou faltar campo; 422 se name for vazio ou rulesText tiver menos de 20 caracteres. O campo com problema vem em field.
Ler campanha
Devolve o mesmo objeto da criação, mais verificationCount , o total de vídeos já enviados para a campanha. O webhookSecret nunca aparece aqui.
{
"id": "cm8x1a2b3c4d5e6f7g8h9i0j",
"name": "Verão 2026: lançamento",
"hasWebhook": true,
"webhookUrl": "https://seu-sistema.com/webhooks/onbriefing",
"verificationCount": 128,
...
}Atualizar campanha
Envie só os campos que quer mudar.
| Campo | Tipo | Descrição |
|---|---|---|
| name | string | Novo nome; não pode ser vazio. |
| brand | string | null | Nova marca; null remove. |
| rulesText | string | Novo briefing, com pelo menos 20 caracteres. Vale para os próximos envios. |
| webhookUrl | string | null | URL que recebe os laudos. null remove o webhook e o segredo. |
O segredo do webhook aparece uma vez
Ao definir webhookUrl numa campanha que ainda não tinha webhook, a resposta traz um campo webhookSecret. Guarde-o nessa hora : ele assina todos os webhooks e não volta em nenhuma leitura.
PATCH /api/v1/campaigns/cm8x1a2b3c4d5e6f7g8h9i0j
{ "webhookUrl": "https://seu-sistema.com/webhooks/onbriefing" }{
"id": "cm8x1a2b3c4d5e6f7g8h9i0j",
"hasWebhook": true,
"webhookUrl": "https://seu-sistema.com/webhooks/onbriefing",
"webhookSecret": "9f2c6b1e...64 caracteres hex"
}- Trocar a URL de um webhook que já existe mantém o mesmo segredo.
- Para gerar um segredo novo, mande
{ "webhookUrl": null }e depois configure a URL de novo.
Enviar vídeos
| Campo | Tipo | Descrição |
|---|---|---|
| urls | string[] | De 1 a 500 URLs de vídeos publicados no TikTok, Instagram ou YouTube. |
POST /api/v1/campaigns/cm8x1a2b3c4d5e6f7g8h9i0j/verifications
{
"urls": [
"https://www.tiktok.com/@creator1/video/7300000000000000001",
"https://www.instagram.com/reel/ABC123/",
"https://www.youtube.com/shorts/dQw4w9WgXcQ",
"https://example.com/video"
]
}A resposta vem linha a linha, na ordem do envio. Uma URL com problema não derruba as outras.
{
"outcomes": [
{ "url": "https://www.tiktok.com/@creator1/video/7300000000000000001", "status": "queued", "id": "cm8x9z..." },
{ "url": "https://www.instagram.com/reel/ABC123/", "status": "duplicate" },
{ "url": "https://www.youtube.com/shorts/dQw4w9WgXcQ", "status": "insufficient_credits", "detail": "..." },
{ "url": "https://example.com/video", "status": "invalid", "detail": "Host não permitido: example.com. Aceitos: TikTok, Instagram e YouTube." }
]
}| Campo | Tipo | Descrição |
|---|---|---|
| queued | status | Entrou na fila. Guarde o id da verificação. |
| duplicate | status | Essa URL já foi enviada para esta campanha. Nada é cobrado; consulte a verificação existente. |
| invalid | status | URL malformada ou de plataforma não suportada. detail explica. |
| insufficient_credits | status | A organização não tem créditos para nem um minuto de vídeo. detail mostra quantos créditos restam. |
Quais URLs são aceitas
- Só
https, sem porta e sem usuário/senha na URL. - Hosts:
tiktok.com,www.tiktok.com,m.tiktok.com,vm.tiktok.com,vt.tiktok.com,instagram.com,www.instagram.com,youtube.com,www.youtube.com,m.youtube.comeyoutu.be. - A URL é normalizada: query string e
#são descartados (exceto ovdo YouTube). A URL devolvida emoutcomes[].urlé a normalizada, e é ela que identifica o vídeo na campanha. - URLs repetidas dentro do mesmo envio contam uma vez só.
- O vídeo precisa ser público. Vídeo privado ou que exige login falha com
AUTH_REQUIRED.
Listar verificações
| Campo | Tipo | Descrição |
|---|---|---|
| status | query, opcional | Filtra por estado: QUEUED, DOWNLOADING, TRANSCRIBING, ANALYZING, COMPLETED ou FAILED. |
| cursor | query, opcional | O nextCursor da página anterior. |
Páginas de 50 itens, das verificações mais recentes para as mais antigas. nextCursor é null na última página. Os itens trazem o resumo; para os achados, use Consultar verificação.
{
"items": [
{
"id": "cm8x9z...",
"videoUrl": "https://www.tiktok.com/@creator1/video/7300000000000000001",
"platform": "TIKTOK",
"status": "COMPLETED",
"verdict": "APPROVED",
"finalVerdict": null,
"errorCode": null,
"createdAt": "2026-10-09T14:01:00.000Z",
"completedAt": "2026-10-09T14:04:12.000Z"
}
],
"nextCursor": "cm8x9y..."
}let cursor = null;
do {
const qs = new URLSearchParams({ status: "COMPLETED", ...(cursor ? { cursor } : {}) });
const page = await api(`/campaigns/${campaignId}/verifications?${qs}`);
for (const item of page.items) handle(item);
cursor = page.nextCursor;
} while (cursor);Consultar verificação
Devolve a verificação completa, com o laudo e as evidências de cada regra.
{
"id": "cm8x9z...",
"campaignId": "cm8x1a2b3c4d5e6f7g8h9i0j",
"videoUrl": "https://www.tiktok.com/@creator1/video/7300000000000000001",
"platform": "TIKTOK",
"status": "COMPLETED",
"verdict": "REJECTED",
"finalVerdict": null,
"summary": "Mostra o produto e usa a hashtag, mas não cita o cupom e dura 22s.",
"contentCategories": ["REVIEW", "DEPOIMENTO"],
"errorCode": null,
"error": null,
"createdAt": "2026-10-09T14:01:00.000Z",
"startedAt": "2026-10-09T14:01:05.000Z",
"completedAt": "2026-10-09T14:04:12.000Z",
"findings": [
{
"ruleText": "Citar o cupom VERAO26 na fala",
"scope": "VERIFIABLE",
"status": "FAIL",
"severity": "MAJOR",
"rationale": "O cupom não aparece na transcrição nem no texto da tela.",
"confidence": 0.86,
"evidence": [
{ "type": "ABSENT", "note": "Transcrição completa e texto da tela; nenhuma menção a VERAO26.",
"frameIndex": null, "timestampMs": null, "quote": null, "field": null, "value": null }
]
},
{
"ruleText": "Usar #MarcaXVerao na legenda",
"scope": "VERIFIABLE",
"status": "PASS",
"severity": "MAJOR",
"rationale": "A hashtag está na legenda.",
"confidence": 0.97,
"evidence": [
{ "type": "METADATA", "field": "hashtags", "value": "marcaxverao, publi",
"frameIndex": null, "timestampMs": null, "quote": null, "note": null }
]
}
]
}Enquanto a análise não termina, verdict, summary e completedAt vêm null e findings vem vazio.
O laudo
Verificação
| Campo | Tipo | Descrição |
|---|---|---|
| status | enum | QUEUED · DOWNLOADING · TRANSCRIBING · ANALYZING · COMPLETED · FAILED |
| platform | enum | TIKTOK · INSTAGRAM · YOUTUBE |
| verdict | enum | null | Veredito automático: APPROVED (on briefing), REJECTED (off briefing) ou INCONCLUSIVE (a evidência não basta e precisa de revisão humana). |
| finalVerdict | enum | null | Veredito depois de revisão humana no painel. null até alguém revisar. Quando preenchido, é a palavra final. |
| summary | string | null | Resumo do laudo em português. |
| contentCategories | string[] | Até 3 categorias de formato do vídeo, da mais para a menos relevante. Vazio quando não categorizado. |
| errorCode | string | null | Só em FAILED. Veja Erros. |
| error | string | null | Só em FAILED. Mensagem legível sobre a falha. |
Achado (finding)
| Campo | Tipo | Descrição |
|---|---|---|
| ruleText | string | A regra, como o OnBriefing a extraiu do briefing. |
| scope | enum | VERIFIABLE: dá para conferir no vídeo. OUT_OF_SCOPE: depende de dado externo (impulsionamento, data de publicação, permanência do post) e vem sempre com status: UNVERIFIABLE. |
| status | enum | PASS · FAIL · UNVERIFIABLE |
| severity | enum | BLOCKER (proibição ou exigência legal), MAJOR (entrega central) ou MINOR (detalhe). É o peso da regra e vale mesmo quando ela passou. |
| rationale | string | Por que a regra passou, falhou ou não pôde ser verificada. |
| confidence | number | De 0 a 1. |
| evidence | Evidence[] | Uma ou mais evidências que sustentam o resultado. |
Evidência
Todo objeto de evidência tem os mesmos campos; os que não se aplicam ao type vêm null.
| Campo | Tipo | Descrição |
|---|---|---|
| FRAME | type | Algo visto num frame. Usa frameIndex, timestampMs e note (o que se vê). |
| TRANSCRIPT | type | Algo dito. Usa timestampMs e quote (trecho literal da fala). |
| SCREEN_TEXT | type | Texto sobreposto ao vídeo. Usa timestampMs e quote. |
| METADATA | type | Campo do post. Usa field (caption, hashtags, mentions, durationMs, author, dimensions) e value. |
| SOURCE_MATCH | type | Trecho que casa com o material oficial da campanha. Usa note. |
| ABSENT | type | O resultado se apoia numa ausência. note diz onde se procurou. |
Categorias de conteúdo
Valores possíveis de contentCategories. A lista pode crescer; trate um código desconhecido como OUTRO.
| Campo | Tipo | Descrição |
|---|---|---|
| MEME | categoria | Meme / humor |
| CASAL | categoria | Casal |
| ESQUETE | categoria | Esquete / encenação |
| TREND | categoria | Trend / dança |
| REVIEW | categoria | Review / unboxing |
| TUTORIAL | categoria | Tutorial / dica |
| RECEITA | categoria | Receita / culinária |
| BELEZA_MODA | categoria | Beleza / moda |
| VLOG | categoria | Vlog / rotina |
| DEPOIMENTO | categoria | Depoimento / opinião |
| REACT | categoria | React / comentário |
| CORTE | categoria | Corte de live / podcast |
| GAMEPLAY | categoria | Gameplay |
| OUTRO | categoria | Outro |
Como usar o veredito
- Use
verdictpara triagem automática:APPROVEDsegue,REJECTEDvolta para o creator com os achadosFAIL,INCONCLUSIVEvai para revisão humana. - Se
finalVerdictestiver preenchido, ele prevalece sobreverdict. - Para o feedback ao creator, mostre
ruleTexterationaledos achados comstatus: FAIL, ordenando porseverity.
Webhooks
Com webhookUrl configurado na campanha, o OnBriefing faz um POST para essa URL sempre que uma verificação chega a um estado final.
| Campo | Tipo | Descrição |
|---|---|---|
| verification.completed | evento | A análise terminou e o laudo está pronto. |
| verification.failed | evento | A análise falhou. Veja errorCode. O crédito já foi devolvido. |
Requisição
POST https://seu-sistema.com/webhooks/onbriefing
Content-Type: application/json
X-OnBriefing-Event: verification.completed
X-OnBriefing-Signature: sha256=5d41402abc4b2a76b9719d911017c592...
{
"event": "verification.completed",
"verification": {
"id": "cm8x9z...",
"campaignId": "cm8x1a2b3c4d5e6f7g8h9i0j",
"videoUrl": "https://www.tiktok.com/@creator1/video/7300000000000000001",
"platform": "TIKTOK",
"status": "COMPLETED",
"verdict": "REJECTED",
"summary": "Mostra o produto e usa a hashtag, mas não cita o cupom e dura 22s.",
"contentCategories": ["REVIEW"],
"errorCode": null,
"completedAt": "2026-10-09T14:04:12.000Z",
"findings": [
{ "ruleText": "Citar o cupom VERAO26 na fala", "scope": "VERIFIABLE",
"status": "FAIL", "severity": "MAJOR",
"rationale": "O cupom não aparece na transcrição.", "confidence": 0.86 }
]
}
}O payload do webhook é enxuto: os achados vêm sem evidence. Para as evidências (frames, falas, metadados), chame GET /verifications/:id.
Validar a assinatura
X-OnBriefing-Signature é o HMAC-SHA256, em hexadecimal, do corpo bruto da requisição, assinado com o webhookSecret da campanha. Calcule sobre os bytes recebidos (não sobre o JSON re-serializado) e compare em tempo constante. Rejeite com 401 se não bater.
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";
const app = express();
app.post(
"/webhooks/onbriefing",
express.raw({ type: "application/json" }), // corpo bruto, sem parse
(req, res) => {
const expected = createHmac("sha256", process.env.ONBRIEFING_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const received = String(req.get("X-OnBriefing-Signature") ?? "").replace("sha256=", "");
const valid =
expected.length === received.length &&
timingSafeEqual(Buffer.from(expected), Buffer.from(received));
if (!valid) return res.sendStatus(401);
const { event, verification } = JSON.parse(req.body);
// Responda rápido; processe em segundo plano.
queue.add({ event, verification });
res.sendStatus(200);
},
);import { createHmac, timingSafeEqual } from "node:crypto";
export async function POST(request: Request) {
const raw = await request.text();
const expected = createHmac("sha256", process.env.ONBRIEFING_WEBHOOK_SECRET!).update(raw).digest("hex");
const received = (request.headers.get("x-onbriefing-signature") ?? "").replace("sha256=", "");
if (expected.length !== received.length ||
!timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
return new Response("assinatura inválida", { status: 401 });
}
const { event, verification } = JSON.parse(raw);
// ...
return new Response(null, { status: 200 });
}import hmac, hashlib, os
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = os.environ["ONBRIEFING_WEBHOOK_SECRET"].encode()
@app.post("/webhooks/onbriefing")
def onbriefing_webhook():
raw = request.get_data() # corpo bruto
expected = hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
received = request.headers.get("X-OnBriefing-Signature", "").removeprefix("sha256=")
if not hmac.compare_digest(expected, received):
abort(401)
payload = request.get_json()
# ...
return "", 200Entrega e novas tentativas
- Responda com qualquer status
2xxem até 10 segundos para confirmar o recebimento. - Resposta fora de
2xx, erro de rede ou timeout geram novas tentativas: até 5, com intervalo crescente a partir de 30 segundos. - A mesma verificação pode chegar mais de uma vez. Trate o handler como idempotente, usando
verification.idcomo chave. - A ordem de chegada não é garantida entre verificações diferentes.
- Mantenha uma consulta periódica de segurança (por exemplo, a cada hora, listando por
status) para recuperar qualquer webhook perdido.
Erros
Erros da API vêm com status HTTP e um corpo JSON com error (mensagem em português) e, em erros de validação de campo, field.
{ "error": "Cole o briefing da campanha. É ele que define o que será verificado.", "field": "rulesText" }Status HTTP
| Campo | Tipo | Descrição |
|---|---|---|
| 200 / 201 | sucesso | Requisição aceita. 201 na criação de campanha. |
| 400 | requisição | Corpo não é JSON, campo com tipo errado, lote com mais de 500 URLs ou status de filtro inválido. |
| 401 | autenticação | Chave ausente, inválida ou revogada. |
| 404 | não encontrado | Campanha ou verificação inexistente ou de outra organização. |
| 422 | validação | Campo com valor inválido (name vazio, rulesText curto). Veja field. No PATCH, esses casos podem vir como 400. |
| 5xx | servidor | Erro do OnBriefing. Tente de novo com espera exponencial; reenviar URLs é seguro. |
Falhas de verificação
Uma verificação em FAILED traz errorCode e error. Os créditos da análise são devolvidos.
| Campo | Tipo | Descrição |
|---|---|---|
| AUTH_REQUIRED | errorCode | O vídeo é privado ou exige login para ser visto. Peça ao creator para torná-lo público. |
| VIDEO_UNAVAILABLE | errorCode | O vídeo foi removido ou não existe. |
| GEO_BLOCKED | errorCode | O vídeo existe, mas a plataforma não o libera para a região de onde a verificação baixa. |
| VIDEO_TOO_LONG | errorCode | O vídeo passa de 10 minutos, o limite atual. |
| RATE_LIMITED | errorCode | A plataforma de vídeo bloqueou o acesso mesmo depois das novas tentativas automáticas. |
| NETWORK_ERROR | errorCode | Não foi possível alcançar a plataforma de vídeo. |
| DOWNLOAD_FAILED | errorCode | O download falhou por outro motivo. |
| PIPELINE_FAILED | errorCode | Falha interna na análise. |
Uma verificação em FAILED continua ocupando a URL na campanha: reenviar a mesma URL volta como duplicate. Para reprocessar, fale com a gente.
Limites e créditos
- Até 500 URLs por chamada de envio. Para mais, divida em lotes.
- Vídeos de até 10 minutos.
- Listagem paginada em 50 itens por página.
- Não há limite publicado de requisições por minuto hoje. O que tem fila é o processamento: enviar 500 vídeos de uma vez é normal, eles ficam prontos ao longo dos minutos seguintes.
- A cobrança é em créditos: 1 crédito por minuto de vídeo, e a fração conta como minuto inteiro. Os créditos vêm do plano mensal da conta ou de créditos adicionais. O envio confere se há ao menos um crédito por vídeo; o débito exato acontece quando o processamento começa, já com a duração conhecida. Sem créditos, a URL volta como
insufficient_creditse não entra na fila. URLsduplicateeinvalidnão custam nada, e análises que falham são estornadas. - O plano e os créditos adicionais ficam no painel, em Créditos, com cartão (contas em dólar pagam com cartão internacional). Volume alto ou contrato: plano Enterprise, pelo formulário de contato.
Boas práticas
- Configure o webhook antes de enviar os vídeos, para não perder nenhum resultado.
- Guarde o
idda verificação junto com o registro da entrega no seu sistema. É ele que liga o webhook à entrega certa. - Use a URL normalizada de
outcomes[].urlpara cruzar dados, não a URL que você enviou. - Sem webhook, consulte a cada 30–60 segundos e só as verificações que ainda não terminaram.
- Em caso de timeout no envio, reenvie o mesmo lote: o que já entrou volta como
duplicate, sem cobrança dupla. - Escreva o briefing como você escreveria para o creator, com regras concretas ("citar o cupom VERAO26 na fala") em vez de genéricas ("falar bem do produto").
- Uma campanha por briefing: se as regras mudam por grupo de creators, crie campanhas separadas.
Versões
A versão atual é a v1, no caminho /api/v1. Mudanças compatíveis, como campos novos em respostas e novos valores de categoria, entram sem mudar a versão. Mudanças incompatíveis vão para uma nova versão, com aviso prévio aos clientes da API.
Ficou alguma dúvida?
Fale direto com quem constrói a API. A gente ajuda a desenhar a integração.
Falar com a equipe