REST API

WipeCert API Documentation

Endpoints for the desktop agent and bootable ISO, public certificate verification, and outbound webhook delivery. Base URL https://wipecert.com.

Getting Started

Overview

The WipeCert API is REST + JSON. All endpoints accept and return UTF-8 JSON with Content-Type: application/json. There is no client SDK — every contract documented here is stable and can be called directly with curl, fetch, or your language's HTTP library.

Endpoint groups:

  • Agent API — used by the desktop agent and bootable ISO. Authenticated by x-api-key.
  • Public Verification API — used by auditors and customers to verify certificates without auth.
  • Outbound Webhooks — pushed to your URL when a wipe completes or fails. HMAC-signed.

Authentication

API Keys

Generate API keys at Dashboard → Settings → API Keys. Keys begin with wc_live_ and are tied to a single organization. The plaintext value is shown once at generation; only a bcrypt hash is stored after that.

Pass the key on the x-api-key header on every Agent API call:

curl -H "x-api-key: wc_live_..." \
     https://wipecert.com/api/agent/poll

Never commit API keys to source control. The desktop agent stores the key in ~/.wipecert/config.json with file-system-level permissions only — treat it the same as an SSH key.

Limits

Rate Limits

Rate limits are enforced server-side per API key (or per IP for the public verify endpoint):

EndpointKeyLimitWindow
GET /api/agent/pollAPI key6060 sec
POST /api/agent/reportAPI key24060 sec
POST /api/wipesUser ID3060 sec
GET /api/verify/[id]Client IP3060 sec

Responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. When exceeded, the API returns HTTP 429 with a Retry-After header.

Agent API

Poll for queued wipes

GET/api/agent/poll

Returns wipes the operator has queued in the dashboard but not yet processed.

Headers

HeaderRequiredDescription
x-api-keyYesOrganization API key, prefix wc_live_
x-agent-versionRecommendedSemver of the agent making the request, e.g. 1.0.11

Response 200

{
  "wipes": [
    {
      "id": "6919b441-ab10-4f24-997f-460a3285fa94",
      "wipe_number": "WC-2026-611157",
      "method": "Multi-pass Overwrite",
      "standard": "NIST 800-88 Clear",
      "status": "queued",
      "created_at": "2026-04-26T04:26:51.200Z",
      "devices": {
        "id": "c82e2459-9eee-4945-a050-66abc8cfbd84",
        "name": "USB Stick",
        "drive_type": "nvme",
        "device_type": "laptop",
        "drive_serial": "",
        "serial_number": "4784984",
        "drive_capacity": "",
        "drive_interface": ""
      }
    }
  ]
}

Errors

StatusReason
401Missing or invalid API key
429Rate limit exceeded — back off and retry after Retry-After seconds

Agent API

Report wipe progress and completion

POST/api/agent/report

Single endpoint for all lifecycle events. Discriminator is the event field:

eventWhen to send
startedImmediately after the agent locks the drive identity and computes hash before
progressEvery 1-5% of the wipe. Fire-and-forget, no retry.
completedAfter the final pass and hash-after / pattern verification
failedIf any unrecoverable error occurs

Body — started

{
  "wipeId": "6919b441-...",
  "event": "started",
  "data": {
    "hashBefore": "<64-char hex sha256>",
    "probeSeed":  "<64-char hex>",
    "merkleRootBefore": "<64-char hex>",
    "samplesChecked": 1024,
    "drive": {
      "path": "/dev/sda",
      "model": "Samsung 870 EVO",
      "serial": "S5HXNX0...",
      "capacityBytes": 512110190592,
      "logicalSectorBytes": 512,
      "physicalSectorBytes": 512,
      "interface": "SATA",
      "type": "ssd",
      "supportsSanitizeCrypto": true,
      "supportsSanitizeBlock":  true,
      "supportsSanitizeOverwrite": true,
      "tcgOpal": false,
      "wwn": "...",
      "firmwareRev": "..."
    },
    "system": {
      "manufacturer": "Dell Inc.",
      "model": "Latitude 5540",
      "serial": "JD7XYZ2",
      "biosVersion": "1.21.0"
    },
    "agentVersion": "1.0.11",
    "methodChosen": "ata_secure_erase",
    "methodReason": "ATA Sanitize advertised — preferred over multipass for SATA SSD",
    "availableDrives": [
      { "path": "/dev/sda", "serial": "S5HX...", "model": "Samsung 870 EVO", "capacityBytes": 512110190592, "isRemovable": false }
    ]
  }
}

Body — completed

{
  "wipeId": "6919b441-...",
  "event": "completed",
  "data": {
    "hashAfter": "<64-char hex sha256>",
    "verificationPassed": true,
    "merkleRootAfter": "<64-char hex>",
    "samplesMatched": 1024,
    "expectedPattern": "0x00",
    "actualMethodUsed": "ata_secure_erase",
    "methodFallbackReason": null,
    "firstFailedOffset": null
  }
}

Body — progress

{
  "wipeId": "6919b441-...",
  "event": "progress",
  "data": {
    "percentage": 42.5,
    "currentPass": 1,
    "totalPasses": 3,
    "bytesProcessed": 217641533440
  }
}

Body — failed

{
  "wipeId": "6919b441-...",
  "event": "failed",
  "data": {
    "error": "device_disconnected_mid_wipe"
  }
}

Response

{ "ok": true }

Agent API

Download an agent binary

GET/api/agent/download?platform=PLATFORM

Streams the latest GitHub-released binary directly. Valid platform values:

platformOutput
wipecert-agent.exeWindows x64 (signed UAC manifest)
wipecert-agent-linuxLinux x64
wipecert-agent-macos-armmacOS Apple Silicon
wipecert-boot.isoBootable ISO (UEFI + Legacy BIOS)

SHA-256 hashes for each binary are published at /api/agent/checksums (JSON). Compare the value against your downloaded file with sha256sum (Linux/macOS) or Get-FileHash (Windows).

# Verify a downloaded binary
curl -fsSL https://wipecert.com/api/agent/download?platform=wipecert-agent.exe -o wipecert-agent.exe
curl -fsSL https://wipecert.com/api/agent/checksums
# -> { "tag": "v1.0.15", "checksums": { "wipecert-agent.exe": "abcd..." } }
sha256sum wipecert-agent.exe   # compare against the value above

Public API

Verify a certificate

GET/api/verify/[id]

No auth required. Returns the signed payload, the Ed25519 detached signature, and the JWKS URL containing the public key. Auditors can re-verify offline; see /security for the procedure.

Path parameters

id — either the certificate UUID (38a067d8-1560-40e2-...) or the human certificate number (WC-CERT-2026-611157).

Response 200

{
  "certificateId": "38a067d8-...",
  "certificateNumber": "WC-CERT-2026-611157",
  "revision": 1,
  "issuedAt": "2026-04-26T08:29:00Z",
  "verification": {
    "status": "VALID",
    "kid": "wc-2026-01",
    "signedAt": "2026-04-26T09:17:47.123Z"
  },
  "payload": { /* canonical signed payload (RFC 8785 / JCS form) */ },
  "signature": "ZFbPrQwhT8WjVUTL...",
  "kid": "wc-2026-01",
  "alg": "Ed25519",
  "signedAt": "2026-04-26T09:17:47.123Z",
  "jwksUrl": "https://wipecert.com/.well-known/jwks.json",
  "summary": {
    "deviceSerial": "4784984",
    "driveSerial": "S5HXNX0...",
    "method": "Multi-pass Overwrite"
  },
  "instructions": "..."
}

Verification status values

statusMeaning
VALIDSignature verified against the active JWKS key. Certificate is authentic.
INVALIDSignature did not verify. Document may have been tampered with.
LEGACY-UNSIGNEDPre-v2 certificate without a signature (rare; only old test data)
UNKNOWN-KEYSignature kid not present in JWKS (key rotation in progress?)

Webhooks

Outbound webhooks

Configure outbound webhook endpoints at Dashboard → Settings → Webhooks. WipeCert will POST a JSON payload to your URL on the events you select. A webhook secret is generated server-side; HMAC-SHA-256 signatures are sent in X-WipeCert-Signature.

Supported events

eventFires when
wipe.completedAn agent reports event=completed and the certificate is generated
wipe.failedAn agent reports event=failed

Headers WipeCert sends

HeaderValue
Content-Typeapplication/json
User-AgentWipeCert-Webhooks/1.0
X-WipeCert-Eventwipe.completed | wipe.failed
X-WipeCert-Signaturesha256=<hex digest>
X-WipeCert-Delivery<webhook delivery UUID, useful for idempotency>

Payload — wipe.completed

{
  "event": "wipe.completed",
  "timestamp": "2026-04-26T08:29:00.000Z",
  "organizationId": "5760cd9b-3bcc-...",
  "data": {
    "wipeId": "6919b441-...",
    "wipeNumber": "WC-2026-611157",
    "method": "Multi-pass Overwrite",
    "standard": "NIST 800-88 Clear",
    "deviceId": "c82e2459-...",
    "durationSeconds": 2225,
    "certificateId": "38a067d8-...",
    "certificateNumber": "WC-CERT-2026-611157"
  }
}

Webhooks

Verify a webhook signature

Compute HMAC-SHA-256 of the raw request body using your webhook secret, then compare against the value of X-WipeCert-Signature (after stripping the sha256= prefix). Use a constant-time comparison.

import crypto from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const provided = signatureHeader.replace(/^sha256=/, "");
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(provided, "hex"),
    Buffer.from(expected, "hex")
  );
}

Always verify the signature before parsing the JSON body. Reject and log mismatches — a failed verification usually means a misconfigured secret on the receiving end.