Webhook

O Webhook é uma configuração que executa automaticamente uma ação previamente definida quando algo acontece no Space (por exemplo, criação ou publicação de Content). A ação é uma de duas: enviar uma requisição HTTP para uma URL externa (url) ou executar um Script dentro do Space (script). É usado para integração com sistemas externos ou automação. Por exemplo, você pode configurá-lo para chamar um servidor de notificações interno sempre que um Content de produto for publicado, ou para executar um trabalho subsequente com um Script previamente definido.

Você especifica exatamente um entre url e script. Especificar ambos, ou deixar ambos vazios, é rejeitado. O Webhook é um recurso subordinado ao Space na CMA, e seu caminho tem como base /spaces/{spaceId}/webhooks.

Estrutura do recurso

A seguir está a resposta da consulta individual do Webhook "Notificação de alteração de produto". Junto com sys (atributos de sistema), ele tem campos de configuração como destino de envio, eventos assinados e condições de disparo.

{
  "sys": {
    "id": "3trmXRM3RqbgSnifyg7PWhk01Examp",
    "type": "Webhook",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "createdAt": "2026-06-18T11:30:00.000Z",
    "updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "updatedAt": "2026-06-18T11:30:00.000Z",
    "version": 1
  },
  "name": "Notificação de alteração de produto",
  "filters": [
    { "doc": "sys.contentType.sys.id", "op": "EQ", "value": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" }
  ],
  "headers": [
    { "key": "X-Source", "value": "weegloo", "secret": false }
  ],
  "httpBasicUsername": "dailywear",
  "topics": ["Content.Create", "Content.Publish"],
  "transformation": { "method": "POST", "contentType": "application/json", "includeBody": true },
  "url": "https://api.dailywear.example/webhooks/products",
  "activate": true,
  "runAs": "HookOwner"
}

Principais chaves:

  • sys.id: identificador único do Webhook. Entra no {webhookId} dos caminhos de consulta individual, modificação e exclusão.
  • url: URL de destino externa a ser chamada quando o evento ocorrer. Especifique exatamente um entre ele e script.
  • script: referência ao Script a executar no lugar de uma chamada externa. Especifique exatamente um entre ele e url. Não está presente no exemplo acima. É explicado abaixo em url e script (apenas um).
  • runAs: identidade de usuário com a qual o script é executado. É explicado abaixo em runAs.
  • topics: array que define quais eventos serão assinados. O formato é explicado abaixo em topics.
  • filters: condições que efetivamente disparam, dentre os eventos assinados. É explicado abaixo em filters.
  • transformation: configuração que altera o formato da requisição de saída (método, corpo etc.). É explicado abaixo em transformation.

Atributos de sistema (sys)

Todo Webhook armazena os atributos de sistema comuns no objeto sys. space, createdBy e updatedBy entram no formato Refer ({ "sys": { "id", "type": "Refer", "targetType" } }).

AtributoTipoDescrição
idstringIdentificador único do recurso.
typestringTipo do recurso. Para Webhook é sempre "Webhook".
spaceRefer<Space>O Space ao qual este Webhook pertence.
createdByRefer<User>Usuário que criou.
createdAtstring (date-time)Momento da criação.
updatedByRefer<User>Último usuário que modificou.
updatedAtstring (date-time)Momento da última modificação.
versioninteger (≥1)Versão do recurso. Aumenta em 1 a cada modificação.

O Webhook é um recurso de configuração, portanto não tem o conceito de publicação. Diferentemente de Content ou Content Type, ele não possui atributos de estado de publicação como publish, archive ou status, apenas o version para rastreamento de alterações. Ligar e desligar não é controlado por publicação, mas pelo campo de corpo activate.

Atributos do corpo

O corpo do Webhook (os valores de configuração enviados na criação e modificação e retornados na resposta) é composto pelos seguintes campos.

CampoTipoObrigatórioDescrição
namestring (1~64)Nome do Webhook.
urlstring (url)URL de destino externa a ser chamada quando o evento ocorrer. Apenas um entre este e script. Consulte url e script (apenas um) abaixo.
scriptRefer<Script>Referência ao Script a executar no lugar de uma chamada externa. Apenas um entre este e url. Consulte url e script (apenas um) abaixo.
runAsWebhookRunAsIdentidade de usuário com a qual o script é executado. HookOwner (padrão) ou EventUser. Consulte runAs abaixo.
activatebooleanSe está ativado. Se false, nada é executado mesmo quando o evento ocorre.
topicsstring[]Array de eventos a assinar. Consulte topics abaixo.
filtersFilter[]Array de condições de disparo. Se vazio, todos os eventos assinados disparam. Consulte filters abaixo.
headersWebhookHeader[] (0~30)Array de cabeçalhos HTTP a enviar na chamada de url.
httpBasicUsernamestring (1~32)Nome de usuário da autenticação HTTP Basic da chamada de url.
httpBasicPasswordstring (1~32)Senha da autenticação HTTP Basic da chamada de url. É somente de escrita. Não aparece na resposta.
transformationTransformationPersonalização da requisição que sai para url. Consulte transformation abaixo.

Você especifica exatamente um entre url e script marcados com △. Especificar ambos, ou deixar ambos vazios, é rejeitado.

Cada item de headers é composto por key (obrigatório), value (obrigatório) e secret (opcional, boolean). Se você deixar secret como true, esse valor fica ocultado no registro de envio (consulte WebhookLog abaixo). No entanto, ao consultar este Webhook, o valor aparece em texto original. O único que fica de fora da resposta é o httpBasicPassword, portanto considere que o valor colocado em um cabeçalho secret é visível para qualquer papel que possa ler este Webhook e mantenha esse papel restrito.

topics

Cada item de topics tem o formato {recurso}.{ação}. Por exemplo: Content.Create, Content.Publish, Media.Create.

A ação é uma das seguintes ou *, que significa todas as ações do recurso (por exemplo, Content.*).

AçãoSignificado
AllTodas as ações.
CreateCriação.
ReadConsulta.
EditEdição.
SaveSalvar (modificação). O evento de modificação é Save. Não é Update.
DeleteExclusão.
PublishPublicação.
UnpublishCancelamento de publicação.
ArchiveArquivamento.
UnarchiveDesarquivamento.

filters

filters é um array que restringe, dentre os topics assinados, as condições que efetivamente disparam o Webhook. Cada filtro tem o seguinte formato.

{ "doc": "sys.contentType.sys.id", "op": "EQ", "value": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA" }
  • doc: caminho do campo a comparar. É um dentre sys.id, sys.contentType.sys.id, sys.createdBy.sys.id e sys.updatedBy.sys.id.
  • op: operador de comparação. É um dentre EQ, NE, IN, NOT_IN, REGEX e NOT_REGEX.
  • value: valor de comparação. Para EQ, NE, REGEX e NOT_REGEX informe uma string; para IN e NOT_IN informe um array de strings.

Quando há vários filtros, todos precisam ser satisfeitos para disparar (AND). Se filters estiver vazio, todos os eventos dos topics assinados disparam.

transformation

transformation altera o formato da requisição HTTP que sai para url (não se aplica a um Webhook que usa script). Se não for especificado, todo o payload do recurso sai como está, com o POST padrão.

ChaveTipoDescrição
methodstringMétodo HTTP. Um dentre GET, POST, PUT, DELETE e PATCH.
contentTypestringContent-Type do corpo da requisição. O corpo é serializado nesse formato (abaixo).
bodyobjectObjeto que compõe o corpo a enviar usando templates de JSON Pointer.
includeBodybooleanSe o corpo do recurso de disparo deve ser enviado junto.

Em que formato o corpo é enviado

contentType define o formato de serialização do corpo. A comparação ignora maiúsculas e minúsculas e parâmetros como ;charset=…, observando apenas a parte inicial. Se você não o especificar, ou se o valor estiver vazio, o corpo é enviado como application/json. Se includeBody for false ou method for GET, nenhum corpo é enviado e, nesse caso, também não é anexado o Content-Type.

O corpo que um Webhook envia é sempre um objeto. Isso porque o template body é um objeto e, quando você não define nenhum template, o recurso disparado inteiro sai como está.

contentType declaradoContent-Type realmente enviadoCorpo enviado
(nenhum)application/jsonJSON
application/jsonO valor declarado como estáJSON
application/x-www-form-urlencodedO valor declarado como estáproduct[sku]=TUMBLER-500&product[price]=24000
text/plainapplication/jsonJSON
Qualquer outro (text/xml e afins)O valor declarado como estáJSON

text/plain não consegue conter um objeto, portanto o corpo é enviado com o formato corrigido para um que consiga contê-lo. O cabeçalho nunca informa algo diferente do corpo real. Se o destino precisar receber o corpo como texto, contentType não resolve isso, então verifique o contrato do lado receptor.

form-urlencoded expande um objeto em chaves com colchetes e um array em índices.

CorpoChaves e valores expandidos
{ "product": { "sku": "TUMBLER-500", "price": 24000 } }product[sku]=TUMBLER-500&product[price]=24000
{ "tags": ["kitchen", "insulated"] }tags[0]=kitchen&tags[1]=insulated
{ "items": [{ "sku": "TUMBLER-500" }] }items[0][sku]=TUMBLER-500
{ "memo": null }memo=

As chaves e os valores saem com codificação percentual em UTF-8. A tabela acima os mostra decodificados para tornar visível a estrutura das chaves. Mesmo que um valor contenha & ou +, ele não é confundido com um separador de pares nem com um espaço, e é entregue como está.

Expandir o aninhamento em chaves com colchetes é uma convenção amplamente usada, não uma especificação do próprio formato. Verifique se o lado receptor restaura product[sku] em um objeto aninhado e, se não restaurar, componha o template body com chaves planas.

Veja um exemplo de transformation que envia um formulário.

"transformation": {
  "method": "POST",
  "contentType": "application/x-www-form-urlencoded",
  "includeBody": true,
  "body": {
    "sku": "{ /payload/fields/sku/ko-KR }",
    "price": "{ /payload/fields/price/ko-KR }"
  }
}

Quando um Content cujo sku é TUMBLER-500 e cujo price é 24000 dispara o Webhook, o corpo sai como sku=TUMBLER-500&price=24000.

url e script (apenas um)

Quando um Webhook é disparado, ele executa uma de duas coisas. Se você especificar url, ele envia uma requisição HTTP para essa URL externa (o formato da requisição é definido por transformation, headers e httpBasic*). Se você especificar script, ele não sai para fora, mas executa um Script dentro do Space.

  • url: URL de destino externa (http/https). Destinos bloqueados, como redes privadas ou loopback, são rejeitados.
  • script: o Refer para o Script a executar.

Você deve especificar exatamente um entre os dois. Especificar ambos, ou deixar ambos vazios, é rejeitado, e o código devolvido varia conforme o caminho (consulte Erros).

"script": { "sys": { "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK", "type": "Refer", "targetType": "Script" } }

Quando disparado, o Script é executado com permissões delegadas, e as permissões de recurso por statement não são reverificadas em tempo de execução. O que é permitido já é verificado quando o Script é criado. Para o modelo detalhado de execução e permissões, consulte Semântica de execução, restrições e segurança do Script.

runAs

runAs define com qual identidade de usuário o script é executado. Essa identidade se torna o createdBy/updatedBy de qualquer recurso criado ou modificado durante a execução, e o filtro createdBy: ":self" dentro de um Script também é resolvido com base nessa identidade. É apenas atribuição (attribution), não um limite de permissão. O que ele pode fazer é determinado pela verificação de permissões realizada quando o Script é criado.

ValorIdentidade de execução
HookOwnerUsuário que criou o Webhook (sys.createdBy). Valor padrão.
EventUserUsuário que causou aquele evento (alteração), ou seja, o sys.updatedBy do recurso disparado.

Em um Webhook que usa apenas url, o runAs é ignorado. Se não for especificado, é HookOwner.

WebhookLog

Cada vez que um Webhook tenta um envio, fica um registro. É somente de consulta e não tem endpoints de criação, modificação nem exclusão. O caminho é /spaces/{spaceId}/webhooks/{webhookId}/logs.

{
  "sys": {
    "id": "3trmXRM3RqbgSnifyg7PWhc01Exam",
    "type": "WebhookLog",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "requestId": "3trmXRM3qWnLb7Vd1yPcYs04kKrjq",
    "statusCode": 200,
    "errors": [],
    "eventType": "Create",
    "url": "https://api.dailywear.example/webhooks/products",
    "requestAt": "2026-06-18T11:35:00.100Z",
    "responseAt": "2026-06-18T11:35:00.350Z",
    "request": {
      "url": "https://api.dailywear.example/webhooks/products",
      "method": "POST",
      "headers": { "Content-Type": "application/json", "X-Source": "weegloo" },
      "body": "{\"sys\":{\"type\":\"Content\"}}"
    },
    "response": {
      "url": "https://api.dailywear.example/webhooks/products",
      "headers": { "Content-Type": "application/json" },
      "body": "{\"ok\":true}",
      "statusCode": 200
    },
    "createdBy": { "sys": { "id": "3trmXRM3RqbgSnifyg7PWhk01Examp", "type": "Refer", "targetType": "Webhook" } },
    "createdAt": "2026-06-18T11:35:00.350Z",
    "updatedBy": { "sys": { "id": "3trmXRM3RqbgSnifyg7PWhk01Examp", "type": "Refer", "targetType": "Webhook" } },
    "updatedAt": "2026-06-18T11:35:00.350Z"
  }
}

Todos os valores ficam dentro de sys e não há atributos do corpo. As chaves sem valor ficam de fora da resposta.

Qual Webhook gerou o registro é indicado pelo sys.createdBy. Não é um usuário, mas o Refer daquele Webhook, e o sys.updatedBy também é o mesmo Webhook.

AtributoTipoDescrição
idstringIdentificador único do registro.
typestringSempre "WebhookLog".
spaceRefer<Space>O Space ao qual este registro pertence.
requestIdstringIdentificador de rastreamento desta tentativa de envio.
statusCodeintegerCódigo de status HTTP da resposta recebida.
errorsstring[]Lista de motivos de falha. No registro de um Webhook que envia para uma URL, ela está sempre vazia (é o código de status que informa a falha). Só no registro de um Webhook que executa um Script via script é que a mensagem de falha desse Script aparece.
eventTypestringÉ o nome da ação que provocou este envio (por exemplo, Create ou Publish). Não vem no formato Content.Create, que se escreve em topics; apenas a ação, a parte final.
urlstringURL de destino do envio.
requestAtstring (date-time)Momento em que a requisição foi enviada.
responseAtstring (date-time)Momento em que a resposta foi recebida.
requestobjectA requisição enviada. A estrutura interna está abaixo. Fica de fora na consulta de lista.
responseobjectA resposta recebida. A estrutura interna está abaixo. Fica de fora na consulta de lista.
createdByRefer<Webhook>O Webhook que gerou este registro.
createdAtstring (date-time)Momento de criação do registro.
updatedByRefer<Webhook>O mesmo que createdBy.
updatedAtstring (date-time)O mesmo que createdAt.

request e response têm, cada um, as seguintes chaves.

  • request: url (a URL de destino a que a requisição foi enviada), method (o método HTTP), headers (o mapa dos cabeçalhos enviados) e body (a string do corpo enviado).
  • response: url (a URL de que a resposta veio), headers (o mapa dos cabeçalhos recebidos), body (a string do corpo recebido) e statusCode (o código de status recebido).

O registro de um Webhook que executa um Script via script tem outro formato. Como não há endereço para onde enviar, não existe url, e o method do request é fixo em "SCRIPT". O body do request traz o payload que provocou esse envio, e o body do response traz o valor que aquele Script devolveu (ou a mensagem de falha).

O valor de um cabeçalho com secret ativado é armazenado ocultado. O valor real não fica no registro.

Corpos longos são armazenados encurtados. O critério é de 65.536 caracteres para o body do request e de 8.192 caracteres para o body do response. Se for mais longo que isso, o começo e o fim são preservados e o meio é omitido, e o número de caracteres omitidos fica anotado nesse lugar. Se o corpo for JSON, para não quebrar a estrutura apenas os valores de string longos são encurtados da mesma forma, portanto as chaves e os valores curtos permanecem como estão.

O critério que separa sucesso de falha varia conforme a forma de integração. Um Webhook que envia para uma URL tem sucesso se a resposta for 2xx ou 3xx. Um Webhook que executa um Script via script tem sucesso quando o statusCode é menor que 400 e o errors está vazio. Esse único julgamento determina, ao mesmo tempo, o período de retenção abaixo e a taxa de sucesso do estado de envio.

A consulta de lista devolve sem request e sem response. Isso porque o valor padrão de select do endpoint de lista é -sys.response,-sys.request. Para ver também o corpo da requisição enviada e da resposta recebida, use a consulta individual ou especifique select você mesmo, sobrescrevendo esse valor padrão.

O registro de um envio bem-sucedido desaparece após 1 hora, e o de um envio malsucedido, após 3 dias. Não há na resposta um campo com o horário de expiração; quando chega a hora, o registro desaparece por si só. Um valor que precise ser guardado por mais tempo que isso deve ser salvo separadamente no servidor que recebe, ou registrado como Content pelo Script executado via script.

Erros

São os códigos que você encontra ao lidar com o Webhook. Para os códigos comuns a todos os recursos, consulte Erros comuns.

CódigoCondição
WGL400042Na criação (POST) ou na substituição completa (PUT), url e script foram ambos especificados ou ambos deixados vazios.
WGL422061Na modificação parcial (PATCH), url e script foram ambos especificados ou ambos deixados vazios.
WGL422050O url aponta para um destino bloqueado, como uma rede privada ou loopback.

API

A URL base de todos os endpoints abaixo é https://cma.weegloo.com/v1, e é necessário um token Bearer no cabeçalho Authorization que autentique na CMA. A modificação (PUT) e a modificação parcial (PATCH) devem enviar também o cabeçalho X-Weegloo-Version (o sys.version do recurso atual) para o controle de concorrência otimista.

  • Content: dados de corpo que disparam o Webhook.
  • Media: recurso de arquivo que pode disparar o Webhook.
  • Script: endpoint de backend declarativo a executar via script. Inclui o modelo de execução e de permissões.
  • SpaceRole: configuração de papel que contém permissões como a execução de Script (Execute).