Referência completa da API REST do Apruvly.
Tudo o que você precisa para começar a automatizar aprovações em minutos.
A API do Apruvly é uma API RESTful JSON. Todas as requisições devem ser autenticadas com uma chave de API. As respostas são sempre JSON, exceto quando o corpo está vazio (204).
https://api.apruvly.io/api/v1
Crie um workflow de aprovação com um único passo usando um comando curl:
curl -X POST https://api.apruvly.io/api/v1/workflow \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"object": {
"title": "Q1 Marketing Budget",
"description": "Marketing budget for Q1, $18k total"
},
"expires": "48h",
"start": "step1",
"workflow": {
"step1": {
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Q1 Marketing Budget – $18k",
"body": "Please review the budget breakdown in the linked document and share your decision."
}
}
}
}'
Todas as requisições à API exigem autenticação via chave de API.
Passe sua chave de API no cabeçalho Authorization como um Bearer token. Você pode criar e gerenciar chaves de API pelo painel.
Authorization: Bearer wf_YOUR_API_KEY
Você pode gerar uma chave de API na seção Chaves de API do painel.
/api/v1/workflow
Cria um novo workflow de aprovação e inicia imediatamente o primeiro passo.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
object |
object | Sim | Metadados sobre o item que está sendo aprovado. |
object.title |
string | Sim | Título legível para o workflow. Máximo de 200 caracteres. |
object.description |
string | Não | Descrição opcional mais detalhada do que está sendo aprovado. |
object.links |
string[] | Não | Lista opcional de URLs relacionadas à aprovação (documentos, arquivos, etc.). |
object.tags |
string[] | Não | Lista opcional de tags para filtragem e organização. |
external_id |
string | Não | Identificador de correlação opcional (máx. 128 caracteres) — ex.: número de contrato, ticket do CRM, referência de pedido. Requer plano Growth ou superior. Deve ser único por conta. |
expires |
duration | Sim | Por quanto tempo o workflow permanece aberto antes de expirar. Formato: 30s, 15m, 2h, 7d, 2w. |
start |
string | Sim | A chave do primeiro passo a executar (deve corresponder a uma chave em workflow). |
workflow |
map[string]Step | Sim | Mapa de chaves de passo para objetos Step definindo a cadeia de aprovação. |
on |
map[string]Action[] | Não | Mapa de eventos do ciclo de vida para listas de ações (webhook, email, twilio-sms) disparadas automaticamente. Eventos: workflow_created, workflow_approved, workflow_rejected, workflow_expired, workflow_canceled, workflow_completed, step_approved, step_escalated, user_approval, user_rejection. |
disable_email_fallback |
boolean | Não | Desativa o fallback de e-mail padrão. Quando omitido (recomendado), a plataforma envia automaticamente a solicitação de aprovação por e-mail se uma notificação via integração (Teams, Slack, WhatsApp) falhar. Defina como true para pular o fallback e aceitar a falha original. |
debug |
boolean | Não |
Ativa o modo de depuração. Todas as notificações (e-mail, Teams, Slack, WhatsApp), webhooks e escalonamentos são suprimidos — o workflow executa toda a sua lógica sem contatar nenhum participante. Útil para testar o fluxo sem disparar comunicações reais.
Mesmo no modo debug, os créditos são consumidos normalmente. O modo debug suprime apenas as comunicações externas — não afeta a cobrança.
|
curl -X POST https://api.apruvly.io/api/v1/workflow \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"object": {
"title": "Contract Sign-off",
"description": "Legal review for client contract #4821",
"links": ["https://drive.example.com/contracts/4821"],
"tags": ["legal", "contract"]
},
"external_id": "CONTRACT-2025-0042",
"expires": "72h",
"start": "legal-review",
"workflow": {
"legal-review": {
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Approval Request: Contract #4821",
"body": "Please review and approve contract #4821."
},
"approved": "ceo-approval",
"escalation": {
"type": "email",
"after": "24h",
"data": {
"to": ["[email protected]"],
"subject": "Escalation: Contract #4821 pending approval",
"body": "Contract #4821 has not been reviewed. Please take action."
}
}
},
"ceo-approval": {
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Final Approval: Contract #4821",
"body": "Legal review is complete. Please provide final approval."
}
}
}
}'
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalId": "CONTRACT-2025-0042"
}
}
Associe sua própria referência de negócio (número de contrato, ticket do CRM, id de deploy) ao criar um workflow e consulte o status ou cancele sem guardar o UUID da plataforma. Requer plano Growth ou superior. Máx. 128 caracteres; permitidos: letras, dígitos e . _ : / -. Único por conta.
{
"success": false,
"message": "Seu plano não inclui external_id. Faça upgrade para Growth ou superior para associar um identificador de negócio aos workflows."
}
curl -X POST https://api.apruvly.io/api/v1/workflow \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"object": {
"title": "Contract Sign-off",
"description": "Legal review for client contract #4821"
},
"external_id": "CONTRACT-2025-0042",
"expires": "72h",
"start": "legal-review",
"workflow": {
"legal-review": {
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Approval Request: Contract #4821",
"body": "Please review and approve contract #4821."
}
}
}
}'
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalId": "CONTRACT-2025-0042"
}
}
Retorna o mesmo payload de GET /workflow/{id}, buscando pelo external_id informado na criação. Requer plano Growth ou superior.
curl https://api.apruvly.io/api/v1/workflow/external/CONTRACT-2025-0042 \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalId": "CONTRACT-2025-0042",
"status": "pending",
"currentStep": "legal-review",
"createdAt": "2025-01-15T10:00:00Z",
"expiresAt": "2025-01-18T10:00:00Z",
"decisions": []
}
}
curl -X DELETE https://api.apruvly.io/api/v1/workflow/external/CONTRACT-2025-0042 \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
curl "https://api.apruvly.io/api/v1/workflows/search?external_id=CONTRACT-2025-0042" \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Contract Sign-off",
"external_id": "CONTRACT-2025-0042",
"current_status": "pending",
"current_step": "legal-review",
"created_at": "2025-01-15T10:00:00Z",
"expires_at": "2025-01-18T10:00:00Z",
"completed_at": null
}
]
}
/api/v1/workflow/validate
Valida uma configuração de workflow sem criá-lo. Útil para verificar o payload antes de enviá-lo.
curl -X POST https://api.apruvly.io/api/v1/workflow/validate \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"object": {
"title": "Test Workflow"
},
"expires": "24h",
"start": "step1",
"workflow": {
"step1": {
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Test Approval",
"body": "Please approve this test request."
}
}
}
}'
{
"success": true
}
/api/v1/workflow/{id}
Retorna o estado completo de um workflow, incluindo o log de atividades e o histórico de decisões.
| Campo | Tipo | Descrição |
|---|---|---|
id |
uuid | O ID do workflow retornado quando o workflow foi criado. |
curl https://api.apruvly.io/api/v1/workflow/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"externalId": "CONTRACT-2025-0042",
"status": "pending",
"currentStep": "ceo-approval",
"currentEscalation": 0,
"createdAt": "2025-01-15T10:00:00Z",
"expiresAt": "2025-01-18T10:00:00Z",
"nextTickAt": "2025-01-16T10:00:00Z",
"decisions": [
{
"user": "[email protected]",
"is_approved": true,
"ip": "203.0.113.42",
"decisionAt": "2025-01-15T14:22:00Z"
}
]
}
}
/api/v1/workflows/search
Retorna uma lista paginada de workflows pertencentes ao usuário autenticado.
| Campo | Tipo | Descrição |
|---|---|---|
status |
string | Filtrar por status: pending, approved, rejected, expired, canceled |
query |
string | Busca textual no título do workflow. |
step |
string | Filtrar pelo nome da etapa ativa atual (ex.: legal-review). |
from |
RFC3339 | Filtrar workflows criados a partir deste timestamp (formato RFC 3339, ex.: 2025-01-01T00:00:00Z). |
to |
RFC3339 | Filtrar workflows criados até este timestamp (formato RFC 3339, ex.: 2025-01-31T23:59:59Z). |
tags |
string | Filtrar por tags do workflow (separadas por vírgula). |
external_id |
string | Correspondência exata no identificador de correlação fornecido pelo chamador. Requer plano Growth ou superior. |
limit |
integer | Número máximo de resultados (padrão 50, máximo 500). Max results per page (default 50, max 500). |
curl "https://api.apruvly.io/api/v1/workflows/search?status=pending&query=contract" \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Contract Sign-off",
"external_id": "CONTRACT-2025-0042",
"current_status": "pending",
"current_step": "ceo-approval",
"created_at": "2025-01-15T10:00:00Z",
"expires_at": "2025-01-18T10:00:00Z",
"completed_at": null
}
]
}
/api/v1/workflows/recent
Retorna os workflows criados mais recentemente para o usuário autenticado.
curl "https://api.apruvly.io/api/v1/workflows/recent" \
-H "Authorization: Bearer wf_YOUR_API_KEY"
/api/v1/billing
Retorna assinatura, plano, saldo de créditos e resumo de uso do usuário autenticado.
curl "https://api.apruvly.io/api/v1/billing" \
-H "Authorization: Bearer wf_YOUR_API_KEY"
/api/v1/integrations
Gerencie credenciais de canais de terceiros (Slack, MS Teams, Twilio, etc.) via a API REST.
| Método | Endpoint | Descrição |
|---|---|---|
| GET | /api/v1/integrations | Lista o status de configuração de todas as integrações suportadas. |
| GET | /api/v1/integrations/{integration} | Retorna o status de configuração de uma integração (segredos nunca são incluídos). |
| PUT | /api/v1/integrations/{integration} | Cria ou substitui credenciais de uma integração. |
| DELETE | /api/v1/integrations/{integration} | Remove credenciais armazenadas de uma integração. |
/api/v1/workflow/{id}
Cancela um workflow pendente. Workflows concluídos ou expirados não podem ser cancelados.
Você também pode cancelar pelo identificador de negócio definido na criação — veja Identificadores de correlação (external_id). Identificadores de correlação (external_id)
| Campo | Tipo | Descrição |
|---|---|---|
id |
uuid | O ID do workflow retornado quando o workflow foi criado. |
curl -X DELETE https://api.apruvly.io/api/v1/workflow/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
/api/v1/workflow/{id}/{challenge}/approve
ou
/api/v1/workflow/{id}/{challenge}/reject
Registra uma decisão de aprovação ou rejeição para uma etapa do workflow. A ação (aprovar ou rejeitar) é determinada pelo sufixo do caminho da URL, não pelo corpo da requisição. Nenhum corpo de requisição é necessário.
| Campo | Tipo | Descrição |
|---|---|---|
id |
uuid | O ID do workflow retornado quando o workflow foi criado. |
challenge |
uuid | Token UUID de desafio por aprovador incluído no link do e-mail de notificação. |
# Approve
curl -X PUT https://api.apruvly.io/api/v1/workflow/550e8400-e29b-41d4-a716-446655440000/7a9f1c2d-4b3e-48f6-9d8c-1a2b3c4d5e6f/approve \
-H "Authorization: Bearer wf_YOUR_API_KEY"
# Reject
curl -X PUT https://api.apruvly.io/api/v1/workflow/550e8400-e29b-41d4-a716-446655440000/7a9f1c2d-4b3e-48f6-9d8c-1a2b3c4d5e6f/reject \
-H "Authorization: Bearer wf_YOUR_API_KEY"
{
"success": true
}
/api/v1/directory
Gerencia a agenda de áreas (times) e pessoas. Contatos alimentam fallback de e-mail nas notificações e vinculam destinatários para análise cross-channel.
| Método | Endpoint | Descrição |
|---|---|---|
| GET | /api/v1/directory/areas | Lista todas as áreas ativas. |
| POST | /api/v1/directory/areas | Cria uma nova área. |
| POST | /api/v1/directory/areas/bulk | Cria até 100 áreas em uma única chamada. |
| PUT | /api/v1/directory/areas/bulk | Renomeia várias áreas de uma vez. Cada item precisa do id da área. |
| GET | /api/v1/directory/areas/{id} | Busca uma área pelo id. |
| PUT | /api/v1/directory/areas/{id} | Renomeia uma área. |
| DELETE | /api/v1/directory/areas/{id} | Remove a área (vínculos com pessoas são removidos; pessoas permanecem). |
| Método | Endpoint | Descrição |
|---|---|---|
| GET | /api/v1/directory/people?q=&area=&page= | Lista paginada de pessoas. Filtros: q (texto), area (uuid), page (1-based). |
| POST | /api/v1/directory/people | Cria uma pessoa com áreas e contatos. |
| POST | /api/v1/directory/people/bulk | Cria até 1.000 pessoas em uma única chamada (com vínculos e contatos). |
| PUT | /api/v1/directory/people/bulk | Atualiza várias pessoas de uma vez (nome, áreas e contatos). Cada item precisa do id da pessoa. |
| GET | /api/v1/directory/people/{id} | Busca uma pessoa com áreas e contatos. |
| PUT | /api/v1/directory/people/{id} | Substitui nome, áreas e contatos em uma só chamada. |
| DELETE | /api/v1/directory/people/{id} | Remove a pessoa (contatos e vínculos são removidos junto). |
curl -X POST https://api.apruvly.io/api/v1/directory/people \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Ana Souza",
"area_ids": ["6c2b6e80-1f74-4cf2-9e2f-0d0e3b9b0001"],
"contacts": [
{ "provider": "email", "address": "[email protected]", "label": "work" },
{ "provider": "twilio-sms", "address": "+5511999999999" }
]
}'
{
"success": true,
"data": {
"id": "a4d1f0c6-2d24-49b3-9e3c-7a2e6c4b0001",
"display_name": "Ana Souza",
"is_active": true,
"area_ids": ["6c2b6e80-1f74-4cf2-9e2f-0d0e3b9b0001"],
"contacts": [
{ "id": "…", "provider": "email", "address": "[email protected]", "label": "work" },
{ "id": "…", "provider": "twilio-sms", "address": "+5511999999999" }
]
}
}
Os endpoints em lote recebem uma lista no campo "items". A criação tem limite por requisição (100 áreas, 1.000 pessoas) e a atualização é limitada a duas vezes o tamanho que o plano do cliente suporta para o recurso correspondente.
curl -X POST https://api.apruvly.io/api/v1/directory/people/bulk \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"display_name": "Ana Souza",
"area_ids": ["6c2b6e80-1f74-4cf2-9e2f-0d0e3b9b0001"],
"contacts": [
{ "provider": "email", "address": "[email protected]", "label": "work" }
]
},
{
"display_name": "Bruno Lima",
"contacts": [
{ "provider": "twilio-sms", "address": "+5511988887777" }
]
}
]
}'
{
"success": true,
"data": {
"count": 2,
"items": [
{ "id": "a4d1f0c6-…", "display_name": "Ana Souza", "area_ids": ["6c2b6e80-…"], "contacts": ["…"] },
{ "id": "f10b2e8a-…", "display_name": "Bruno Lima", "area_ids": [], "contacts": ["…"] }
]
}
}
O lote é processado em conjunto: se qualquer item for inválido, a requisição é rejeitada e nada é gravado.
Cada endpoint exige o escopo correspondente na API key. Conceda escopos em Chaves de API no painel.
| Escopos | Descrição |
|---|---|
api:directory:list | API · Diretório · listar |
api:directory:read | API · Diretório · ler |
api:directory:write | API · Diretório · criar / atualizar |
api:directory:bulk | API · Diretório · operações em massa |
api:directory:delete | API · Diretório · excluir |
Cada contato é um par (provider, address). Só providers configurados em /integrations (além de e-mail) são aceitos.
| Canal | Endereço |
|---|---|
email, slack, ms-teams | E-mail address |
twilio-sms, twilio-whatsapp, whatsapp | E.164 phone (e.g. +5511999999999) |
telegram | Numeric chat id |
discord | 17–20 digit snowflake |
Robôs de grupo DingTalk não ficam no diretório — eles enviam para um grupo, não para um contato individual.
| Status | Descrição |
|---|---|
| 400 | Campo obrigatório ausente ou contato inválido (e-mail ou telefone malformado, por exemplo). |
| 402 | O plano atual não inclui a feature de diretório. |
| 409 | Diretório está desativado — ative em /directory no painel antes de chamar a API. |
Efeitos colaterais que o engine dispara quando eventos de ciclo de vida do workflow ocorrem.
Use o campo `on` para registrar ações em eventos de ciclo de vida do workflow. Cada ação tem um tipo (webhook, email ou twilio-sms) e um payload de dados. Quando o evento dispara, todas as ações são executadas em ordem.
Cada action é um objeto JSON que pode ser serializado em duas formas. A forma wrapped ({"type":"...", "data":{...}}) é a canônica produzida pela API e a única aceita para twilio-sms. A forma flat infere o tipo a partir dos campos do payload (url → webhook, to → email) e é mantida por compatibilidade com clientes antigos.
{
"on": {
"workflow_approved": [
{ "type": "webhook", "data": { "url": "https://example.com/hooks/approved", "method": "POST" } },
{ "type": "email", "data": { "to": ["[email protected]"], "subject": "Approved", "body": "Workflow ${id} is approved." } },
{ "type": "twilio-sms", "data": { "to": ["+14155552671"], "body": "Workflow ${id} approved" } }
]
}
}
| Evento | Descrição |
|---|---|
workflow_created |
Disparado quando um workflow é criado com sucesso. |
workflow_approved |
Disparado quando o workflow inteiro atinge o estado final de aprovado. |
workflow_rejected |
Disparado quando o workflow inteiro é rejeitado. |
workflow_expired |
Disparado quando o workflow expira antes de atingir uma decisão final. |
workflow_canceled |
Disparado quando o workflow é explicitamente cancelado via API. |
workflow_completed |
Disparado quando o workflow atinge qualquer estado terminal (aprovado, rejeitado, expirado ou cancelado). |
step_approved |
Disparado quando um step individual é aprovado e o workflow avança para o próximo step. |
step_escalated |
Disparado quando o timer de escalonamento de um step é acionado e a notificação de escalonamento é enviada. |
user_approval |
Disparado cada vez que um usuário registra um voto de aprovação em um step. |
user_rejection |
Disparado cada vez que um usuário registra um voto de rejeição em um step. |
WebhookAction
— type: "webhook"
Envia uma requisição HTTP para um endpoint externo. Hosts privados e de loopback são rejeitados no momento do envio.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type |
string | Sim | Deve ser "webhook". |
url |
string | Sim | A URL de destino. Deve ser uma URI válida. |
method |
string | Não | Método HTTP: GET, POST, PUT, PATCH ou DELETE. Padrão: POST. |
headers |
object | Não | Headers HTTP customizados enviados com a requisição. Útil para tokens de autenticação ou chaves de API. |
body |
object|string | Não | Corpo da requisição. Suporta interpolação de variáveis com sintaxe ${variável}. |
timeout |
duration | Não | Timeout da requisição (ex: "30s", "5m"). Padrão: configuração do servidor. |
async |
boolean | Não | Se verdadeiro, a requisição é enviada de forma assíncrona e não bloqueia o workflow. |
skipCertVerify |
boolean | Não | Se verdadeiro, ignora a verificação do certificado TLS. Use apenas em ambientes de desenvolvimento. |
EmailAction
— type: "email"
Envia um email pelo SMTP customizado (quando configurado) ou pelo postman do sistema.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Sim | Endereços destinatários. Pelo menos um é obrigatório. |
subject |
string | Não | Assunto do email. |
body |
string | Não | Corpo do email. Suporta interpolação ${variável}. |
cc |
string[] | Não | Lista opcional de destinatários em cópia (CC). |
bcc |
string[] | Não | Lista opcional de destinatários em cópia oculta (BCC). |
html |
boolean | Não | Se verdadeiro, o corpo é enviado como HTML; caso contrário, como texto simples. |
SmsAction
— type: "twilio-sms"
Dispara um SMS fire-and-forget via Twilio. Apenas informativo — sem correlação por short-code nem rastreio de resposta.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Sim | Números em formato E.164 (ex.: +14155552671). Duplicatas e entradas inválidas são rejeitadas. |
body |
string | Sim | Texto da mensagem (até 1600 caracteres). Suporta interpolação ${variável}. |
Você pode usar as seguintes variáveis dentro dos valores do body do webhook. Elas são substituídas automaticamente no momento da execução.
| Variável | Descrição |
|---|---|
${id} |
O UUID único do workflow. |
${status} |
Status atual do workflow (ex: approved, rejected, expired). |
${current_step} |
O identificador do step atualmente ativo. |
${escalation_level} |
Nível de profundidade do escalonamento atual (0 se nenhum escalonamento ocorreu). |
{
"on": {
"workflow_approved": [
{
"type": "webhook",
"data": {
"url": "https://api.yourapp.com/webhooks/approved",
"method": "POST",
"headers": { "Authorization": "Bearer your-token" },
"body": {
"workflow_id": "${id}",
"status": "${status}",
"current_step": "${current_step}"
},
"timeout": "30s"
}
}
],
"workflow_rejected": [
{
"type": "webhook",
"data": {
"url": "https://api.yourapp.com/webhooks/rejected",
"async": true
}
}
],
"step_approved": [
{
"type": "webhook",
"data": {
"url": "https://api.yourapp.com/webhooks/step-done",
"body": {
"step": "${current_step}"
}
}
}
]
}
}
Além dos eventos no nível do workflow, cada step pode registrar suas próprias ações que disparam quando AQUELE step é aprovado ou rejeitado — independente do resultado final do workflow. Use `step.actions.approved` e `step.actions.rejected` para disparar webhooks ou emails por decisão.
{
"workflow": {
"review": {
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Please review",
"body": "Approve or reject ${id}"
},
"actions": {
"approved": [
{
"type": "webhook",
"data": {
"url": "https://example.com/hooks/review-approved",
"method": "POST"
}
}
],
"rejected": [
{
"type": "email",
"data": {
"to": ["[email protected]"],
"subject": "Review rejected",
"body": "${id} was rejected"
}
}
]
}
}
}
}
Custo: cada webhook conta como 1 crédito; cada destinatário em ações de email ou twilio-sms conta como 1 crédito por destinatário. CC e BCC em ações de email não são cobrados.
Cada step custa 1 crédito mais 1 por nível de escalonamento configurado. Actions de envio externo adicionam um único crédito flat, compartilhado entre webhook e twilio-sms.
| Tipo | Custo |
|---|---|
webhook |
+1 por workflow (independente da quantidade de webhooks ou eventos). |
email |
Sem custo adicional. |
twilio-sms |
+1 por workflow (compartilhado com webhook — máximo +1 no total). |
twilio-whatsapp |
+1 por workflow (compartilhado com webhook — máximo +1 no total). |
discord |
+1 por workflow (independente da quantidade de webhooks ou eventos). |
Os créditos são debitados uma única vez no momento da criação do workflow. Não há cobrança por disparo.
Descrição detalhada de todos os objetos de requisição e resposta.
Step| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type |
string | Sim | Tipo de notificação. Suportado atualmente: email, ms-teams, slack, whatsapp, telegram, dingtalk, discord, twilio-sms, twilio-whatsapp |
data |
EmailData | MSTeamsData | SlackData | WhatsAppData | TelegramData | DingTalkData | DiscordData | TwilioSMSData | TwilioWhatsAppData | Sim | Payload de notificação. O formato depende do tipo. |
minApprovals |
integer | Não | Número mínimo de aprovações necessárias para avançar. Padrão: 1. |
minRejections |
integer | Não | Número mínimo de rejeições necessárias para rejeitar o workflow. Padrão: 1. |
approved |
string | Não | Chave do passo a executar quando este for aprovado. Omitir para encerrar o workflow como aprovado. |
rejected |
string | Não | Chave do passo a executar quando este for rejeitado. Omitir para encerrar o workflow como rejeitado. |
escalation |
Escalation | Não | Configuração opcional de escalonamento para acionar caso os aprovadores não respondam a tempo. |
actions |
{approved, rejected} | Não | Ações opcionais disparadas quando ESTE step for aprovado ou rejeitado, independente do resultado final do workflow. Veja a seção Actions para os formatos suportados. (Ações por Step) |
Channel delivery
A entrega em canal compartilhado publica uma mensagem de aprovação em canal de equipe, grupo ou chat. Apenas usuários em allowList podem clicar nos botões interativos; o log registra quem clicou, não o ID do canal.
| Tipo | Descrição |
|---|---|
slack |
to: ID do canal (C…). allowList: IDs Slack (U…) e/ou e-mails do workspace. Exige Signing Secret. |
ms-teams |
to: teamId/channelId. allowList: object IDs Azure AD e/ou e-mails. Posts em canal usam uma API protegida do Microsoft Graph — o tenant precisa conceder Resource-Specific Consent (ex.: ChannelMessage.Send) no app Teams ou permissão de aplicação aprovada pelo administrador. O bot Apruvly deve estar instalado na equipe de destino. |
telegram |
to: chat ID negativo de grupo/canal (-100…). allowList: IDs de usuário Telegram. Bot precisa ser membro do grupo. |
discord |
to: snowflake do canal (17–20 dígitos). allowList: snowflakes de usuário Discord. Exige URL de Interactions e Public Key. |
dingtalk |
DingTalk sempre faz broadcast para o grupo do robot — delivery: "channel" é rejeitado. |
CardOverride| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
title |
string | Não | Título opcional que substitui o título da notificação ou embed. |
description |
string | Não | Texto opcional exibido no corpo da notificação ou na descrição do embed. |
links |
string[] | Não | URLs opcionais renderizadas como botões de ação (ex: ver solicitação). |
EmailData — usado quando type = email
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Sim | Lista de endereços de e-mail dos aprovadores para este passo. |
subject |
string | Sim | Assunto do e-mail de aprovação. |
body |
string | Sim | Mensagem em texto simples ou HTML para o aprovador. object.title e object.description aparecem automaticamente em um card de resumo; os botões de aprovar/rejeitar são adicionados para você. |
cc |
string[] | Não | Lista opcional de destinatários em cópia (CC). |
bcc |
string[] | Não | Lista opcional de destinatários em cópia oculta (BCC). |
isHtml |
boolean | Não | Defina como true se o body contiver marcação HTML. Padrão: false. |
Estes placeholders podem ser usados no assunto e no corpo.
| Variável | Descrição |
|---|---|
${title} |
Título do objeto do workflow (também exibido no card de resumo). |
${description} |
Descrição do objeto do workflow (também exibida no card de resumo). |
${id} |
O UUID único do workflow. |
${user_email} |
Endereço de e-mail do destinatário. |
${user_name} |
Nome de exibição do destinatário, ou a parte local do e-mail quando não houver nome. |
SlackData — usado quando type = slack
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
delivery |
string | Não | Modo de entrega: omitir ou "direct" (padrão) envia uma mensagem por destinatário; "channel" publica uma mensagem em destino compartilhado com lista de autorizados. Suportado em slack, ms-teams, telegram e discord. |
allowList |
string[] | Não | Quando delivery for "channel", lista de e-mails e/ou IDs nativos do provedor autorizados a clicar em Aprovar/Rejeitar. Obrigatório no modo canal. |
to |
string[] | Sim | Modo direct: e-mails do workspace (uma DM por destinatário). Modo channel: IDs de canal Slack começando com C. |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
MSTeamsData — usado quando type = ms-teams
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
delivery |
string | Não | Modo de entrega: omitir ou "direct" (padrão) envia uma mensagem por destinatário; "channel" publica uma mensagem em destino compartilhado com lista de autorizados. Suportado em slack, ms-teams, telegram e discord. |
allowList |
string[] | Não | Quando delivery for "channel", lista de e-mails e/ou IDs nativos do provedor autorizados a clicar em Aprovar/Rejeitar. Obrigatório no modo canal. |
to |
string[] | Sim | Modo direct: e-mails Azure AD. Modo channel: pares teamId/channelId (uma mensagem por entrada). |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
WhatsAppData — usado quando type = whatsapp
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Sim | Lista de telefones dos aprovadores em formato E.164 (ex: +5511999999999). |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
TelegramData — usado quando type = telegram
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
delivery |
string | Não | Modo de entrega: omitir ou "direct" (padrão) envia uma mensagem por destinatário; "channel" publica uma mensagem em destino compartilhado com lista de autorizados. Suportado em slack, ms-teams, telegram e discord. |
allowList |
string[] | Não | Quando delivery for "channel", lista de e-mails e/ou IDs nativos do provedor autorizados a clicar em Aprovar/Rejeitar. Obrigatório no modo canal. |
to |
string[] | Sim | Modo direct: chat IDs positivos de usuário (ex: 123456789). Modo channel: chat IDs negativos de grupo/canal (ex: -1001234567890). |
markdown |
boolean | Não | Quando verdadeiro, a mensagem é enviada em formato MarkdownV2 do Telegram em vez de HTML. O campo de descrição pode conter sintaxe MarkdownV2 (ex: *negrito*, _itálico_, `código`). Padrão: false. |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
DiscordData — usado quando type = discord
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
delivery |
string | Não | Modo de entrega: omitir ou "direct" (padrão) envia uma mensagem por destinatário; "channel" publica uma mensagem em destino compartilhado com lista de autorizados. Suportado em slack, ms-teams, telegram e discord. |
allowList |
string[] | Não | Quando delivery for "channel", lista de e-mails e/ou IDs nativos do provedor autorizados a clicar em Aprovar/Rejeitar. Obrigatório no modo canal. |
to |
string[] | Sim | Modo direct: snowflakes de usuário Discord (17–20 dígitos). Modo channel: snowflake do canal. O bot precisa compartilhar servidor com destinatários de DM. |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
DingTalkData — usado quando type = dingtalk
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Não | Celulares opcionais (E.164) para @mention no ActionCard do grupo. DingTalk sempre posta no grupo do robot configurado. |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
TwilioSMSData — usado quando type = twilio-sms
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Sim | Informe números em formato E.164 (ex: +5511999999999). Os destinatários precisam ter consentido em receber SMS. |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
TwilioWhatsAppData — usado quando type = twilio-whatsapp
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
to |
string[] | Sim | Telefone do WhatsApp Sender registrado na Twilio em formato E.164 (sem o prefixo whatsapp:). |
card |
CardOverride | Não | Substituição opcional por step para o título, descrição e links de ação da notificação. Quando omitido, os campos do objeto do workflow são usados. |
Escalation| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type |
string | Sim | Tipo de notificação para o escalonamento. Suportado atualmente: email, ms-teams, slack, whatsapp, telegram, dingtalk, discord, twilio-sms, twilio-whatsapp |
after |
duration | Sim | Quanto tempo aguardar antes de acionar o escalonamento. Mínimo: 5m. |
data |
EmailData | TelegramData | … | Sim | Payload de notificação enviado aos destinatários do escalonamento. |
escalation |
Escalation | Não | Escalonamento aninhado opcional para acionar caso este nível de escalonamento também não seja respondido. Profundidade máxima: 5. |
Decision — retornado dentro de decisions[] em GET /workflow/{id}| Campo | Tipo | Descrição |
|---|---|---|
user |
string | Endereço de e-mail do aprovador que submeteu a decisão. |
is_approved |
boolean | true se aprovado, false se rejeitado. |
ip |
string | Endereço IP de onde a decisão foi submetida. |
decisionAt |
RFC3339 | Timestamp RFC 3339 de quando a decisão foi registrada. |
Planos Business e Professional podem enviar e-mails de aprovação pelo seu SMTP em vez do mailer da plataforma. Configure em Configurações → Integrações → SMTP personalizado (não no JSON do workflow).
As chaves de etapa (usadas nos campos start, approved e rejected, e como chaves do mapa workflow) devem corresponder ao seguinte padrão - letra minúscula seguida de letras minúsculas, dígitos, hífens ou underscores:
^[a-z][a-z0-9_-]+$
Durações são expressas como um número seguido de um sufixo de unidade:
30s — 30 segundos
15m — 15 minutos
2h — 2 horas
7d — 7 dias
2w — 2 semanas
A expiração do workflow deve estar entre 5 minutos (mínimo) e 7 dias (máximo).
A API usa códigos de status HTTP padrão. Respostas de erro incluem um corpo JSON com os campos error e code.
| Código de Status | Significado |
|---|---|
| 200 | Requisição realizada com sucesso. |
| 202 | Accepted - o workflow foi criado e está em execução. |
| 400 | Bad Request - o corpo ou parâmetros da requisição são inválidos. |
| 401 | Unauthorized - chave de API ausente ou inválida. |
| 402 | Payment Required - sem assinatura ativa, créditos insuficientes ou o plano atual não inclui a feature solicitada. |
| 403 | Forbidden - a chave de API não tem permissão para este recurso (ex.: você não é o dono do workflow). |
| 404 | Not Found - o workflow ou recurso não existe. |
| 406 | Not Acceptable - a operação não pode ser realizada no estado atual do workflow (ex.: cancelar um workflow já concluído). |
| 429 | Too Many Requests - limite de requisições excedido. |
| 500 | Internal Server Error - algo deu errado do nosso lado. |
{
"success": false,
"message": "Invalid workflow ID.",
"data": {
"field": "id",
"value": "not-a-valid-uuid"
}
}
Casos de uso comuns com descrições amigáveis para ajudá-lo a começar rapidamente.
O caso de uso mais básico: uma única pessoa precisa aprovar algo antes de você prosseguir. Ideal para aprovações de despesas, revisão de conteúdo ou qualquer cenário com um único aprovador.
Encaminhe uma aprovação por várias pessoas em sequência - Jurídico → Gerente → CEO. Cada etapa deve ser aprovada antes que a próxima comece. Perfeito para assinaturas de contratos ou aprovações de políticas.
Se o aprovador designado não responder dentro de um prazo, notifique automaticamente um contato substituto. Mantém os processos em andamento sem acompanhamento manual.
Exija um número mínimo de aprovações de um grupo - qualquer N de M membros pode aprovar. Útil para decisões de diretoria, aprovações de comitê ou revisões por pares.
Envie automaticamente um POST para o seu backend quando um workflow atingir uma decisão final. Acione automação subsequente sem fazer polling da API.
Verifique se a configuração do seu workflow é válida antes de criá-lo. Não requer autenticação, não consome créditos - apenas uma verificação rápida de sintaxe e lógica.
Encaminhe a aprovação de um novo contratado pelo RH, gerente de contratação e provisionamento de TI em sequência. Cada equipe só recebe a solicitação após a etapa anterior ser concluída.
Uma solicitação de folga enviada ao gestor direto. Se não houver resposta em 24 horas, o RH é notificado automaticamente. Um webhook é disparado quando a decisão é tomada.
Condicione um deploy em produção a três aprovações sequenciais: revisão de código pelo líder técnico, sign-off do QA e autorização de operações. Um webhook aciona o pipeline de CI/CD após aprovação.
Cadeia de aprovação em dois níveis (gerente e depois CFO), cada um com seu próprio escalonamento. Se o gerente não responder, o VP assume; se o CFO atrasar, o CEO é notificado. Webhooks cuidam da automação financeira.
Publica uma mensagem de aprovação em um canal Slack compartilhado. Configure delivery: "channel", o ID do canal em to e uma allowList de usuários autorizados a clicar em Aprovar/Rejeitar.
Endpoint JSON-RPC 2.0 para agentes de IA e pipelines de automação
O endpoint MCP segue a especificação do Model Context Protocol usando JSON-RPC 2.0 sobre HTTP. Permite que agentes de IA e ferramentas de automação pausem a execução e solicitem aprovação humana antes de realizar ações críticas.
POST https://mcp.apruvly.io/mcp
Authorization: Bearer wf_YOUR_API_KEY
Content-Type: application/json
Clientes MCP-aware podem buscar um documento de descoberta público em GET /.well-known/mcp para auto-detectar a URL do endpoint, transports e versões de protocolo suportadas, esquema de autenticação, e o catálogo de ferramentas disponíveis. Não requer autenticação.
GET https://mcp.apruvly.io/.well-known/mcp
{
"endpoint": "https://mcp.apruvly.io/mcp",
"transports": ["streamable-http"],
"protocolVersions": ["2025-03-26"],
"auth": { "scheme": "bearer" },
"tools": ["create_approval_request", "get_approval_status", "cancel_approval_request"]
}
Seu agente de IA chama create_approval_request com um título, descrição e os emails dos aprovadores.
Apruvly envia um email de aprovação para cada aprovador contendo links de aprovar/rejeitar.
O agente consulta get_approval_status até o status mudar para aprovado, rejeitado ou expirado.
Exemplos de configuração para ferramentas de IA populares
Adicione a seguinte entrada de servidor MCP ao arquivo .mcp.json do seu projeto ou nas configurações globais:
{
"mcpServers": {
"apruvly": {
"type": "streamable-http",
"url": "https://mcp.apruvly.io/mcp",
"headers": {
"Authorization": "Bearer wf_YOUR_API_KEY"
}
}
}
}
Adicione o seguinte à seção mcpServers no arquivo de configuração do Claude Desktop:
{
"mcpServers": {
"apruvly": {
"url": "https://mcp.apruvly.io/mcp",
"headers": {
"Authorization": "Bearer wf_YOUR_API_KEY"
}
}
}
}
Adicione o servidor MCP nas configurações do Cursor em Features > MCP Servers, ou adicione ao .cursor/mcp.json no seu projeto:
{
"mcpServers": {
"apruvly": {
"url": "https://mcp.apruvly.io/mcp",
"headers": {
"Authorization": "Bearer wf_YOUR_API_KEY"
}
}
}
}
Adicione a seguinte entrada de servidor MCP ao arquivo .mcp.json do seu projeto ou nas configurações globais:
// .vscode/mcp.json
{
"servers": {
"apruvly": {
"type": "http",
"url": "https://mcp.apruvly.io/mcp",
"headers": {
"Authorization": "Bearer wf_YOUR_API_KEY"
}
}
}
}
Qualquer cliente compatível com MCP pode se conectar ao endpoint Apruvly usando transporte Streamable HTTP. Envie requisições JSON-RPC 2.0 diretamente:
curl -X POST https://mcp.apruvly.io/mcp \
-H "Authorization: Bearer wf_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"clientInfo": {"name": "my-agent", "version": "1.0"},
"capabilities": {}
}
}'
Ferramentas disponíveis que agentes de IA podem invocar via tools/call
create_approval_requestCria uma solicitação de aprovação humana e retorna um workflow_id que pode ser usado para consultar a decisão. A notificação é enviada pelo canal escolhido em `channel` (padrão email); canais não-email precisam estar configurados na conta.
| Campo | Tipo | Descrição | |
|---|---|---|---|
title |
string | Obrigatório | Título curto (máx 200 caracteres) descrevendo o que requer aprovação. |
description |
string | Opcional | Descrição detalhada da ação que requer aprovação humana (máx 4000 caracteres). |
channel |
string | Opcional | Canal de entrega. Padrão: "email". Permitidos: email, slack, ms-teams, whatsapp, telegram, dingtalk, discord, twilio-sms, twilio-whatsapp. Canais que não sejam email exigem que a integração correspondente esteja configurada em /integrations. |
recipients |
array | Opcional | Lista uniforme de destinatários, uma entrada por aprovador. Use para mirar qualquer canal. O formato de address depende do canal (email/slack/ms-teams = endereço de email, whatsapp/twilio-sms/twilio-whatsapp = telefone E.164, telegram = chat ID numérico, discord = snowflake de 17-20 dígitos). Mutuamente exclusivo com approvers e steps. |
approvers |
array | Opcional | Aprovadores (emails separados por vírgula) — {"email":"…","name":"…"}. Email-only shortcut; for other channels use recipients. |
steps |
array | Opcional | Cadeia opcional de aprovações sequenciais. Cada step precisa ser aprovado antes do próximo rodar; qualquer rejeição encerra o workflow. Requer plano Growth, Business ou Professional. Mutuamente exclusivo com recipients/approvers no nível superior. |
expires |
string | Opcional | String de duração: "1h", "24h", "7d". Padrão: "24h". Mínimo: 5 minutos — valores menores são rejeitados antes de qualquer débito de crédito. |
links |
array | Opcional | Lista de URLs relacionadas (documentos, arquivos, links). |
tags |
array | Opcional | Lista de rótulos para filtragem e categorização. |
idempotency_key |
string | Opcional | Identificador opcional fornecido pelo cliente (máx 128 caracteres) que torna a chamada idempotente. Repetir a mesma chave em até 24h retorna o workflow_id original sem recriar workflow nem cobrar créditos. Equivalente ao header HTTP Idempotency-Key. |
callback_url |
string | Opcional | URL https opcional que recebe um POST assinado quando o workflow chega a um estado terminal. Útil para agentes em batch que não conseguem manter uma conexão de polling ou SSE aberta. |
external_id |
string | Opcional | Identificador opcional fornecido pelo chamador (máx 128 caracteres) — ex: run_id do agente, tool_call_id externo, ticket id interno. Requer plano Growth ou superior. Persistido na linha do workflow e ecoado em get_approval_status. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_approval_request",
"arguments": {
"title": "Deploy to production",
"description": "Requesting approval to deploy v2.5.0 to production.",
"channel": "slack",
"recipients": [
{ "address": "[email protected]" }
],
"expires": "24h",
"idempotency_key": "agent-run-2026-05-03-00042",
"external_id": "deploy-pipeline-7831"
}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{ "type": "text", "text": "Approval request created…" },
{ "type": "text", "text": "{\"workflow_id\":\"550e8400-…\",\"status\":\"pending\",\"expires_at\":\"2026-05-04T12:00:00Z\",\"external_id\":\"deploy-pipeline-7831\"}" }
],
"structuredContent": {
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"expires_at": "2026-05-04T12:00:00Z",
"external_id": "deploy-pipeline-7831"
}
}
}
As respostas das tools também carregam um campo structuredContent espelhando o snapshot JSON do segundo content — declarado pelo outputSchema da tool para que clientes MCP-aware façam parse tipado sem varrer o payload em texto.
A two-step chain: the manager has 24h to approve before the request escalates to the director, and only after the manager approves does the VP get the second-level request.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_approval_request",
"arguments": {
"title": "Vendor Contract – Novatek",
"channel": "email",
"steps": [
{
"name": "manager",
"recipients": [{ "address": "[email protected]" }],
"escalate_after": "24h",
"escalate_to": [{ "address": "[email protected]" }]
},
{
"name": "vp",
"recipients": [{ "address": "[email protected]" }]
}
],
"expires": "7d"
}
}
}
get_approval_statusRetorna o status atual e as decisões de etapa de uma solicitação de aprovação. Consulte após create_approval_request até o status mudar para aprovado, rejeitado ou expirado.
| Campo | Tipo | Descrição | |
|---|---|---|---|
workflow_id |
string | Obrigatório | O ID do workflow retornado quando o workflow foi criado. |
wait |
string | Opcional | Duração opcional de long-poll (ex: "30s", "60s", "1m"). Quando setado, a chamada bloqueia até o workflow sair do estado pendente ou a duração esgotar, o que vier primeiro. Limitado a 60s. Reduz o número de round-trips de polling. |
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_approval_status",
"arguments": {
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"wait": "60s"
}
}
}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text", "text": "Approval status retrieved." },
{ "type": "text", "text": "{\"workflow_id\":\"550e8400-…\",\"status\":\"approved\",\"current_step\":\"approval\",\"external_id\":\"deploy-pipeline-7831\",\"decisions\":[…]}" }
],
"structuredContent": {
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "approved",
"current_step": "approval",
"created_at": "2026-05-03T11:00:00Z",
"expires_at": "2026-05-04T12:00:00Z",
"external_id": "deploy-pipeline-7831",
"decisions": [{ "user": "[email protected]", "is_approved": true, "decided_at": "2026-05-03T11:42:18Z", "step": "manager" }]
}
}
}
Cada entrada em decisions pode incluir um campo step opcional com o nome do step no momento da decisão. Workflows single-step legados podem omiti-lo.
cancel_approval_requestCancela uma solicitação de aprovação pendente. Para os lembretes, notifica os aprovadores em todos os canais configurados que a solicitação foi cancelada e marca o workflow como cancelado em estado terminal. Idempotente: uma segunda chamada em um workflow já cancelado retorna sucesso com already_canceled=true.
| Campo | Tipo | Descrição | |
|---|---|---|---|
workflow_id |
string | Obrigatório | O ID do workflow retornado quando o workflow foi criado. |
reason |
string | Opcional | Motivo opcional em texto livre para o cancelamento (máx 500 caracteres). Registrado no log de atividades do workflow para auditoria do motivo da retirada. |
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "cancel_approval_request",
"arguments": {
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"reason": "agent retry resolved the action without human approval"
}
}
}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{ "type": "text", "text": "Approval request canceled." },
{ "type": "text", "text": "{\"workflow_id\":\"550e8400-…\",\"status\":\"canceled\",\"already_canceled\":false,\"canceled_at\":\"2026-05-03T12:34:56Z\"}" }
],
"structuredContent": {
"workflow_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "canceled",
"already_canceled": false,
"canceled_at": "2026-05-03T12:34:56Z"
}
}
}
Métodos JSON-RPC 2.0, handshake e códigos de erro
| Método | Descrição |
|---|---|
initialize |
Inicializa uma sessão MCP. Negocia a versão do protocolo (ecoa a versão do cliente quando suportada, faz downgrade para a maior versão suportada abaixo dela, ou retorna -32602 com a lista suportada quando nenhuma versão compatível existe) e retorna informações do servidor e capacidades. |
ping |
Verificação de saúde. Retorna um objeto de resultado vazio. |
tools/list |
Retorna a lista de ferramentas disponíveis, suas definições de esquema JSON de entrada e um outputSchema descrevendo o structuredContent que cada ferramenta retorna. |
tools/call |
Invoca uma ferramenta pelo nome com os argumentos fornecidos. |
notifications/* |
Métodos iniciados com notifications/ são aceitos com HTTP 202 e sem corpo de resposta, conforme exigido pela especificação. notifications/cancelled é honrado para abortar uma tools/call em vôo (veja "Notificações" abaixo); o restante é descartado silenciosamente. |
initialize{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"clientInfo": { "name": "my-agent", "version": "1.0" },
"capabilities": {}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"serverInfo": { "name": "apruvly", "version": "1.0.0" },
"capabilities": { "tools": {} },
"instructions": "Apruvly is a human-in-the-loop approval service…"
}
}
O endpoint aceita um array JSON de requisições no corpo (máx. 50 itens) e retorna um array de respostas. Itens são processados sequencialmente; wait em get_approval_status é limitado a 5s dentro de um lote. Entradas notifications/cancelled no mesmo array são aplicadas antes de qualquer tools/call. Notificações não geram entrada no array; um lote contendo apenas notificações retorna 202 Accepted com corpo vazio. Um array vazio é rejeitado com -32600 Invalid Request.
[
{ "jsonrpc": "2.0", "id": 1, "method": "ping" },
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": { "name": "get_approval_status",
"arguments": { "workflow_id": "550e8400-e29b-41d4-a716-446655440000" } } }
]
[
{ "jsonrpc": "2.0", "id": 1, "result": {} },
{ "jsonrpc": "2.0", "id": 2, "result": { "content": [ … ], "structuredContent": { … } } }
]
notifications/cancelled aborta uma chamada tools/call em vôo para que o agente encurte um long-poll sem esperar o timer disparar. Combine o campo requestId com o id da requisição que se quer cancelar; a chamada em execução devolve o snapshot atual imediatamente. Dentro de um lote, inclua a notificação no mesmo array — ela é honrada antes dos itens tools/call. Para abortar um long-poll já em vôo em outra conexão, envie notifications/cancelled como POST sibling. Cancelar um requestId que não está em vôo é um no-op silencioso.
notifications/cancelled{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": 2,
"reason": "agent changed its mind"
}
}
Resposta 202 Accepted — empty body, per the JSON-RPC notification convention. The matching tools/call wakes from its long-poll and returns its current snapshot to the original caller.
Erros no nível da aplicação usam o código -32000 com um slug estável em data.code para que agentes possam ramificar programaticamente sem fazer parse do texto da mensagem.
| Código | Significado |
|---|---|
-32700 |
Parse error — invalid JSON body. |
-32600 |
Invalid Request — missing jsonrpc or method. |
-32601 |
Method not found. |
-32602 |
Invalid params — missing or malformed arguments. Also returned by initialize when the client requests a protocol version older than anything the server supports (the response carries data.supported with the list of acceptable versions). |
-32603 |
Internal error. |
-32000 |
Application error — branch on the stable slug under data.code (see table below). |
data.code slugs (application errors)data.code |
Significado | extra data fields |
|---|---|---|
subscription_required |
The caller has no active subscription. | — |
plan_feature_required |
The current plan does not include the requested feature (MCP access, multi-step approval, …). | feature |
integration_not_configured |
The chosen channel needs an integration that the tenant has not configured at /integrations. |
channel, integration |
trial_expired |
Trial period has expired; upgrade to continue. | — |
approver_limit_exceeded |
The workflow lists more approvers than the plan allows. | max |
escalation_limit_exceeded |
The escalation chain is deeper than the plan allows. | max |
concurrent_workflow_limit |
The plan's cap on simultaneously-pending workflows was reached. | max |
rate_limited |
Too many requests in the current window. Retry after retry_after_seconds. |
window, retry_after_seconds |
insufficient_credits |
Account balance cannot cover the cost of the workflow. | — |
workflow_not_found |
The workflow_id does not exist for the calling account. Cross-tenant lookups intentionally return the same slug to avoid leaking existence. |
— |
workflow_not_cancelable |
cancel_approval_request was called on a workflow already in a non-pending terminal state (approved, rejected, expired, error). |
status |
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000,
"message": "Rate limit exceeded, try again in a moment",
"data": {
"code": "rate_limited",
"window": "minute",
"retry_after_seconds": 60
}
}
}