CyberTwin
Developer documentation

Outbound webhooks + API.

CyberTwin pushes every critical / high finding into your Jira / ServiceNow / SIEM via signed webhooks, serves a read-only machine API for posture and findings, and accepts scheduled artifact uploads over the same API tokens — so the re-upload loop your proof-over-time evidence depends on can run from cron, not clicks. Writing remediation status back is on the roadmap; this page documents what already ships.

Outbound webhooks

Configure endpoints at Settings → Webhooks. Each endpoint receives every event whose severity meets or exceeds the configured floor.

Events fire on finding.created (the moment a config-review surfaces a finding) and finding.remediated (when a CISO marks the remediation ledger as remediated or re-verified).

Signing + verification

Each delivery includes an x-cybertwin-signature header in the form sha256=<hex>. Receivers MUST verify this signature before processing the payload. Reject any request where the comparison fails.

# Node.js example
import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(rawBody, signatureHeader, secret) {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader);
  return a.length === b.length && timingSafeEqual(a, b);
}

The secret is shown once at endpoint creation — copy it then. If lost, rotate by deleting and re-creating the endpoint.

Payload reference

finding.created

{
  "type": "finding.created",
  "emitted_at": "2026-05-07T12:34:56.789Z",
  "org_id": "org_abcd1234",
  "payload": {
    "title": "MFA not enforced for Marketing group",
    "severity": "critical",
    "description": "Conditional Access policy excludes the Marketing group from tenant-wide MFA.",
    "link": "https://cybertwin.io/config-review/cr_xyz#entra-ca-mfa-001",
    "external_id": "cwt:cr_xyz:entra-ca-mfa-001",
    "labels": {
      "vendor": "microsoft-entra-ca",
      "environment": "prod",
      "checkId": "entra-ca-mfa-001"
    }
  }
}

finding.remediated

{
  "type": "finding.remediated",
  "emitted_at": "2026-05-12T09:15:22.450Z",
  "org_id": "org_abcd1234",
  "payload": {
    "title": "MFA not enforced for Marketing group",
    "severity": "critical",
    "description": "CA policy updated to include Marketing group; verified by re-running config-review.",
    "link": "https://cybertwin.io/config-review/cr_xyz#entra-ca-mfa-001",
    "external_id": "cwt:cr_xyz:entra-ca-mfa-001",
    "labels": { "checkId": "entra-ca-mfa-001", "status": "re_verified" }
  }
}

external_id is stable for a (config-review, finding) pair — receivers should use it to de-dupe and update the existing ticket on remediation rather than creating a new one.

Retry behaviour

Deliveries are persisted to a queue and retried with exponential backoff:

We retry on any non-2xx, including 4xx — receivers that reject a payload should accept it (200) and discard server-side rather than 4xx. Persistent 4xx will dead-letter the delivery and surface on your endpoint health.

Read-only machine API

Mint an API token at Settings → API tokens (owner / admin; the plaintext is shown once). The read API is available on every paid plan — no particular tier is required (the scheduled uploads below are the Operate+ path). Send it as Authorization: Bearer cwk_…. Read endpoints accept both read and read_write scopes and are always scoped to the token's organization:

GET /api/v1/posture            # environments + latest posture snapshot
GET /api/v1/summary            # posture + open findings by severity + freshness
GET /api/v1/compliance         # per-framework score + proven/modeled provenance, per environment
GET /api/v1/findings?severity=critical&limit=50
GET /api/v1/risk-acceptances

Scheduled artifact uploads

The four artifact upload routes accept the same Bearer tokens, so the exports CyberTwin analyzes can be pushed on a schedule. Requirements: a read_write token, an Operate or Program plan, and an active subscription. Plan quotas and rate limits apply exactly as in the browser — a cron push consumes the same Configuration-Review quota a click does. Every headless upload is attributed to the human who minted the token and writes an audit entry recording the token that acted.

# Nightly firewall config re-upload (the proof-over-time loop).
# jq --rawfile safely JSON-encodes the whole config — newlines, quotes and all.
curl -X POST https://cybertwin.io/api/config-review \
  -H "Authorization: Bearer $CYBERTWIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg vendorId fortinet-fortigate --rawfile raw backup.conf --arg tag nightly-cron \
        '{ vendorId: $vendorId, raw: $raw, tag: $tag }')"

POST /api/config-review        # config export → full review (secrets redacted by default)
POST /api/identity-export      # Okta / Entra admin export
POST /api/ingest/cspm          # canonical CSPM report, or ?vendor=wiz rows
POST /api/ingest/ot-inventory  # OT asset inventory

Uploads are parsed with the same honesty rules as the browser: unparseable input is refused with the reasons — never silently scored.

/api/health

Public health-check endpoint suitable for uptime monitors and load balancers. Always returns 200; component health is in the body.

GET https://cybertwin.io/api/health

{
  "ok": true,
  "uptime_seconds": 1209384,
  "elapsed_ms": 4,
  "components": [
    { "name": "database", "ok": true, "detail": "connected" },
    { "name": "webhooks", "ok": true, "detail": "0 pending, 0 dead-letter" },
    { "name": "stripe", "ok": true, "detail": "configured" }
  ],
  "version": "0.4.2"
}

API roadmap

  • Shipped — read-only machine API (posture, findings, summary, risk acceptances) + scheduled artifact uploads over Bearer tokens (both above).
  • Q4 2026 — Write endpoints for the remediation ledger (mark in-progress, mark remediated, request re-verification).
  • 2027 — GraphQL + bidirectional Jira / ServiceNow connectors (status sync, not just push).

Need something on the roadmap sooner? Email hello@cybertwin.io with your use case.