Your first analysis.
A clear path.
Use the same analysis service as the workspace, from your own tools. Submit a file, keep its job ID, and retrieve the evidence when it is ready.
https://devirt.re/api/v1Interactive Try the three-step API example
/api/v1/submitBearer ••••- job_id
- demo_001
- status
- queued
- progress
- 0%
Local simulation, not a live API request. No file is uploaded and no credit is used.
Create your key.
API access comes with an active Team, Professional or Enterprise plan. Open API & settings, create a key, and store it as DEVIRT_API_KEY in your server environment. Never put it in browser code or a public repository.
jobs:writeSubmit files and fund jobsjobs:readRead your job statusresults:readRetrieve your analysisOnly reading existing jobs? Leave out jobs:write. Keys are shown once and can be revoked.
Send your file.
POST/packages/triage
Request a Triage Plus summary for one authorized file. This bounded static check identifies file structure and protection indicators; it does not recover code.
A working request.
The Python example uses httpx: install it with pip install httpx.
Request fields
| Field | Default | What to send |
|---|---|---|
binary | Required | Your authorized file. Maximum 500 MiB. |
product_id | community_triage | community_triage or triage_plus. Neither product performs VM recovery. |
use_allowance | false | Apply one available Triage Plus allowance. General Analysis and recovery use separate product allowances. |
authorization | Required | true confirms your authorization to analyze the file. |
Use community_triage for a free workspace inventory with no artifact download. General Analysis and protected recovery begin with an assessment. Choose an approved package offer for that exact binary; its outputs and price are fixed before payment.
Reuse the same key after a connection failure. A different file or selection requires a new key.
Keep the returned job_id. If checkout_required is true, POST to /job/{job_id}/checkout and open the returned URL. A confirmed payment event activates the job.
Follow its progress.
GET/job/{job_id}
Poll every 5–15 seconds with the same Bearer key, or use a completion webhook. Payment state distinguishes an unfunded submission from a funded queue entry.
A job can also fail. Read its error and refund state instead of waiting indefinitely.
{
"job_id": "demo_001",
"status": "processing",
"progress": 60,
"stage": "Comparing recovered behavior"
}
Save your evidence.
GET/job/{job_id}/result
Once complete, paid work returns a signed output_url. Recovery results also include coverage_ledger and proof_summary. Static triage returns static_summary; Community Triage has no artifact download. Save paid outputs in your own evidence store.
Completed recovery response
{
"job_id": "demo_001",
"status": "complete",
"product_id": "protected_full",
"output_url": "https://storage.example/result.zip?signature=…",
"coverage_ledger": {
"proven": 86,
"runtime_dependent": 7,
"unresolved": 2,
"permanently_bounded": 5,
"total": 100,
"scope": "Synthetic example: 100 assessed protected functions",
"notes": []
},
"proof_summary": {
"proven_count": 86,
"sat_count": 2,
"timeout_count": 3,
"permanent_bounds_count": 5
}
}
While output is retained, request another signed link if needed. Renewing a link never extends retention. SAT and timeout counts are proof-summary outcomes, not extra coverage buckets.
Receive completion events.
Configure a public HTTPS endpoint in settings and securely save its signing secret.
- Keep the raw body. Sign the timestamp, a period, and the unmodified request bytes.
- Verify authenticity. Compare HMAC-SHA256 with v1 in X-Devirt-Signature using a constant-time comparison.
- Check freshness. Reject timestamps outside five minutes. Deduplicate X-Devirt-Event or event_id.
- Record, then acknowledge. Return 2xx after durable storage; process the event separately.
Delivery can repeat. Redirects are not followed; private-network destinations are rejected.
Assess before committing.
For General Analysis, protected recovery or custom work, POST binary, description, contact_email, and authorization=true to /novel/assess with an idempotency key. The email must match the verified account. Keep the returned assessment_id.
Completed assessments can include package_offers. Each offer identifies the exact binary, accepted outputs, price and expiry. POST to /packages/offers/{offer_id}/accept with {"accept_terms": true, "use_allowance": false, "priority": "standard"}. Use only an allowance for that product. Express is available only when the offer permits it. The returned job_id identifies the accepted order; use its checkout path if checkout_required is true. General Analysis allowances never purchase recovery.
For a separately quoted engagement, GET /novel/assess/{assessment_id}to read its written offer. POST to its /accept path with {"accept_terms": true}, then fund the deposit. Or POST to /decline with nothing charged. Offers and assessment reports expire after 72 hours. Acceptance and decline require the assessments:write scope.
The endpoint map.
Paths begin with /api/v1. The OpenAPI schema is available for tools and code generation; this page is the human reference.
POST/packages/triage
Required scope: jobs:write.
POST/packages/offers/{offer_id}/accept
Required scope: jobs:write.
GET/job/{job_id}
Required scope: jobs:read.
GET/job/{job_id}/result
Required scope: results:read.
POST/job/{job_id}/checkout
Required scope: jobs:write.
POST/novel/assess
Required scope: assessments:write.
GET/novel/assess/{assessment_id}
Required scope: assessments:read.
GET/database/list
Required scope: database:read.
GET/database/{entry_id}/download
Required scope: database:read.
Database routes also require permanent library access. Search with q, category, and page; download with format=ida or another available format.
Errors with a next step.
401Replace an invalid or revoked key.403Check key scopes and your active plan.402Add eligible credit or fund the balance.409Inspect the job state or idempotency conflict.413Use a file within the 500 MiB limit.422Read the field errors and correct the request.429Wait for the Retry-After interval.5xxBack off and retry with the same idempotency key.
Keep this job ID.
The accepted scope and funding determine when processing starts. Every later request refers to the same job.