Referência da API FPP
Este documento descreve como integrar com a API de prevenção à fraude da Guardline. Ele cobre autenticação, envio de transações para análise, interpretação das decisões, recebimento de notificações via webhook e o tratamento do ciclo de vida completo das decisões.
O modelo de integração segue uma separação clara de responsabilidades: a Guardline decide e sinaliza, o integrador executa. A Guardline nunca acessa o sistema de core banking diretamente. Todas as ações (bloqueios cautelares, bloqueios de conta) são comunicadas por resposta síncrona ou webhook, e o integrador é responsável por executá-las.
Autenticação
Seção intitulada “Autenticação”Todas as requisições à API devem incluir uma API key válida no header X-API-Key.
X-API-Key: gl_live_your_api_key_hereAs API keys são provisionadas pela equipe da Guardline e têm escopo por ambiente (sandbox, produção). Mantenha a sua API key confidencial. Em caso de comprometimento, entre em contato com a Guardline imediatamente para rotação.
Além do escopo de ambiente, as API keys carregam um ou mais escopos de permissão que controlam o acesso a grupos específicos de endpoints. Cada seção de endpoint deste documento indica o escopo exigido, quando aplicável. Entre em contato com a Guardline para habilitar escopos adicionais na sua chave.
Todos os endpoints exigem HTTPS. Requisições HTTP são rejeitadas.
Análise de transações
Seção intitulada “Análise de transações”Envie uma transação para análise de fraude em tempo real. Este é o principal endpoint de integração.
Endpoint
Seção intitulada “Endpoint”POST /api/v2/decisions/analyzeRequisição
Seção intitulada “Requisição”Content-Type: application/json
Campos obrigatórios
Seção intitulada “Campos obrigatórios”Estes cinco campos são obrigatórios em toda requisição de análise. Note que não é necessário nenhum cadastro prévio do cliente. A Guardline tenta enriquecer o contexto consultando os dados do cliente a partir do accountId, mas, se nenhum cliente for encontrado, a análise segue normalmente com os dados fornecidos na requisição.
| Campo | Tipo | Descrição |
|---|---|---|
transactionId | string | Identificador único da transação no seu sistema. Usado para idempotência (requisições duplicadas retornam a decisão original). Recomendamos um padrão como TX-YYYYMMDD-NNNNNNNN. |
accountId | string | Identificador da conta no seu sistema. Usado para consultar os dados do cliente (se cadastrado previamente) e para correlacionar transações na análise de velocidade e de comportamento. |
transactionType | string | Código do tipo de transação. Crítico para o roteamento do workflow: o motor de fraude usa este campo para determinar qual workflow executar. Para transações PIX, use PIX. Os demais tipos suportados dependem da sua configuração. |
transactionDate | string | Timestamp ISO 8601 com fuso horário (por exemplo, 2026-03-08T14:30:00-03:00). Usado para análise temporal e cálculo do SLA. |
totalAmount | string | Valor da transação como string decimal (por exemplo, "15000.00"). Use ponto como separador decimal, sem separador de milhar. |
Campos opcionais
Seção intitulada “Campos opcionais”Estes campos são opcionais. Quanto mais contexto for fornecido, mais precisa é a análise de fraude. O integrador decide quais blocos incluir com base nos dados disponíveis.
| Campo | Tipo | Descrição |
|---|---|---|
accountHolderId | string | Fortemente recomendado. CPF ou CNPJ do titular da conta (por exemplo, 12345678900). A resolução de identidade se baseia na quantidade de dígitos depois de removida a pontuação: 11 dígitos são tratados como CPF, 14 como CNPJ, e qualquer outro comprimento é ignorado para fins de resolução. Habilita a resolução de identidade do cliente, as baselines comportamentais, a análise de velocidade e o perfil de risco. Sem este campo, cada transação é avaliada isoladamente, sem histórico do cliente. Em uma transação de entrada, este é o documento do recebedor, não o do pagador (consulte PIX In). |
currency | string | Código de moeda ISO 4217 (padrão: BRL) |
channel | string | Canal de origem (MOBILE, WEB, API) |
country | string | Código de país ISO 3166-1 alpha-2 |
metadata | object | Metadados da transação (direção, status) |
customer | object | Dados do perfil do cliente |
counterPart | object | Informações da contraparte (beneficiário) |
device | object | Device fingerprint e sinais do dispositivo |
location | object | Geolocalização e inteligência de IP |
instantPayment | object | Dados específicos de PIX, incluindo DICT (veja abaixo) |
riskSignals | object | Scores e sinais de risco preexistentes |
compliance | object | Flags de compliance |
Os blocos adicionais (location, riskSignals, compliance) seguem o mesmo princípio: envie o que estiver disponível, omita o que não estiver. A estrutura de campos desses blocos é definida em conjunto durante a configuração da integração, de acordo com os dados que o integrador pode fornecer.
Flexibilidade do payload de entrada
Seção intitulada “Flexibilidade do payload de entrada”O payload da requisição é flexível por design. Além dos cinco campos obrigatórios (transactionId, accountId, transactionType, transactionDate, totalAmount), o integrador controla quais blocos opcionais incluir e quais campos preencher dentro de cada bloco.
Não é necessário cadastro prévio: não é preciso criar clientes, contas ou quaisquer outras entidades antes de enviar transações. A Guardline vai:
- Enriquecer automaticamente: se um cliente com o
accountIdinformado existir na base de dados da Guardline (de cadastros ou sincronizações anteriores), os dados do perfil dele são usados para aprimorar a análise. - Resolver pelo documento: se nenhum cliente corresponder ao
accountId, masaccountHolderIdcontiver um CPF ou CNPJ válido, a Guardline busca o cliente pelo documento. Se encontrado, o perfil dele é usado na análise. Se não encontrado, a Guardline cadastra o cliente automaticamente, para que as transações futuras acumulem histórico e baselines comportamentais. - Prosseguir sem dados do cliente: se nenhum cliente for encontrado por nenhum dos métodos, a análise é executada com os dados fornecidos na requisição. As regras que dependem de atributos do cliente simplesmente não são acionadas.
- Usar os dados da requisição: se você incluir o bloco
customerna requisição, esses dados têm precedência e são usados diretamente.
A estrutura de cada bloco opcional (customer, counterPart, device, location, instantPayment, riskSignals, compliance) é definida pela Guardline, mas o integrador decide quais blocos são relevantes para o seu caso de uso e quais campos consegue fornecer. As regras de fraude são configuradas para trabalhar com os dados disponíveis. Os campos que não são enviados simplesmente não são avaliados.
O exemplo abaixo é uma referência que mostra um cenário realista de PIX Out. O payload real deve ser adaptado aos dados disponíveis nos sistemas do integrador.
Exemplo de requisição (PIX Out)
Seção intitulada “Exemplo de requisição (PIX Out)”{ "transactionId": "TX-20260308-00001234", "accountId": "ACC-00086", "accountHolderId": "12345678900", "transactionType": "PIX", "transactionDate": "2026-03-08T14:30:00-03:00", "totalAmount": "15000.00", "currency": "BRL", "channel": "MOBILE", "country": "BR", "metadata": { "direction": "OUT", "status": "pending", "originSystem": "IPAY" }, "customer": { "age": 42, "kycStatus": "approved", "kycLevel": "complete", "riskScore": 15.0, "riskLevel": "low", "isPEP": false, "country": "BR", "accountAgeDays": 730, "accountStatus": "active", "isNewCustomer": false }, "counterPart": { "name": "Maria Santos", "taxIdentifier": { "taxId": "987.654.321-00", "country": "BR" }, "isNewCounterpart": true, "transactionsCount": 0, "isSameNetwork": false }, "device": { "id": "DEV-9f8e7d6c", "type": "mobile", "os": "android", "isNewDevice": false, "isTrustedDevice": true, "ipAddress": "189.44.120.33" }, "instantPayment": { "keyType": "cpf", "keyValue": "987.654.321-00", "endToEndId": "E60701190202603081430abcd1234ef", "initiationMethod": "DICT", "payer": { "ispb": "60701190", "ispbName": "Itaú Unibanco S.A.", "document": "123.456.789-00", "branch": "0001", "account": "12345-6", "name": "João Oliveira" }, "receiver": { "ispb": "00000000", "ispbName": "Banco do Brasil S.A.", "document": "987.654.321-00", "branch": "3456", "account": "78901-2", "name": "Maria Santos" }, "dict": { "keyCreationDate": "2024-06-15T00:00:00Z", "keyOwnershipDate": "2024-06-15T00:00:00Z", "accountType": "CACC", "accountOpeningDate": "2023-01-10T00:00:00Z", "pspName": "Banco do Brasil S.A.", "pspIspb": "00000000", "fraudMarkersCount": 0, "infractionCount": 0, "isFlagged": false, "claimsCount": 0, "portabilityCount": 0, "correlationId": "A20260308143052899607011905AD7C8", "registeredAccounts": "1", "naturalPersonAntifraudPercentage": 0, "legalPersonAntifraudPercentage": 0, "spi": { "d90": "0", "m12": "0", "m60": "0" }, "reports": { "openReports": "0", "distinctReports": "0", "rejectedD90": "0", "rejectedM12": "0", "rejectedM60": "0" }, "frauds": [] } }}Idempotência
Seção intitulada “Idempotência”Se o mesmo transactionId for enviado mais de uma vez, a Guardline retorna a decisão original sem reprocessar. A resposta inclui "idempotent_replay": true para indicar isso.
Isso permite retries seguros em caso de timeout de rede, sem risco de processamento duplicado.
Entendendo a resposta
Seção intitulada “Entendendo a resposta”Os três cenários (ALLOW, REVIEW, BLOCK) retornam a mesma estrutura de resposta. Este é o formato de payload unificado usado em toda a plataforma, tanto nas respostas síncronas quanto nos webhooks.
Envelope de resposta
Seção intitulada “Envelope de resposta”As respostas da API são encapsuladas em um envelope padrão:
{ "error": false, "data": { ... }}O campo data contém o payload de decisão descrito a seguir. As respostas de erro usam "error": true (consulte Tratamento de erros).
Estrutura do payload de decisão
Seção intitulada “Estrutura do payload de decisão”| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
id | UUID | sim | Identificador único da decisão |
transaction_id | UUID | sim | Identificador interno da transação |
workflow_id | UUID | sim | Workflow que processou a transação |
workflow_name | string | sim | Nome do workflow |
workflow_version | integer | sim | Versão do workflow |
assessment | string | sim | Resultado da decisão: ALLOW, REVIEW, BLOCK ou ESCALATE. As respostas síncronas trazem apenas ALLOW, REVIEW ou BLOCK (o motor não produz ESCALATE). ESCALATE aparece exclusivamente no evento de webhook em que o analista escala um caso em REVIEW (consulte Quando os webhooks são enviados). |
score | number | sim | Score de risco final (0-100) |
thresholds | object | sim | Thresholds aplicados (revisão e bloqueio) |
resolution_source | string | sim | Quem tomou a decisão (veja abaixo) |
reason_code | string | não | Código de motivo estruturado da decisão (veja abaixo) |
reason_description | string | não | Descrição legível do motivo |
actions | array | não | Ações a executar (veja abaixo) |
review_info | object | não | Presente apenas quando assessment é REVIEW |
execution_time_ms | integer | sim | Tempo de processamento do motor em milissegundos |
analysis_time_ms | integer | sim | Tempo total de análise, incluindo o enriquecimento |
created_at | datetime | sim | Timestamp ISO 8601 |
idempotent_replay | boolean | não | true se esta for uma resposta repetida (replay) |
sources_loaded | object | não | Fontes de dados carregadas com sucesso |
source_errors | object | não | Fontes de dados que falharam ao carregar |
explanation | object | sim | Breakdown do score por estágio |
Origem da resolução
Seção intitulada “Origem da resolução”| Valor | Significado |
|---|---|
ENGINE | Decisão automática do motor de fraude (resposta síncrona e, opcionalmente, um webhook quando o workflow vincula send_webhook ao tipo de decisão resolvido) |
ANALYST | Decisão manual de um analista na Mesa de Decisão (webhook) |
SLA_TIMEOUT | Fallback automático por expiração do SLA (webhook) |
Código de motivo
Seção intitulada “Código de motivo”Os campos reason_code e reason_description fornecem contexto sobre por que a decisão foi tomada. Isso é crítico para o reporte regulatório (R6, MED) e para determinar como executar as ações sinalizadas.
Nas respostas síncronas (resolution_source: "ENGINE"), o código de motivo reflete a avaliação automatizada do motor. Essa mesma avaliação do motor também pode ser entregue como webhook quando o workflow vincula send_webhook ao tipo de decisão resolvido; nesse caso, o corpo do webhook carrega o mesmo código de motivo da resposta síncrona. Nas resoluções via webhook (resolution_source: "ANALYST" ou "SLA_TIMEOUT"), ele reflete o julgamento do analista ou a política de timeout.
| Origem | Exemplo de reason_code | Exemplo de reason_description |
|---|---|---|
ENGINE | HIGH_RISK_SCORE | Transaction blocked due to high risk score |
ENGINE | LOW_RISK | Transaction approved with low risk |
ANALYST | CONFIRMED_FRAUD | Analyst confirmed fraudulent activity |
ANALYST | CUSTOMER_CONFIRMED | Customer confirmed the transaction is legitimate |
ANALYST | SUSPICIOUS_UNCONFIRMED | Suspicious activity, insufficient evidence to confirm fraud |
ANALYST | FALSE_POSITIVE | Analysis determined the alert was a false positive |
SLA_TIMEOUT | SLA_TIMEOUT_AUTO_APPROVED | Automatically approved due to SLA expiration |
O conjunto de códigos de motivo não é fixo. Novos códigos podem ser introduzidos conforme as necessidades operacionais evoluem. O integrador deve tratar reason_code como uma string livre e lidar com valores desconhecidos sem falhar. O campo reason_description sempre fornece uma explicação legível, independentemente do código.
Os dois campos são null quando não se aplicam (por exemplo, na resposta síncrona inicial de REVIEW, em que o motivo final ainda não é conhecido).
As ações representam efeitos colaterais que o integrador deve executar. Cada ação tem um type e parameters opcionais.
| Tipo de ação | Descrição | Parâmetros |
|---|---|---|
CAUTIONARY_HOLD | Congelar os fundos creditados por até 72 horas (Resolução 142/2021 do BCB). O titular da conta deve ser notificado. | duration_hours (integer) |
ACCOUNT_BLOCK | Suspensão preventiva da conta. | nenhum |
BLOCK_BENEFICIARY | Bloquear a contraparte (beneficiário) para transações futuras. | nenhum |
BLOCK_DEVICE | Bloquear o dispositivo usado na transação. | nenhum |
ADD_TO_WATCHLIST | Adicionar o cliente a uma watchlist de monitoramento, para escrutínio reforçado em transações futuras. | nenhum |
CAUTIONARY_HOLD_CLEAR | Liberar um bloqueio cautelar aplicado anteriormente; levantar o congelamento temporário dos fundos creditados. Emitida no evento de webhook em que o analista libera o bloqueio cautelar e nas resoluções de caso em que o analista ativa a flag de liberação. | nenhum |
ACCOUNT_BLOCK_CLEAR | Liberar um bloqueio preventivo de conta aplicado anteriormente; restaurar a conta para o status ativo. Emitida no evento de webhook em que o analista libera o bloqueio de conta e nas resoluções de caso em que o analista ativa a flag de liberação. | nenhum |
Informações de revisão
Seção intitulada “Informações de revisão”Presente apenas quando assessment é REVIEW. Fornece informações para notificar o cliente final.
| Campo | Tipo | Descrição |
|---|---|---|
estimated_resolution_minutes | integer | Tempo estimado para a resolução (28 ou 58 minutos) |
review_reason | string | Motivo genérico adequado para a notificação ao usuário |
tracking_id | UUID | Identificador para o usuário acompanhar o caso |
Exemplo de resposta: ALLOW
Seção intitulada “Exemplo de resposta: ALLOW”{ "error": false, "data": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "transaction_id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321", "workflow_id": "11223344-5566-7788-99aa-bbccddeeff00", "workflow_name": "pix_out_standard", "workflow_version": 3, "assessment": "ALLOW", "score": 12.5, "thresholds": { "review_threshold": 45.0, "block_threshold": 80.0, "adjustments": [] }, "stages_executed": 4, "stages_total": 4, "early_terminated": false, "execution_time_ms": 23, "analysis_time_ms": 45, "explanation": { "stages": [ { "name": "identity_verification", "score": 0 }, { "name": "transaction_patterns", "score": 5.0 }, { "name": "counterpart_analysis", "score": 7.5 }, { "name": "device_signals", "score": 0 } ] }, "created_at": "2026-03-08T17:30:00.123Z", "resolution_source": "ENGINE", "reason_code": "LOW_RISK", "reason_description": "Transaction approved with low risk", "actions": [], "sources_loaded": { "customer": true, "counterpart": true, "device": true, "dict": true, "datarudder": true }, "enrich_time_ms": 18, "eval_time_ms": 23 }}Exemplo de resposta: REVIEW
Seção intitulada “Exemplo de resposta: REVIEW”Quando a decisão é REVIEW, a transação fica retida para análise manual. O integrador não deve processar a transação e deve informar ao cliente final que ela está em análise.
{ "error": false, "data": { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210", "workflow_id": "11223344-5566-7788-99aa-bbccddeeff00", "workflow_name": "pix_out_standard", "workflow_version": 3, "assessment": "REVIEW", "score": 62.0, "thresholds": { "review_threshold": 45.0, "block_threshold": 80.0, "adjustments": [] }, "stages_executed": 4, "stages_total": 4, "early_terminated": false, "execution_time_ms": 31, "analysis_time_ms": 52, "explanation": { "stages": [ { "name": "identity_verification", "score": 0 }, { "name": "transaction_patterns", "score": 25.0 }, { "name": "counterpart_analysis", "score": 30.0 }, { "name": "device_signals", "score": 7.0 } ] }, "created_at": "2026-03-08T17:30:00.456Z", "resolution_source": "ENGINE", "reason_code": null, "reason_description": null, "actions": [], "review_info": { "estimated_resolution_minutes": 28, "review_reason": "Transaction held for security analysis", "tracking_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901" }, "sources_loaded": { "customer": true, "counterpart": true, "device": true, "dict": true, "datarudder": false }, "source_errors": { "datarudder": "timeout after 1000ms" }, "enrich_time_ms": 1012, "eval_time_ms": 31 }}Exemplo de resposta: BLOCK
Seção intitulada “Exemplo de resposta: BLOCK”{ "error": false, "data": { "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "transaction_id": "d7c6b5a4-9382-1010-dcba-098765432109", "workflow_id": "11223344-5566-7788-99aa-bbccddeeff00", "workflow_name": "pix_out_standard", "workflow_version": 3, "assessment": "BLOCK", "score": 91.0, "thresholds": { "review_threshold": 45.0, "block_threshold": 80.0, "adjustments": [] }, "stages_executed": 2, "stages_total": 4, "early_terminated": true, "blocked_at": "counterpart_analysis", "execution_time_ms": 15, "analysis_time_ms": 38, "explanation": { "stages": [ { "name": "identity_verification", "score": 10.0 }, { "name": "counterpart_analysis", "score": 81.0 } ], "blocked_at": "counterpart_analysis" }, "created_at": "2026-03-08T17:30:00.789Z", "resolution_source": "ENGINE", "reason_code": "HIGH_RISK_SCORE", "reason_description": "Transaction blocked due to high risk score", "actions": [ { "type": "ACCOUNT_BLOCK", "parameters": {} } ], "sources_loaded": { "customer": true, "counterpart": true, "dict": true, "datarudder": true }, "enrich_time_ms": 22, "eval_time_ms": 15 }}Webhooks
Seção intitulada “Webhooks”Os webhooks são o canal assíncrono pelo qual a Guardline notifica o integrador sobre eventos do ciclo de vida das decisões. Todo webhook é entregue pela configuração de resultado do workflow: um resultado com uma ação send_webhook entrega pelo transporte configurado naquele workflow. Todas as classes de evento trafegam por esse pipeline único:
- Eventos do ciclo de vida da decisão: decisões do motor, resoluções de casos pelo analista (aprovar, bloquear, escalar) e resoluções automáticas por expiração do SLA.
- Ações manuais do analista: um bloqueio cautelar ou um bloqueio preventivo de conta que o analista aplica ou libera na estação de trabalho de operações, fora de qualquer caso aberto. Essas ações trafegam pelo mesmo pipeline e pelo mesmo transporte da instância; não existe um endpoint manual separado.
Todo corpo carrega três campos discriminadores (event_id, event_kind, subject) que classificam o evento. Consulte os campos do contrato unificado a seguir.
Quando os webhooks são enviados
Seção intitulada “Quando os webhooks são enviados”Webhooks orientados a resultado
Seção intitulada “Webhooks orientados a resultado”A emissão de webhooks é controlada pela configuração de resultado do workflow: uma ação send_webhook é vinculada a um ou mais tipos de decisão (allow, review, block, escalate), e o webhook só é disparado quando a decisão resolvida corresponde a um tipo de decisão vinculado. Os vínculos são configurados durante a configuração da integração, de acordo com os eventos que você deseja receber.
Isso significa que não existe uma regra fixa como “webhooks apenas em REVIEW”. Uma decisão ALLOW pode disparar um webhook se o workflow vincular send_webhook a allow; uma decisão BLOCK pode disparar um webhook se estiver vinculada a block; e assim por diante. Por outro lado, uma decisão REVIEW não dispara webhook a menos que o workflow tenha o vínculo. Suas escolhas de configuração determinam o conjunto real de entregas.
Os eventos emitidos por esse pipeline são:
| Evento | resolution_source | assessment típico |
|---|---|---|
| Motor decide ALLOW | ENGINE | ALLOW |
| Motor decide REVIEW | ENGINE | REVIEW |
| Motor decide BLOCK | ENGINE | BLOCK |
| Analista aprova um caso em REVIEW | ANALYST | ALLOW |
| Analista bloqueia um caso em REVIEW | ANALYST | BLOCK |
| Analista escala um caso em REVIEW | ANALYST | ESCALATE |
| SLA expira e resolve automaticamente | SLA_TIMEOUT | ALLOW ou BLOCK |
Ações manuais do analista
Seção intitulada “Ações manuais do analista”O analista pode agir fora de um caso em REVIEW aberto: aplicar ou liberar um bloqueio cautelar em uma transação, ou aplicar ou liberar um bloqueio preventivo em uma conta. Cada ação emite um webhook para que o integrador aplique ou libere o estado correspondente do seu lado. As quatro carregam event_kind: "manual_action" e são entregues pelo mesmo pipeline e pelo mesmo transporte da instância que os eventos do ciclo de vida da decisão; não existe um endpoint manual separado.
| Evento | Gatilho | subject.type | assessment |
|---|---|---|---|
analyst_cautionary_hold_apply | Analista aplica um bloqueio cautelar em uma transação | transaction | BLOCK (ação aplicada em actions) |
analyst_cautionary_hold_clear | Analista libera um bloqueio cautelar ativo | transaction | ALLOW (ação de liberação em actions) |
analyst_account_block_apply | Analista aplica um bloqueio preventivo em uma conta | account | BLOCK (ação aplicada em actions) |
analyst_account_block_clear | Analista libera um bloqueio de conta ativo | account | ALLOW (ação de liberação em actions) |
Esses eventos usam os mesmos cabeçalhos, modos de autenticação, política de retentativas e semântica de idempotência descritos a seguir. Os bloqueios cautelares se ancoram na decisão de fraude da transação, portanto o corpo deles carrega o contexto completo da decisão (transaction_id, workflow_*, score e assim por diante) junto de resolution_source: "ANALYST" e da ação aplicada ou liberada. Os bloqueios preventivos de conta não têm decisão: o analista age diretamente sobre a conta, sem transação de origem nem decisão de fraude, portanto o corpo deles omite o contexto da decisão e carrega apenas o sujeito conta. Para esses eventos de conta, decision_id e transaction_id são nulos nas superfícies de polling e de monitoramento; nenhum UUID zerado é emitido. Consulte os eventos com escopo de conta (sem decisão) a seguir.
Formato do payload
Seção intitulada “Formato do payload”Nos eventos com escopo de transação, o corpo do webhook usa a mesma estrutura plana da resposta síncrona da API (o payload da decisão), mas sem o envelope {"error": false, "data": ...}, e carrega adicionalmente três campos do contrato unificado (event_id, event_kind, subject). Todos os campos planos do payload síncrono da decisão são preservados, de modo que um parser existente continua funcionando e um consumidor conforme ignora os campos adicionais que não conhece.
Isso significa que o integrador pode manter um único parser para os campos planos da decisão (reutilizando-o tanto na resposta síncrona, extraindo de .data, quanto no corpo do webhook) e ramificar por event_kind mais subject para classificar o evento.
Campos do contrato unificado
Seção intitulada “Campos do contrato unificado”Todo corpo de webhook carrega três campos de primeiro nível que classificam o evento:
| Campo | Tipo | Descrição |
|---|---|---|
event_id | UUID | Único por evento de webhook. Não é o id da decisão (resolver e escalar reutilizam o id da decisão ao longo de um ciclo de vida; o event_id é distinto a cada emissão). Estável entre as retentativas da mesma entrega. |
event_kind | string | O discriminador do evento. Um entre engine_decision, case_resolution, case_escalation, sla_timeout_resolution, manual_action. Classifique por este campo, nunca pela presença de actions[]. |
subject | objeto | O sujeito tipado. subject.type é transaction ou account. subject.transaction_id está presente nos eventos com escopo de transação; subject.account_id está presente nos eventos com escopo de conta. |
Eventos com escopo de conta (sem decisão)
Seção intitulada “Eventos com escopo de conta (sem decisão)”A aplicação e a liberação de bloqueio preventivo de conta não têm decisão: o analista age diretamente sobre uma conta, sem transação de origem nem decisão de fraude. O corpo delas é deliberadamente mínimo e honesto:
subjecté{ "type": "account", "account_id": "<id>" }.event_kindémanual_action;assessmentéBLOCKna aplicação eALLOWna liberação;actions[]carregaACCOUNT_BLOCKouACCOUNT_BLOCK_CLEAR;resolution_sourceéANALYST;created_até o momento em que a ação do analista foi efetivada.- Os campos de contexto da decisão são omitidos (sem
id, semtransaction_id, semworkflow_*,score,thresholds,stages_*,explanation, tempos,trace_idourequest_id). Nenhum id de decisão sintético nem id de transação zerado é emitido. Nas superfícies de leitura de polling e de monitoramento, odecision_ide otransaction_iddo ledger sãonullnesses eventos.
Os eventos com escopo de transação (decisões do motor, resolução e escalonamento de caso, bloqueios cautelares) mantêm todos os seus campos planos; apenas os três campos do contrato unificado são acrescentados.
Exemplo de webhook: analista aprova com bloqueio cautelar
Seção intitulada “Exemplo de webhook: analista aprova com bloqueio cautelar”{ "event_id": "9a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9", "event_kind": "case_resolution", "subject": { "type": "transaction", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210" }, "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210", "workflow_id": "11223344-5566-7788-99aa-bbccddeeff00", "workflow_name": "pix_out_standard", "workflow_version": 3, "assessment": "ALLOW", "score": 62.0, "thresholds": { "review_threshold": 45.0, "block_threshold": 80.0, "adjustments": [] }, "stages_executed": 4, "stages_total": 4, "early_terminated": false, "execution_time_ms": 31, "analysis_time_ms": 52, "explanation": { "stages": [ { "name": "identity_verification", "score": 0 }, { "name": "transaction_patterns", "score": 25.0 }, { "name": "counterpart_analysis", "score": 30.0 }, { "name": "device_signals", "score": 7.0 } ] }, "created_at": "2026-03-08T17:30:00.456Z", "resolution_source": "ANALYST", "reason_code": "CUSTOMER_CONFIRMED", "reason_description": "Customer confirmed the transaction is legitimate", "actions": [ { "type": "CAUTIONARY_HOLD", "parameters": { "duration_hours": 72 } } ]}Exemplo de webhook: aprovação automática por expiração do SLA
Seção intitulada “Exemplo de webhook: aprovação automática por expiração do SLA”{ "event_id": "1d2e3f40-5161-7283-94a5-b6c7d8e9f001", "event_kind": "sla_timeout_resolution", "subject": { "type": "transaction", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210" }, "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210", "workflow_id": "11223344-5566-7788-99aa-bbccddeeff00", "workflow_name": "pix_out_standard", "workflow_version": 3, "assessment": "ALLOW", "score": 62.0, "thresholds": { "review_threshold": 45.0, "block_threshold": 80.0, "adjustments": [] }, "stages_executed": 4, "stages_total": 4, "early_terminated": false, "execution_time_ms": 31, "analysis_time_ms": 52, "explanation": { "stages": [ { "name": "identity_verification", "score": 0 }, { "name": "transaction_patterns", "score": 25.0 }, { "name": "counterpart_analysis", "score": 30.0 }, { "name": "device_signals", "score": 7.0 } ] }, "created_at": "2026-03-08T17:30:00.456Z", "resolution_source": "SLA_TIMEOUT", "reason_code": "SLA_TIMEOUT_AUTO_APPROVED", "reason_description": "Automatically approved due to SLA expiration", "actions": [ { "type": "CAUTIONARY_HOLD", "parameters": { "duration_hours": 72 } } ]}Exemplo de webhook: analista bloqueia com suspensão da conta
Seção intitulada “Exemplo de webhook: analista bloqueia com suspensão da conta”{ "event_id": "2e3f4051-6273-8495-a6b7-c8d9e0f10203", "event_kind": "case_resolution", "subject": { "type": "transaction", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210" }, "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210", "workflow_id": "11223344-5566-7788-99aa-bbccddeeff00", "workflow_name": "pix_out_standard", "workflow_version": 3, "assessment": "BLOCK", "score": 62.0, "thresholds": { "review_threshold": 45.0, "block_threshold": 80.0, "adjustments": [] }, "stages_executed": 4, "stages_total": 4, "early_terminated": false, "execution_time_ms": 31, "analysis_time_ms": 52, "explanation": { "stages": [ { "name": "identity_verification", "score": 0 }, { "name": "transaction_patterns", "score": 25.0 }, { "name": "counterpart_analysis", "score": 30.0 }, { "name": "device_signals", "score": 7.0 } ] }, "created_at": "2026-03-08T17:30:00.456Z", "resolution_source": "ANALYST", "reason_code": "CONFIRMED_FRAUD", "reason_description": "Analyst confirmed fraudulent activity", "actions": [ { "type": "CAUTIONARY_HOLD", "parameters": { "duration_hours": 72 } }, { "type": "ACCOUNT_BLOCK", "parameters": {} } ]}Exemplo de webhook: analista aplica um bloqueio preventivo de conta (sem decisão)
Seção intitulada “Exemplo de webhook: analista aplica um bloqueio preventivo de conta (sem decisão)”Um evento de conta sem decisão carrega o sujeito conta e omite o contexto da decisão. O created_at é o momento em que o analista aplicou o bloqueio. O evento de liberação tem o mesmo formato, com assessment: "ALLOW" e actions[0].type: "ACCOUNT_BLOCK_CLEAR".
{ "event_id": "7c1f0a2b-3d4e-5f60-7182-93a4b5c6d7e8", "event_kind": "manual_action", "subject": { "type": "account", "account_id": "ACC-00086" }, "assessment": "BLOCK", "resolution_source": "ANALYST", "reason_code": "SUSPECTED_FRAUD", "reason_description": null, "created_at": "2026-03-08T17:32:10.004Z", "actions": [ { "type": "ACCOUNT_BLOCK", "parameters": {} } ]}Cabeçalhos
Seção intitulada “Cabeçalhos”Toda requisição de webhook inclui os seguintes cabeçalhos HTTP:
| Cabeçalho | Descrição |
|---|---|
Content-Type | Sempre application/json |
X-Guardline-Delivery-ID | UUID estável desta entrega, idêntico em todas as retentativas. Use para deduplicação |
X-Guardline-Attempt-Number | Número sequencial da tentativa (1 para a primeira entrega, 2 para a primeira retentativa, etc.) |
X-Guardline-Timestamp | Timestamp Unix do momento da assinatura (quando o HMAC está habilitado) |
X-Guardline-Signature | Assinatura HMAC-SHA256 em hexadecimal (quando o HMAC está habilitado) |
Authorization | Token Bearer (quando o OAuth está habilitado) |
Autenticação de webhooks
Seção intitulada “Autenticação de webhooks”A Guardline oferece quatro modos de autenticação de webhooks. O modo é configurado por endpoint de webhook durante a configuração da integração. A assinatura HMAC fornece verificação de integridade da mensagem e pode ser combinada com qualquer modo. No modo somente HMAC, ela é a única autenticação e é obrigatória. Nos modos OAuth, mTLS e OAuth + mTLS, ela é opcional, mas recomendada como defesa em profundidade; quando nenhum segredo HMAC está configurado nesses modos, os cabeçalhos X-Guardline-Signature e X-Guardline-Timestamp não são enviados.
| Modo | Assinatura HMAC | OAuth Bearer | Certificado de cliente |
|---|---|---|---|
| Somente HMAC (padrão) | Obrigatória | Não | Não |
| OAuth 2.0 | Opcional, recomendada | Sim | Não |
| mTLS | Opcional, recomendada | Não | Sim |
| OAuth 2.0 + mTLS | Opcional, recomendada | Sim | Sim |
Autenticação HMAC-SHA256
Seção intitulada “Autenticação HMAC-SHA256”A autenticação HMAC usa um segredo compartilhado provisionado durante a configuração do integrador.
Processo de verificação no receptor:
- Extraia o cabeçalho
X-Guardline-Timestamp - Rejeite se o timestamp for mais antigo que 5 minutos em relação ao relógio do servidor
- Concatene o timestamp e o corpo da requisição:
{timestamp}.{body} - Calcule o
HMAC-SHA256da concatenação usando o segredo compartilhado - Codifique o resultado em hexadecimal
- Compare com o cabeçalho
X-Guardline-Signatureusando comparação em tempo constante - Rejeite se houver divergência
Pseudocódigo:
import hmac, hashlib, time
def verify_webhook(body: bytes, timestamp: str, signature: str, secret: str) -> bool: if abs(time.time() - int(timestamp)) > 300: return False
message = f"{timestamp}.".encode() + body expected = hmac.new( secret.encode(), message, hashlib.sha256 ).hexdigest()
return hmac.compare_digest(expected, signature)Autenticação mTLS
Seção intitulada “Autenticação mTLS”A autenticação TLS mútua garante a identidade da Guardline na camada de transporte, sem exigir validação no nível da aplicação.
Configuração:
- Durante o provisionamento, a Guardline fornece o certificado da CA raiz (
guardline-ca.pem) - O integrador configura o seu servidor de webhook para exigir certificados de cliente
- O integrador adiciona
guardline-ca.pemà lista de CAs confiáveis do servidor - Em cada entrega, a Guardline apresenta um certificado de cliente assinado pela CA raiz
- O servidor do integrador valida a cadeia de certificados automaticamente na camada TLS
O campo CN (Common Name) do certificado de cliente contém o identificador da instância do integrador. Opcionalmente, o integrador pode validar esse campo para garantir que a requisição vem da instância correta.
Quando o mTLS é o único modo de autenticação e nenhum segredo HMAC está configurado, os cabeçalhos X-Guardline-Signature e X-Guardline-Timestamp não são enviados. A mesma omissão vale para os modos OAuth e OAuth + mTLS quando nenhum segredo HMAC está configurado. Consulte a matriz de autenticação de webhooks acima para o detalhamento completo por modo.
Autenticação OAuth 2.0
Seção intitulada “Autenticação OAuth 2.0”A autenticação OAuth permite que a Guardline obtenha um token de acesso antes de cada entrega, usando o fluxo Client Credentials (RFC 6749, seção 4.4).
Configuração:
- O integrador fornece, durante a configuração da integração:
token_endpoint,client_id,client_secrete, opcionalmente,scope - Antes de cada entrega, a Guardline solicita um token ao endpoint informado
- A requisição do token segue o formato padrão:
POST {token_endpoint}Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}&scope={scope}- A Guardline inclui o token obtido no cabeçalho de autorização do webhook:
Authorization: Bearer {access_token}- O integrador valida o token no seu endpoint de webhook conforme a sua implementação OAuth
A Guardline mantém o token em cache respeitando o campo expires_in da resposta do endpoint de token, com uma margem de segurança de 60 segundos. Se o receptor do webhook retornar 401, o token em cache é invalidado e um novo token é obtido para uma única retentativa.
Se a obtenção do token falhar por credenciais inválidas (401 ou 400 do endpoint de token), a primeira tentativa de disparo registra uma entrega com falha. O worker de retentativas reconhece o erro de autenticação não recuperável no ciclo seguinte e marca a entrega como exhausted sem novas tentativas, de modo que o integrador não fique sujeito a um backoff longo por uma falha de configuração de credenciais. Falhas transitórias do endpoint de token (500, timeout) seguem a política de retentativas normal.
Configuração do endpoint
Seção intitulada “Configuração do endpoint”O endpoint de webhook é configurado durante a configuração da integração. Requisitos:
| Requisito | Detalhe |
|---|---|
| Protocolo | HTTPS obrigatório |
| Versão do TLS | 1.2 ou superior |
| Resposta de sucesso | Qualquer código 2xx (corpo ignorado) |
| Timeout | Responder em até 10 segundos |
| Idempotência | Deduplicar entregas usando X-Guardline-Delivery-ID |
Recomendação de implementação: receba o webhook, enfileire para processamento assíncrono e responda imediatamente com 200. Isso evita timeouts e garante uma entrega confiável.
Rotação de credenciais
Seção intitulada “Rotação de credenciais”Quando as credenciais OAuth ou os certificados mTLS são rotacionados, as retentativas em andamento de entregas já disparadas continuam usando as credenciais que estavam ativas no momento do disparo. As novas entregas usam as credenciais atualizadas imediatamente.
Se as entregas com falha precisarem ser reenviadas com as novas credenciais, um redespacho pode ser acionado pelo lado da operação da Guardline. O endpoint correspondente (POST /api/v2/webhooks/deliveries/{id}/redispatch) é exclusivo de administradores: exige autenticação JWT com o papel SUPERVISOR ou ADMIN e não pode ser chamado com uma API key de integrador. Para acionar um redespacho após a rotação de credenciais, entre em contato com o seu representante de suporte da Guardline; ele executará o redespacho em seu nome. O redespacho cria uma nova entrega usando as credenciais configuradas mais recentes, preservando o payload e o contexto da decisão originais, e a entrega original é mantida intacta para fins de auditoria.
Política de retentativas
Seção intitulada “Política de retentativas”Se a Guardline não receber uma resposta HTTP 2xx, o webhook é reenviado com backoff exponencial:
| Tentativa | Atraso após a falha |
|---|---|
| 1 | 5 segundos |
| 2 | 30 segundos |
| 3 | 2 minutos |
| 4 | 10 minutos |
| 5 | 30 minutos |
| 6 | 1 hora |
| 7 | 2 horas |
| 8 | 4 horas |
| 9 | 8 horas |
| 10 | 12 horas |
Após 10 tentativas com falha, a entrega é marcada como exhausted e um alerta interno é gerado. A notificação ainda pode ser recuperada pelo endpoint de polling.
Timeout: Cada tentativa de entrega tem um timeout de 10 segundos. Garanta que o seu handler de webhook responda dentro dessa janela.
Resposta esperada: Retorne HTTP 200 OK com qualquer corpo. Apenas o código de status importa.
Idempotência
Seção intitulada “Idempotência”Os webhooks podem ser entregues mais de uma vez (por causa de retentativas após problemas de rede). Use o cabeçalho X-Guardline-Delivery-ID para deduplicar:
- Armazene cada
X-Guardline-Delivery-IDprocessado. - Ao receber um webhook, verifique se o ID de entrega já foi processado.
- Em caso positivo, responda
200 OKsem reprocessar.
Gerenciamento de decisões
Seção intitulada “Gerenciamento de decisões”Consulta de uma decisão
Seção intitulada “Consulta de uma decisão”Recupere o estado atual de uma decisão pelo seu ID.
GET /api/v2/decisions/{id}Cabeçalhos:
X-API-Key: gl_live_your_api_key_hereResposta: Mesmo envelope e mesma estrutura de payload da decisão do endpoint de análise.
Cancelamento de uma decisão em REVIEW
Seção intitulada “Cancelamento de uma decisão em REVIEW”Quando uma transação em REVIEW deixa de ser relevante (desistência do usuário, expiração da sessão, duplicidade, etc.), o integrador deve cancelá-la para que os analistas parem de trabalhar nela. Nenhum webhook é enviado após o cancelamento.
POST /api/v2/decisions/{id}/cancelCabeçalhos:
Content-Type: application/jsonX-API-Key: gl_live_your_api_key_hereRequisição:
{ "reason": "Client cancelled the transaction"}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
reason | string | sim | Motivo do cancelamento (3 a 500 caracteres) |
Resposta (200 OK):
{ "error": false, "data": { "decision_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "case_id": "d4e5f6a7-b890-1234-efab-567890123456", "previous_status": "PENDING", "new_status": "CANCELLED", "cancelled_at": "2026-03-08T17:45:00.123Z" }}Comportamento:
- Retorna
200se o caso for cancelado com sucesso. - Retorna
200se o caso já estiver cancelado (idempotente). - Retorna
409se o caso já tiver sido resolvido por um analista ou por expiração do SLA. - Somente casos com status
PENDINGouIN_PROGRESSpodem ser cancelados.
Polling de notificações (fallback)
Seção intitulada “Polling de notificações (fallback)”Se os webhooks falharem repetidamente (por exemplo, durante uma indisponibilidade prolongada), o integrador pode consultar por polling as notificações não entregues e confirmar o processamento depois de tratá-las.
Este é um mecanismo de fallback. O webhook é o canal de entrega principal.
Listagem de notificações pendentes
Seção intitulada “Listagem de notificações pendentes”GET /api/v2/decisions/notificationsCabeçalhos:
X-API-Key: gl_live_your_api_key_hereParâmetros de query:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
since | string | nenhum | Timestamp ISO 8601. Retorna apenas as notificações criadas depois desse momento. |
status | string | nenhum | Filtra por status: pending, failed ou exhausted |
limit | integer | 50 | Máximo de resultados (1 a 200) |
Resposta (200 OK):
{ "error": false, "data": { "notifications": [ { "delivery_id": "aabbccdd-1122-3344-5566-778899001122", "decision_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210", "status": "exhausted", "payload": { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "transaction_id": "e8d7c6b5-a493-2101-edcb-a09876543210", "assessment": "ALLOW", "resolution_source": "ANALYST", "actions": [ { "type": "CAUTIONARY_HOLD", "parameters": { "duration_hours": 72 } } ], "score": 62.0, "created_at": "2026-03-08T17:30:00.456Z" }, "created_at": "2026-03-08T17:35:00.000Z", "attempt_number": 10 } ], "total": 1 }}O campo payload contém o mesmo corpo enviado no webhook, incluindo os campos event_id, event_kind e subject. Nos eventos de conta sem decisão (event_kind: "manual_action" com sujeito conta), o decision_id e o transaction_id de primeiro nível são null, e o payload omite o contexto da decisão, carregando apenas o sujeito conta.
Confirmação do processamento de uma notificação
Seção intitulada “Confirmação do processamento de uma notificação”Depois de processar uma notificação obtida por polling, confirme o processamento para que ela não seja mais retornada nas consultas seguintes.
POST /api/v2/decisions/notifications/{delivery_id}/ackCabeçalhos:
X-API-Key: gl_live_your_api_key_hereResposta (200 OK):
{ "error": false, "data": { "delivery_id": "aabbccdd-1122-3344-5566-778899001122", "acknowledged": true }}Comportamento:
- Retorna
200se a confirmação for registrada com sucesso. - Retorna
200se já tiver sido confirmada (idempotente).
Fluxos de integração
Seção intitulada “Fluxos de integração”PIX Out: decisão direta (ALLOW ou BLOCK)
Seção intitulada “PIX Out: decisão direta (ALLOW ou BLOCK)”Integrator Guardline | | | POST /decisions/analyze | |---------------------------->| | | Enrich context (DICT, Data Rudder) | | Execute fraud rules | | Calculate score + decision | 200 OK (ALLOW or BLOCK) | |<----------------------------| | | | Execute actions | | (if any in response) |Responsabilidades do integrador:
- Se
ALLOW: autorize o PIX. - Se
BLOCK: rejeite o PIX e execute quaisqueractions(por exemplo,ACCOUNT_BLOCK).
Orçamento de tempo: a resposta da Guardline normalmente é concluída em menos de 100ms. O SLA regulatório do PIX é de 40 segundos ponta a ponta, portanto o integrador tem margem de sobra.
PIX Out: fluxo de revisão
Seção intitulada “PIX Out: fluxo de revisão”Integrator Guardline Analyst | | | | POST /decisions/analyze | | |---------------------------->| | | | Score in review zone | | 200 OK (REVIEW) | | |<----------------------------| | | | Create case (async) | | Hold transaction | | | Notify end user | | | | | | | Case assigned | | |<---------------------------| | | Resolve case | | |<---------------------------| | | | | Webhook (resolution) | | |<----------------------------| | | | | | Execute decision | | | Execute actions | |Responsabilidades do integrador:
- Em
REVIEW: retenha a transação, notifique o cliente final usando os dados dereview_info. - No webhook: execute a decisão final (
ALLOWouBLOCK) e quaisqueractions. - Use
review_info.estimated_resolution_minutespara informar ao cliente final o tempo de espera previsto.
SLA: se nenhum analista resolver o caso dentro do prazo regulatório, a Guardline aplica automaticamente o fallback configurado (normalmente ALLOW com CAUTIONARY_HOLD) e envia o webhook com resolution_source: "SLA_TIMEOUT".
O PIX In usa o mesmo contrato de API e os mesmos nomes de campo do PIX Out, mas as partes que eles carregam são invertidas, e a semântica da resposta é diferente porque a Guardline é chamada depois que o crédito já foi liquidado.
Qual parte cada campo carrega
Seção intitulada “Qual parte cada campo carrega”A regra é a mesma para qualquer direção: accountId e accountHolderId sempre identificam o seu cliente, o titular da conta sobre cujo histórico e cujas baselines comportamentais a análise é construída, e counterPart sempre descreve a outra parte. O que muda com a direção é qual parte do mundo real ocupa cada papel.
| Campo | PIX Out (direction: "OUT") | PIX In (direction: "IN") |
|---|---|---|
accountId | A conta pagadora | A conta recebedora |
accountHolderId | O CPF ou CNPJ do pagador | O CPF ou CNPJ do recebedor |
counterPart | O beneficiário | O pagador |
instantPayment.payer | O seu cliente | A contraparte |
instantPayment.receiver | A contraparte | O seu cliente |
Semântica da resposta
Seção intitulada “Semântica da resposta”ALLOW: nenhuma ação necessária.BLOCK: não significa “rejeitar” (os recursos já foram creditados). Significa “aplicar remediação”. Execute asactionssinalizadas (normalmenteCAUTIONARY_HOLDsobre o valor creditado e/ouACCOUNT_BLOCK).REVIEW: o crédito já ocorreu. Isso sinaliza “em investigação”. A resolução e eventuais ações de remediação chegam via webhook.
Essa semântica pressupõe que a integração de entrada chama a Guardline depois que o crédito foi liquidado, que é o modo de operação para o qual o PIX In foi desenhado. A Guardline não verifica isso: a liquidação é carregada pelos campos opcionais metadata.settledAt e metadata.transactionStatus, e nenhum dos dois é obrigatório nem validado. Envie-os quando os tiver, para que o registro da decisão reflita o momento real da liquidação.
Definindo a direção
Seção intitulada “Definindo a direção”Defina metadata.direction como "IN" para o PIX In. Os valores canônicos são IN, OUT e SELF, a comparação não diferencia maiúsculas de minúsculas, e os apelidos INBOUND e OUTBOUND são aceitos e canonizados para IN e OUT.
Exemplo de requisição (PIX In)
Seção intitulada “Exemplo de requisição (PIX In)”O exemplo abaixo espelha o exemplo de PIX Out acima, com os papéis invertidos: ACC-00086 é a conta recebedora, 12345678900 é o documento do recebedor, e o bloco counterPart descreve o pagador que enviou o dinheiro.
{ "transactionId": "TX-20260308-00005678", "accountId": "ACC-00086", "accountHolderId": "12345678900", "transactionType": "PIX", "transactionDate": "2026-03-08T09:12:00-03:00", "totalAmount": "8400.00", "currency": "BRL", "channel": "API", "metadata": { "direction": "IN", "status": "settled", "settledAt": "2026-03-08T09:12:01-03:00", "transactionStatus": "Success", "originSystem": "IPAY" }, "customer": { "age": 42, "kycStatus": "approved", "kycLevel": "complete", "riskScore": 15.0, "riskLevel": "low", "isPEP": false, "isNewCustomer": false }, "counterPart": { "name": "Carlos Pereira", "taxIdentifier": { "taxId": "321.654.987-00", "country": "BR" }, "isNewCounterpart": true, "transactionsCount": 0, "isSameNetwork": false }, "instantPayment": { "keyValue": "12345678900", "endToEndId": "E60701190202603080912wxyz5678gh", "initiationMethod": "DICT", "payer": { "ispb": "60701190", "ispbName": "Itaú Unibanco S.A.", "document": "321.654.987-00", "branch": "0042", "account": "55555-1", "name": "Carlos Pereira" }, "receiver": { "ispb": "00000000", "ispbName": "Banco do Brasil S.A.", "document": "123.456.789-00", "branch": "3456", "account": "78901-2", "name": "João Oliveira" } }}Repare que instantPayment.payer carrega a contraparte e instantPayment.receiver carrega o seu cliente, o inverso do exemplo de PIX Out. A Guardline lê o nome do recebedor desse bloco para manter o cadastro do cliente atualizado nas transações de entrada, portanto preenchê-lo corretamente é o que mantém o nome do cliente atrelado à pessoa certa.
Tratamento de erros
Seção intitulada “Tratamento de erros”Formato da resposta de erro
Seção intitulada “Formato da resposta de erro”Todos os erros seguem esta estrutura:
{ "error": true, "message": "description of the error", "code": "ERROR_CODE", "details": "additional context (optional)", "request_id": "550e8400-e29b-41d4-a716-446655440000"}Códigos de status HTTP
Seção intitulada “Códigos de status HTTP”| Código | Significado |
|---|---|
| 200 | Sucesso |
| 400 | Requisição inválida (JSON malformado, falha de validação) |
| 401 | Falha de autenticação (API key inválida ou ausente) |
| 404 | Recurso não encontrado (ID de decisão inexistente) |
| 409 | Conflito (caso já resolvido, não é possível cancelar) |
| 429 | Limite de requisições excedido (requisições em excesso) |
| 500 | Erro interno do servidor |
Tratamento de erros recomendado
Seção intitulada “Tratamento de erros recomendado”- Em
400: corrija o payload da requisição. Não faça retry. - Em
401: verifique a API key. Não faça retry. - Em
404: verifique o ID da decisão. Não faça retry. - Em
409: o caso já foi resolvido. Trate como sucesso. - Em
429: aplique backoff e faça retry após o intervalo indicado. - Em
500: faça retry com backoff exponencial (até 3 tentativas). - Em timeout de rede: faça retry. A idempotência do
transactionIdgarante que não haja processamento duplicado.
Calendário de feriados
Seção intitulada “Calendário de feriados”Retorna a lista de feriados nacionais e bancários usada pela Guardline para janelas de SLA e lógica de dias úteis. Útil para integradores que precisam alinhar seu próprio agendamento ao mesmo calendário adotado pela Guardline.
Endpoint
Seção intitulada “Endpoint”GET /api/v2/holidays?year=<int>Autenticação
Seção intitulada “Autenticação”Requer uma API key com o escopo holidays.read. Entre em contato com a Guardline para habilitar esse escopo na sua chave.
Parâmetros de consulta
Seção intitulada “Parâmetros de consulta”| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
year | integer | Não | Ano a filtrar. O padrão é o ano atual. Intervalo válido: 2000 a 2100. |
Resposta
Seção intitulada “Resposta”{ "error": false, "data": { "items": [ { "date": "2026-12-25", "name": "Natal", "type": "NATIONAL", "created_at": "2025-01-01T00:00:00Z" } ], "total": 12 }}| Campo | Tipo | Descrição |
|---|---|---|
data.items[].date | string | Data ISO 8601 (YYYY-MM-DD) |
data.items[].name | string | Nome de exibição do feriado (em português) |
data.items[].type | string | NATIONAL (feriados federais) ou BANKING (fechamentos específicos de bancos observados pelo sistema bancário brasileiro) |
data.items[].created_at | string | Timestamp ISO 8601 do momento em que a entrada foi registrada |
data.total | integer | Quantidade de itens retornados |
Exemplo
Seção intitulada “Exemplo”GET /api/v2/holidays?year=2026 HTTP/1.1X-API-Key: gl_live_your_api_key_hereA lista de feriados muda com pouca frequência, normalmente uma vez por ano, quando novos calendários são confirmados. Recomenda-se que os integradores armazenem a resposta em cache do seu lado e a atualizem semanal ou mensalmente, em vez de a cada requisição.
Horário de funcionamento
Seção intitulada “Horário de funcionamento”Retorna as janelas configuráveis de horário de funcionamento que determinam o nível de SLA e as regras de horário comercial da Guardline. Duas janelas são expostas em uma única resposta:
pixcontrola o nível de SLA para retenções PIX (janela de 30 minutos em horário comercial, 60 minutos fora dele).enginecontrola o predicadois_business_hoursreferenciado pelas regras táticas do motor de decisão.
Ambas as janelas são definidas por dia da semana, com flags explícitas de aberto/fechado e strings de início/fim no formato HH:MM. Feriados fecham as duas janelas, independentemente da configuração por dia da semana.
Endpoint
Seção intitulada “Endpoint”GET /api/v2/calendar/working-hoursAutenticação
Seção intitulada “Autenticação”Requer um JWT ou uma API key com o escopo calendar.read. Entre em contato com a Guardline para habilitar esse escopo na sua chave. O mesmo escopo dará acesso a futuras leituras de calendário (por exemplo, um avaliador por timestamp), de modo que uma única concessão cobre todo o conjunto.
Resposta
Seção intitulada “Resposta”{ "error": false, "data": { "pix": { "version": 1, "timezone": "America/Sao_Paulo", "weekdays": { "sunday": {"open": false, "start": "00:00", "end": "00:00"}, "monday": {"open": true, "start": "08:00", "end": "20:00"}, "tuesday": {"open": true, "start": "08:00", "end": "20:00"}, "wednesday": {"open": true, "start": "08:00", "end": "20:00"}, "thursday": {"open": true, "start": "08:00", "end": "20:00"}, "friday": {"open": true, "start": "08:00", "end": "20:00"}, "saturday": {"open": false, "start": "00:00", "end": "00:00"} } }, "engine": { "version": 1, "timezone": "America/Sao_Paulo", "weekdays": { "sunday": {"open": false, "start": "00:00", "end": "00:00"}, "monday": {"open": true, "start": "08:00", "end": "18:00"}, "tuesday": {"open": true, "start": "08:00", "end": "18:00"}, "wednesday": {"open": true, "start": "08:00", "end": "18:00"}, "thursday": {"open": true, "start": "08:00", "end": "18:00"}, "friday": {"open": true, "start": "08:00", "end": "18:00"}, "saturday": {"open": false, "start": "00:00", "end": "00:00"} } } }}| Campo | Tipo | Descrição |
|---|---|---|
data.pix | object | Janela de horário de funcionamento do nível de SLA do PIX. |
data.engine | object | Janela de horário de funcionamento do predicado is_business_hours do motor. |
data.<window>.version | integer | Versão do payload. O formato atual é a versão 1. |
data.<window>.timezone | string | Nome do fuso horário IANA. Atualmente fixo em America/Sao_Paulo no nível do deploy para todos os integradores. |
data.<window>.weekdays.<day>.open | boolean | Indica se o dia da semana está aberto. Quando false, start e end são ignorados. |
data.<window>.weekdays.<day>.start | string | Início da janela em horário local, no formato de 24 horas HH:MM. |
data.<window>.weekdays.<day>.end | string | Fim da janela em horário local, no formato de 24 horas HH:MM. O fim é exclusivo: uma janela que termina às 20:00 não inclui 20:00:00. |
Exemplo
Seção intitulada “Exemplo”GET /api/v2/calendar/working-hours HTTP/1.1X-API-Key: gl_live_your_api_key_hereNotas sobre o comportamento
Seção intitulada “Notas sobre o comportamento”- O fuso horário está atualmente fixo em
America/Sao_Paulopara todos os integradores. Fusos horários por tenant estão no roadmap; esse campo já é exposto hoje para que futuros deploys por tenant não exijam mudança de contrato. - Feriados fecham as duas janelas. Use o Calendário de feriados para alinhar sua própria lista de feriados à da Guardline.
start/endsão limites de relógio em horário local, não offsets de UTC. Converta para sua interpretação local usando otimezoneretornado.- A janela
enginepode ser diferente depix(por exemplo,pix08:00-20:00 enquantoengine08:00-18:00). Leia os dois campos em vez de assumir uma única janela global.
Respostas de erro
Seção intitulada “Respostas de erro”| Status | Motivo |
|---|---|
| 401 | Credencial ausente ou inválida. |
| 403 | A API key não tem o escopo calendar.read. |
| 500 | Erro inesperado. |
Não há 400 porque o endpoint não recebe parâmetros.
A configuração de horário de funcionamento muda com pouca frequência. Recomenda-se que os integradores armazenem a resposta em cache do seu lado e a atualizem semanal ou mensalmente, em vez de a cada requisição.
Apêndice A: referência de SLA
Seção intitulada “Apêndice A: referência de SLA”Transação PIX padrão
Seção intitulada “Transação PIX padrão”O Banco Central do Brasil determina um SLA de 40 segundos ponta a ponta para transações PIX padrão. O tempo de resposta da Guardline (normalmente abaixo de 100ms) é uma pequena fração desse orçamento.
Transferência inteligente (retenção em REVIEW)
Seção intitulada “Transferência inteligente (retenção em REVIEW)”Quando uma transação é retida para análise de fraude (decisão REVIEW), o SLA regulatório depende do momento em que ela foi retida:
| Momento da retenção | Tempo máximo de retenção |
|---|---|
| Horário comercial (dias úteis, das 08:00 às 20:00 BRT) | 30 minutos |
| Fora do horário comercial (noites, fins de semana, feriados) | 60 minutos |
A Guardline aplica uma margem de segurança de 2 minutos, acionando o fallback automático aos 28 ou 58 minutos, respectivamente.
“Dia útil” segue o calendário de feriados nacionais do Banco Central do Brasil. A lista completa está disponível pelo endpoint Calendário de feriados.
Bloqueio cautelar
Seção intitulada “Bloqueio cautelar”O bloqueio cautelar congela os recursos creditados por até 72 horas quando há suspeita fundada de fraude, conforme a Resolução BCB 142/2021. O titular da conta deve ser notificado sobre o bloqueio.
Apêndice B: referência de campos
Seção intitulada “Apêndice B: referência de campos”As tabelas abaixo documentam os campos disponíveis em cada bloco da requisição. Todos os campos dos blocos opcionais são, eles próprios, opcionais. O integrador deve enviar os campos que estiverem disponíveis em seus sistemas. A Guardline usa o que for enviado e ignora o que estiver ausente.
Requisição de análise: objeto instantPayment
Seção intitulada “Requisição de análise: objeto instantPayment”| Campo | Tipo | Descrição |
|---|---|---|
keyType | string | Tipo de chave PIX: cpf, cnpj, phone, email, evp |
keyValue | string | Valor da chave PIX |
endToEndId | string | Identificador ponta a ponta do SPI |
originalEndToEndId | string | ID E2E original (para devoluções/estornos) |
reconciliationId | string | Identificador de conciliação (txid) |
initiationMethod | string | Método de iniciação (DICT, QRCODE, MANUAL) |
transactionPurpose | string | Código de finalidade da transação |
isQRCode | boolean | Indica se foi iniciada via QR Code |
isScheduled | boolean | Indica se é um pagamento agendado |
payer | object | Dados da parte pagadora (veja PixParty abaixo) |
receiver | object | Dados da parte recebedora (veja PixParty abaixo) |
dict | object | Dados de enriquecimento do DICT (veja abaixo) |
Requisição de análise: payer / receiver (PixParty)
Seção intitulada “Requisição de análise: payer / receiver (PixParty)”| Campo | Tipo | Descrição |
|---|---|---|
ispb | string | Código ISPB da instituição |
ispbName | string | Nome da instituição |
document | string | CPF ou CNPJ |
branch | string | Número da agência |
account | string | Número da conta |
name | string | Nome do titular da conta |
Requisição de análise: objeto dict
Seção intitulada “Requisição de análise: objeto dict”| Campo | Tipo | Descrição |
|---|---|---|
keyCreationDate | string | Data ISO 8601 de criação da chave PIX |
keyOwnershipDate | string | Data ISO 8601 em que a titularidade foi estabelecida |
accountType | string | Tipo de conta (CACC, SVGS, etc.) |
accountOpeningDate | string | Data ISO 8601 de abertura da conta |
pspName | string | Nome da instituição PSP |
pspIspb | string | Código ISPB do PSP |
fraudMarkersCount | integer | Quantidade de marcações de fraude (notificações de infração) |
infractionCount | integer | Quantidade de infrações |
lastFraudReportDate | string | Data ISO 8601 do último relato de fraude |
isFlagged | boolean | Indica se a chave está marcada no momento |
flaggedSince | string | Data ISO 8601 desde quando a chave está marcada |
claimsCount | integer | Quantidade de reivindicações de titularidade |
portabilityCount | integer | Quantidade de eventos de portabilidade |
correlationId | string | Identificador de correlação R6 |
registeredAccounts | string | Quantidade de contas registradas para o titular desta chave |
lastMarkFraudDate | string | Data ISO 8601 da última marcação de fraude |
naturalPersonAntifraudPercentage | integer | Percentual antifraude para pessoas físicas |
legalPersonAntifraudPercentage | integer | Percentual antifraude para pessoas jurídicas |
spi | object | Estatísticas do SPI (veja abaixo) |
reports | object | Relatos de infração (veja abaixo) |
frauds | array | Registros de fraude por tipo (veja abaixo) |
Requisição de análise: objeto dict.spi
Seção intitulada “Requisição de análise: objeto dict.spi”| Campo | Tipo | Descrição |
|---|---|---|
d90 | string | Transações no SPI nos últimos 90 dias |
m12 | string | Transações no SPI nos últimos 12 meses |
m60 | string | Transações no SPI nos últimos 60 meses |
Requisição de análise: objeto dict.reports
Seção intitulada “Requisição de análise: objeto dict.reports”| Campo | Tipo | Descrição |
|---|---|---|
openReports | string | Quantidade de relatos de infração em aberto |
distinctReports | string | Quantidade de instituições relatoras distintas |
rejectedD90 | string | Transações rejeitadas nos últimos 90 dias |
rejectedM12 | string | Transações rejeitadas nos últimos 12 meses |
rejectedM60 | string | Transações rejeitadas nos últimos 60 meses |
Requisição de análise: itens do array dict.frauds
Seção intitulada “Requisição de análise: itens do array dict.frauds”| Campo | Tipo | Descrição |
|---|---|---|
fraudType | string | Tipo de fraude (por exemplo, SCAMMER_ACCOUNT, MULE_ACCOUNT) |
d90 | string | Ocorrências nos últimos 90 dias |
m12 | string | Ocorrências nos últimos 12 meses |
m60 | string | Ocorrências nos últimos 60 meses |
Requisição de análise: objeto customer
Seção intitulada “Requisição de análise: objeto customer”| Campo | Tipo | Descrição |
|---|---|---|
age | integer | Idade do cliente |
kycStatus | string | Status do KYC (approved, pending, rejected) |
kycLevel | string | Nível do KYC (basic, intermediate, complete) |
riskScore | number | Score de risco preexistente |
riskLevel | string | Nível de risco (low, medium, high) |
isPEP | boolean | Indicador de Pessoa Exposta Politicamente |
country | string | País do cliente (ISO 3166-1 alpha-2) |
accountAgeDays | integer | Idade da conta em dias |
accountStatus | string | Status da conta (active, suspended, blocked) |
hasNegativeBalance | boolean | Indica se a conta está com saldo negativo |
isNewCustomer | boolean | Indica se é um cliente com onboarding recente |
Requisição de análise: objeto metadata
Seção intitulada “Requisição de análise: objeto metadata”| Campo | Tipo | Descrição |
|---|---|---|
direction | string | Direção da transação. Valores canônicos: IN, OUT, SELF. Não diferencia maiúsculas de minúsculas; INBOUND e OUTBOUND são aceitos como apelidos de IN e OUT. Um valor não reconhecido ou ausente é registrado como OUT, sem erro de validação (consulte PIX In). |
status | string | Status da transação no sistema de origem |
isInternational | boolean | Indica se é uma transação internacional |
originSystem | string | Identificador do sistema de origem |
Requisição de análise: objeto device
Seção intitulada “Requisição de análise: objeto device”| Campo | Tipo | Descrição |
|---|---|---|
id | string | Identificador do dispositivo |
type | string | Tipo de dispositivo (mobile, desktop, tablet) |
os | string | Sistema operacional (android, ios, windows) |
isNewDevice | boolean | Primeira vez que este dispositivo é visto |
isTrustedDevice | boolean | O dispositivo está na lista de confiáveis |
hasScreenSharing | boolean | Compartilhamento de tela detectado |
isEmulator | boolean | Emulador detectado |
isRootedJailbroken | boolean | Dispositivo com root/jailbreak detectado |
ipAddress | string | Endereço IP de origem |
Requisição de análise: objeto counterPart
Seção intitulada “Requisição de análise: objeto counterPart”| Campo | Tipo | Descrição |
|---|---|---|
name | string | Nome da contraparte |
taxIdentifier | object | { "taxId": "...", "country": "..." } |
isNewCounterpart | boolean | Primeira transação com esta contraparte |
riskScore | number | Score de risco preexistente da contraparte |
transactionsCount | integer | Quantidade histórica de transações com esta contraparte |
isSanctionedEntity | boolean | Indica se a contraparte está em uma lista de sanções |
isSameNetwork | boolean | Indica se a contraparte está na mesma rede |
Resumo de endpoints
Seção intitulada “Resumo de endpoints”| Método | Caminho | Autenticação | Descrição |
|---|---|---|---|
| POST | /api/v2/decisions/analyze | API Key | Envia a transação para análise de fraude |
| GET | /api/v2/decisions/{id} | API Key | Consulta uma decisão pelo ID |
| POST | /api/v2/decisions/{id}/cancel | API Key | Cancela uma decisão em REVIEW |
| GET | /api/v2/decisions/notifications | API Key | Lista notificações não entregues (polling) |
| POST | /api/v2/decisions/notifications/{delivery_id}/ack | API Key | Confirma o processamento de uma notificação obtida por polling |
| GET | /api/v2/holidays | API Key (holidays.read) | Consulta os feriados nacionais e bancários de um determinado ano |
Versão 18, atualizada em