Seqlense docs

Alerts

Raise, triage and annotate the alerts Seqlense produces about your wallets, identities and order-book clients.

An alert is something Seqlense wants you to look at. It carries a severity, a source, optionally the subject it concerns, and a status you move as you work through it.

Alerts come from two places: Seqlense raises them itself, when a market abuse scan (market_abuse) or an order-book abuse run (orderbook_abuse) finds something, and you can raise your own through the API. Both kinds behave identically once created.

Alerts belong to the workspace of the API key on the request. A dev scoped key reads and writes the development workspace, whose alerts and channels are separate from production.

The shape of an alert

FieldMeaning
severityINFO, MEDIUM, HIGH or CRITICAL, nothing else
sourcewho raised it: market_abuse, orderbook_abuse, or your own string (1-100 characters)
title / messagethe headline (1-200 characters) and the detail (not empty)
entity_type / entity_idwhat it is about, for example WALLET or IDENTITY plus the UUID. Empty strings when not set
metadatafree-form JSON, kept as sent
statusOPEN, ACKNOWLEDGED or RESOLVED (MUTED exists in storage, but no API call sets it)
created_atUTC, formatted YYYY-MM-DD HH:MM:SS

source matters more than it looks: it is what notification channels filter on, so pick one stable value per producer rather than a per-event one.

Raising one

POST /v1/alerts/ with source, severity, title and message:

curl -X POST https://monitoring.seqlense.com/api/v1/alerts/ \
  -H "Authorization: Bearer sq_..." \
  -H "Content-Type: application/json" \
  -d '{
    "source": "my-risk-engine",
    "severity": "HIGH",
    "title": "Unusual counterparty",
    "message": "Wallet 0xabc... received funds from a newly created address.",
    "entity_type": "WALLET",
    "entity_id": "9a0c3e2b-7d41-4f5a-b6e8-1c2d3e4f5a6b",
    "metadata": { "tx_hash": "0x1234...", "amount": "150" }
  }'
{ "status": "ok", "id": "5b1f7c1e-2a4d-4c8e-9f3a-8d2e6b0c1a47" }

A few rules the endpoint applies:

  • severity and entity_type are upper-cased, so high is stored as HIGH.
  • entity_id, when present, must be a UUID v4.
  • There is no de-duplication: posting the same alert twice creates two.
  • The call waits for the notification channels to be delivered (see Notification channels) before it answers. Each outbound request has a 10 second timeout, and a failed delivery never fails the call.

Linking an alert to a subject is worth the effort: for WALLET and IDENTITY alerts, the detail endpoint resolves the subject into a readable label and a link, and lists the other alerts on the same wallet.

Finding them

GET /v1/alerts/ returns one page, newest first:

curl "https://monitoring.seqlense.com/api/v1/alerts/?status=OPEN&severity=CRITICAL&limit=50" \
  -H "Authorization: Bearer sq_..."
ParameterEffect
status, severity, source, entity_typeexact match
tag_idonly alerts carrying this tag (ignored if not a UUID)
from, today bounds YYYY-MM-DD, both inclusive
qsubstring of title, message or source (ignored above 100 characters)
page1-based, default 1
limitpage size, default 20, clamped to 10-100

The response is { "alerts": [...], "total": 42, "page": 1, "limit": 50 }, where total counts every alert matching the filters.

GET /v1/alerts/count returns total, open and critical_open for the whole workspace, the numbers you would put on a dashboard badge. open counts only OPEN alerts, not acknowledged ones.

GET /v1/alerts/detail?id=... returns one alert with:

FieldContent
metadataparsed back into JSON
subject{ kind, label, url, identity } for wallet, identity and order-book client alerts, otherwise null
relatedup to 10 other alerts on the same wallet or order-book client
acknowledged_by / resolved_byuser id, 0 when done with an API key
deliveriesevery webhook, Discord or Slack delivery attempt and its result

Working through them

CallEffect
POST /v1/alerts/acknowledge { "id": ... }OPEN becomes ACKNOWLEDGED
POST /v1/alerts/resolve { "id": ... }OPEN or ACKNOWLEDGED becomes RESOLVED
POST /v1/alerts/bulk-action { "action": "resolve", "ids": [...] }the same on up to 100 alerts
DELETE /v1/alerts/?id=...removes the alert and its delivery records

These calls answer {"status":"ok"} even when nothing changed: an unknown id, an alert that is already resolved, or acknowledging something that is not OPEN. Read the alert back if you need to know its state. A resolved alert cannot be reopened.

Notes

Investigators can attach notes to an alert:

curl -X POST https://monitoring.seqlense.com/api/v1/alerts/notes \
  -H "Authorization: Bearer sq_..." \
  -H "Content-Type: application/json" \
  -d '{ "alert_id": "5b1f7c1e-2a4d-4c8e-9f3a-8d2e6b0c1a47", "text": "Known OTC desk, checking with the client." }'
  • GET /v1/alerts/notes?alert_id=... lists them newest first, each with id, text, created_by, created_by_name and created_at.
  • POST needs text of 1-2000 characters and returns 404 if the alert is not in your workspace.
  • DELETE /v1/alerts/notes?id=... takes the note id and returns 404 if it does not exist.

History

GET /v1/alerts/history is the append-only event log: one event per alert raised, as it was at that moment. It is filtered by severity and source, paginated with limit (default 50, max 200) and offset, and returns { "events": [...], "total", "limit", "offset" }.

Events are never updated: their status is always OPEN, and events of deleted alerts remain. Use it to answer "what was raised, and when". It is not a delivery log; delivery results live in the deliveries of each alert.

Signal heatmap

GET /v1/alerts/heatmap?source=market_abuse&days=30 shows which detector signals fire most across all your scans, including scans that raised no alert. source is market_abuse or orderbook_abuse; days defaults to 30, 0 means all time.

{
  "runs": 12,
  "patterns": [
    {
      "pattern": "wash_trading",
      "title": "Wash trading",
      "hits": 20,
      "rate": 0.5,
      "quiet": [],
      "signals": [
        { "id": "w1", "label": "Self-matched trades", "hits": 20, "evaluated": 40, "rate": 0.5 }
      ]
    }
  ]
}

hits is how often a signal was confirmed, evaluated how often it could be assessed, and rate is their ratio rounded to 3 decimals. Signals that never fired are listed by label in quiet.

Where alerts go

Every new alert is forwarded to the workspace's active notification channels whose filters it matches: a signed webhook, Discord, or Slack. See Notification channels.

For every field and error message, see the API reference.

On this page