{
  "openapi": "3.1.0",
  "info": {
    "title": "UFO VPN Agent API",
    "version": "1.0.0",
    "description": "Anonymous, machine-friendly VPN purchase API. No email, no personal data: POST an order, pay the returned Bitcoin address on-chain, then poll the order until the VPN config is returned. The 20-digit account number in the order response is the only credential — store it.",
    "contact": {
      "email": "hello@ufovpn.app"
    }
  },
  "servers": [
    {
      "url": "https://www.ufovpn.xyz"
    }
  ],
  "paths": {
    "/api/public/v1/plans": {
      "get": {
        "operationId": "listPlans",
        "summary": "List purchasable plans and their USD prices.",
        "responses": {
          "200": {
            "description": "Plan catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanList"
                }
              }
            }
          }
        }
      }
    },
    "/api/public/v1/orders": {
      "post": {
        "operationId": "createOrder",
        "summary": "Create an anonymous account and a Bitcoin invoice for a plan.",
        "description": "Returns the account number (store it — it cannot be recovered), an order token used to poll status, and the exact on-chain amount to send before `payment.expiresAt`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "planId"
                ],
                "properties": {
                  "planId": {
                    "type": "string",
                    "enum": [
                      "1m",
                      "2m",
                      "3m",
                      "6m",
                      "1y"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "$ref": "#/components/responses/Error"
          },
          "503": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/api/public/v1/orders/{orderId}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Get payment status and, once active, the VPN config.",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "description": "The `token` returned by createOrder.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderStatus"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "months": {
            "type": "integer"
          },
          "priceUsd": {
            "type": "number"
          },
          "monthlyUsd": {
            "type": "number"
          }
        }
      },
      "PlanList": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "example": "USD"
          },
          "paymentMethods": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "bitcoin-onchain"
            ]
          },
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plan"
            }
          }
        }
      },
      "Payment": {
        "type": "object",
        "properties": {
          "method": {
            "type": "string",
            "example": "bitcoin-onchain"
          },
          "network": {
            "type": "string",
            "example": "mainnet"
          },
          "address": {
            "type": "string",
            "description": "Single-use receiving address."
          },
          "amountSats": {
            "type": "string",
            "description": "Exact amount in satoshis (integer string)."
          },
          "amountBtc": {
            "type": "string"
          },
          "uri": {
            "type": "string",
            "description": "BIP21 URI."
          },
          "btcRateUsd": {
            "type": "number",
            "description": "Locked USD/BTC rate for this order."
          },
          "requiredConfirmations": {
            "type": "integer"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "token": {
            "type": "string",
            "description": "Bearer-less polling token for this order."
          },
          "accountNumber": {
            "type": "string",
            "description": "The only credential for this account. Not recoverable."
          },
          "plan": {
            "$ref": "#/components/schemas/Plan"
          },
          "payment": {
            "$ref": "#/components/schemas/Payment"
          },
          "status": {
            "type": "string"
          },
          "statusUrl": {
            "type": "string",
            "format": "uri"
          },
          "pollIntervalSeconds": {
            "type": "integer"
          }
        }
      },
      "OrderStatus": {
        "type": "object",
        "properties": {
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "detected",
              "underpaid",
              "confirmed",
              "expired",
              "late_payment",
              "review_required",
              "cancelled"
            ]
          },
          "paid": {
            "type": "boolean"
          },
          "confirmations": {
            "type": "integer"
          },
          "requiredConfirmations": {
            "type": "integer"
          },
          "receivedSats": {
            "type": "string"
          },
          "expectedSats": {
            "type": "string"
          },
          "payment": {
            "$ref": "#/components/schemas/Payment"
          },
          "subscription": {
            "type": "object",
            "properties": {
              "active": {
                "type": "boolean"
              },
              "expiresAt": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "config": {
            "type": "object",
            "nullable": true,
            "description": "Returned only while the subscription is active.",
            "properties": {
              "link": {
                "type": "string",
                "description": "Xray/VLESS client URI."
              },
              "qrUrl": {
                "type": "string",
                "format": "uri",
                "nullable": true
              },
              "note": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "pollIntervalSeconds": {
            "type": "integer"
          }
        }
      }
    }
  }
}