{
  "version": "1.0",
  "service": {
    "name": "Cryptorefills Gift Card Store",
    "description": "Buy gift cards, mobile top-ups, and digital products with USDC on Base. 10,001+ brands across 180 countries.",
    "url": "https://x402.cryptorefills.com"
  },
  "payment": {
    "protocol": "x402",
    "scheme": "exact",
    "network": "eip155:8453",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bDA02913",
    "assetSymbol": "USDC",
    "assetDecimals": 6,
    "note": "Prices are set by the product. Amount is returned in PAYMENT-REQUIRED header on first POST /v1/orders call."
  },
  "flow": [
    "1. GET /v1/brands?country_code=us — discover brand names available in a country.",
    "2. GET /v1/catalog?country_code=us&brand_name=<brand_name> — get product_id values and pricing for that brand.",
    "3. POST /v1/orders (no payment header) — server responds 402 with PAYMENT-REQUIRED header containing the USDC amount and destination wallet.",
    "4. Sign a USDC EIP-3009 transferWithAuthorization for the amount/wallet in PAYMENT-REQUIRED. Encode as base64url JSON matching the AcceptedPayment schema.",
    "5. Re-POST /v1/orders with the PAYMENT-SIGNATURE header — server verifies, settles on-chain, and returns 200 with order receipt.",
    "6. Poll GET /v1/orders/{order_id} until status is 'completed'. Voucher codes appear in deliveries[]."
  ],
  "endpoints": {
    "brands": {
      "method": "GET",
      "path": "/v1/brands",
      "description": "Discover all brands available in a country. Use this first to get brand_name values for the catalog endpoint.",
      "parameters": {
        "country_code": { "type": "string", "required": true, "example": "us", "note": "Lowercase ISO 3166-1 alpha-2 country code." }
      },
      "response_fields": {
        "brand_name": "Use this value as brand_name in /v1/catalog.",
        "family":     "Product family (e.g. Gift Cards, Mobile Recharge).",
        "category":   "Product category (e.g. Gaming, Entertainment).",
        "min":        "Minimum denomination available (informational).",
        "max":        "Maximum denomination available (informational)."
      }
    },
    "catalog": {
      "method": "GET",
      "path": "/v1/catalog",
      "description": "Get available denominations and product_id values for a specific brand. Use brand_name values from /v1/brands.",
      "parameters": {
        "country_code": { "type": "string", "required": true, "example": "us", "note": "Lowercase ISO 3166-1 alpha-2 country code." },
        "brand_name":   { "type": "string", "required": false, "example": "Amazon.com", "note": "Brand name from /v1/brands. At least one of brand_name or family_name is required." },
        "family_name":  { "type": "string", "required": false, "example": "Gaming", "note": "Filter by product family from /v1/brands response." }
      },
      "response_fields": {
        "product_id":         "Use this value in items[].product_id when placing an order.",
        "product_name":       "Human-readable product name, including denomination (e.g. 'Free Fire Gift Card 100 Diamonds').",
        "brand_name":         "Brand for this product.",
        "is_range":           "Boolean. true = range product (caller picks USD amount via product_value). false = fixed denomination.",
        "denomination":       "Upstream descriptive denomination when available (e.g. '100 Diamonds'). Absent for generic currency-only products.",
        "denomination_label": "Short human-readable tag that is unique per row of the same brand ('100 Diamonds', '$25', '$5 – $500').",
        "face_value_usd":     "Fixed USD face value. Present only when is_range is false.",
        "currency":           "Face-value currency (typically 'USD').",
        "min_value":          "Minimum USD amount for range products. Present only when is_range is true.",
        "max_value":          "Maximum USD amount for range products. Present only when is_range is true.",
        "price_usdc":         "Indicative USDC price for fixed products; 'variable' for range products. Final amount is confirmed in PAYMENT-REQUIRED.",
        "country_code":       "ISO country code for this product.",
        "type":               "Product family (e.g. 'Free Fire', 'Amazon.com').",
        "product_value_required": "Set items[].product_value when is_range is true; omit otherwise."
      }
    },
    "createOrder": {
      "method": "POST",
      "path": "/v1/orders",
      "description": "Two-phase endpoint. First call (no PAYMENT-SIGNATURE) returns 402. Second call (with PAYMENT-SIGNATURE) returns 200.",
      "request_body": {
        "email":        { "type": "string", "required": true, "description": "Contact email for the order." },
        "items":        { "type": "array",  "required": true, "description": "List of products to purchase.", "item_fields": {
          "product_id":          { "type": "string", "required": true,  "description": "From catalog product_id." },
          "beneficiary_account": { "type": "string", "required": true,  "description": "Email or account to receive the voucher." },
          "product_value":       { "type": "number", "required": false, "description": "Required for range products. USD amount to load." }
        }},
        "callback_url": { "type": "string", "required": false, "description": "Webhook URL for order state change notifications." }
      },
      "phase1_response": {
        "status": 402,
        "header": "PAYMENT-REQUIRED",
        "header_format": "base64url-encoded JSON",
        "decoded_schema": {
          "x402Version": "integer",
          "accepts": [{
            "scheme": "exact",
            "network": "eip155:8453",
            "maxAmountRequired": "USDC amount in atomic units (6 decimals)",
            "asset": "USDC contract address on Base",
            "extra": { "name": "USD Coin", "version": "2", "decimals": 6, "_note": "name and version are the USDC EIP-712 domain fields the facilitator uses to reconstruct the signed digest." },
            "payTo": "Destination wallet address for this order session",
            "description": "Human-readable amount and product description"
          }],
          "resource": "POST /v1/orders"
        }
      },
      "phase2_request_header": {
        "name": "PAYMENT-SIGNATURE",
        "format": "base64url-encoded JSON",
        "schema": {
          "x402Version": 2,
          "scheme": "exact",
          "network": "eip155:8453",
          "payload": {
            "signature": "EIP-712 signature hex string",
            "authorization": {
              "from":        "Payer wallet address",
              "to":          "payTo address from PAYMENT-REQUIRED",
              "value":       "maxAmountRequired from PAYMENT-REQUIRED",
              "validAfter":  "Unix timestamp (seconds) — use 0",
              "validBefore": "Unix timestamp (seconds) — order expiry",
              "nonce":       "32-byte random hex"
            }
          }
        }
      },
      "phase2_response": {
        "status": 200,
        "fields": {
          "order_id":                   "CryptoRefills order ID.",
          "status":                     "processing | completed | failed | expired",
          "email":                      "Order contact email.",
          "estimated_delivery_seconds": "Typical delivery time. Poll until completed.",
          "poll_url":                   "GET path to check order status.",
          "deliveries":                 "Array of delivery items (may be empty initially — poll for codes)."
        }
      }
    },
    "getOrder": {
      "method": "GET",
      "path": "/v1/orders/{order_id}",
      "description": "Poll for order status and voucher delivery. Poll every 5–10 seconds until status = 'completed' or 'failed'. Voucher fields appear inside deliveries[] once delivery_state = 'completed'.",
      "response_fields": {
        "order_id":    "Order identifier.",
        "status":      "processing | completed | failed | expired",
        "deliveries":  "Array of delivered items. Each item is populated only after CryptoRefills provisions the code; empty/pending items will fill in on subsequent polls.",
        "delivery_fields": {
          "id":                  "Delivery identifier.",
          "delivery_state":      "pending | completed | failed",
          "brand_name":          "Product brand.",
          "product_name":        "Product name (often includes denomination, e.g. '100 Diamonds').",
          "denomination":        "Denomination descriptor when available (e.g. '100 Diamonds', '$25').",
          "face_value":          "Face value amount as a string.",
          "currency":            "Face value currency code (typically 'USD').",
          "voucher_code":        "Redemption code / PIN. Primary field for redemption.",
          "pin_serial":          "Serial number accompanying the voucher code (if issued).",
          "security_code":       "Extra activation code (if issued).",
          "redeem_instructions": "HTML instructions from the brand for redeeming the code.",
          "terms_and_conditions": "Brand terms & conditions, when provided.",
          "url":                 "Redemption URL — falls back to barcode_image_url, qr_image_url, or a URL parsed out of redeem_instructions.",
          "barcode_image_url":   "Barcode image URL, when applicable.",
          "qr_image_url":        "QR image URL, when applicable.",
          "beneficiary_account": "Email or account the voucher was sent to (confirms delivery target).",
          "country_code":        "ISO country code for the voucher.",
          "delivery_type":       "by_email | by_sms | inline",
          "failure_reason":      "Populated when delivery_state = 'failed'."
        }
      }
    }
  }
}
