Event monitoring
Build with

Once a user exists as an entity, stream their activity — payments, transfers, logins, profile changes, anything you want scored — to the monitoring engine. Each event is scored against your monitoring rules, stored as a browsable signal, and — when it scores high enough — raises an alert.

Ingest an event
Build with

POST /api/identity/events — secret (sk_) key, same base URL and auth as the rest of the Identity Hub.

Request

json
{
  "externalUserId": "user_42",
  "externalEventId": "txn_10001",
  "type": "transaction.transfer",
  "data": {
    "amount": 48000,
    "currency": "USD",
    "country": "NG",
    "counterparty": "acct_998877",
    "direction": "outbound",
    "channel": "transfer",
    "ip": "102.89.x.x"
  }
}
FieldRequiredNotes
externalUserIdYesThe entity this event belongs to (your own reference).
externalEventIdYesYour stable reference for the event — use it as an idempotency key.
typeYesA free-form event type you choose, e.g. transaction.transfer, login, withdrawal.
dataNoThe event payload the rules read (see below).

Response

json
{
  "id": "evt_01j9ghi000",
  "decision": "ALLOW",
  "riskScore": 0,
  "alertId": null
}
FieldMeaning
idThe stored signal's ID.
decisionALLOW, REVIEW, or BLOCK — the outcome of scoring against your thresholds.
riskScoreComposite risk score, 0–100.
alertIdThe alert opened for this event, or null when none was raised.

Use the decision to gate your own flow — e.g. let ALLOW through, hold REVIEW for manual approval, reject BLOCK.

Scoring rollout. Rule evaluation is being enabled progressively per organization. Until it is active for yours, events are accepted and stored but return decision: "ALLOW" with riskScore: 0. The request and response shapes do not change when scoring turns on — so you can integrate against this contract now and start acting on decisions the moment it's live.

The data payload
Build with

data is a free-form object, but the built-in monitoring rules look for a set of standard fields. Send the ones that apply and the matching rules light up; omit a field and the rules that need it stay dormant.

FieldTypeFeeds
amountnumberThreshold, Velocity, Pattern (structuring), New-beneficiary, Round-amount, Baseline anomaly.
currencystring (ISO 4217)Per-currency money limits across the amount-based rules.
countrystringGeography, Cross-border.
counterpartystringCounterparty lists, New-beneficiary, Smurfing.
directionstring (inbound/outbound, credit/debit)Pass-through, Rapid-movement, Smurfing.
channelstring (e.g. cash, card, crypto)Cash-intensive.
ipstringAvailable to custom rules.

Anything else you include is preserved and addressable from custom rules via meta_data.* paths.

The event.flagged webhook
Build with

Whenever an event scores to a non-ALLOW decision, a webhook fires so you don't have to poll:

Eventdata
event.flaggedeventId, decision, riskScore, alertId, externalUserId, type, environment

Device & session signals
Build with

POST /api/identity/signals records device/session signals (fingerprints, session context) tied to an entity. This stream is store-only today — it's persisted for future correlation but not yet scored or surfaced in the dashboard.

json
{ "externalUserId": "user_42", "type": "device.fingerprint", "data": { "deviceId": "d_123" } }

Returns 202 { "id": "sig_01j9jkl111" }.

Where events show up
Build with

  • Every scored event appears in Dashboard → Compliance → Signals (requires signals:read).
  • Events that raise an alert appear in Dashboard → Compliance → Alerts (requires alerts:read), where your team can group them into a case.

Best practices
Build with

  • Send one event per logical action, with a stable externalEventId, so retries don't double-count.
  • Register the entity first. An event references an entity by externalUserId; keep your entity records current so rules that read entity.riskTier / entity.nationality have data.
  • Include the standard fields you have — the more of amount, currency, direction, counterparty you send, the more rules can contribute.
  • Test on sandbox. Use sk_test_ keys and exercise your rule configuration before pointing production traffic at it.

Errors
Build with

StatusBodyCause
400{ "error": "invalid_request", "details": … }Missing externalUserId / externalEventId / type, or malformed body.
403{ "error": "secret_key_required" }A publishable key was used — event ingestion is secret-key only.

Next steps
Build with