PHP API Documentation & Wrapper

Validate KVs, ZIP packs, serials, and purchases from PHP

Unshared.shop / Blog / PHP API Documentation & Wrapper
Cyanokit March 31, 2026 18 min read API Documentation

What this API actually does in 2026

UnsharedSHOP exposes a single router at https://api.unshared.shop/api/. Ban checks go through KVChecker.com, then we add console metadata parsed from the 16,384-byte KeyVault and (when you are signed in) account helpers for credits, purchases, and downloads.

The old “one 16 KB file only, ZIP rejected if two KVs exist” rule is no longer true for validate / validate_url. Packs return a multi report with one result per 16 KB file. Serial sharing checks and rarity lookups are still public.

Base URL: https://api.unshared.shop/api/
Token: Dashboard → My Profile (authenticated routes only).
Interactive docs: open /api/?action=info with no id for the HTML tester.

Authentication

Validation, rarity, product listing, and serial info do not require a token. Profile, credit checkout, and purchase downloads do. Send the token in one of these ways (query string is checked first):

X-API-Token: YOUR_API_TOKEN
Authorization: Bearer YOUR_API_TOKEN
?api_token=YOUR_API_TOKEN

A missing or bad token on a protected route returns HTTP 401: {"success":false,"error":"Authentication required"}.

Public endpoints

POST ?action=validate

Multipart upload. Accepted field names, in order: kv_files[] (one or more), kv_file, then file. Each part may be a raw kv.bin (exactly 16,384 bytes) or a ZIP of those files. Nested folders are fine; zip-slip paths are ignored.

curl -F "file=@kv.bin" "https://api.unshared.shop/api/?action=validate"
curl -F "kv_files[]=@pack.zip" "https://api.unshared.shop/api/?action=validate"

POST ?action=validate_url

Fetches a remote .bin or .zip. Optional product is the shop product name (for example 2keys) so the expected KV count can be checked on packs.

curl -X POST "https://api.unshared.shop/api/?action=validate_url" \
  -d "url=https://dl.unshared.shop/kv.bin?id=YOUR_ID&dl=true"

Hitting a customer download URL with dl=true spends a download credit. Prefer uploading the file you already have, or use stream=1 on action=download after a purchase.

GET ?action=info&id={serial}

id must be exactly 12 digits. Returns whether other UnsharedSHOP users have logged that serial, last known status, a coarse last-check label, and whether it appears in our supply list. Optional status=1 (unbanned) or status=2 (banned) writes a log row.

GET /api/?action=info&id=000000000000

GET ?action=rarity&date=MM-DD-YY

Manufacturing-date rarity (Xbox 360 production window). Response includes rarity, production, and likely console family (Xenon through Corona).

GET ?action=products

In-stock catalog: id, name, price, credit_cost, type (digital / physical), is_kv, and stock.

Authenticated endpoints

  • GET ?action=profile — username, credits, referral code, purchase count.
  • POST ?action=purchaseproduct_name, optional product_id and discount_code. Digital products only.
  • GET ?action=downloads — purchase list with download_token and relative download_url. Add include_deleted=true if you need hidden rows.
  • GET ?action=download&token=...&txn=... — JSON redirect to https://dl.unshared.shop/kv.bin?id=...&dl=true.
  • GET ?action=download&stream=1&token=...&txn=... — streams bytes. Default extract=1 pulls a single 16 KB KV out of a ZIP; pass extract=0 to keep the archive.
  • POST ?action=regenerate_token — issues a new API token and invalidates the old one.

Single-KV response

error is the legacy string flag ("0" / "1") alongside boolean success. Partner and KVChecker blocks are present on successful live checks.

{
  "success": true,
  "error": "0",
  "unbanned": true,
  "status": "Unbanned",
  "message": "KV is unbanned",
  "serial": "012345678901",
  "console_name": "XE.000000000000",
  "console_id": "...",
  "mfg_date": "01-15-09",
  "region": "N/A",
  "motherboard": "Jasper",
  "console": "Phat (Jasper)",
  "drive_id": "DG-16D2S",
  "part_number": "",
  "model_number": "",
  "rarity": "Common",
  "color": "#95a5a6",
  "partner_checks": {
    "Cipher": { "checked": true, "first_seen": null },
    "xbGuard": { "checked": true, "first_seen": "2022-06-05T22:26:42Z" }
  },
  "sharing": {
    "is_shared": true,
    "shared_partner_count": 1,
    "shared_partners": { "xbGuard": "2022-06-05T22:26:42Z" }
  },
  "kvchecker": {
    "server_time": "2026-08-16T14:00:00Z",
    "xbl_system_version": 17559,
    "total_unique_keyvaults": 40000,
    "partners": ["Cipher", "xbGuard", "Nfinite"],
    "verify_link": "https://kvchecker.com/verify?id=...",
    "signature": "..."
  },
  "extracted_from_zip": false,
  "kv_inner_path": null
}

Multi-KV (ZIP / several uploads)

When more than one 16 KB KV is found, the router returns the pack object instead of the flattened single-KV shape: multi: true, summary counts, and results[]. unbanned at the top level is true only when every KV in the pack is unbanned.

{
  "success": true,
  "multi": true,
  "status": "Mixed",
  "summary": { "total": 2, "unbanned": 1, "banned": 1, "unknown": 0, "errors": 0 },
  "results": [ { "serial": "...", "unbanned": true, "kv_index": 1 }, { "unbanned": false, "kv_index": 2 } ],
  "kvchecker": { "partners": ["Cipher", "xbGuard", "Nfinite"] }
}

Production PHP client

$api = new UnsharedApi("YOUR_TOKEN"); // token optional for validate
$res = $api->validateFile(__DIR__ . "/kv.bin");

if (!empty($res["multi"])) {
    echo $res["message"] ?? "pack checked";
} elseif (!empty($res["success"])) {
    echo ($res["status"] ?? "Unknown") . " serial " . ($res["serial"] ?? "");
    if (!empty($res["serial"])) {
        $share = $api->checkSerial($res["serial"]);
        echo $share["shared"] ? " shared on UnsharedSHOP" : " not in our share log";
    }
} else {
    echo $res["error"] ?? $res["message"] ?? "unknown";
}

Practical notes

  • Give validate at least 60–90 seconds. KVChecker.com is a live Xbox Live check.
  • A partner first_seen of null with checked: true means they scanned it and have no record — that is “clear,” not “unchecked.”
  • info.shared is UnsharedSHOP’s own check log, not Cipher/xbGuard/Nfinite. Use sharing.is_shared for partners.
  • Do not put API tokens in public repos or client-side JavaScript.
  • Legacy aliases still work: /api/checkkv.php → validate, /api/pub_api.php → info, /api/kv_rarity.php → rarity.
Wrapper: UnsharedApiWrapper.php — validate, packs, serials, products, credits, and streaming downloads.

Stuck? Open a support ticket.