DecompilerAI API
Headless REST access to the same engines the web UI uses: upload a binary, decompile it, fetch the C. Same credits, same cache, no browser required.
1Get an API key
Keys are created on your profile page (section "API keys").
A key looks like dcai_... and is shown in full exactly once, when it is created or rotated;
store it in a secret manager. You can label keys, give each one an optional monthly credit cap and
its own rate limit, rotate them and revoke them at any time. API keys are separate from your browser
session: a session token never works on the API, and an API key never works as a login.
2Authentication
Send the key on every request, either as a header of its own or as a bearer token:
curl -s https://decompiler.ai/api/v1/me -H "X-API-Key: dcai_YOUR_KEY"
curl -s https://decompiler.ai/api/v1/me -H "Authorization: Bearer dcai_YOUR_KEY"Missing or revoked keys answer 401 {"error": ...}. All errors are JSON with an error field.
3The full flow: upload, decompile, fetch C
3.1 Upload a binary
curl -s https://decompiler.ai/api/v1/binaries \
-H "X-API-Key: dcai_YOUR_KEY" \
-F "file=@./program"
# 201 {"id": 42, "name": "1755600000000_program", "sha256": "...", "size_bytes": 16384, "format": "elf"}ELF, PE/EXE, Mach-O, Android APK, APK sets (XAPK / APKS / APKM) and DEX are accepted (64 MB global cap; your plan sets the per-file size, an APK's own size cap, and how many files you can keep). An APK is a container: its summary lists the members (classes*.dex, lib/<abi>/*.so), and POST /api/analysis/:file/apk-open {member} extracts one into a file of its own (linked to the package, no file slot) that every other call then analyses. An APK set lists its base and split APKs the same way; opening one yields an APK. Use the returned id (or name) in every later call.
3.2 List its functions
curl -s "https://decompiler.ai/api/v1/binaries/42/functions?limit=50" \
-H "X-API-Key: dcai_YOUR_KEY"
# {"total": 128, "functions": [{"name": "main", "addr": 4416, "size": 214}, ...]}3.3a Decompile one function (synchronous)
curl -s https://decompiler.ai/api/v1/binaries/42/decompile \
-H "X-API-Key: dcai_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"engine": "ghidra", "level": "l0", "addr": "0x1140"}'
# {"ok": true, "scope": "function", "code": "int main(void) { ... }", "cached": false, ...}
Engines: ghidra (free, instant), gpt, decai (the in-house model, per function and whole program).
decai decompiles ELF (x86-64, AArch64) and PE (x86-64) with a COFF symbol table (a stripped PE is refused); ghidra and gpt decompile every ELF and PE;
Mach-O can be browsed but not decompiled yet. An engine the binary's format does not support is refused
before anything is billed: 400 for one function, 415 for a whole-program run;
a full whole-program queue answers 503 with Retry-After.
Results are cached per function, engine and level: repeating a call is free and returns
"cached": true. Per-function levels are l0, l0-l1,
l0-l4, l0-l1-l4 (L2/L3 need the whole program).
3.3b Decompile the whole program (async job)
curl -s https://decompiler.ai/api/v1/binaries/42/decompile \
-H "X-API-Key: dcai_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"engine": "ghidra", "level": "l0-l4"}'
# 202 {"ok": true, "scope": "program", "job_id": 1337, "poll": "/api/v1/jobs/1337", "estimated_credits": 128, ...}
curl -s https://decompiler.ai/api/v1/jobs/1337 -H "X-API-Key: dcai_YOUR_KEY"
# {"id": 1337, "status": "RUNNING", "stages": {"analysis": {"status": "done"}, ...}}Poll until status is DONE (or FAILED, with an error).
FORGE. Library functions the signature database recognizes (GET /api/v1/binaries/{id}/forge:
name, library, version, tier, confidence) are left out of a whole-program run: they appear in the output under their
real name with the library's source text, are not decompiled and not charged (forge_skipped in the 202,
estimated_credits excludes them). Send "include_forge": true to decompile them too.
3.4 Fetch the C (or a .zip project)
# JSON (program C + per-function code)
curl -s "https://decompiler.ai/api/v1/binaries/42/decompiled?engine=ghidra&level=l0-l4" \
-H "X-API-Key: dcai_YOUR_KEY"
# one .c file
curl -s "https://decompiler.ai/api/v1/binaries/42/decompiled?engine=ghidra&level=l0-l4&format=c" \
-H "X-API-Key: dcai_YOUR_KEY" -o program.c
# a .zip project (program.c, functions/*.c, include/decompiled.h, Makefile)
curl -s "https://decompiler.ai/api/v1/binaries/42/decompiled.zip?engine=ghidra&level=l0-l4" \
-H "X-API-Key: dcai_YOUR_KEY" -o program.zip4Levels (stage tokens)
A level names exactly the pipeline stages that run:
L1, L2 and L3 are the cumulative verify chain: requesting l3 implies l1 and
l2. L4 is independent of them. Examples: l0, l0-l4,
l0-l1-l2-l3-l4. Verify stages (L1 and up) need a Pro or Team plan.
5Endpoint reference
/api/v1/binariesUpload (multipart field file) -> id, sha256, format/api/v1/binariesList your binaries with latest job + finished runs/api/v1/binaries/{id}Summary + status of one binary/api/v1/binaries/{id}/functionsFunction list (q, offset, limit)/api/v1/binaries/{id}/forgeLibrary functions recognized by FORGE (name, lib, version, tier, confidence)/api/v1/binaries/{id}/decompileWith addr: one function, sync. Without: whole program -> 202 + job id/api/v1/jobs/{id}Whole-program job status with per-stage progress/api/v1/binaries/{id}/decompiledA finished run's C (?engine&level, format=json|c)/api/v1/binaries/{id}/decompiled.zipThe run as a .zip project/api/v1/meAccount, key, credit balance and the current price list6Credits and limits
-
credits
Same credits as the web UI. An API decompile charges exactly what the same click costs in the browser; prices come from
GET /api/v1/me. Ghidra L0 is free. Cached results are free. - 402 Insufficient credits (top up or upgrade on the pricing page), or this key's monthly credit cap is reached (the error says which).
-
429
The key's per-minute rate limit was exceeded; honour the
Retry-Afterheader. The default is 60 requests/min, settable per key via therate_per_minfield ofPOST /api/keys(up to the server ceiling, 600/min). -
jobs
Whole-program runs are billed per function by the run itself; the 202 response carries an
estimated_creditsfigure from a pre-count. The per-key monthly cap is reserved atomically before a billable request runs and given back when nothing ran (refused, cached, failed).
7OpenAPI spec
The machine-readable contract lives at https://decompiler.ai/openapi.yaml
(OpenAPI 3.1). Point your client generator, Postman or any agent framework at it. Its analysis
tag lists the analysis routes the inspector and the agent tools use (project documents and snapshots,
code/data marks and flow repairs, decompiler corrections, debug files, header import, Android resources and JNI,
the live debugger's session routes and its saved run configurations):
they take the same key as a bearer token.
8Agents: MCP server and the in-app agent
Every analysis capability is also a tool an AI agent can call. Read tools: list
functions, disassemble, decompile (Ghidra free, gpt priced; decai runs whole programs), cross-references, call graph, strings,
imports, regex/byte search, semantic search, raw bytes, function diff, the functions of an older version matched to this one
with a confidence and reason per pair and the ambiguous ones listed, never picked (match_versions), the patch list, packer detection,
the script library, the type header and what it declares (get_types), where a function's decompilation
can be corrected (correction_sites), every line that uses a struct member (member_xrefs: read / write / address-taken),
the call-graph paths between two functions (call_paths: a connection, not a data-flow proof),
the C++ classes from the RTTI (classes: bases, vtables, every slot new / override / inherited / pure),
what a virtual call can reach (virtual_targets: exact / heuristic / unresolved, per call site or per target),
static value queries over Ghidra's data flow (call_arguments: every call site of a function with the value
of one argument, exact or unknown with its origin; value_origin: where one value comes from, where it goes,
and whether it is compared on every path to a call - read-only, nothing runs the binary),
the project snapshots (snapshot_list, and snapshot_diff: what a restore
would change), and for Android packages the resources (android_resources, where one is used:
android_resource_xrefs) and the JNI map (jni_map: native methods to their functions in
each ABI's libraries). Write tools change the binary or run code: annotate (rename, comment,
prototype, bookmark, and code vs data: define data, mark a string, mark code, undefine), the flow repairs (set_function_bounds,
set_noreturn, set_sp_delta, set_switch_table), the decompiler corrections
(correct_decompilation: a call's prototype, a union member, a split variable), the type header and
import_header (a real .h file appended to it), vectorize, patch / remove_patch (bytes,
assembled instructions, strings, added code blocks, detours, hooks, wrappers), emulate (the
jailed Unicorn emulator: arguments, registers, memory, breakpoints, trace, stdin/stdout), run_script
(a Python script in the scripting SDK), unpack / unpack_analyze and
snapshot_save / snapshot_restore (the whole project state of a binary: every annotation,
the type header, loader settings and the patch set, saved under a name and restored exactly),
transfer_annotations (carry the names, prototypes, comments, bookmarks, local names and types of an
older version into this one: a preview first, then one batch with a transfer id that one call undoes). Every read after a
patch sees the patched bytes, and an open Inspect tab refreshes live when an agent changes the file. The same
tool set is exposed two ways.
8.1 In the inspector: Agent mode
Open a binary in Inspect and press 🤖 Agent next to the chat. The assistant then calls the tools itself, shows each step, and answers from what it read. Each model turn costs one chat message; a tool costs what it costs in the API (a Ghidra decompile is free).
8.2 From your own agent: MCP
DecompilerAI is an MCP server. Any MCP client (Claude Desktop, Claude Code, Cursor, your own) can connect with an API key from /profile:
// hosted (no install): MCP over HTTP
POST https://decompiler.ai/mcp
Authorization: Bearer dcai_...
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
// Claude Desktop / Claude Code: a local stdio server (needs node)
{ "mcpServers": { "decompilerai": {
"command": "node", "args": ["/path/to/DecompilerAI/mcp/server.js"],
"env": { "DECOMPILERAI_API_KEY": "dcai_...", "DECOMPILERAI_URL": "https://decompiler.ai" } } } }
Tools act with the key's identity and are billed like the API: the key's monthly credit cap and rate
limit apply. Upload binaries through the API or the site first; list_binaries tells the
agent the file names to use.
Key scope. A key is created read-only or read-write on
/profile. A read-only key is only shown the read tools and every write it attempts
(through MCP, the analysis API or /api/v1) answers 403 with
read_only: true - the safe choice for an agent you do not fully trust. A read-write key can do
everything your account can, patching included. Neither kind can create, rotate or revoke keys.
8.3 The live debugger
An agent drives the same debug session you see in the inspector's Emulate tab: one per file, the
emulator paused between commands, every step the agent takes shown live in your tab and labelled
agent (status line, Console, API log). debug_state says what is open, what a whole-program
start costs and which run configurations are saved; debug_start runs a function, from an
address, or the whole program with argv, environment, stdin and files (or a saved configuration by name);
debug_breakpoint sets / deletes / lists breakpoints (conditions, hit counts, log-only, memory and
API breakpoints, one-click hooks); debug_continue, debug_step (into, over, out, back in
time) and debug_run_to wait for the next stop and answer compactly (pc, reason, the registers
that changed, top of stack, the console's last output); debug_set changes a register, flag,
memory or the pc; debug_read_memory, debug_eval, debug_origin (who
wrote this value), debug_stdin, debug_files, debug_api_log and
debug_stop complete it. A read-only key may look (state, memory, expressions, files, API log)
but not start, run or change a session.
A whole-program session costs credits per start (the same price as the button). An agent never starts one
blind: without accept_price (the price you agreed to) the start answers 428 with the
price and nothing runs or is charged. Function and from-cursor sessions are free. Over plain HTTP the routes are
POST /api/analysis/{file}/debug/start, GET /api/analysis/{file}/debug/session and
POST /api/analysis/{file}/debug/current/{command}?wait=10 (see the OpenAPI spec); run
configurations are GET|PUT|DELETE /api/analysis/{file}/run-configs[/{name}].