Dump Triage API — v1
Upload a Windows crash or memory dump, get an AI-triaged report back — automatically, or escalated to a human engineer when the evidence calls for it. Built for enterprise IT, ISVs shipping crash-reporting integrations, and solo developers debugging one dump at a time.
1. Overview
Every dump goes through the same pipeline: upload → Tier 1 (fast automated triage) → Tier 2 (deep automated review, if Tier 1 isn't confident) → Tier 3 (human engineer, if the evidence still doesn't add up). Most dumps resolve automatically; you'll see that in the report's decision field either way.
V1 analyzes Windows user-mode (minidump) and kernel-mode (full/kernel memory) dumps. Linux dump support is tracked as a future addition, not yet available.
2. Authentication
Every request except signup and verification needs a bearer API key:
Authorization: Bearer dts_<your-key>
Keys are issued once, at signup verification (§5) — store it immediately, it isn't retrievable again. Keys aren't scoped per-user; one key represents one account/organization.
3. Tiers & Quotas
Self-serve accounts get a free, metered quota per rolling 30-day period. Uploading past your quota returns 429 until the period rolls over. There's no paid tier yet — if you need a higher limit, get in touch.
| Tier | Monthly dumps | Largest dump | Monthly upload volume | Who it's for |
|---|---|---|---|---|
solo | 1 | 2 GiB | 2 GiB | An individual developer debugging their own crashes. |
isv | 10 | 8 GiB | 40 GiB | A software vendor piping customer crash dumps through automated triage. |
enterprise | 25 | 16 GiB | 100 GiB | An internal IT/engineering team triaging a fleet's worth of dumps. |
Re-uploading a dump you've already uploaded (identical bytes) is deduplicated and doesn't count against your quota.
4. Quickstart
# 1. Sign up (choose tier: solo | isv | enterprise)
curl -X POST https://api.performanceinsights.ai/api/v1/signup \
-H "Content-Type: application/json" \
-d '{"org":"Acme Inc","contact":"Jane Dev","email":"jane@acme.example","tier":"solo"}'
# -> {"customer_id": "...", "status": "pending_verification"}
# 2. Click the link in the verification email, or verify directly:
curl -X POST https://api.performanceinsights.ai/api/v1/signup/verify \
-H "Content-Type: application/json" \
-d '{"token":""}'
# -> {"customer_id": "...", "api_key": "dts_..."} <-- save this, shown once
# 3. Upload a dump
curl -X POST https://api.performanceinsights.ai/api/v1/dumps \
-H "Authorization: Bearer dts_..." \
-F "file=@crash.dmp"
# -> {"id": "...", "dump_type": "user_mode", "status": "uploaded", "job_state": "queued",
# "size_bytes": 123456, "uploaded_at": "...", "download_url": "/api/v1/dumps/download?uri=...&token=..."}
# 4. Poll for the report
curl https://api.performanceinsights.ai/api/v1/dumps/<id>/report \
-H "Authorization: Bearer dts_..."
# -> {"job_state": "delivered", "decision": "delivered", "reports": [...]}
5. Signup
Body: {org, contact, email, tier} — tier is one of solo, isv, enterprise. Returns 202 with {customer_id, status: "pending_verification"} and sends a verification email. Posting again with the same (unverified) email resends the link, at most once per 60 seconds (429 otherwise). An email that's already verified returns 409. Also rate-limited per source IP (a handful of signups per hour) — a 429 past that limit carries a Retry-After header.
Body: {token} (from the emailed link). Returns {customer_id, api_key} — the only time the plaintext key is shown. An invalid, already-used, or expired (24h) token returns 400. The emailed link opens a confirmation page; the key is only issued once you press its button, so a mail scanner fetching the link can't use up your token.
6. Dumps
Multipart upload, field name file. Dump type (user-mode vs kernel-mode) is detected from the file itself, not a parameter — recognized by magic bytes MDMP (user-mode minidump) or PAGE (kernel/full memory dump); anything else is the 422 below. Returns 201 with the dump record: {id, dump_type, status, size_bytes, uploaded_at, job_state, download_url}. 422 for an unrecognized format, 413 if the file is larger than your tier's per-dump size (or what's left of your monthly upload volume), or 429 if you're over quota (§3). Oversized uploads are cut off at the limit, not after the full transfer.
Lists your dumps, most recent first. Same shape as the upload response, one per dump.
Fetch one dump's status. Same shape as the upload response.
Downloads the original file via a short-lived (1h) signed URL. Take uri/token straight from the download_url field on the dump record above — don't construct them yourself. An expired or tampered token returns 403.
7. Reports
Returns {dump_id, job_state, decision, reports}. decision is null while still processing, otherwise "delivered" (automated triage resolved it) or "escalated" (a human is on it). reports holds each tier's findings, confidence signals, and cost accounting as they complete.
8. Symbols
Multipart upload (file, module_name, module_hash) for private PDBs — isolated per account, never shared across customers, used to symbolicate your own modules during analysis.
9. Account
Body: {retention_preference_days} — how long uploaded dumps are retained.
10. Webhooks
Body: {url, secret} — url must be a public http(s) address; secret is 16–256 characters of your choosing. Once registered, your endpoint receives a POST when a dump's report is delivered, instead of (or alongside) polling §7. Failed deliveries are retried.
Every delivery is signed with your secret so you can verify it came from us:
X-Triage-Timestamp: 1789761600
X-Triage-Signature: sha256=<hex HMAC-SHA256(secret, "<timestamp>.<raw request body>")>
Compute the HMAC over the timestamp, a literal ., and the raw body bytes exactly as received (don't re-serialize the JSON), compare in constant time, and reject timestamps more than five minutes old:
import hashlib, hmac, time
def verify(secret: str, headers, raw_body: bytes) -> bool:
ts = headers["X-Triage-Timestamp"]
if abs(time.time() - int(ts)) > 300:
return False
expected = "sha256=" + hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, headers["X-Triage-Signature"])
11. Errors
| Status | Meaning |
|---|---|
401 | Missing, malformed, or invalid API key. |
403 | Valid key, wrong permissions (staff-only routes). |
404 | No such dump/report/customer, or it belongs to a different account. |
409 | Signup email already registered and verified. |
422 | Malformed request body, or an unrecognized dump format. |
429 | Monthly quota exceeded, or a signup/verification resend was attempted too soon. |