> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# API de ingestão de eventos - Monitorização não monetária

> Com a Didit, envie atividade não monetária (início de sessão, bónus, pagamentos, disputas) para o motor que pontua as suas transações.

Transações são o dinheiro. Os eventos são tudo o resto que a sua plataforma conhece: o início de sessão que antecedeu o levantamento, a mão que moveu fichas entre duas contas, o bónus reclamado duas vezes, o estorno que chegou uma semana depois.

Os eventos usam um único envelope para todas as categorias, são idempotentes por conceção e são avaliados pelo [mesmo motor de regras](https://docs.didit.me/pt/transaction-monitoring/event-rules.md) que pontua as suas [transações](https://docs.didit.me/pt/transaction-monitoring/transactions.md).

> [!NOTE]
>
> A ingestão de eventos é **opt-in**. Ative-a em **Transactions → Settings → Event monitoring**.
> Até lá, nada muda: as suas regras de transação existentes continuam a ser acionadas apenas em transações, e não é possível criar uma regra de evento por engano, porque uma regra se aplica a transações, a menos que inclua explicitamente eventos.
>
> Enquanto estiver desativada, todas as vias de escrita - `POST /v3/events/`, `POST /v3/events/batch/`, `POST /v3/events/sdk-token/` e a via de dispositivo `/v1/events/` - respondem com `403` e `{"code": "event_monitoring_disabled"}`, e nada é guardado, enriquecido ou avaliado. As leituras não são afetadas.

## Endpoints

| Endpoint | Autenticação | Utilizar para |
| - | - | - |
| `POST /v3/events/` | Chave de API | Um evento do seu backend |
| `POST /v3/events/batch/` | Chave de API | Até 500 eventos num único pedido |
| `POST /v3/events/sdk-token/` | Chave de API | Gerar uma credencial de dispositivo com âmbito limitado |
| `POST /v1/events/` | `X-Monitoring-Token` | Um evento do SDK de dispositivo |
| `POST /v1/events/batch/` | `X-Monitoring-Token` | Um buffer do SDK esvaziado |
| `GET /v3/events/` | Chave de API | Listar e filtrar eventos |
| `GET /v3/events/{event_uuid}/` | Chave de API | Um evento com as respetivas evidências de regras |
| `GET /v3/events/subjects/{vendor_data}/` | Chave de API | Cronologia de um sujeito (ver `entity_type` abaixo) |
| `GET /v3/events/enrichment-metrics/` | Chave de API | Estado da cache de enriquecimento de IP |

A via `/v3/` é a via do servidor e usa a mesma autenticação `x-api-key` do restante da API de transações. A via `/v1/events/` é a via do dispositivo - ver [Envio de eventos pelo SDK](https://docs.didit.me/pt/transaction-monitoring/sdk-event-submission.md).

## O envelope

```bash theme={null}
curl -X POST https://verification.didit.me/v3/events/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "login-2026-08-31-000001",
    "event_category": "auth",
    "action_type": "login",
    "occurred_at": "2026-08-31T20:40:31.123Z",
    "time_zone": "UTC",
    "subject": {
      "entity_type": "individual",
      "vendor_data": "user_391"
    },
    "session": { "session_id": "web-session-abc", "sequence": 142 },
    "device_context": {
      "fingerprint": "didit-fp-v2:a8c1",
      "network_context": { "ip_address": "203.0.113.42" }
    },
    "payload": { "method": "password" }
  }'
```

```json theme={null}
{
  "event_uuid": "0f2b...",
  "event_id": "login-2026-08-31-000001",
  "status": "ACCEPTED",
  "score": 0,
  "rules_evaluated_count": 6,
  "rules_matched_count": 0,
  "correlation_pending": false,
  "retention_class": "standard",
  "expires_at": "2026-09-30T20:40:31.123Z",
  "idempotent_replay": false,
  "rule_matches": []
}
```

| Campo | Obrigatório | Notas |
| - | - | - |
| `event_id` | Sim | O seu próprio identificador, único por aplicação. É a chave de idempotência. |
| `event_category` | Sim | Uma das dez categorias abaixo. |
| `action_type` | Sim | Cadeia de texto livre, com até 128 caracteres. |
| `occurred_at` | Sim | Quando aconteceu do seu lado. Até 7 dias no passado e 5 minutos no futuro. |
| `subject.vendor_data` | Sim | O seu ID de utilizador. Resolvido para o mesmo utilizador ao qual uma transação seria associada. |
| `subject.entity_type` | Não | `individual` (predefinido) ou `company`. |
| `business.vendor_data` | Não | A empresa à qual o evento pertence. |
| `session` | Não | `session_id`, `sequence`, `page_url`, `referrer`. |
| `device_context` | Não | `fingerprint`, `persistent_device_id`, `bot_score` e `network_context.ip_address`. |
| `transaction_context` | Não | `amount`, `currency`, `direction`, `payment_reference_id`. |
| `payload` | Não | Os campos de domínio da categoria. Até 16 KB. |
| `custom_values` | Não | Até 100 chaves escalares, endereçáveis nas regras como `custom_values.<key>`. |

## Categorias

Dez categorias de primeira classe, cada uma com validação tipada e [campos de regra](https://docs.didit.me/pt/transaction-monitoring/event-rules.md#campos-de-eventos) geridos.

| Categoria | Ações típicas |
| - | - |
| `auth` | `signup`, `login`, `login_failed`, `logout`, `password_forgot`, `password_reset`, `mfa_reset`, `mfa_challenge` |
| `session` | `session_started`, `session_ended`, `page_view`, `sdk_loaded`, `device_seen`, `bot_signal_observed`, `sdk_heartbeat` |
| `gameplay` | `round_started`, `round_completed`, `bet_placed`, `bet_settled`, `cashout`, `limit_change`, `p2p_settlement` |
| `bonus` | `bonus_claimed`, `bonus_wagered`, `bonus_released`, `promotion_viewed` |
| `affiliate` | `affiliate_attributed`, `referral_clicked`, `campaign_joined`, `commission_event` |
| `payment` | `deposit_initiated`, `deposit_completed`, `withdrawal_requested`, `withdrawal_completed`, `withdrawal_address_changed`, `payment_instrument_seen` |
| `dispute` | `chargeback_opened`, `chargeback_won`, `chargeback_lost`, `refund_issued`, `payment_dispute_updated` |
| `security` | `login_attempt`, `login_succeeded`, `login_failed`, `password_changed`, `mfa_changed`, `credential_reset`, `country_changed`, `device_changed`, `account_locked` |
| `responsible_gambling` | `self_exclusion_checked`, `self_exclusion_match`, `re_registration_attempt`, `limit_breach_attempt`, `registry_status_changed` |
| `custom` | Tudo o que definir |

`auth` é a categoria geral do produto; `security` é o subconjunto orientado para o risco, com o ciclo de vida ordenado que as regras de tomada de controlo da conta analisam.

### Chaves obrigatórias do payload

Algumas ações não podem ser correlacionadas sem chaves específicas, por isso a validação as rejeita em vez de guardar provas que ninguém consegue cruzar.

| Ação | Obrigatório |
| - | - |
| `gameplay.p2p_settlement` | `game_id`, `counterparty_vendor_data`, `stake_amount`, `net_result_amount`, `role`, e um dos campos `hand_id` / `round_id` / `match_id` |
| `gameplay.bet_placed`, `gameplay.bet_settled` | `game_id` |
| `payment.deposit_*`, `payment.withdrawal_completed`, `payment.withdrawal_requested`, `payment.deposit_initiated` | `payment_reference_id`, `amount`, `currency`, `payment_method`, `status` |
| `payment.withdrawal_address_changed` | `withdrawal_address_hash` |
| `dispute.chargeback_*` | `payment_reference_id`, e um dos campos `dispute_id` / `chargeback_id` |
| `security.*_changed` | `changed_field`; as alterações de controlo de conta ou de pagamentos de prémios também exigem `previous_reference_hash` ou `new_reference_hash` |
| `session.bot_signal_observed` | `telemetry_schema_version`, mais um `bot_score` ou pelo menos uma métrica de telemetria |
| `responsible_gambling.self_exclusion_match` | `registry_source`, `exclusion_status`, `identity_match_ref` |

> [!WARNING]
>
> Envie **referências e hashes**, nunca segredos em bruto. Os instrumentos de pagamento, os destinos de levantamento e as alterações de controlo de conta são guardados como a referência com hash que envia. Nunca envie um número de cartão, um endereço de levantamento completo, um hash de palavra-passe nem um segredo MFA.

### Exemplo: uma liquidação P2P

```json theme={null}
{
  "event_id": "p2p-hand-8842-user-391",
  "event_category": "gameplay",
  "action_type": "p2p_settlement",
  "occurred_at": "2026-08-31T12:34:17.392Z",
  "subject": { "vendor_data": "user_391" },
  "payload": {
    "game_id": "poker_holdem",
    "table_id": "table_17",
    "hand_id": "hand_8842",
    "role": "winner",
    "counterparty_vendor_data": "user_812",
    "stake_amount": "250.00",
    "net_result_amount": "240.50",
    "effective_margin": "0.038",
    "operator_ledger_ref": "ledger_998123"
  }
}
```

### Exemplo: um estorno

```json theme={null}
{
  "event_id": "chargeback-cb_921-opened",
  "event_category": "dispute",
  "action_type": "chargeback_opened",
  "occurred_at": "2026-08-31T09:22:05.000Z",
  "subject": { "vendor_data": "user_391" },
  "transaction_context": {
    "amount": "1000.00",
    "currency": "EUR",
    "payment_reference_id": "dep_735"
  },
  "payload": {
    "dispute_id": "disp_498",
    "chargeback_id": "cb_921",
    "reason_code": "fraudulent",
    "liability_shift": false
  }
}
```

Os ciclos de vida das disputas permitem apenas acrescentos: uma correção é um novo evento `dispute`, nunca uma edição do primeiro evento.

## Idempotência

`event_id` é único por aplicação e constitui todo o contrato de idempotência.

* **Mesmo `event_id`, mesmo conteúdo** devolve `200` com `"idempotent_replay": true` e o evento originalmente guardado. Pode repetir tantas vezes quanto quiser.
* **Mesmo `event_id`, conteúdo diferente** devolve `409`. Reutilizou um id por engano.

## Lotes

`POST /v3/events/batch/` aceita até **500 eventos**. Um lote tem sucesso parcial por conceção: uma visualização de página mal formatada nunca deve fazer falhar o estorno que está ao lado.

```json theme={null}
{
  "accepted_count": 2,
  "replayed_count": 0,
  "rejected_count": 1,
  "results": [
    { "index": 0, "outcome": "rejected", "errors": { "occurred_at": ["This field is required."] } },
    { "index": 1, "outcome": "accepted", "event_uuid": "…", "status": "ACCEPTED" },
    { "index": 2, "outcome": "accepted", "event_uuid": "…", "status": "IN_REVIEW" }
  ]
}
```

A resposta é `207 Multi-Status` quando algum evento foi rejeitado e `201 Created` quando todos foram aceites.

## Estados

| Estado | Significado |
| - | - |
| `ACCEPTED` | Guardado. Nenhuma regra alterou a sua situação (esta é a resposta normal para a maioria dos eventos). |
| `APPROVED` | Uma regra foi executada e a pontuação ficou abaixo do limiar de revisão. |
| `IN_REVIEW` | Uma regra levou o evento acima do limiar de revisão, ou definiu o estado diretamente. |
| `DECLINED` | Uma regra recusou o evento. |

`correlation_pending: true` significa que ainda tem de ser executada uma regra entre sujeitos; é resolvida em minutos e o estado e a pontuação do evento são atualizados no próprio registo. Veja [regras assíncronas](https://docs.didit.me/pt/transaction-monitoring/event-rules.md#regras-em-tempo-real-e-assíncronas).

## Retenção

Os eventos têm um volume muito superior ao das transações, por isso cada um é arquivado numa classe de retenção à chegada.

| Classe | Retenção a quente predefinida | O que entra aqui |
| - | - | - |
| `low_value` | 14 dias | Visualizações de página, batimentos, pings de dispositivo visto, telemetria de bots, visualizações de promoções |
| `standard` | 30 dias | Autenticação, sessão, jogabilidade, bónus, afiliados, personalizados |
| `risk_relevant` | 90 dias | Eventos de segurança e de jogo responsável, e **qualquer evento que tenha sido abrangido por uma regra** |
| `monetary_or_compliance` | Retenção de transações | Eventos de pagamento e de disputa |

Duas regras decorrem da tabela:

* Um evento que corresponde a uma regra é prova, por isso é promovido automaticamente a `risk_relevant`.
* Os eventos de pagamento e de disputa mantêm a retenção de transações. Nunca expiram segundo o calendário de eventos, e as substituições por classe não os podem encurtar.

Substitua as três classes expiráveis por aplicação em **Transactions → Settings → Event monitoring** (1-730 dias cada).

## Enriquecimento de IP

Os eventos trazem o mesmo [enriquecimento de IP](https://docs.didit.me/pt/transaction-monitoring/ip-enrichment.md) que as transações (país, ASN, indicadores de VPN/proxy e de centro de dados), e o enriquecimento é resolvido **por endereço IP único, nunca por evento**. Uma sessão que gera 200 visualizações de página a partir de um endereço resolve esse endereço uma única vez.

A telemetria de baixo valor vai mais longe: só lê o enriquecimento se algum outro evento já tiver resolvido esse endereço. Nunca desencadeia uma consulta própria.

`GET /v3/events/enrichment-metrics/` reporta o resultado, e a consola mostra os mesmos números acima da lista de eventos:

```json theme={null}
{
  "events_ingested": 128450,
  "enrichment_lookups": 41230,
  "enrichment_cache_hits": 40118,
  "enrichment_provider_calls": 1112,
  "enrichment_skipped_low_value": 74320,
  "unique_ips_seen": 1112,
  "cache_hit_rate": 0.973,
  "unique_ip_ratio": 0.0087,
  "provider_calls_per_1k_events": 8.65,
  "period_days": 30
}
```

## Consultar eventos

```bash theme={null}
curl "https://verification.didit.me/v3/events/?event_category=payment&event_category=dispute&matched_only=true" \
  -H "x-api-key: YOUR_API_KEY"
```

Filtros: `event_category`, `action_type`, `status`, `retention_class`, `subject_vendor_data`, `business_vendor_data`, `session_id`, `device_fingerprint`, `ip_address`, `game_id`, `round_id`, `affiliate_code`, `payment_reference_id`, `counterparty_vendor_data`, `matched_only`, `occurred_from`, `occurred_to`, `search`. Os filtros com vários valores repetem o parâmetro (`?status=A&status=B`).

### Cronologia de um sujeito

```bash theme={null}
curl "https://verification.didit.me/v3/events/subjects/acct_9931/?entity_type=company" \
  -H "x-api-key: YOUR_API_KEY"
```

Um `vendor_data` só é único dentro de um tipo de entidade: o mesmo identificador pode designar um utilizador e uma empresa, e a Didit trata-os como dois sujeitos diferentes. `entity_type` indica qual dos dois é pedido: `individual` (o predefinido) ou `company`. Se o omitir num identificador de empresa, devolve a cronologia da pessoa singular, e não as duas. Aplicam-se os mesmos filtros à lista.

`GET /v3/events/{event_uuid}/` acrescenta o payload, o contexto do dispositivo, o enriquecimento de IP, os sinais de risco em cache do sujeito e todas as correspondências de regras com a respetiva evidência, incluindo se cada campo correspondente foi derivado no servidor, derivado do SDK ou fornecido pelo cliente.

`DELETE /v3/events/{event_uuid}/delete/` elimina um evento. Deixa de ser devolvido por todas as leituras, e a eliminação é irreversível.

## Próximos passos

> [card] [Regras sobre eventos](https://docs.didit.me/pt/transaction-monitoring/event-rules.md)
>
> Regras de velocidade, rácio, sequência e correlação sobre dados de eventos.

> [card] [Submissão de eventos pelo SDK](https://docs.didit.me/pt/transaction-monitoring/sdk-event-submission.md)
>
> Capte eventos diretamente do dispositivo com uma credencial com âmbito limitado.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.