Zdexby TheHolyOneZ

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

EndpointReturns
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.ActorOne 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}/statusImport 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:

  1. Start. POST /upload/init with a JSON body {"filename":"game.json.gz","size":<bytes>,"game":"Game title","label":"1.4.2","notes":""}. The answer contains upload_id, chunk_bytes and chunk_count. Accepted files: .json, .json.gz, or a .zip containing the JSON (a zip of the whole zircon-out folder works; only the JSON is kept). Send just the gzipped JSON from tools — a 300 MB dump becomes about 30 MB.
  2. Send chunks. For each index 0 … chunk_count-1: POST /upload/chunk?upload_id=…&index=N with 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.
  3. Finish. POST /upload/finish with {"upload_id":"…"}. The server assembles the file, checks it is a Zircon dump, rejects exact duplicates (422 rejected, by SHA-256 of the JSON, naming the existing dump) and answers with dump_id and an absolute url. If chunks are missing it answers 409 incomplete with the received indices. Indexing runs in the background; poll GET /dump/{dump_id}/status until it reports pending (waiting for review) or ready.

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's cpp_prefix.
  • Member size is the total size of the property including static arrays; array_dim tells you the element count.
  • Bitfields carry bitfield.bit and bitfield.mask; several share one byte offset.
  • Native RVAs are relative to the module base recorded in the dump header.
  • The .usmap download is version 3 (long names, large enums), uncompressed, readable by CUE4Parse and FModel.

Something missing? Tell me through the contact form.