Upload a crash dump and poll for the report (API)
Upload a dump with POST /api/v1/dumps, poll GET /api/v1/dumps/{id}/report until job_state is final, or use a webhook. Statuses, failures and 503 retries.
Short answer: Send the file as multipart form data to POST /api/v1/dumps with your API key, keep the id it returns, then call GET /api/v1/dumps/{id}/report until job_state is delivered, escalated or failed. Or register a webhook and let DumpTriage call you.
1. Upload the dump
The key goes in an Authorization: Bearer header; an upload-scoped key is enough for this call. The file is the multipart field file. The dump type is detected from the file's own bytes, so there is no type parameter.
curl -X POST https://api.performanceinsights.ai/api/v1/dumps \
-H "Authorization: Bearer dts_..." \
-H "X-Content-SHA256: <hex sha256 of the file>" \
-F "file=@crash.dmp" \
-F "comment=Crashed while the backup job started"
The optional X-Content-SHA256 header makes the service compare the bytes it received with your hash: a mismatch is refused with 422 content_sha256_mismatch and nothing is stored. The optional comment field is plain text of at most 2000 characters, shown back to you on the dump and to the engineer if it is escalated; the automated analysis does not read it. Other optional fields are hostname (only a keyed hash is stored) and human_review, described in the API reference.
A successful upload returns 201 with the dump record. Keep its id:
{"id": "...", "dump_type": "user_mode", "status": "uploaded", "job_state": "queued",
"size_bytes": 123456, "uploaded_at": "...", "download_url": "..."}
During the pilot, upload only synthetic or sample data (see Signup in the API reference). How big a file may be depends on the tier: crash dump too big, or no WinDbg on this machine? has the limits.
2. Poll for the report
curl https://api.performanceinsights.ai/api/v1/dumps/<id>/report \
-H "Authorization: Bearer dts_..."
The response always has dump_id, job_state and reports. reports holds each tier's findings and confidence signals as that tier completes, so it can be empty or partial while the job runs. decision is null while the dump is still processing.
job_state | Meaning | Keep polling? |
|---|---|---|
queued | Uploaded, waiting for a worker. | Yes |
tier1_running, tier1_done | The first automated pass is running or has finished. | Yes |
tier2_queued, tier2_running, tier2_done | The second automated pass is waiting, running or finished. | Yes |
delivered | Automated triage resolved it; decision is delivered. | No |
escalated | A human is on it; decision is escalated. | No |
failed | The analysis failed. failure holds a code and a message that are safe to show a customer. | No |
A small loop in Python:
import time, requests
H = {"Authorization": "Bearer dts_..."}
BASE = "https://api.performanceinsights.ai/api/v1"
with open("crash.dmp", "rb") as f:
dump = requests.post(f"{BASE}/dumps", headers=H, files={"file": f})
dump.raise_for_status()
dump_id = dump.json()["id"]
while True:
r = requests.get(f"{BASE}/dumps/{dump_id}/report", headers=H)
if r.status_code == 503: # overloaded: wait as long as the server says
time.sleep(int(r.headers.get("Retry-After", "30")))
continue
r.raise_for_status()
report = r.json()
if report["job_state"] in ("delivered", "escalated", "failed"):
break
time.sleep(30)
print(report["job_state"], report.get("failure"))
Poll at an interval you can live with; the loop above uses 30 seconds, which is our choice for the example, not a documented limit. If a response sets waiting_for_capacity, the job is waiting for room to run, and retry_at may say when it will be tried again.
Or let DumpTriage call you
Register an endpoint once with POST /api/v1/customers/me/webhook (body {url, secret}). When a dump's report is delivered or its analysis fails, DumpTriage sends a POST with {dump_id, status} to it, signed with your secret. The signature check, with code, is under Webhooks in the API reference. You can use a webhook instead of polling or alongside it.
Errors on these two calls
| Status | When |
|---|---|
401 | Missing or invalid API key. |
403 | Terms not accepted, the account is closed, or human_review on a plan without engineer review. An upload-scoped key cannot read reports. |
404 | No such dump, or it belongs to another account. |
413 | The file is over the tier's per-dump limit; the upload is cut off at the limit. |
422 | An unrecognized dump format, a hash mismatch, or a comment over 2000 characters. |
429 | Over quota. |
503 | Temporarily overloaded; retry after the seconds in the Retry-After header. |
Every error body is {"detail": "..."}. Uploading the same bytes again returns the existing dump rather than a second one.
Common questions
- How do I know the analysis is finished?
- Call GET /api/v1/dumps/{id}/report and read job_state. delivered, escalated and failed are final. Anything else (queued, tier1_running, tier1_done, tier2_queued, tier2_running, tier2_done) means the analysis is still running.
- Can I get a callback instead of polling?
- Yes. Register a webhook with POST /api/v1/customers/me/webhook. Your endpoint then receives a POST with the dump_id and status when a dump's report is delivered or its analysis fails. Failed deliveries are retried.
- What happens if I upload the same dump twice?
- An identical file is deduplicated: the upload returns the existing dump unchanged and does not count against the quota again.
Ready to send a dump?
Upload a minidump to DumpTriage. It runs the debugger, reads the output and sends back the faulting module, the stack and a plain-language root cause (how the analysis works). Except on the Solo plan, cases the automated passes can't settle go to an engineer. Free during the pilot.
Create an account