API
Everything the site shows is also available as JSON, and uploads can be scripted. Base URL: https://zlogic.eu/zdex/api/v1.
Authentication
Reading public dumps needs no account. Uploading needs an API key: create one on your account page and send it as a bearer token. Keys act as your account, so treat them like a password; revoke them on the same page.
Authorization: Bearer zdx_…
Every response is JSON with an ok field. Errors carry error (a short code) and message (human readable). A missing or invalid key answers 401 (unauthenticated / invalid_key), an account without a verified email 403 unverified. Rate limits answer with HTTP 429 and a Retry-After header: 600 requests per minute per key, 8 upload starts per hour, 300 dump reads and 60 searches per minute per address. Public reads are cached for ten minutes; dumps never change after they are published.
Send a descriptive User-Agent (for example Zircon/0.4.0). The site sits behind Cloudflare, which turns away generic library user agents with a plain-text 403 before the request reaches Zdex.
Reading dumps
| Endpoint | Returns |
|---|---|
| GET / | Server descriptor: chunk_bytes, max_upload_bytes, terms_version. The v1 shape is frozen; changes are additive only |
| GET /games?q= | Games with published dumps |
| GET /dump/{id} | Header data: engine, source process, counts, globals, derived engine offsets |
| GET /dump/{id}/types?kind=class|struct|enum&q=&package=&sort=&after= | Type list, 300 per page; follow next as after |
| GET /dump/{id}/functions?q=&package=&after= | Function list with owner class and native RVA |
| GET /dump/{id}/type?path=/Script/Engine.Actor | One type: members with offsets, sizes, bitfields, flags, defaults; functions with parameters; enum values. path also accepts a C++ name like AActor |
| GET /dump/{id}/search?q=&kind= | Full-text search inside one dump (types, members, functions, enum values) |
| GET /dump/{id}/packages?kind= | Packages with counts |
| GET /dump/{id}/status | Import state and progress: queued, importing (with progress and phase), pending, ready or failed |
| GET /search?q= | Search across every published dump |
Downloads are plain URLs: /zdex/d/{id}/download/usmap, …/download/sdk (zip of headers) and …/download/json (the original Zircon dump).
curl -s "https://zlogic.eu/zdex/api/v1/dump/1/type?path=AActor" | jq '.members[] | select(.name=="RootComponent")'
Uploading a dump (the zircon publish protocol)
Zircon already implements all of this — zircon login once, then zircon publish game.json --game "Game title" --label "1.4.2", or --publish on the dump command. Read on if you are writing your own client.
Uploads are chunked so large files survive flaky connections and shared-hosting limits. Three calls, all with the bearer token:
- Start.
POST /upload/initwith a JSON body{"filename":"game.json.gz","size":<bytes>,"game":"Game title","label":"1.4.2","notes":""}. The answer containsupload_id,chunk_bytesandchunk_count. Accepted files:.json,.json.gz, or a.zipcontaining the JSON (a zip of the wholezircon-outfolder works; only the JSON is kept). Send just the gzipped JSON from tools — a 300 MB dump becomes about 30 MB. - Send chunks. For each index
0 … chunk_count-1:POST /upload/chunk?upload_id=…&index=Nwith the raw bytes of that slice as the body (Content-Type: application/octet-stream). The last chunk is shorter. Chunks can be sent in any order and repeated;GET /upload/status/{upload_id}lists what has arrived, so a resumed upload only sends what is missing. - Finish.
POST /upload/finishwith{"upload_id":"…"}. The server assembles the file, checks it is a Zircon dump, rejects exact duplicates (422rejected, by SHA-256 of the JSON, naming the existing dump) and answers withdump_idand an absoluteurl. If chunks are missing it answers 409incompletewith thereceivedindices. Indexing runs in the background; pollGET /dump/{dump_id}/statusuntil it reportspending(waiting for review) orready.
Uploads through the API are bound by the same terms as uploads through the site: the key holder is the uploader and responsible for the content. Trusted uploaders' dumps go live immediately; everyone else's are reviewed first. Quotas and limits: 512 MB per file, 2.0 GB per account by default, eight new uploads per hour.
gzip -k game.json
KEY=zdx_…; UA="Zircon/0.4.0 (+https://zlogic.eu/zircon/)"
SIZE=$(stat -c %s game.json.gz)
INIT=$(curl -s -A "$UA" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d "{\"filename\":\"game.json.gz\",\"size\":$SIZE,\"game\":\"My Game\",\"label\":\"1.0.3\"}" \
https://zlogic.eu/zdex/api/v1/upload/init)
ID=$(echo "$INIT" | jq -r .upload_id); CH=$(echo "$INIT" | jq -r .chunk_bytes); N=$(echo "$INIT" | jq -r .chunk_count)
for i in $(seq 0 $((N-1))); do
dd if=game.json.gz bs=$CH skip=$i count=1 2>/dev/null | \
curl -s -A "$UA" -H "Authorization: Bearer $KEY" -H "Content-Type: application/octet-stream" \
--data-binary @- "https://zlogic.eu/zdex/api/v1/upload/chunk?upload_id=$ID&index=$i" > /dev/null
done
curl -s -A "$UA" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d "{\"upload_id\":\"$ID\"}" https://zlogic.eu/zdex/api/v1/upload/finish
Dump format
Uploads must be JSON in the Zdex dump format (schema_version 1). Zircon writes it natively; the format page documents every key so any other dumper can produce it.
Data notes
- Type identity is the object path (
/Script/Engine.Actor); C++ names (AActor) are derived from Zircon'scpp_prefix. - Member
sizeis the total size of the property including static arrays;array_dimtells you the element count. - Bitfields carry
bitfield.bitandbitfield.mask; several share one byte offset. - Native RVAs are relative to the module base recorded in the dump header.
- The
.usmapdownload is version 3 (long names, large enums), uncompressed, readable by CUE4Parse and FModel.
Something missing? Tell me through the contact form.