> ## Documentation Index
> Fetch the complete documentation index at: https://developer.allscale.io/llms.txt
> Use this file to discover all available pages before exploring further.

# AllScale_OpenAPI.postman_collection.json

```json theme={null}
{
  "info": {
    "_postman_id": "a11sc4le-0pen-4p1-0000-000000000001",
    "name": "AllScale OpenAPI (v1)",
    "description": "Ready-to-use Postman collection for AllScale's third-party OpenAPI.\n\n_Aligned with docs/openapi (Create v4 / Get v5 / Get-Status v2 — 2026-05-06)._\n\n**Setup**\n\n1. Import this collection **and** the companion environment file (`AllScale_OpenAPI.postman_environment.json`).\n2. Pick the environment (top-right dropdown).\n3. Fill in `api_key` and `api_secret` (shown once in the merchant dashboard — store them in the environment, not the collection).\n4. `base_url` defaults to the **sandbox** host; switch to the production host when ready.\n\n**How signing works**\n\nThe collection has a pre-request script at the root that runs before every request. It:\n\n- Reads `api_key` / `api_secret` from the active environment\n- Builds the canonical string `METHOD\\nPATH\\nQUERY\\nTIMESTAMP\\nNONCE\\nBODY_SHA256`\n- Signs it with HMAC-SHA256 + Base64\n- Upserts `X-API-Key`, `X-Timestamp`, `X-Nonce`, `X-Signature: v1=<sig>` headers\n\nYou should not need to touch the script for normal QA usage — just run a request.\n\n**Ordered happy-path**\n\n1. `Test / GET /v1/test/ping` — confirms connectivity + signing.\n2. `Test / POST /v1/test/post` — confirms body hashing.\n3. `Checkout Intent / Create — fiat` (or `Create — native stable-coin`) — creates an intent and auto-captures `checkout_intent_id` into the environment.\n4. `Checkout Intent / GET /v1/checkout_intents/{id}/status` — polls status.\n5. `Checkout Intent / GET /v1/checkout_intents/{id}` — full payload.\n\n**Pricing modes on Create** (pick exactly one per request):\n\n- `currency` (fiat IntEnum, Appendix A) → server FX-converts to the resolved settlement coin (USDT or USDC); use `accepted_stable_coins` to pick which.\n- `stable_coin` (IntEnum, Appendix B) → `1` (USDT) and `2` (USDC) are accepted; amount is stable-coin cents, no FX.\n\nSending both, or neither, returns `10001`.\n\n**Settlement:** USDT or USDC. `stable_coin_type` in the response matches the resolved coin (defaults to `1` USDT when neither `stable_coin` nor `accepted_stable_coins` is set).\n\n**Error codes** (from the server's unified envelope):\n\n| Code  | Meaning |\n|-------|---------|\n| 0     | Success |\n| 10001 | Validation error |\n| 20001 | Missing auth headers |\n| 20002 | Bad signature |\n| 30001 | Forbidden (IP / ownership) |\n| 40001 | Rate limit exceeded |\n| 50001 | Checkout intent not found |\n| 50002 | Create checkout intent error (e.g. amount at or below the 0.1-coin floor) |\n| 90000 | Internal server error |\n",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "noauth"
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// AllScale HMAC-SHA256 request signing.",
          "// See docs/openapi/docs/API Doc - Auth.md for the canonical-string format.",
          "",
          "const apiKey = pm.environment.get('api_key') || pm.collectionVariables.get('api_key') || '';",
          "const apiSecret = (pm.environment.get('api_secret') || pm.collectionVariables.get('api_secret') || '').trim();",
          "",
          "if (!apiKey || !apiSecret) {",
          "    console.warn('[AllScale] api_key or api_secret is empty — requests will be rejected (20001/20002).');",
          "}",
          "",
          "// Method",
          "const method = (pm.request.method || 'GET').toUpperCase();",
          "",
          "// Path — resolve {{var}} placeholders and :path params via pm.variables.replaceIn.",
          "const urlObj = pm.request.url;",
          "const rawPathSegments = (urlObj.path || []).map(function (seg) {",
          "    return pm.variables.replaceIn(String(seg));",
          "});",
          "let path = '/' + rawPathSegments.join('/');",
          "// Postman treats a trailing slash in the URL as an empty segment; keep it so the canonical path",
          "// matches what Starlette sees on the server (e.g. /v1/checkout_intents/).",
          "",
          "// Query — use Postman's resolved query string so encoding matches what actually goes on the wire.",
          "let query = '';",
          "try {",
          "    query = urlObj.getQueryString({ ignoreDisabled: true }) || '';",
          "} catch (e) {",
          "    // Older Postman runtimes — fall back to manual build.",
          "    const parts = [];",
          "    (urlObj.query || []).each(function (q) {",
          "        if (q.disabled) return;",
          "        const k = pm.variables.replaceIn(q.key || '');",
          "        const v = pm.variables.replaceIn(q.value || '');",
          "        parts.push(k + '=' + v);",
          "    });",
          "    query = parts.join('&');",
          "}",
          "",
          "// Body — only raw JSON bodies are signed with content. Other modes sign an empty body.",
          "let body = '';",
          "if (pm.request.body && pm.request.body.mode === 'raw' && pm.request.body.raw) {",
          "    body = pm.variables.replaceIn(pm.request.body.raw);",
          "}",
          "",
          "// Canonical pieces",
          "const bodyHash = CryptoJS.SHA256(body).toString(CryptoJS.enc.Hex);",
          "const timestamp = Math.floor(Date.now() / 1000).toString();",
          "",
          "function uuidv4() {",
          "    if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {",
          "        return crypto.randomUUID();",
          "    }",
          "    // RFC 4122 v4 fallback",
          "    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {",
          "        const r = Math.random() * 16 | 0;",
          "        const v = c === 'x' ? r : (r & 0x3 | 0x8);",
          "        return v.toString(16);",
          "    });",
          "}",
          "const nonce = uuidv4();",
          "",
          "const canonical = [method, path, query, timestamp, nonce, bodyHash].join('\\n');",
          "const signature = CryptoJS.HmacSHA256(canonical, apiSecret).toString(CryptoJS.enc.Base64);",
          "",
          "pm.request.headers.upsert({ key: 'X-API-Key', value: apiKey });",
          "pm.request.headers.upsert({ key: 'X-Timestamp', value: timestamp });",
          "pm.request.headers.upsert({ key: 'X-Nonce', value: nonce });",
          "pm.request.headers.upsert({ key: 'X-Signature', value: 'v1=' + signature });",
          "",
          "// Uncomment for debugging:",
          "// console.log('[AllScale canonical]\\n' + canonical);",
          "// console.log('[AllScale signature] v1=' + signature);",
          ""
        ]
      }
    },
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Collection-wide sanity checks.",
          "pm.test('Response is JSON', function () {",
          "    pm.response.to.be.withBody;",
          "    pm.response.to.be.json;",
          "});",
          "",
          "pm.test('Envelope has `code` and `request_id`', function () {",
          "    const body = pm.response.json();",
          "    pm.expect(body).to.have.property('code');",
          "    pm.expect(body).to.have.property('request_id');",
          "});",
          ""
        ]
      }
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "{{base_url}}",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Test",
      "description": "Smoke-test endpoints. Run these first to validate credentials, signing, and body hashing before touching real payment flows.",
      "item": [
        {
          "name": "GET /v1/test/ping",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/test/ping",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "test",
                "ping"
              ]
            },
            "description": "Health-check. Verifies that:\n\n- `api_key` / `api_secret` are valid\n- Your clock is in sync (±5 min window)\n- The signing pre-request script is producing a correct signature\n\nExpected: `{ \"code\": 0, \"payload\": { \"pong\": \"ok\" }, ... }`"
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('code == 0', function () {",
                  "    pm.expect(pm.response.json().code).to.eql(0);",
                  "});",
                  "pm.test('payload.pong == \"ok\"', function () {",
                  "    pm.expect(pm.response.json().payload.pong).to.eql('ok');",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "GET /v1/test/fail",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/test/fail",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "test",
                "fail"
              ]
            },
            "description": "Always returns `10001 Validation error`. Use it to verify your error-handling branch parses the envelope correctly."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('code == 10001 (validation error)', function () {",
                  "    pm.expect(pm.response.json().code).to.eql(10001);",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "POST /v1/test/post",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"everything\": \"is_fine\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/test/post",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "test",
                "post"
              ]
            },
            "description": "Echo endpoint. Verifies body-hash signing — if this passes but real endpoints return `20002`, the client almost certainly isn't hashing the body the same way the server does.\n\nThe server echoes the body back under `payload.your_request_body`."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test('code == 0', function () {",
                  "    pm.expect(pm.response.json().code).to.eql(0);",
                  "});",
                  "pm.test('body was echoed', function () {",
                  "    pm.expect(pm.response.json().payload.your_request_body.everything).to.eql('is_fine');",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "Checkout Intent",
      "description": "End-to-end checkout-intent lifecycle. Create → poll status → fetch full detail. `Create` captures the returned intent id into the `checkout_intent_id` environment variable so the two GETs work without manual copy-paste.\n\n**Two create flavors** (pick exactly one on each request):\n\n- **Fiat pricing** — send `currency` (IntEnum, Appendix A). The server FX-converts to the resolved settlement coin (USDT or USDC) at the current rate; `currency_rate` in the response is non-null. Use `accepted_stable_coins` (first entry wins) to pick the settlement coin; defaults to USDT.\n- **Native stable-coin pricing** — send `stable_coin` (IntEnum, Appendix B). `amount_cents` is stable-coin cents (`1000` = `10.00` of the chosen coin). No FX happens, so `currency_rate` in the response is `null`. Both `stable_coin = 1` (USDT) and `stable_coin = 2` (USDC) are accepted.\n\nSending both — or neither — of `currency`/`stable_coin` returns `10001`.",
      "item": [
        {
          "name": "POST /v1/checkout_intents/  (Create — fiat)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"currency\": 1,\n  \"amount_cents\": 100,\n  \"order_id\": \"qa_order_{{$timestamp}}\",\n  \"order_description\": \"QA test order\",\n  \"user_id\": \"qa_user_001\",\n  \"user_name\": \"QA Tester\",\n  \"redirect_url\": \"https://example.com/checkout/allscale\",\n  \"extra\": {\n    \"source\": \"postman\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/checkout_intents/",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "checkout_intents",
                ""
              ]
            },
            "description": "Create a checkout intent priced in fiat. Server FX-converts the amount into the resolved settlement coin (USDT or USDC) at the current rate.\n\n**Field notes**\n\n- `currency` is the fiat IntEnum (1 = USD, 44 = EUR, …). Full table in `API Doc - Checkout Intent Routes - Create Checkout Intent.md` → Appendix A.\n- `amount_cents` is integer **fiat** cents. The resulting stable-coin amount must be greater than `0.1` (USDT or USDC); orders at or below the floor are rejected with `50002`.\n- Do **not** also send `stable_coin` on this request — sending both returns `10001`.\n- `redirect_url` must be `https://…` in production; sandbox also allows `http://`.\n- Settlement coin is **USDT or USDC**. To pin it on a fiat-priced order, send `accepted_stable_coins: [1]` (USDT) or `[2]` (USDC); the first entry picks the settlement coin used for FX conversion. `stable_coin_type` in the response matches whichever was resolved (defaults to `1` USDT).\n\nThe post-response test captures `payload.allscale_checkout_intent_id` into `{{checkout_intent_id}}` for the follow-up GETs."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('code == 0', function () {",
                  "    pm.expect(body.code).to.eql(0);",
                  "});",
                  "pm.test('payload.allscale_checkout_intent_id exists', function () {",
                  "    pm.expect(body.payload).to.have.property('allscale_checkout_intent_id');",
                  "    pm.expect(body.payload.allscale_checkout_intent_id).to.be.a('string');",
                  "});",
                  "",
                  "if (body && body.payload && body.payload.allscale_checkout_intent_id) {",
                  "    pm.environment.set('checkout_intent_id', body.payload.allscale_checkout_intent_id);",
                  "    console.log('[AllScale] captured checkout_intent_id = ' + body.payload.allscale_checkout_intent_id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "POST /v1/checkout_intents/  (Create — native stable-coin)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"stable_coin\": 1,\n  \"amount_cents\": 1000,\n  \"order_id\": \"qa_stable_{{$timestamp}}\",\n  \"order_description\": \"QA native USDT order\",\n  \"user_id\": \"qa_user_001\",\n  \"user_name\": \"QA Tester\",\n  \"redirect_url\": \"https://example.com/checkout/allscale\",\n  \"extra\": {\n    \"source\": \"postman\",\n    \"pricing\": \"native_stable_coin\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/checkout_intents/",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "checkout_intents",
                ""
              ]
            },
            "description": "Create a checkout intent priced **natively in a stable coin** — no FX happens.\n\n**Field notes**\n\n- `stable_coin` is the StableCoin IntEnum (see Appendix B). Both `1` (USDT) and `2` (USDC) are accepted; other values are reserved and will be rejected.\n- `amount_cents` is **stable-coin cents** of the chosen `stable_coin`: `1000` = `10.00` of that coin. The example above (`stable_coin: 1`) produces a `10 USDT` order; switch to `stable_coin: 2` for the equivalent USDC order.\n- Do **not** also send `currency` — sending both, or neither, returns `10001`.\n- The response's `currency_rate` will be `null` (no FX). In the full GET, the fiat fields (`currency`, `currency_symbol`, `amount_cents`, `currency_rate`) will all be `null`; the authoritative amount is `amount_coins`.\n\nThe post-response test captures `payload.allscale_checkout_intent_id` into `{{checkout_intent_id}}` just like the fiat flavor."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('code == 0', function () {",
                  "    pm.expect(body.code).to.eql(0);",
                  "});",
                  "pm.test('payload.allscale_checkout_intent_id exists', function () {",
                  "    pm.expect(body.payload).to.have.property('allscale_checkout_intent_id');",
                  "});",
                  "pm.test('rate is null for native stable-coin pricing', function () {",
                  "    pm.expect(body.payload.rate).to.be.oneOf([null, undefined]);",
                  "});",
                  "",
                  "if (body && body.payload && body.payload.allscale_checkout_intent_id) {",
                  "    pm.environment.set('checkout_intent_id', body.payload.allscale_checkout_intent_id);",
                  "    console.log('[AllScale] captured checkout_intent_id = ' + body.payload.allscale_checkout_intent_id);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "GET /v1/checkout_intents/{id}/status",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/checkout_intents/{{checkout_intent_id}}/status",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "checkout_intents",
                "{{checkout_intent_id}}",
                "status"
              ]
            },
            "description": "Poll-friendly lightweight status check. `payload` is the status integer (see status enum in the doc).\n\nUse this instead of the full GET when all you need is the lifecycle state."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('code == 0', function () {",
                  "    pm.expect(body.code).to.eql(0);",
                  "});",
                  "pm.test('payload is integer status', function () {",
                  "    pm.expect(body.payload).to.be.a('number');",
                  "});"
                ]
              }
            }
          ]
        },
        {
          "name": "GET /v1/checkout_intents/{id}",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/checkout_intents/{{checkout_intent_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "checkout_intents",
                "{{checkout_intent_id}}"
              ]
            },
            "description": "Full checkout intent object — order metadata, currency/coin fields, on-chain tx hashes when payment has settled. Ownership is enforced: the intent must belong to the store identified by `api_key`, otherwise `30001 Forbidden`."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('code == 0', function () {",
                  "    pm.expect(body.code).to.eql(0);",
                  "});",
                  "pm.test('payload has core fields', function () {",
                  "    const p = body.payload;",
                  "    pm.expect(p).to.have.property('all_scale_checkout_intent_id');",
                  "    pm.expect(p).to.have.property('currency');",
                  "    pm.expect(p).to.have.property('amount_cents');",
                  "    pm.expect(p).to.have.property('status');",
                  "    pm.expect(p).to.have.property('tx_to');",
                  "});"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "Claim Link",
      "item": [
        {
          "name": "POST /v1/claim_link_auto_payouts  (Create + Auto-Payout)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": \"10.50\",\n  \"stable_coin\": 1,\n  \"chain\": 5,\n  \"receiver_email\": \"recipient@example.com\",\n  \"sender_display_name\": \"Acme Payouts\",\n  \"sender_message\": \"Your July payout\",\n  \"reference_id\": \"payout_2026_07_0001\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{base_url}}/v1/claim_link_auto_payouts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "claim_link_auto_payouts"
              ]
            },
            "description": "Create a single claim link and auto-fund it from the merchant's custodied wallet. Requires the claim_link:auto_payout scope, a non-sandbox key, and CLAIM_LINK_LIVE_SIGNING_ENABLED. See 'API Doc - Claim Link Routes - Create Auto-Payout.md'."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('code == 0', function () {",
                  "    pm.expect(body.code).to.eql(0);",
                  "});",
                  "pm.test('payload.claim_link_id exists', function () {",
                  "    pm.expect(body.payload).to.have.property('claim_link_id');",
                  "    pm.expect(body.payload.claim_link_id).to.be.a('string');",
                  "});",
                  "pm.test('payload.status is a string', function () {",
                  "    pm.expect(body.payload).to.have.property('status');",
                  "    pm.expect(body.payload.status).to.be.a('string');",
                  "});",
                  "pm.test('payload.idempotent_hit is a boolean', function () {",
                  "    pm.expect(body.payload).to.have.property('idempotent_hit');",
                  "    pm.expect(body.payload.idempotent_hit).to.be.a('boolean');",
                  "});",
                  "",
                  "if (body && body.payload) {",
                  "    if (body.payload.claim_link_id) {",
                  "        pm.environment.set('claim_link_id', body.payload.claim_link_id);",
                  "        console.log('[AllScale] captured claim_link_id = ' + body.payload.claim_link_id);",
                  "    }",
                  "    // The bearer token is returned ONCE on a fresh create (null on an idempotent replay).",
                  "    if (body.payload.token) {",
                  "        pm.environment.set('claim_link_token', body.payload.token);",
                  "        console.log('[AllScale] captured claim_link_token (bearer, treat as secret)');",
                  "    }",
                  "}"
                ]
              }
            }
          ],
          "response": []
        },
        {
          "name": "POST /v1/claim_link_auto_payouts/{id}/cancel  (Cancel / Claim-Back)",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/claim_link_auto_payouts/{{claim_link_id}}/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "claim_link_auto_payouts",
                "{{claim_link_id}}",
                "cancel"
              ]
            },
            "description": "Cancel (claim back) one of your own FUNDED, UNCLAIMED claim links. No request body. Flips the link to 'cancelled' and schedules the refund off the request path; the 'cancelled' webhook fires once the refund settles on-chain. Requires the claim_link:auto_payout scope and a non-sandbox key; NOT gated by CLAIM_LINK_LIVE_SIGNING_ENABLED. 50107 = unknown/non-owned/malformed id, 50108 = not cancellable (pending_deposit / claiming / terminal / batch). Uses {{claim_link_id}} captured by the Create request. See 'API Doc - Claim Link Routes - Cancel Auto-Payout.md'."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.json();",
                  "pm.test('code == 0', function () {",
                  "    pm.expect(body.code).to.eql(0);",
                  "});",
                  "pm.test(\"payload.status == 'cancelled'\", function () {",
                  "    pm.expect(body.payload).to.have.property('status');",
                  "    pm.expect(body.payload.status).to.eql('cancelled');",
                  "});",
                  "pm.test(\"payload.refund_status == 'refund_pending'\", function () {",
                  "    pm.expect(body.payload).to.have.property('refund_status');",
                  "    pm.expect(body.payload.refund_status).to.eql('refund_pending');",
                  "});",
                  "// The refund settles OFF the request path — wait for the 'cancelled' webhook",
                  "// (refund_tx_hash) rather than treating this 200 as 'money is back'."
                ]
              }
            }
          ],
          "response": []
        }
      ],
      "description": "Merchant claim-link create endpoint (auto-payout). Flag-gated + scoped; see the Claim Link Auto-Payout API doc. (Batch endpoint docs land with the batch launch.)"
    }
  ]
}
```
