Entrega
Cada evento gera uma requisição POST para a URL do webhook, com o payload em JSON no corpo.
Webhooks permitem que a API Maestron notifique sua aplicação sobre eventos assim que eles acontecem, sem necessidade de polling. Quando um evento ocorre na empresa ativa, a Maestron envia uma requisição POST para a URL configurada, contendo o payload do evento.
A empresa (tenant) é resolvida automaticamente a partir do token usado para configurar o webhook. Para os fundamentos de autenticação, veja Autenticação; para o formato de erros, veja Erros.
Entrega
Cada evento gera uma requisição POST para a URL do webhook, com o payload em JSON no corpo.
Assinatura
Toda entrega é assinada com HMAC-SHA256 no header X-Maestron-Signature, derivada do secret.
Retentativas
Entregas que falham são reenviadas automaticamente com backoff exponencial.
Histórico
Cada tentativa de entrega fica registrada e pode ser consultada e reenviada manualmente.
Os tipos de evento seguem o padrão dominio.recurso.acao. A lista abaixo é o conjunto inicial, voltado ao módulo CRM. Novos eventos serão adicionados conforme outros módulos forem lançados.
| Evento | Disparado quando |
|---|---|
crm.contact.created | Um contato é criado |
crm.contact.updated | Um contato é atualizado |
crm.contact.deleted | Um contato é removido |
crm.company.created | Uma empresa CRM é criada |
crm.company.updated | Uma empresa CRM é atualizada |
crm.company.deleted | Uma empresa CRM é removida |
crm.deal.created | Um negócio é criado |
crm.deal.updated | Um negócio é atualizado |
crm.deal.stage_changed | Um negócio muda de estágio |
crm.deal.won | Um negócio é marcado como ganho |
crm.deal.lost | Um negócio é marcado como perdido |
crm.activity.created | Uma atividade é criada |
crm.activity.completed | Uma atividade é concluída |
A lista canônica de eventos sempre pode ser obtida via API:
Listar eventos disponíveis
Retorna os tipos de eventos que podem ser assinados por um webhook.
curl -X GET https://api.maestron.com.br/v1/webhooks/events \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.maestron.com.br/v1/webhooks/events', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.get(
"https://api.maestron.com.br/v1/webhooks/events",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/events", {
method: "GET",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.GetAsync("https://api.maestron.com.br/v1/webhooks/events");
var data = await response.Content.ReadAsStringAsync(); GET /webhooks/events HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Eventos listados.",
"data": [
{
"event": "crm.contact.created",
"description": "Um contato é criado."
},
{
"event": "crm.deal.won",
"description": "Um negócio é marcado como ganho."
},
{
"event": "crm.activity.completed",
"description": "Uma atividade é concluída."
}
]
} {
"message": "Não autenticado."
} Toda entrega tem o mesmo envelope, independentemente do evento. O campo data carrega o recurso no estado relevante ao evento.
{ "id": "evt_01J9Z3K8", "event": "crm.deal.won", "created_at": "2026-06-20T14:30:00Z", "data": { "id": "deal_01J9Z3K8", "title": "Plano Anual - Acme", "value": 1500000, "currency": "BRL", "pipeline_id": "pipe_01J9Z3K8", "stage_id": "stg_01J9Z3K8", "contact_id": "cont_01J9Z3K8", "company_id": "comp_01J9Z3K8", "won_at": "2026-06-20T14:30:00Z" }}| Campo | Tipo | Descrição |
|---|---|---|
id | string | Identificador do evento (prefixo evt_). Único por entrega de evento. |
event | string | Tipo do evento (ex.: crm.deal.won). |
created_at | string | Momento em que o evento ocorreu, em ISO-8601. |
data | object | O recurso relacionado ao evento. A forma de data segue o recurso do domínio. |
Valores monetários são inteiros em centavos e datas seguem ISO-8601, como em toda a API.
Cada requisição enviada ao endpoint do webhook inclui os headers abaixo:
| Header | Descrição |
|---|---|
Content-Type | application/json |
User-Agent | Maestron-Webhooks/1.0 |
X-Maestron-Event | Tipo do evento (ex.: crm.deal.won) |
X-Maestron-Delivery | Identificador da entrega (prefixo whd_) |
X-Maestron-Signature | Assinatura HMAC-SHA256 da entrega (ver abaixo) |
X-Maestron-Timestamp | Timestamp Unix (segundos) usado na assinatura |
Cada entrega é assinada com HMAC-SHA256 usando o secret do webhook. O endpoint receptor deve recalcular a assinatura e compará-la com o header X-Maestron-Signature antes de confiar no payload.
O header tem o formato:
X-Maestron-Signature: t=1718894400,v1=5257a869e7 ... 9d2ft: o timestamp Unix da entrega (idêntico a X-Maestron-Timestamp).v1: a assinatura HMAC-SHA256 em hexadecimal.A string assinada (signed payload) é a concatenação do timestamp, um ponto e o corpo bruto da requisição:
signed_payload = t + "." + corpo_bruto_da_requisiçãoA assinatura esperada é HMAC_SHA256(signed_payload, secret), em hexadecimal.
A comparação deve usar uma função de comparação em tempo constante (timingSafeEqual ou equivalente) para evitar ataques de timing.
import crypto from 'node:crypto';
function isValidSignature(rawBody, signatureHeader, secret) { const parts = Object.fromEntries( signatureHeader.split(',').map((kv) => kv.split('=')), ); const timestamp = parts.t; const received = parts.v1;
const signedPayload = `${timestamp}.${rawBody}`; const expected = crypto .createHmac('sha256', secret) .update(signedPayload) .digest('hex');
const a = Buffer.from(received, 'hex'); const b = Buffer.from(expected, 'hex'); return a.length === b.length && crypto.timingSafeEqual(a, b);}function isValidSignature(string $rawBody, string $signatureHeader, string $secret): bool{ parse_str(str_replace(',', '&', $signatureHeader), $parts); $timestamp = $parts['t'] ?? ''; $received = $parts['v1'] ?? '';
$signedPayload = $timestamp . '.' . $rawBody; $expected = hash_hmac('sha256', $signedPayload, $secret);
return hash_equals($expected, $received);}import hmacimport hashlib
def is_valid_signature(raw_body: bytes, signature_header: str, secret: str) -> bool: parts = dict(kv.split("=", 1) for kv in signature_header.split(",")) timestamp = parts.get("t", "") received = parts.get("v1", "")
signed_payload = f"{timestamp}.".encode() + raw_body expected = hmac.new(secret.encode(), signed_payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received)O secret é a chave usada para assinar as entregas. Ele é retornado apenas na criação do webhook (e ao rotacionar) — a API nunca o reenvia em leituras subsequentes. Se for perdido, gere um novo com a rotação de secret.
Listar webhooks
Lista os webhooks configurados na empresa ativa. Suporta paginação.
Parâmetros de query
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
page | integer | — | Página atual (padrão: 1). |
per_page | integer | — | Itens por página (padrão: 20, máx: 100). |
curl -X GET https://api.maestron.com.br/v1/webhooks \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.maestron.com.br/v1/webhooks', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.get(
"https://api.maestron.com.br/v1/webhooks",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks", {
method: "GET",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.GetAsync("https://api.maestron.com.br/v1/webhooks");
var data = await response.Content.ReadAsStringAsync(); GET /webhooks HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Webhooks listados.",
"data": [
{
"id": "whk_01J9Z3K8",
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost"
],
"is_active": true,
"created_at": "2026-06-20T14:30:00Z",
"updated_at": "2026-06-20T14:30:00Z"
}
],
"meta": {
"current_page": 1,
"per_page": 20,
"total": 1,
"last_page": 1
}
} {
"message": "Não autenticado."
} O secret é opcional no corpo. Se omitido, a API gera um automaticamente. Em ambos os casos, o valor final é retornado apenas nesta resposta.
Criar webhook
Cria um webhook na empresa ativa. O secret é retornado somente nesta resposta.
Corpo (body)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
url | string | Sim | URL HTTPS que receberá as entregas. |
events | string[] | Sim | Lista de tipos de evento a assinar. |
secret | string | — | Secret de assinatura. Se omitido, é gerado automaticamente. |
is_active | boolean | — | Define se o webhook está ativo (padrão: true). |
curl -X POST https://api.maestron.com.br/v1/webhooks \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost"
],
"is_active": true
}' <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.maestron.com.br/v1/webhooks', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
'json' => [
'url' => 'https://app.exemplo.com/webhooks/maestron',
'events' => crm.deal.won,crm.deal.lost,
'is_active' => true,
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
payload = {
"url": "https://app.exemplo.com/webhooks/maestron",
"events": crm.deal.won,crm.deal.lost,
"is_active": True,
}
response = requests.post(
"https://api.maestron.com.br/v1/webhooks",
headers=headers,
json=payload,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks", {
method: "POST",
headers: {
"Authorization": "Bearer SEU_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost"
],
"is_active": true
}),
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var payload = new StringContent(
"{\"url\":\"https://app.exemplo.com/webhooks/maestron\",\"events\":[\"crm.deal.won\",\"crm.deal.lost\"],\"is_active\":true}",
System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.maestron.com.br/v1/webhooks", payload);
var data = await response.Content.ReadAsStringAsync(); POST /webhooks HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN
Content-Type: application/json
{
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost"
],
"is_active": true
} Respostas
{
"message": "Webhook criado.",
"data": {
"id": "whk_01J9Z3K8",
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost"
],
"secret": "whsec_2b7f1c9a4d8e6f0a3c5b9d2e7f1a4c8b",
"is_active": true,
"created_at": "2026-06-20T14:30:00Z",
"updated_at": "2026-06-20T14:30:00Z"
}
} {
"message": "Não autenticado."
} {
"message": "Os dados informados são inválidos.",
"errors": {
"url": [
"O campo url deve ser uma URL válida."
],
"events": [
"O campo events é obrigatório."
]
}
} Retornar webhook
Retorna um webhook pelo identificador. O secret não é incluído.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
curl -X GET https://api.maestron.com.br/v1/webhooks/{id} \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.maestron.com.br/v1/webhooks/{id}', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.get(
"https://api.maestron.com.br/v1/webhooks/{id}",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}", {
method: "GET",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.GetAsync("https://api.maestron.com.br/v1/webhooks/{id}");
var data = await response.Content.ReadAsStringAsync(); GET /webhooks/{id} HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Webhook retornado.",
"data": {
"id": "whk_01J9Z3K8",
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost"
],
"is_active": true,
"created_at": "2026-06-20T14:30:00Z",
"updated_at": "2026-06-20T14:30:00Z"
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} Atualizar webhook
Atualiza url, eventos, secret ou status de um webhook. Campos omitidos permanecem inalterados.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
Corpo (body)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
url | string | — | Nova URL HTTPS de destino. |
events | string[] | — | Nova lista de tipos de evento a assinar. |
secret | string | — | Novo secret de assinatura. |
is_active | boolean | — | Ativa ou desativa o webhook. |
curl -X PATCH https://api.maestron.com.br/v1/webhooks/{id} \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"events": [
"crm.deal.won",
"crm.deal.lost",
"crm.deal.stage_changed"
],
"is_active": false
}' <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('PATCH', 'https://api.maestron.com.br/v1/webhooks/{id}', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
'json' => [
'events' => crm.deal.won,crm.deal.lost,crm.deal.stage_changed,
'is_active' => false,
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
payload = {
"events": crm.deal.won,crm.deal.lost,crm.deal.stage_changed,
"is_active": False,
}
response = requests.patch(
"https://api.maestron.com.br/v1/webhooks/{id}",
headers=headers,
json=payload,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}", {
method: "PATCH",
headers: {
"Authorization": "Bearer SEU_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
"events": [
"crm.deal.won",
"crm.deal.lost",
"crm.deal.stage_changed"
],
"is_active": false
}),
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var payload = new StringContent(
"{\"events\":[\"crm.deal.won\",\"crm.deal.lost\",\"crm.deal.stage_changed\"],\"is_active\":false}",
System.Text.Encoding.UTF8, "application/json");
var response = await client.SendAsync(new HttpRequestMessage(
new HttpMethod("PATCH"), "https://api.maestron.com.br/v1/webhooks/{id}") { Content = payload });
var data = await response.Content.ReadAsStringAsync(); PATCH /webhooks/{id} HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN
Content-Type: application/json
{
"events": [
"crm.deal.won",
"crm.deal.lost",
"crm.deal.stage_changed"
],
"is_active": false
} Respostas
{
"message": "Webhook atualizado.",
"data": {
"id": "whk_01J9Z3K8",
"url": "https://app.exemplo.com/webhooks/maestron",
"events": [
"crm.deal.won",
"crm.deal.lost",
"crm.deal.stage_changed"
],
"is_active": false,
"created_at": "2026-06-20T14:30:00Z",
"updated_at": "2026-06-20T15:10:00Z"
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} {
"message": "Os dados informados são inválidos.",
"errors": {
"url": [
"O campo url deve ser uma URL válida."
]
}
} Remover webhook
Remove um webhook. Entregas pendentes deixam de ser tentadas.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
curl -X DELETE https://api.maestron.com.br/v1/webhooks/{id} \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('DELETE', 'https://api.maestron.com.br/v1/webhooks/{id}', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.delete(
"https://api.maestron.com.br/v1/webhooks/{id}",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}", {
method: "DELETE",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.DeleteAsync("https://api.maestron.com.br/v1/webhooks/{id}");
var data = await response.Content.ReadAsStringAsync(); DELETE /webhooks/{id} HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Webhook removido."
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} Gera um novo secret de assinatura, invalidando o anterior. O novo valor é retornado apenas nesta resposta.
Rotacionar secret
Gera um novo secret de assinatura e o retorna. O secret anterior deixa de ser válido.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
curl -X POST https://api.maestron.com.br/v1/webhooks/{id}/rotate-secret \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.maestron.com.br/v1/webhooks/{id}/rotate-secret', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.post(
"https://api.maestron.com.br/v1/webhooks/{id}/rotate-secret",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}/rotate-secret", {
method: "POST",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.PostAsync("https://api.maestron.com.br/v1/webhooks/{id}/rotate-secret", null);
var data = await response.Content.ReadAsStringAsync(); POST /webhooks/{id}/rotate-secret HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Secret rotacionado.",
"data": {
"id": "whk_01J9Z3K8",
"secret": "whsec_9f3a1d7c2b8e4f6a0c5d9b3e7f1a4c8b"
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} Envia um evento de teste para a URL configurada e registra a entrega no histórico. Útil para validar conectividade e a verificação de assinatura do endpoint receptor.
Testar webhook
Envia um evento de teste para a URL do webhook e registra a entrega.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
curl -X POST https://api.maestron.com.br/v1/webhooks/{id}/ping \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.maestron.com.br/v1/webhooks/{id}/ping', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.post(
"https://api.maestron.com.br/v1/webhooks/{id}/ping",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}/ping", {
method: "POST",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.PostAsync("https://api.maestron.com.br/v1/webhooks/{id}/ping", null);
var data = await response.Content.ReadAsStringAsync(); POST /webhooks/{id}/ping HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Webhook testado.",
"data": {
"delivery_id": "whd_01J9Z3K8",
"event": "webhook.ping",
"status": "success",
"response_code": 200
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} Uma entrega é considerada bem-sucedida quando o endpoint responde com status 2xx. Qualquer outro status, timeout ou erro de conexão marca a tentativa como falha e agenda uma retentativa.
failed e não é mais tentada automaticamente.| Tentativa | Atraso aproximado após a falha anterior |
|---|---|
| 1 | imediata |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
| 6 | 6 horas |
Cada tentativa de entrega é registrada com o payload enviado, o código HTTP de resposta, o número de tentativas e os timestamps.
Listar entregas
Lista as entregas (tentativas) de um webhook. Suporta paginação e filtros.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
Parâmetros de query
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
status | string | — | Filtra por status: pending, success ou failed. |
event | string | — | Filtra pelo tipo de evento. |
page | integer | — | Página atual (padrão: 1). |
per_page | integer | — | Itens por página (padrão: 20, máx: 100). |
curl -X GET https://api.maestron.com.br/v1/webhooks/{id}/deliveries \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.maestron.com.br/v1/webhooks/{id}/deliveries', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.get(
"https://api.maestron.com.br/v1/webhooks/{id}/deliveries",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}/deliveries", {
method: "GET",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.GetAsync("https://api.maestron.com.br/v1/webhooks/{id}/deliveries");
var data = await response.Content.ReadAsStringAsync(); GET /webhooks/{id}/deliveries HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Entregas listadas.",
"data": [
{
"id": "whd_01J9Z3K8",
"event": "crm.deal.won",
"status": "failed",
"response_code": 500,
"attempts": 3,
"created_at": "2026-06-20T14:30:00Z",
"last_attempt_at": "2026-06-20T15:05:00Z"
}
],
"meta": {
"current_page": 1,
"per_page": 20,
"total": 1,
"last_page": 1
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} Retornar entrega
Retorna uma entrega com o payload enviado, código HTTP de resposta, tentativas e timestamps.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
delivery_id | string | Sim | Identificador da entrega (prefixo whd_). |
curl -X GET https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id} \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.get(
"https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}", {
method: "GET",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.GetAsync("https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}");
var data = await response.Content.ReadAsStringAsync(); GET /webhooks/{id}/deliveries/{delivery_id} HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Entrega retornada.",
"data": {
"id": "whd_01J9Z3K8",
"event": "crm.deal.won",
"status": "failed",
"response_code": 500,
"attempts": 3,
"payload": {
"id": "evt_01J9Z3K8",
"event": "crm.deal.won",
"created_at": "2026-06-20T14:30:00Z",
"data": {
"id": "deal_01J9Z3K8",
"title": "Plano Anual - Acme",
"value": 1500000
}
},
"response_body": "Internal Server Error",
"created_at": "2026-06-20T14:30:00Z",
"last_attempt_at": "2026-06-20T15:05:00Z"
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} Reenvia manualmente uma entrega que falhou. Só é possível reenviar entregas em estado reenviável (failed); tentar reenviar uma entrega já bem-sucedida ou em andamento retorna 409.
Reenviar entrega
Reenvia manualmente uma entrega que falhou.
Parâmetros de caminho
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Identificador do webhook (prefixo whk_). |
delivery_id | string | Sim | Identificador da entrega (prefixo whd_). |
curl -X POST https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}/retry \
-H "Authorization: Bearer SEU_TOKEN" <?php
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}/retry', [
'headers' => [
'Authorization' => 'Bearer SEU_TOKEN',
'Accept' => 'application/json',
],
]);
$data = json_decode($response->getBody(), true); import requests
headers = {"Authorization": "Bearer SEU_TOKEN"}
response = requests.post(
"https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}/retry",
headers=headers,
)
data = response.json() const response = await fetch("https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}/retry", {
method: "POST",
headers: {
"Authorization": "Bearer SEU_TOKEN",
},
});
const data = await response.json(); using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "SEU_TOKEN");
var response = await client.PostAsync("https://api.maestron.com.br/v1/webhooks/{id}/deliveries/{delivery_id}/retry", null);
var data = await response.Content.ReadAsStringAsync(); POST /webhooks/{id}/deliveries/{delivery_id}/retry HTTP/1.1
Host: api.maestron.com.br
Authorization: Bearer SEU_TOKEN Respostas
{
"message": "Entrega reenviada.",
"data": {
"id": "whd_01J9Z3K8",
"event": "crm.deal.won",
"status": "success",
"response_code": 200,
"attempts": 4,
"last_attempt_at": "2026-06-20T16:00:00Z"
}
} {
"message": "Não autenticado."
} {
"message": "Registro não encontrado."
} {
"message": "A entrega não está em um estado reenviável."
} Endpoints de webhook precisam de uma URL pública acessível pela Maestron. Em desenvolvimento, exponha o servidor local com um túnel HTTP, por exemplo o ngrok.
# Expõe a porta local 3000 com uma URL HTTPS públicangrok http 3000A saída mostra uma URL pública, por exemplo https://a1b2c3d4.ngrok-free.app.
# Use a URL pública do túnel como destino do webhook# (rota local de recebimento: /webhooks/maestron)# URL final: https://a1b2c3d4.ngrok-free.app/webhooks/maestronCrie o webhook com POST /webhooks apontando para a URL do túnel e dispare um teste com POST /webhooks/{id}/ping.