Skip to content

Generic HTTPS (JSON)

Works with: anything that takes JSON over HTTPS: Sumo Logic (HTTP source), Cribl, Logstash (http input), Graylog (HTTP input), the Elastic Agent HTTP endpoint input, or your own receiver.

A POST with Content-Type: application/json, up to 500 events per request, in order:

{
"source": "safehanded",
"version": 1,
"org_id": "01h…",
"events": [
{ "seq": 41, "prev_hash": "…", "hash": "…", "sig": "…", "sig_key_id": "…", "event": "revealed", "level": "security",
"actor_type": "member", "actor_id": "…", "actor_label": "Jane Smith <jane@example.com>",
"request_id": "…", "share_id": null, "client_id": null, "ip": "203.0.113.9",
"user_agent": "…", "metadata": {}, "created_at": "2026-10-01T12:00:00Z" }
]
}

With OCSF chosen, each item in events is an OCSF 1.1 event instead.

Answer with any 2xx to accept the batch. A timeout, 408, 429 or 5xx is retried up to three times in the same run (honouring Retry-After up to 10 seconds). If the batch still isn’t accepted, the destination is marked Needs attention and later runs try again from the same event, backing off from one minute up to fifteen while it keeps failing, until it is accepted.

Choose one:

  • Bearer token: Authorization: Bearer <token>.
  • HMAC signature: X-SafeHanded-Signature: t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 with your secret over "<t>.<raw body>". Recompute it over the exact bytes received, compare in constant time, and reject a t more than five minutes old.
[$t, $v1] = sscanf($header, 't=%d,v1=%s');
$ok = abs(time() - $t) <= 300
&& hash_equals(hash_hmac('sha256', $t.'.'.$rawBody, $secret), $v1);

Settings → Integrations → Connect → Generic HTTPS (JSON): endpoint URL, authentication, token or secret (8 characters or more) and format. Save, then Send test event. The test event has "event": "siem_test" and "seq": 0.

De-duplicate on org_id + seq: after a failure an event can be delivered twice.