{
  "info": {
    "name": "BitBooth No-Spend Starter",
    "description": "Run a free echo call, then inspect a real PageDelta x402 v2 challenge. The second request does not sign, submit, or pay anything. XRPL is selected only as the preferred offer to inspect. Paid execution stays manual and disabled until the XRPL Testnet demo is available.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_exporter_id": "bitbooth"
  },
  "auth": {
    "type": "noauth"
  },
  "item": [
    {
      "name": "1. Free echo — expect 200",
      "request": {
        "auth": {
          "type": "noauth"
        },
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{BITBOOTH_BASE}}/v1/free/echo",
          "host": [
            "{{BITBOOTH_BASE}}"
          ],
          "path": [
            "v1",
            "free",
            "echo"
          ]
        },
        "body": {
          "mode": "raw",
          "raw": "{\n  \"message\": \"{{ECHO_MESSAGE}}\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "description": "A real, free, rate-limited request. Send it and open Postman's Visualize tab to see the returned value. No account, wallet, API key, or payment is used."
      },
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "const body = pm.response.json();",
              "pm.test('Free echo returns HTTP 200', () => pm.response.to.have.status(200));",
              "pm.test('Free echo returns the submitted message', () => {",
              "  pm.expect(body).to.include({ ok: true, paid: false });",
              "  pm.expect(body.service).to.equal('BitBooth /v1/free/echo (free demo)');",
              "  pm.expect(body.youSent).to.equal(pm.collectionVariables.get('ECHO_MESSAGE'));",
              "  pm.expect(body.rateLimit).to.be.an('object');",
              "});",
              "pm.collectionVariables.set('LAST_FREE_ECHO_JSON', JSON.stringify(body, null, 2));",
              "pm.visualizer.set('<h2>BitBooth free echo: HTTP {{status}}</h2><p><strong>You sent:</strong> {{youSent}}</p><pre>{{json}}</pre>', { status: pm.response.code, youSent: body.youSent, json: JSON.stringify(body, null, 2) });"
            ]
          }
        }
      ]
    },
    {
      "name": "2. PageDelta challenge — expect 402, no payment",
      "request": {
        "auth": {
          "type": "noauth"
        },
        "method": "POST",
        "header": [
          {
            "key": "content-type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{BITBOOTH_BASE}}/v1/cdp/render-pro",
          "host": [
            "{{BITBOOTH_BASE}}"
          ],
          "path": [
            "v1",
            "cdp",
            "render-pro"
          ]
        },
        "body": {
          "mode": "raw",
          "raw": "{\n  \"url\": \"{{PAGEDELTA_URL}}\",\n  \"extract\": \"{{PAGEDELTA_EXTRACT}}\",\n  \"focus\": \"{{PAGEDELTA_FOCUS}}\"\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "description": "A safe, unpaid probe of PageDelta. It must return HTTP 402 with the same x402 v2 document in the JSON body and base64 PAYMENT-REQUIRED header. The collection saves the challenge and preferred XRPL offer for inspection only. It has no payment request, signing code, wallet secret, or broadcast step."
      },
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('PageDelta returns HTTP 402', () => pm.response.to.have.status(402));",
              "const body = pm.response.json();",
              "const paymentRequired = pm.response.headers.get('PAYMENT-REQUIRED');",
              "pm.test('PAYMENT-REQUIRED header is present', () => pm.expect(paymentRequired).to.be.a('string').and.not.empty);",
              "pm.test('Challenge is x402 v2 for PageDelta', () => {",
              "  pm.expect(body.x402Version).to.equal(2);",
              "  pm.expect(body.resource).to.be.an('object');",
              "  pm.expect(body.resource.url).to.equal(pm.collectionVariables.get('BITBOOTH_BASE') + '/v1/cdp/render-pro');",
              "  pm.expect(body.accepts).to.be.an('array').and.not.empty;",
              "});",
              "const decoded = JSON.parse(atob(paymentRequired));",
              "pm.test('PAYMENT-REQUIRED decodes to the exact JSON body', () => pm.expect(decoded).to.deep.equal(body));",
              "const preferredNetwork = pm.collectionVariables.get('PREFERRED_NETWORK');",
              "const preferredOffer = body.accepts.find((offer) => offer.network === preferredNetwork);",
              "pm.test('Challenge includes the preferred XRPL offer', () => pm.expect(preferredOffer).to.be.an('object'));",
              "pm.test('No payment proof was attached', () => {",
              "  pm.expect(pm.request.headers.has('PAYMENT-SIGNATURE')).to.equal(false);",
              "  pm.expect(pm.request.headers.has('X-PAYMENT')).to.equal(false);",
              "});",
              "pm.collectionVariables.set('LAST_PAYMENT_REQUIRED', paymentRequired);",
              "pm.collectionVariables.set('LAST_X402_CHALLENGE_JSON', JSON.stringify(body, null, 2));",
              "pm.collectionVariables.set('LAST_PREFERRED_OFFER_JSON', JSON.stringify(preferredOffer, null, 2));",
              "pm.visualizer.set('<h2>PageDelta challenge verified</h2><p><strong>HTTP {{status}}. No payment was sent.</strong></p><p>Preferred offer: {{network}}</p><pre>{{offer}}</pre>', { status: pm.response.code, network: preferredNetwork, offer: JSON.stringify(preferredOffer, null, 2) });"
            ]
          }
        }
      ]
    }
  ],
  "variable": [
    {
      "key": "BITBOOTH_BASE",
      "value": "https://app.heinrichstech.com",
      "description": "BitBooth gateway base URL. Leave this unchanged for the public demo."
    },
    {
      "key": "ECHO_MESSAGE",
      "value": "hello from Postman",
      "description": "Text returned by the free echo request."
    },
    {
      "key": "PAGEDELTA_URL",
      "value": "https://example.com/",
      "description": "Public HTTP(S) URL bound into the unpaid PageDelta challenge."
    },
    {
      "key": "PAGEDELTA_EXTRACT",
      "value": "article",
      "description": "PageDelta extraction mode: article or raw."
    },
    {
      "key": "PAGEDELTA_FOCUS",
      "value": "Example Domain",
      "description": "Optional exact text PageDelta will locate after payment."
    },
    {
      "key": "PREFERRED_NETWORK",
      "value": "xrpl:0",
      "description": "XRPL is the default offer to inspect. This collection never signs or pays on mainnet."
    },
    {
      "key": "LAST_FREE_ECHO_JSON",
      "value": "",
      "description": "Most recent free echo response."
    },
    {
      "key": "LAST_PAYMENT_REQUIRED",
      "value": "",
      "description": "Most recent base64 x402 v2 challenge header. This is not a payment proof."
    },
    {
      "key": "LAST_X402_CHALLENGE_JSON",
      "value": "",
      "description": "Most recent decoded PageDelta challenge."
    },
    {
      "key": "LAST_PREFERRED_OFFER_JSON",
      "value": "",
      "description": "Most recent XRPL offer selected for inspection only."
    }
  ]
}