Como usar a API
Referência de API Key — Cloakup
Visão geral
- URL base:
https://api.cloakup.me(sem barra no final). Env:CLOAKUP_API_URL. - Caminho base da API pública:
/v1 - Formato da API key:
ck_+ 64 caracteres hex (ex.:ck_a1b2c3...) - Header de autenticação:
Authorization: Bearer ck_<secret> - Content-Type:
application/json - IDs: numéricos (
bigintserializado como número ou string JSON, dependendo do serializador) - Enums de filtros de campanha: regras em Valores permitidos nos filtros de campanha (3 exemplos cada + links de formato)
- Segurança em produção: leia Crítico: não publique campanhas em revisão antes de criar campanhas
- Criação de campanha: você não precisa de todos os campos — veja Defaults na criação de campanha
Fluxo recomendado
- Garanta que um domínio existe:
POST /v1/domains→PATCH /v1/domains/:id/verify(atéverified: true). - Crie a campanha com o exemplo mínimo — mantenha
"deny_always": false(ou omita). - Confirme com
GET /v1/campaigns/:idou listagem (in_reviewdeve serfalsepara produção).
Anti-padrões (não faça)
- Não defina
filters.deny_always: truea menos que o usuário queira explicitamente modo revisão/teste. - Não copie o objeto
filterscompleto de uma resposta GET para POST/PUT. - Não invente códigos de país ou idiomas de navegador — siga os links de formato abaixo; case/nome errado →
422. - Não envie valores de
filters.query.paramscomo string simples — semprestring[](ex.:"utm_source": ["google"]). - Não coloque
http(s)://,wwwou/nonamedo domínio. - Não trate PUT como PATCH parcial — envie um
CampaignBodycompleto. - Não use
https://api.example.com— usehttps://api.cloakup.me(ouCLOAKUP_API_URL).
Crítico: não publique campanhas em revisão
Para agentes de IA e scripts: defaults errados aqui queimam verba de anúncios — todo visitante vê apenas a página segura.
Campo na requisição | Campo na resposta de listagem | Onde na resposta show/create | Efeito quando |
|---|---|---|---|
|
|
| Sempre mostra a página segura (white). Sem tráfego para a oferta. Use apenas durante testes. |
Default para produção: omita deny_always ou defina "deny_always": false.
Nunca copie deny_always: true dos exemplos a menos que o usuário peça explicitamente modo revisão/teste.
Parâmetros de query na URL (filters.query)
O Cloakup compara parâmetros de query da URL com filters.query.params. Cada chave mapeia para um array de valores permitidos (não uma string simples).
"query": {
"allow": true,
"remove_params": false,
"condition": "some",
"params": {
"utm_source": ["google"]
},
"rules": {
"utm_source": "equals"
}
}Campo | Tipo | Descrição |
|---|---|---|
|
| Nome do parâmetro → lista de valores permitidos na URL |
|
| Regra de match por parâmetro: |
|
|
|
|
|
|
|
| Remove os params correspondentes da URL antes do redirect |
Curinga: use "*" como valor para aceitar qualquer valor daquela chave:
"params": {
"utm_source": ["*"]
},
"rules": {
"utm_source": "equals"
}Isso só verifica se utm_source existe na URL — o valor real não importa.
params: {} vazio significa sem filtro por parâmetros de URL.
Pré-requisitos (toda requisição /v1)
Cadeia de middleware aplicada a todas as rotas /v1:
- API key válida (
Authorization: Bearer ck_...) - Rate limit: 120 requisições/minuto por key
- Plano deve ter API keys habilitadas (
plan.api_keys_enabled) - Assinatura cloakup ativa
- Scope específico da rota (veja cada endpoint)
Scopes
Scope | Descrição |
|---|---|
| Listar campanhas |
| Criar campanha |
| Obter campanha por ID |
| Atualizar campanha |
| Excluir campanha |
| Clonar campanha |
| Alternar status ativo da campanha |
| Listar domínios |
| Registrar domínio |
| Verificar DNS/certificado do domínio |
| Excluir domínio |
Resposta de erro
Todos os erros da aplicação retornam JSON:
{
"message": "string",
"action": "string",
"code": "string",
"data": {}
}HTTP | Significado |
|---|---|
| API key ausente/inválida/expirada/revogada |
| Scope ausente, API keys desabilitadas no plano ou assinatura inativa |
| Recurso não encontrado (ou não pertence ao usuário) |
| Erro de validação ( |
| Rate limit excedido |
Schemas compartilhados
Error
{
"$id": "Error",
"type": "object",
"properties": {
"message": { "type": "string" },
"action": { "type": "string" },
"code": { "type": "string" },
"data": { "type": "object", "additionalProperties": true }
},
"required": ["message", "action"]
}Valores permitidos nos filtros de campanha
Para agentes de IA: create/update retorna
422se um valor não bate com o formato (ou não está na allowlist da API). Não adivinhe nomes de país ou strings de locale livres.
Campo | Tipo | Máx. itens | Formato |
|---|---|---|---|
|
| 256 | ISO 3166-1 alpha-2, maiúsculas |
|
| 255 | Tag de idioma IETF, tudo minúsculo ( |
|
| 100 | Nome do lugar (veja abaixo) |
|
| 100 | Nome do lugar (veja abaixo) |
|
| 256 | Igual a |
Códigos de país
Usados em filters.geolocation.countries e pages.offers[].segmentation.country.
Regra | Valor |
|---|---|
Formato | Exatamente 2 letras maiúsculas (ISO 3166-1 alpha-2) |
Lista completa | |
Exemplos |
|
Inválido |
|
Códigos de idioma do navegador
Usados em filters.browser_language.languages.
Regra | Valor |
|---|---|
Formato | Tag de idioma IETF em minúsculas: |
Lista / referência | |
Exemplos |
|
Inválido |
|
Nomes de estado e cidade
Usados em filters.state.states e filters.city.cities.
Regra | Valor |
|---|---|
Tamanho | 1–100 caracteres (após trim) |
Caracteres permitidos | Letras Unicode, espaços, |
Deve começar com | Uma letra |
Exemplos |
|
Inválido |
|
Nomes de lugar GeoIP em texto livre (não códigos ISO).
CampaignFilters
Usado no body de create/update de campanha.
Agentes: chaves aninhadas com default podem ser omitidas ou enviadas como
{}/ objetos parciais. O JSON Schema abaixo lista chaves de topo que devem estar presentes no create/update.allow/remove_params/ arrays vazios aninhados costumam ter default no servidor — veja Defaults na criação de campanha e o exemplo mínimo de POST. Não trate toda propriedade aninhada como obrigatória.
Enviar obrigatoriamente (topo de filters): geolocation, referer, query, domain, browser, browser_language, isp, os, user_agent, blacklist.
Opcional (defaults aplicam): flags de rede de anúncios, deny_always, bots, proxy, adspy, cloakup_ai, state, city, network_type, device, whitelist.
{ "$id": "CampaignFilters", "type": "object", "required": [ "geolocation", "referer", "query", "domain", "browser", "browser_language", "isp", "os", "user_agent", "blacklist" ], "properties": { "facebook": { "type": "boolean", "default": false }, "google": { "type": "boolean", "default": false }, "tiktok": { "type": "boolean", "default": false }, "kwai": { "type": "boolean", "default": false }, "taboola": { "type": "boolean", "default": false }, "pinterest": { "type": "boolean", "default": false }, "yandex": { "type": "boolean", "default": false }, "mgid": { "type": "boolean", "default": false }, "outbrain": { "type": "boolean", "default": false }, "sms": { "type": "boolean", "default": false }, "revcontent": { "type": "boolean", "default": false }, "adskeeper": { "type": "boolean", "default": false }, "newsbreak": { "type": "boolean", "default": false }, "adspy": { "type": "boolean", "default": true }, "deny_always": { "type": "boolean", "default": false, "description": "PERIGO: true = modo in_review, sempre mostra página segura. Use false em produção." }, "bots": { "type": "boolean", "default": true }, "proxy": { "type": "boolean", "default": true }, "cloakup_ai": { "type": "boolean", "default": true }, "geolocation": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "countries": { "type": "array", "maxItems": 256, "items": { "type": "string", "pattern": "^[A-Z]{2}$", "description": "ISO 3166-1 alpha-2 maiúsculo. Veja https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2", "examples": ["BR", "US", "PT"] } } } }, "state": { "type": "object", "properties": { "allow": { "type": "boolean" }, "states": { "type": "array", "maxItems": 100, "items": { "type": "string", "minLength": 1, "maxLength": 100, "pattern": "^[\\p{L}\\p{M}][\\p{L}\\p{M}\\s'.-]{0,99}$", "description": "Nome do lugar (não código ISO). Letras, espaços, apóstrofo, hífen, ponto.", "examples": ["São Paulo", "California", "St. Louis"] } } } }, "city": { "type": "object", "properties": { "allow": { "type": "boolean" }, "cities": { "type": "array", "maxItems": 100, "items": { "type": "string", "minLength": 1, "maxLength": 100, "pattern": "^[\\p{L}\\p{M}][\\p{L}\\p{M}\\s'.-]{0,99}$", "description": "Nome do lugar (não código ISO). Letras, espaços, apóstrofo, hífen, ponto.", "examples": ["Campinas", "New York", "O'Fallon"] } } } }, "network_type": { "type": "object", "properties": { "allow": { "type": "boolean" }, "types": { "type": "array", "items": { "enum": ["residential", "business", "wireless", "hosting", "unknown"] } } } }, "device": { "type": "object", "properties": { "allow": { "type": "boolean" }, "devices": { "type": "array", "items": { "enum": ["desktop", "smartphone", "tablet", "unknown"] } } } }, "referer": { "type": "object", "required": ["block_null", "domains"], "properties": { "block_null": { "type": "boolean" }, "allow": { "type": "boolean", "default": true }, "domains": { "type": "array", "items": { "type": "string", "maxLength": 255 } } } }, "query": { "type": "object", "required": ["params", "condition", "rules"], "properties": { "allow": { "type": "boolean", "default": true }, "remove_params": { "type": "boolean", "default": false }, "params": { "type": "object", "description": "Record<string, string[]>. Nome do parâmetro → array de valores permitidos na URL.", "additionalProperties": { "type": "array", "items": { "type": "string" } } }, "condition": { "enum": ["some", "every"] }, "rules": { "type": "object", "additionalProperties": { "enum": ["equals", "contains", "starts_with", "ends_with"] } } } }, "domain": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "domains": { "type": "array", "items": { "type": "string", "maxLength": 255 } } } }, "browser": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "browsers": { "type": "array", "items": { "type": "string", "maxLength": 255 } } } }, "browser_language": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "languages": { "type": "array", "maxItems": 255, "items": { "type": "string", "pattern": "^[a-z]{2}(-[a-z]{2})?$", "description": "Tag IETF, tudo minúsculo (xx ou xx-yy). Veja https://en.wikipedia.org/wiki/IETF_language_tag", "examples": ["pt-br", "en", "es"] } } } }, "isp": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "isps": { "type": "array", "items": { "type": "string", "maxLength": 255 } } } }, "os": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "os": { "type": "array", "items": { "type": "string", "maxLength": 255 } } } }, "user_agent": { "type": "object", "properties": { "allow": { "type": "boolean", "default": true }, "user_agents": { "type": "array", "items": { "type": "string", "maxLength": 255 } } } }, "blacklist": { "type": "array", "items": { "type": "string", "description": "Endereço IP" } }, "whitelist": { "type": "array", "items": { "type": "string", "description": "Endereço IP" } } } }
Defaults na criação de campanha
Campos omitidos são preenchidos no servidor (validação campaign-schema). Não copie o objeto filters completo dos exemplos — envie só o que precisar.
Campo | Default quando omitido |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ainda obrigatórios (sem default para a chave em si): name, mode, pages, domain, alias, e em filters: geolocation, referer, query, domain, browser, browser_language, isp, os, user_agent, blacklist.
Dentro dos objetos obrigatórios você pode omitir defaults aninhados (ex.: enviar "domain": {}, "referer": { "block_null": true, "domains": [] }).
Para mirar uma única rede de anúncios, envie só ela como true (ex.: "facebook": true). As demais redes ficam false por default.
Regras de negócio de pages / offers (422 se violadas)
Regra | Detalhe |
|---|---|
| Dentro de cada grupo de segmentação, os valores de |
Oferta fallback | Pelo menos uma oferta deve não ter segmentação por país (lista |
| Exatamente uma flag de rede de anúncios |
| Zero ou uma rede de anúncios; |
CampaignBody
Body de create e update de campanha. PUT usa o mesmo body completo — não há update parcial.
{
"$id": "CampaignBody",
"type": "object",
"required": ["name", "mode", "pages", "filters", "domain", "alias"],
"properties": {
"name": { "type": "string", "minLength": 3, "maxLength": 255 },
"active": { "type": "boolean", "default": true, "description": "Opcional. Default true." },
"mode": { "enum": ["advanced", "basic"] },
"domain": { "type": ["string", "null"], "maxLength": 128 },
"alias": { "type": ["string", "null"], "maxLength": 32 },
"pages": {
"type": "object",
"required": ["white", "offers"],
"properties": {
"white": {
"type": "object",
"required": ["type", "content"],
"properties": {
"type": { "enum": ["content", "redirect", "iframe"] },
"content": { "type": "string", "maxLength": 255 }
}
},
"offers": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["type", "content", "share"],
"properties": {
"type": { "enum": ["content", "redirect", "iframe"] },
"content": { "type": "string", "maxLength": 255 },
"share": { "type": "number", "description": "Percentual; somas por grupo devem ser 100" },
"segmentation": {
"type": "object",
"properties": {
"country": {
"type": "array",
"maxItems": 256,
"items": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"description": "ISO 3166-1 alpha-2 maiúsculo. Igual a filters.geolocation.countries."
}
}
}
}
}
}
}
}
},
"filters": { "$ref": "CampaignFilters" }
}
}CampaignFull
Resposta de campanha única (show, create, update, clone). Modo revisão = filters.deny_always (listagem expõe a mesma flag como in_review no topo).
{
"$id": "CampaignFull",
"type": "object",
"properties": {
"id": { "type": "integer" },
"created_at": { "type": "string", "format": "date-time" },
"updated_at": { "type": "string", "format": "date-time" },
"name": { "type": "string" },
"active": { "type": "boolean" },
"slug": { "type": "string" },
"mode": { "enum": ["advanced", "basic"] },
"domain": { "type": ["string", "null"] },
"alias": { "type": ["string", "null"] },
"network": { "type": "string" },
"show_content_enabled": { "type": "boolean" },
"pages": { "type": "object" },
"filters": { "$ref": "CampaignFilters" },
"is_test_mode": { "type": "boolean", "description": "Só no GET show: true se o IP do cliente está em filters.whitelist" }
}
}CampaignShort
Item na resposta de listagem de campanhas.
{
"$id": "CampaignShort",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"active": { "type": "boolean" },
"created_at": { "type": "string", "format": "date-time" },
"updated_at": { "type": "string", "format": "date-time" },
"mode": { "enum": ["advanced", "basic"] },
"network": { "type": "string" },
"in_review": { "type": "boolean", "description": "Espelho somente leitura de filters.deny_always. true = campanha bloqueia todo tráfego de oferta." }
}
}Domain
{
"$id": "Domain",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"verified": { "type": "boolean" },
"migrated": { "type": "boolean" },
"created_at": { "type": "string", "format": "date-time" }
}
}Campanhas (/v1/campaigns)
Todos os endpoints exigem Authorization: Bearer ck_....
GET /v1/campaigns
Listar campanhas.
Scope: campaigns:list
Query:
{
"type": "object",
"properties": {
"page": { "type": "integer", "minimum": 1, "default": 1 },
"limit": { "enum": [1, 5, 10, 25, 50, 100], "default": 10 },
"active": { "type": "boolean" },
"name": { "type": "string", "maxLength": 255 },
"network": {
"enum": [
"facebook",
"google",
"tiktok",
"kwai",
"taboola",
"pinterest",
"yandex",
"mgid",
"outbrain",
"sms",
"revcontent",
"adskeeper",
"newsbreak"
]
}
}
}Resposta 200:
{
"type": "object",
"properties": {
"count": { "type": "integer" },
"data": {
"type": "array",
"items": { "$ref": "CampaignShort" }
}
}
}Exemplo:
curl -H "Authorization: Bearer ck_YOUR_KEY" \
"https://api.cloakup.me/v1/campaigns?page=1&limit=10"POST /v1/campaigns
Criar campanha.
Scope: campaigns:create
Request body: { "$ref": "CampaignBody" }
Resposta 201: { "$ref": "CampaignFull" }
Defaults: veja Defaults na criação de campanha. Chaves omitidas são preenchidas no servidor — não envie o blob
filterscompleto a menos que precise sobrescrever tudo.
Regras de negócio: veja Regras de negócio de pages / offers (somas de
share, oferta fallback, modobasic).
Exemplo mínimo (seguro para produção; só valores não-default):
{
"name": "Minha Campanha",
"mode": "advanced",
"domain": null,
"alias": null,
"pages": {
"white": { "type": "content", "content": "safe.html" },
"offers": [{ "type": "content", "content": "offer.html", "share": 100 }]
},
"filters": {
"facebook": true,
"geolocation": { "countries": ["BR"] },
"referer": { "block_null": true, "domains": [] },
"query": { "condition": "some", "params": {}, "rules": {} },
"domain": {},
"browser": {},
"browser_language": { "languages": ["pt-br"] },
"isp": {},
"os": {},
"user_agent": {},
"blacklist": []
}
}Omitido aqui (defaults aplicam): active, demais redes de anúncios, deny_always (= false), bots, proxy, adspy, cloakup_ai, state, city, network_type, device, e toda flag allow / remove_params.
Modo teste/revisão apenas — defina "deny_always": true para forçar página segura para todo visitante (in_review: true na listagem).
GET /v1/campaigns/:id
Obter campanha por ID.
Scope: campaigns:show
Path params:
{
"type": "object",
"properties": { "id": { "type": "integer" } },
"required": ["id"]
}Resposta 200: { "$ref": "CampaignFull" } (inclui is_test_mode conforme o IP do caller está em filters.whitelist).
PUT /v1/campaigns/:id
Atualizar campanha. Substituição completa — mesmo schema do create (CampaignBody). Envie o body inteiro; chaves de filtro omitidas ainda seguem os defaults de create, mas isso não é JSON Merge Patch.
Scope: campaigns:update
Path params: igual ao show.
Request body: { "$ref": "CampaignBody" }
Resposta 200: { "$ref": "CampaignFull" }
DELETE /v1/campaigns/:id
Exclusão lógica (soft-delete) da campanha.
Scope: campaigns:delete
Path params: igual ao show.
Resposta 204: O status HTTP é 204. O handler pode ainda anexar body JSON { "message": "..." } (quirk do Express); trate sucesso como status 204 e ignore o body se vazio/não parseado.
POST /v1/campaigns/:id/clone
Clonar campanha.
Scope: campaigns:clone
Path params: igual ao show.
Request body: nenhum
Resposta 200: { "$ref": "CampaignFull" }
PUT /v1/campaigns/:id/toggle-status
Alternar flag active da campanha.
Scope: campaigns:toggle
Path params: igual ao show.
Request body: nenhum
Resposta 200: body vazio (use case retorna void; re-busque com show se precisar)
Domínios (/v1/domains)
GET /v1/domains
Listar domínios.
Scope: domains:list
Query:
{
"type": "object",
"properties": {
"page": { "type": "integer", "minimum": 1, "default": 1 },
"limit": { "enum": [1, 5, 10, 25, 50, 100], "default": 100 },
"verified": { "type": "boolean" },
"name": { "type": "string", "maxLength": 128 }
}
}Resposta 200:
{
"type": "object",
"properties": {
"count": { "type": "integer" },
"data": {
"type": "array",
"items": { "$ref": "Domain" }
}
}
}POST /v1/domains
Registrar domínio (subdomínio obrigatório, ex.: track.example.com). Rejeitado se name contiver http, www ou /, ou não for hostname de subdomínio válido.
Scope: domains:create
Request body:
{ "type": "object", "required": ["name"], "properties": { "name": { "type": "string", "maxLength": 128, "description": "Hostname de subdomínio, ex. track.example.com — sem scheme, www ou path" } } }
Resposta 201:
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"verified": { "type": "boolean" },
"migrated": { "type": "boolean" }
}
}PATCH /v1/domains/:id/verify
Verificar propagação DNS/CNAME do domínio e ativar certificado.
Scope: domains:verify
Path params:
{
"type": "object",
"properties": { "id": { "type": "integer" } },
"required": ["id"]
}Request body: nenhum
Resposta 200:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"verified": { "type": "boolean" }
}
}DELETE /v1/domains/:id
Excluir domínio.
Scope: domains:delete
Path params: igual ao verify.
Request body: nenhum
Resposta 204: Mesmo quirk do delete de campanha — status 204, body opcional { "message": "..." }; trate o status como sucesso.
Referência rápida (mapeamento para ferramentas de IA)
Sugestão de nome da ferramenta | Método | Path | Scope |
|---|---|---|---|
| GET |
|
|
| POST |
|
|
| GET |
|
|
| PUT |
|
|
| DELETE |
|
|
| POST |
|
|
| PUT |
|
|
| GET |
|
|
| POST |
|
|
| PATCH |
|
|
| DELETE |
|
|
Variáveis de ambiente (para clientes)
Variável | Descrição |
|---|---|
| URL base sem barra no final (ex.: |
| Key completa |
Exemplo de requisição autenticada:
GET /v1/campaigns?page=1&limit=10 HTTP/1.1 Host: api.cloakup.me Authorization: Bearer ck_0123456789abcdef... Accept: application/json
Atualizado em: 27/07/2026
Obrigado!
