{
  "openapi": "3.1.0",
  "info": {
    "title": "Private Payments API",
    "version": "0.1.0",
    "description": "Build an unsigned transaction that withdraws SPL tokens from an ephemeral rollup back to Solana."
  },
  "servers": [
    {
      "url": "https://payments.magicblock.app",
      "description": "Mainnet - Private Payments API"
    }
  ],
  "paths": {
    "/v1/spl/withdraw": {
      "post": {
        "summary": "Withdraw SPL Tokens",
        "description": "Wraps the SDK `withdrawSpl(...)` flow. The API generates `shuttleId` server-side.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "owner": {
                    "type": "string",
                    "example": "3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE"
                  },
                  "cluster": {
                    "anyOf": [
                      { "type": "string", "enum": ["mainnet", "devnet"] },
                      { "type": "string" }
                    ],
                    "example": "mainnet",
                    "description": "Optional. Use `mainnet` for BASE_RPC_URL and EPHEMERAL_RPC_URL, `devnet` for BASE_DEVNET_RPC_URL and EPHEMERAL_DEVNET_RPC_URL, or provide a custom http(s) RPC URL to override the base RPC while keeping the configured ephemeral RPC."
                  },
                  "mint": {
                    "type": "string",
                    "example": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "description": "SPL mint on Solana."
                  },
                  "amount": {
                    "type": "integer",
                    "minimum": 1,
                    "example": 1000000,
                    "description": "Base-unit amount as an integer JSON value with minimum 1."
                  },
                  "validator": {
                    "type": "string",
                    "example": "MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57",
                    "description": "Optional. Defaults to the selected ephemeral RPC identity resolved via `getIdentity`."
                  },
                  "initIfMissing": { "type": "boolean", "description": "Optional. Initialize the transfer queue if missing." },
                  "initAtasIfMissing": { "type": "boolean", "description": "Optional. Initialize associated token accounts if missing." },
                  "escrowIndex": { "type": "integer", "minimum": 0, "description": "Optional. Escrow index for the withdrawal." },
                  "idempotent": { "type": "boolean", "description": "Optional. When `true`, the API uses idempotent variants for any preparatory init instructions." }
                },
                "required": ["owner", "mint", "amount"],
                "example": {
                  "owner": "3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE",
                  "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                  "amount": 1000000,
                  "idempotent": true
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Unsigned serialized transaction",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kind": { "type": "string", "enum": ["withdraw"] },
                    "version": { "type": "string", "enum": ["legacy", "v0"] },
                    "transactionBase64": { "type": "string" },
                    "sendTo": { "type": "string", "enum": ["base", "ephemeral"] },
                    "recentBlockhash": { "type": "string" },
                    "lastValidBlockHeight": { "type": "integer" },
                    "instructionCount": { "type": "integer", "minimum": 0 },
                    "requiredSigners": { "type": "array", "items": { "type": "string" } },
                    "validator": { "type": "string" }
                  },
                  "required": ["kind", "version", "transactionBase64", "sendTo", "recentBlockhash", "lastValidBlockHeight", "instructionCount", "requiredSigners"]
                },
                "example": {
                  "kind": "withdraw",
                  "version": "legacy",
                  "transactionBase64": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIDKmcfsS5XfSOLaLlaBHJry50iH2Ufk2TMz4STC2fHzIcFKkerg3q2DD3Yn8TISmGeKoxSLz+BiP7iQ4pYqXYXsgu8D8C7R8ovdMQRLpSrE8+jxjTl3BfqywPNGiPNfnh8AazZ0ixOauLjpxaRgDCv6MChaoMAZAJg8BnPbZl31jECAgEBBAECAwQCAQEEAgIDBA==",
                  "sendTo": "base",
                  "recentBlockhash": "7YH7nE6qj8vH3L9pR5uM2cD1xK4sT8wQ6bN3fJ2mP9z",
                  "lastValidBlockHeight": 284512451,
                  "instructionCount": 2,
                  "requiredSigners": ["3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE"],
                  "validator": "MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57"
                }
              }
            }
          },
          "400": { "description": "Build error" },
          "422": { "description": "Validation error" }
        }
      }
    }
  }
}
