{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/depixapp-com/json-schema/depixapp-com-merchant-checkout-request-schema.json",
  "title": "MerchantCheckoutRequest",
  "description": "Public charge against a merchant storefront: the payer chooses the amount. Description, image and URLs are NOT accepted here — callback_url and redirect_url always come from the merchant's saved defaults. Rules differ per rail — see `payment_method`.",
  "x-generated": "2026-11-05",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/depixapp-com-openapi.yml#/components/schemas/MerchantCheckoutRequest",
  "type": "object",
  "required": [
    "amount"
  ],
  "properties": {
    "amount": {
      "type": "integer",
      "description": "Charge amount in cents (BRL). Range: 500–600000. When `items` is sent this MUST equal the sum of qty × the catalog price of every line, otherwise the request is rejected. On the depix rail this is the FACE amount, before the merchant's discount.",
      "minimum": 500,
      "maximum": 600000
    },
    "payment_method": {
      "$ref": "#/$defs/PaymentMethod",
      "default": "pix",
      "description": "Rail to charge on. Omit it (or send \"pix\") for the PIX QR flow. \"depix\" requires the merchant to have the direct DePix rail enabled, otherwise the request is rejected with 400 `depix_not_enabled`."
    },
    "expires_in": {
      "type": "integer",
      "description": "How long this checkout stays open, in seconds. pix rail: 300–1200, default 1200. depix rail: 300–3600, default 1800. On the pix rail it governs the checkout, not the PIX BR Code — the payment provider sets its own QR expiry.",
      "minimum": 300,
      "maximum": 3600
    },
    "expected_discount_pct": {
      "type": "integer",
      "description": "The DePix discount percentage the page showed the payer, 0–90. Send it on the depix rail to make a stale page fail loudly: if the merchant's current discount differs, the request is rejected with 409 `discount_changed` carrying the fresh values instead of charging a different price.",
      "minimum": 0,
      "maximum": 90
    },
    "payer_tax_number": {
      "type": "string",
      "description": "CPF/CNPJ of the payer. Required on the pix rail — omitting it returns 400 `validation_error` naming the field. Ignored on the depix rail."
    },
    "items": {
      "type": "array",
      "description": "Optional cart. Each line names one of the merchant's products by slug; names and unit prices are rebuilt server-side from the catalog and are never trusted from the request. At most 50 lines, no duplicate slugs. Omit it for a plain amount-only charge.",
      "maxItems": 50,
      "items": {
        "type": "object",
        "description": "One cart line.",
        "required": [
          "slug",
          "qty"
        ],
        "additionalProperties": false,
        "properties": {
          "slug": {
            "type": "string",
            "description": "Slug of an active, live product of this merchant."
          },
          "qty": {
            "type": "integer",
            "description": "Quantity for this line (1–9999).",
            "minimum": 1,
            "maximum": 9999
          }
        }
      }
    }
  },
  "allOf": [
    {
      "description": "Rail-conditional rules. On `depix`: expires_in accepts 300–3600 (default 1800) and no payer document is used. On `pix` (default): expires_in accepts 300–1200 (default 1200) and payer_tax_number is required.",
      "if": {
        "description": "Matches a body that explicitly selects the depix rail.",
        "properties": {
          "payment_method": {
            "const": "depix",
            "description": "The depix rail."
          }
        },
        "required": [
          "payment_method"
        ]
      },
      "then": {
        "description": "depix rail — wider lifetime window, no payer document.",
        "properties": {
          "expires_in": {
            "type": "integer",
            "description": "Payment-URI lifetime in seconds on the depix rail: 300–3600; default 1800.",
            "minimum": 300,
            "maximum": 3600
          }
        }
      },
      "else": {
        "description": "pix rail — the payer document is mandatory and `expires_in` caps at 20 minutes.",
        "required": [
          "payer_tax_number"
        ],
        "properties": {
          "expires_in": {
            "type": "integer",
            "description": "How long THIS CHECKOUT stays open, in seconds, on the pix rail: 300–1200; default 1200. It governs the checkout, not the PIX BR Code: the payment provider is not sent an expiry and applies its own, which can be longer. Treat a paid-after-expiry PIX as possible and reconcile from the deposit.* webhooks.",
            "minimum": 300,
            "maximum": 1200
          }
        }
      }
    }
  ],
  "$defs": {
    "PaymentMethod": {
      "type": "string",
      "enum": [
        "pix",
        "depix"
      ],
      "description": "Which rail settles the checkout. `pix` (default): the payer pays a PIX QR and the provider delivers DePix to the merchant. `depix`: the payer sends DePix wallet-to-wallet on Liquid to an address dedicated to this merchant, and settlement is observed on-chain — no PIX QR exists on this rail."
    }
  }
}