{
  "openapi": "3.1.0",
  "info": {
    "title": "XL Pay public payments API",
    "version": "1.0.0",
    "description": "Pay a business on XL Pay, or anyone with a crypto domain (.crypto, .nft, .x, .wallet, .bitcoin, .eth and more), in stablecoins or crypto. Built for people and AI agents. XL Pay is non-custodial: every payment goes straight from the payer's wallet to the payee's wallet, and XL Pay never holds funds or keys. Flow: (1) GET who you're paying and which coins they accept, (2) POST action=sale to get the exact address and amount, (3) send exactly that amount from your wallet, (4) POST action=check until status is paid. Amounts are unique per sale, so send the exact amount returned; for XRP also set the destination tag. Agents that speak x402 can instead call /api/x402/pay: one request returns HTTP 402 with USDC payment options, and a retry with a PAYMENT-SIGNATURE header pays and returns the receipt.",
    "contact": {
      "name": "Xperience Levels",
      "email": "info@xperiencelevels.com",
      "url": "https://xperiencelevels.com/to"
    }
  },
  "servers": [
    {
      "url": "https://xperiencelevels.com"
    }
  ],
  "paths": {
    "/api/xlpay/pay": {
      "get": {
        "operationId": "lookupPayee",
        "summary": "Look up who you're paying and which coins they accept",
        "parameters": [
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "An XL Pay business code (e.g. living-room-wine) or a crypto domain (e.g. xperiencelevels.crypto, name.eth)."
          },
          {
            "name": "l",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Signed pay-link token from a fixed-price XL Pay link (the l= value in /to/<code>?l=...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Payee found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "enum": [
                        "business",
                        "domain"
                      ]
                    },
                    "name": {
                      "type": "string"
                    },
                    "rails": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Rail"
                      }
                    },
                    "fixed": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "amount": {
                          "type": "number"
                        },
                        "note": {
                          "type": "string"
                        }
                      },
                      "description": "Set when the pay link has a fixed USD price; your amount is ignored."
                    },
                    "addresses": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "For crypto domains: the public addresses the domain points to."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No business with that code, or the domain has no payment addresses"
          }
        }
      },
      "post": {
        "operationId": "payment",
        "summary": "Open a payment (action=sale), check it (action=check), or email a receipt (action=receipt, businesses only)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "action",
                      "to",
                      "rail",
                      "amount"
                    ],
                    "properties": {
                      "action": {
                        "const": "sale"
                      },
                      "to": {
                        "type": "string",
                        "description": "Same value as the lookup's to."
                      },
                      "l": {
                        "type": "string",
                        "description": "Signed pay-link token, if any."
                      },
                      "rail": {
                        "$ref": "#/components/schemas/RailId"
                      },
                      "amount": {
                        "type": "number",
                        "minimum": 0.5,
                        "maximum": 25000,
                        "description": "Amount in US dollars. Crypto rails are priced at the live rate and locked for 15 minutes."
                      },
                      "note": {
                        "type": "string",
                        "maxLength": 80
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "action",
                      "token"
                    ],
                    "properties": {
                      "action": {
                        "const": "check"
                      },
                      "token": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "action",
                      "token",
                      "email"
                    ],
                    "properties": {
                      "action": {
                        "const": "receipt"
                      },
                      "token": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string",
                        "format": "email"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "For action=sale: what to send. For action=check: the payment status.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Sale"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "paid",
                            "invalid"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "explorer": {
                          "type": "string",
                          "description": "Block explorer link once paid."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Unsupported coin or amount out of range"
          },
          "410": {
            "description": "The payment token expired; open a new sale"
          },
          "429": {
            "description": "Rate limited (30 sales per minute per IP)"
          }
        }
      }
    },
    "/api/x402/pay": {
      "get": {
        "operationId": "x402Pay",
        "summary": "Pay a business or crypto domain with x402 (v2)",
        "description": "Without a payment header: HTTP 402 with a base64 PAYMENT-REQUIRED header (the same JSON is in the body) listing USDC 'exact' options on Base (eip155:8453), Polygon (eip155:137) and Arbitrum (eip155:42161), paid straight to the payee's wallet. Retry the same URL with a PAYMENT-SIGNATURE header (base64 x402 v2 PaymentPayload with an EIP-3009 authorization) and the payment is verified and settled through an x402 facilitator. POST works the same way.",
        "parameters": [
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "XL Pay business code or crypto domain."
          },
          {
            "name": "amount",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "minimum": 0.01,
              "maximum": 25000
            },
            "description": "US dollars (USDC, 1:1). Ignored for fixed-price pay links."
          },
          {
            "name": "note",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "l",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Signed pay-link token."
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Base64 x402 v2 PaymentPayload."
          }
        ],
        "responses": {
          "200": {
            "description": "Paid. Body: {paid, payee, usd, unit, network, transaction, payer, explorer}. PAYMENT-RESPONSE header carries the facilitator's settlement response."
          },
          "402": {
            "description": "Payment required, or the payment was not valid (see error)."
          },
          "404": {
            "description": "Unknown payee"
          },
          "409": {
            "description": "Payee doesn't take USDC on Base, Polygon or Arbitrum; use /api/xlpay/pay"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "RailId": {
        "type": "string",
        "enum": [
          "solana",
          "base",
          "ethereum",
          "arbitrum",
          "polygon",
          "sui",
          "stellar",
          "solana_pyusd",
          "ethereum_pyusd",
          "arbitrum_pyusd",
          "sol",
          "eth",
          "eth_base",
          "btc",
          "xrp"
        ],
        "description": "Coin and network. solana/base/ethereum/arbitrum/polygon/sui/stellar = USDC on that network; *_pyusd = PYUSD; sol, eth (Ethereum), eth_base (ETH on Base), btc, xrp = native coins at the live rate."
      },
      "Rail": {
        "type": "object",
        "properties": {
          "id": {
            "$ref": "#/components/schemas/RailId"
          },
          "label": {
            "type": "string"
          },
          "asset": {
            "type": "string"
          },
          "network": {
            "type": "string"
          },
          "group": {
            "type": "string",
            "enum": [
              "stable",
              "coin"
            ]
          },
          "speed": {
            "type": "string"
          }
        }
      },
      "Sale": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Pass to action=check. Valid for 24 hours."
          },
          "to": {
            "type": "string",
            "description": "Receiving address. Send here."
          },
          "amount": {
            "type": "string",
            "description": "Exact amount of unit to send. It is unique to this sale; do not round."
          },
          "unit": {
            "type": "string",
            "description": "Asset to send, e.g. USDC, PYUSD, SOL, ETH, BTC, XRP."
          },
          "network": {
            "type": "string"
          },
          "tag": {
            "type": [
              "integer",
              "null"
            ],
            "description": "XRP destination tag. Required for XRP."
          },
          "uri": {
            "type": "string",
            "description": "Wallet payment URI (EIP-681, Solana Pay, SEP-7, BIP21 or XRP X-address) with the same details."
          },
          "total": {
            "type": "number",
            "description": "US dollar total."
          },
          "expires": {
            "type": "integer",
            "description": "Unix ms. Crypto prices are locked until then; send before it."
          }
        }
      }
    }
  }
}
