{
  "openapi": "3.1.0",
  "info": {
    "title": "AtlasPay Merchant API",
    "version": "2026-07-22",
    "summary": "Live custodial wallet, checkout, deposit address and withdrawal APIs for merchants and AI agents.",
    "description": "This contract documents customer-facing AtlasPay endpoints only. Platform-admin and internal MPC signing endpoints are intentionally excluded. Monetary values are fixed-point decimal strings. Never use binary floating-point arithmetic for balances or fees.",
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://atlaspay.one",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "AI onboarding",
      "description": "Create a live merchant integration package and hand the one-time console token to the human owner."
    },
    {
      "name": "Orders",
      "description": "Hosted checkout order creation and reconciliation."
    },
    {
      "name": "Wallets",
      "description": "Asset portfolio, policies, transaction search and collection."
    },
    {
      "name": "Deposit addresses",
      "description": "Long-term external-user deposit address assignment."
    },
    {
      "name": "Withdrawals",
      "description": "Fee quoting and withdrawal request creation. Human approval remains in the merchant console."
    },
    {
      "name": "Developer",
      "description": "Machine-readable contract and API change history."
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/v1/openapi.json": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "Download the OpenAPI contract",
        "operationId": "getOpenAPIContract",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 JSON document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "description": "Only GET and HEAD are allowed."
          }
        }
      }
    },
    "/v1/api-changelog": {
      "get": {
        "tags": [
          "Developer"
        ],
        "summary": "Get the API change history",
        "operationId": "getAPIChangelog",
        "security": [],
        "responses": {
          "200": {
            "description": "Versioned API change entries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIChangelog"
                }
              }
            }
          },
          "405": {
            "description": "Only GET and HEAD are allowed."
          }
        }
      }
    },
    "/v1/ai/merchant-apply": {
      "post": {
        "tags": [
          "AI onboarding"
        ],
        "summary": "Apply for and provision a live merchant",
        "description": "No API key is required. Store env values only in the project backend. Give merchant_console.console_token or token_login_url only to the human owner. The console token is one-time and becomes invalid after account binding.",
        "operationId": "applyMerchantWithAI",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIMerchantApplyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing application or completed provisioning result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIMerchantApplyResponse"
                }
              }
            }
          },
          "201": {
            "description": "New live merchant integration package",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AIMerchantApplyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/ai/onboarding-status/{merchant_id}": {
      "get": {
        "tags": [
          "AI onboarding"
        ],
        "summary": "Get live merchant provisioning status",
        "description": "Poll the URL returned by /v1/ai/merchant-apply from the project backend. The X-API-Key must be the live key returned for the same merchant; AtlasPay rejects cross-merchant status reads.",
        "operationId": "getAIOnboardingStatus",
        "parameters": [
          {
            "name": "merchant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current provisioning and live-readiness status"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The authenticated API key belongs to a different merchant."
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/orders": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "List merchant orders",
        "operationId": "listOrders",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chain",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Chain"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated orders",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Orders"
        ],
        "summary": "Create a hosted checkout order",
        "description": "Send X-AtlasPay-Idempotency-Key for retry-safe creation. The key is scoped to the authenticated merchant and this endpoint. The same key with the same normalized request returns the existing order; the same key with a different request returns 409. out_trade_no is a merchant reconciliation identifier, not the server idempotency key.",
        "operationId": "createOrder",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout order created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/orders/{order_id}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "summary": "Get an order",
        "operationId": "getOrder",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderID"
          }
        ],
        "responses": {
          "200": {
            "description": "Order state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/wallet-portfolio": {
      "get": {
        "tags": [
          "Wallets"
        ],
        "summary": "Get authoritative portfolio balances",
        "description": "Use this endpoint for total, available, uncollected and locked balances. Legacy wallet-assets totals must not be treated as withdrawable balance.",
        "operationId": "getWalletPortfolio",
        "parameters": [
          {
            "name": "quote",
            "in": "query",
            "description": "Quote currency. Currently USDT.",
            "schema": {
              "type": "string",
              "default": "USDT"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Portfolio grouped by currency and network",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletPortfolio"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/wallet-asset-policies": {
      "get": {
        "tags": [
          "Wallets"
        ],
        "summary": "List live asset capabilities",
        "description": "Clients must fail closed. Only enable actions explicitly marked live and implemented.",
        "operationId": "listWalletAssetPolicies",
        "responses": {
          "200": {
            "description": "Asset capability policies",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AssetPolicy"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/wallet-asset-enrollments": {
      "post": {
        "tags": [
          "Wallets"
        ],
        "summary": "Enable a platform-supported asset for this merchant",
        "description": "Enables one live asset for the authenticated merchant. Custom assets are not monitored or exposed to checkout until enrolled. The operation is idempotent.",
        "operationId": "enableMerchantWalletAsset",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "chain",
                  "currency"
                ],
                "properties": {
                  "chain": {
                    "$ref": "#/components/schemas/Chain"
                  },
                  "currency": {
                    "type": "string",
                    "examples": ["VELNX"]
                  },
                  "source": {
                    "type": "string",
                    "default": "merchant_api"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The enabled merchant asset policy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetPolicy"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/wallet-assets": {
      "get": {
        "tags": [
          "Wallets"
        ],
        "summary": "List legacy wallet asset aggregates",
        "description": "Compatibility endpoint. Use wallet-portfolio for withdrawable balance decisions.",
        "operationId": "listWalletAssets",
        "deprecated": true,
        "responses": {
          "200": {
            "description": "Legacy asset aggregates",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/wallet-assets/{asset_key}": {
      "get": {
        "tags": [
          "Wallets"
        ],
        "summary": "Get addresses and transactions for one network asset",
        "operationId": "getWalletAsset",
        "parameters": [
          {
            "$ref": "#/components/parameters/AssetKey"
          },
          {
            "name": "q",
            "in": "query",
            "description": "Address, wallet number or transaction hash search.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Asset detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/wallet-assets/{asset_key}/sweep": {
      "post": {
        "tags": [
          "Wallets"
        ],
        "summary": "Collect a receive-address balance into the asset main wallet",
        "description": "Omit amount to sweep the full available balance. Calls for the same from_wallet_id must be serialized. Token collection can return a gas-funding state before the token sweep is ready.",
        "operationId": "sweepWalletAsset",
        "parameters": [
          {
            "$ref": "#/components/parameters/AssetKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SweepRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sweep or gas-funding operation state",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/v1/deposit-addresses": {
      "get": {
        "tags": [
          "Deposit addresses"
        ],
        "summary": "List long-term deposit addresses",
        "operationId": "listDepositAddresses",
        "parameters": [
          {
            "name": "external_user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chain",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Chain"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Assigned deposit addresses",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositAddressList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Deposit addresses"
        ],
        "summary": "Assign a long-term deposit address",
        "description": "Idempotent for external_user_id + chain + currency. For merchants on the shared-network-address rollout, one external_user_id reuses the same address across supported assets on the same network; id remains asset-specific.",
        "operationId": "createDepositAddress",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDepositAddressRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Address assignment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositAddress"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/v1/deposit-addresses/batch": {
      "post": {
        "tags": [
          "Deposit addresses"
        ],
        "summary": "Assign deposit addresses in a batch",
        "operationId": "createDepositAddressesBatch",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchCreateDepositAddressRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per-item assignment results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "succeeded",
                    "failed",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer"
                    },
                    "succeeded": {
                      "type": "integer"
                    },
                    "failed": {
                      "type": "integer"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/deposit-addresses/{deposit_address_id}/transactions": {
      "get": {
        "tags": [
          "Deposit addresses"
        ],
        "summary": "List transactions for a deposit address",
        "operationId": "listDepositAddressTransactions",
        "parameters": [
          {
            "$ref": "#/components/parameters/DepositAddressID"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Address transactions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/transactions": {
      "get": {
        "tags": [
          "Wallets"
        ],
        "summary": "Search merchant transactions",
        "operationId": "listTransactions",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Transaction hash, address, order number or withdrawal number.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chain",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Chain"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching transactions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/withdrawal-fee-quote": {
      "post": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "Quote withdrawal fees and native gas budget",
        "description": "Call immediately before withdrawal creation. No quote_id is returned. AtlasPay recalculates and snapshots the fee policy when POST /v1/withdrawals is called. Send the original gross amount and do not send fee fields back. Token network_fee is denominated in network_fee_asset and is not deducted from the token amount when network_fee_included is false.",
        "operationId": "quoteWithdrawalFee",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WithdrawalFeeQuoteRequest"
              },
              "examples": {
                "trc20Usdt": {
                  "value": {
                    "chain": "TRC20",
                    "currency": "USDT",
                    "amount": "10.00"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fee quote. network_fee is denominated in network_fee_asset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WithdrawalFeeQuote"
                },
                "examples": {
                  "trc20Usdt": {
                    "value": {
                      "chain": "TRC20",
                      "currency": "USDT",
                      "fee_currency": "USDT",
                      "amount": "10.000000",
                      "platform_fee": "0.100000",
                      "network_fee": "30.000000",
                      "network_fee_asset": "TRX",
                      "network_fee_included": false,
                      "total_fee": "0.100000",
                      "net_amount": "9.900000",
                      "platform_fee_bps": 5,
                      "model": "native_gas_policy",
                      "policy_version": "2026-07-19.2"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The authenticated merchant actor lacks read permission."
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/withdrawals": {
      "get": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "List withdrawal requests",
        "operationId": "listWithdrawals",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/WithdrawalStatus"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Withdrawal requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WithdrawalList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "Create a withdrawal request",
        "description": "Use the original gross amount from the fee quote request. Do not submit fee fields. Send X-AtlasPay-Idempotency-Key for retry-safe creation. The same merchant-scoped key with the same normalized request returns the existing withdrawal; reuse with a different request returns 409. The request enters the merchant approval workflow; approved requests are signed and broadcast automatically.",
        "operationId": "createWithdrawal",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWithdrawalRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Withdrawal request created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Withdrawal"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/withdrawals/{withdrawal_id}": {
      "get": {
        "tags": [
          "Withdrawals"
        ],
        "summary": "Get a withdrawal request",
        "operationId": "getWithdrawal",
        "parameters": [
          {
            "$ref": "#/components/parameters/WithdrawalID"
          }
        ],
        "responses": {
          "200": {
            "description": "Withdrawal state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Withdrawal"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "webhooks": {
    "orderUpdated": {
      "post": {
        "summary": "Order status or order-attributed deposit update",
        "operationId": "receiveOrderUpdatedWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderWebhookEvent"
          },
          {
            "$ref": "#/components/parameters/WebhookIdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx after durable, idempotent acceptance."
          }
        }
      }
    },
    "walletDepositConfirmed": {
      "post": {
        "summary": "Confirmed deposit to a long-term address or wallet",
        "operationId": "receiveWalletDepositConfirmedWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/WalletDepositWebhookEvent"
          },
          {
            "$ref": "#/components/parameters/WebhookIdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletDepositWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx after durable, idempotent acceptance."
          }
        }
      }
    },
    "walletWithdrawalTerminal": {
      "post": {
        "summary": "Completed or failed withdrawal",
        "operationId": "receiveWalletWithdrawalTerminalWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/WithdrawalWebhookEvent"
          },
          {
            "$ref": "#/components/parameters/WebhookIdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WithdrawalWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return any 2xx after durable, idempotent acceptance."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Merchant live API key. Store only in backend secrets. AtlasPay resolves the merchant from this key; X-Merchant-ID is not required."
      }
    },
    "parameters": {
      "Page": {
        "name": "page",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "Size": {
        "name": "size",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      },
      "OrderID": {
        "name": "order_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "WithdrawalID": {
        "name": "withdrawal_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "DepositAddressID": {
        "name": "deposit_address_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "AssetKey": {
        "name": "asset_key",
        "in": "path",
        "required": true,
        "description": "Uppercase CHAIN-CURRENCY key, for example TRC20-USDT.",
        "schema": {
          "type": "string",
          "pattern": "^[A-Z0-9]+-[A-Z0-9]+$"
        }
      },
      "RequestIdempotencyKey": {
        "name": "X-AtlasPay-Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Optional request idempotency key for POST /v1/orders and POST /v1/withdrawals only. Maximum 128 visible ASCII characters with no whitespace. Omission makes the create request non-idempotent. On timeout, retry with the exact same key and request body.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "pattern": "^[!-~]+$"
        }
      },
      "OrderWebhookEvent": {
        "name": "X-FACET-EVENT",
        "in": "header",
        "required": true,
        "description": "Transport event name for all order webhook deliveries.",
        "schema": {
          "type": "string",
          "const": "order.updated"
        }
      },
      "WalletDepositWebhookEvent": {
        "name": "X-FACET-EVENT",
        "in": "header",
        "required": true,
        "description": "Transport event name for confirmed wallet deposits.",
        "schema": {
          "type": "string",
          "const": "wallet.deposit.confirmed"
        }
      },
      "WithdrawalWebhookEvent": {
        "name": "X-FACET-EVENT",
        "in": "header",
        "required": true,
        "description": "Transport event name for terminal withdrawals.",
        "schema": {
          "type": "string",
          "enum": [
            "wallet.withdrawal.completed",
            "wallet.withdrawal.failed"
          ]
        }
      },
      "WebhookIdempotencyKey": {
        "name": "X-FACET-IDEMPOTENCY-KEY",
        "in": "header",
        "required": true,
        "description": "Stable across retries. Order chain events use deposit:{chain}:{currency}:{tx_hash}:{to_address}:{event_index}:{body_event}; order non-chain fallbacks use {order_id}:{body_event}:{STATUS}; wallet deposits use wallet.deposit.confirmed:{chain}:{currency}:{tx_hash}:{to_address}:{event_index}; terminal withdrawals use {event}:{withdrawal_id}:{tx_hash}.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookSignature": {
        "name": "X-FACET-SIGNATURE",
        "in": "header",
        "required": true,
        "description": "Lowercase hex HMAC-SHA256 of the exact raw request body using ATLASPAY_WEBHOOK_SECRET.",
        "schema": {
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid JSON, amount precision, asset policy, address or request state.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid or inactive merchant authentication.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "missing": {
                "value": {
                  "error": "merchant authentication required"
                }
              },
              "invalid": {
                "value": {
                  "error": "invalid or inactive api key"
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested merchant-owned resource does not exist.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "Idempotency, concurrent operation or resource-state conflict.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "A required AtlasPay service is temporarily unavailable. Retry idempotent reads with bounded exponential backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Stable human-readable error message. Clients must branch primarily on HTTP status until a future additive machine code is introduced."
          }
        },
        "additionalProperties": true
      },
      "DecimalString": {
        "type": "string",
        "pattern": "^[0-9]+(?:\\.[0-9]+)?$",
        "description": "Non-negative fixed-point decimal string."
      },
      "Chain": {
        "type": "string",
        "description": "Canonical chain identifier. POLYGON may appear in historical records, but is sunset for new orders, deposit addresses, collection, and withdrawals.",
        "enum": [
          "TRC20",
          "BEP20",
          "POLYGON",
          "SOLANA"
        ]
      },
      "WithdrawalStatus": {
        "type": "string",
        "enum": [
          "PENDING",
          "APPROVED",
          "REJECTED",
          "CANCELLED",
          "BROADCAST",
          "COMPLETED",
          "FAILED"
        ]
      },
      "AIMerchantApplyRequest": {
        "type": "object",
        "required": [
          "project_name",
          "business_type",
          "use_case",
          "agree_terms"
        ],
        "properties": {
          "project_name": {
            "type": "string",
            "minLength": 2
          },
          "website": {
            "type": "string",
            "format": "uri"
          },
          "repository_url": {
            "type": "string",
            "format": "uri"
          },
          "contact_channel": {
            "type": "string"
          },
          "contact_email": {
            "type": "string",
            "format": "email"
          },
          "business_type": {
            "type": "string",
            "examples": [
              "exchange"
            ]
          },
          "monthly_volume": {
            "type": "string"
          },
          "use_case": {
            "type": "string"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri"
          },
          "return_url": {
            "type": "string",
            "format": "uri"
          },
          "preferred_chains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Chain"
            }
          },
          "ai_provider": {
            "type": "string"
          },
          "agree_terms": {
            "type": "boolean",
            "const": true
          }
        },
        "additionalProperties": true
      },
      "AIMerchantApplyResponse": {
        "type": "object",
        "required": [
          "status",
          "mode",
          "live_ready",
          "env",
          "merchant_console",
          "generated_at"
        ],
        "properties": {
          "status": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "const": "live"
          },
          "live_ready": {
            "type": "boolean"
          },
          "application_id": {
            "type": "string"
          },
          "merchant_no": {
            "type": "string"
          },
          "env": {
            "type": "object",
            "description": "Backend-only environment values. Never expose in client applications.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "merchant_console": {
            "$ref": "#/components/schemas/MerchantConsoleHandoff"
          },
          "integration_prompt": {
            "type": "string"
          },
          "onboarding_status_url": {
            "type": "string",
            "format": "uri"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "MerchantConsoleHandoff": {
        "type": "object",
        "properties": {
          "console_token": {
            "type": "string",
            "writeOnly": true,
            "description": "One-time human-owner setup token."
          },
          "token_login_url": {
            "type": "string",
            "format": "uri"
          },
          "dashboard_url": {
            "type": "string",
            "format": "uri"
          },
          "suggested_login_name": {
            "type": "string"
          },
          "setup_required": {
            "type": "boolean"
          },
          "console_token_expires_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "CreateOrderRequest": {
        "type": "object",
        "required": [
          "amount"
        ],
        "properties": {
          "out_trade_no": {
            "type": "string",
            "description": "Merchant order ID. Recommended for reconciliation, but not a substitute for X-AtlasPay-Idempotency-Key. It may be empty and is not enforced as unique by AtlasPay."
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "currency": {
            "type": "string",
            "description": "Omit when merchant checkout configuration selects the currency."
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "checkout_mode": {
            "type": "string",
            "enum": [
              "single_asset",
              "multi_asset"
            ],
            "description": "Optional checkout presentation mode. Every accepted asset is still filtered by the merchant's live policy."
          },
          "accepted_assets": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "chain",
                "currency"
              ],
              "properties": {
                "chain": {
                  "$ref": "#/components/schemas/Chain"
                },
                "currency": {
                  "type": "string"
                }
              },
              "additionalProperties": false
            },
            "description": "Optional order-level allow-list. Assets not live for the authenticated merchant are rejected or removed; POLYGON is not available for new checkout orders."
          },
          "exchange_rate": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "notify_url": {
            "type": "string",
            "format": "uri"
          },
          "return_url": {
            "type": "string",
            "format": "uri"
          },
          "expire_minutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440,
            "default": 15
          },
          "merchant_user_id": {
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "product_desc": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "Order": {
        "type": "object",
        "required": [
          "order_id",
          "out_trade_no",
          "status",
          "amount",
          "currency",
          "chain",
          "expire_at",
          "created_at"
        ],
        "properties": {
          "order_id": {
            "type": "string"
          },
          "out_trade_no": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Order statuses are uppercase."
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "paid_amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "currency": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "pay_address": {
            "type": "string"
          },
          "pay_qrcode": {
            "type": "string"
          },
          "checkout_url": {
            "type": "string",
            "format": "uri"
          },
          "return_url": {
            "type": "string",
            "format": "uri"
          },
          "tx_hash": {
            "type": "string"
          },
          "expire_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "available_assets": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      },
      "OrderList": {
        "type": "object",
        "required": [
          "total",
          "page",
          "size",
          "items"
        ],
        "properties": {
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "size": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          }
        }
      },
      "WalletPortfolio": {
        "type": "object",
        "required": [
          "quote_currency",
          "as_of",
          "price_source",
          "totals",
          "assets"
        ],
        "properties": {
          "quote_currency": {
            "type": "string"
          },
          "as_of": {
            "type": "string",
            "format": "date-time"
          },
          "price_source": {
            "type": "string"
          },
          "totals": {
            "$ref": "#/components/schemas/PortfolioTotals"
          },
          "assets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortfolioAsset"
            }
          }
        }
      },
      "PortfolioTotals": {
        "type": "object",
        "required": [
          "value_usdt",
          "available_value_usdt",
          "uncollected_value_usdt",
          "locked_value_usdt",
          "unpriced_asset_count",
          "network_count",
          "address_count"
        ],
        "properties": {
          "value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "available_value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "uncollected_value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "locked_value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "unpriced_asset_count": {
            "type": "integer"
          },
          "network_count": {
            "type": "integer"
          },
          "address_count": {
            "type": "integer"
          }
        }
      },
      "PortfolioAsset": {
        "type": "object",
        "required": [
          "asset_id",
          "currency",
          "total_balance",
          "available_balance",
          "uncollected_balance",
          "locked_balance",
          "networks"
        ],
        "properties": {
          "asset_id": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "total_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "available_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "uncollected_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "locked_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "available_value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "uncollected_value_usdt": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "networks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortfolioNetwork"
            }
          }
        },
        "additionalProperties": true
      },
      "PortfolioNetwork": {
        "type": "object",
        "required": [
          "network_asset_id",
          "chain",
          "currency",
          "main_address",
          "total_balance",
          "available_balance",
          "uncollected_balance",
          "locked_balance",
          "gas_asset",
          "gas_balance",
          "gas_status",
          "actions"
        ],
        "properties": {
          "network_asset_id": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "main_address": {
            "type": "string"
          },
          "total_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "available_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "uncollected_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "locked_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "gas_asset": {
            "type": "string"
          },
          "gas_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "gas_status": {
            "type": "string"
          },
          "actions": {
            "type": "object",
            "required": [
              "deposit",
              "withdraw",
              "collect"
            ],
            "properties": {
              "deposit": {
                "type": "boolean"
              },
              "withdraw": {
                "type": "boolean"
              },
              "collect": {
                "type": "boolean"
              }
            }
          }
        },
        "additionalProperties": true
      },
      "AssetPolicy": {
        "type": "object",
        "required": [
          "chain",
          "currency",
          "main_key_mode",
          "receive_key_mode",
          "collection_mode",
          "sweep_requires_gas",
          "signing_implemented",
          "status",
          "default_for_new_merchants",
          "merchant_enabled"
        ],
        "properties": {
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "main_key_mode": {
            "type": "string"
          },
          "receive_key_mode": {
            "type": "string"
          },
          "collection_mode": {
            "type": "string"
          },
          "sweep_requires_gas": {
            "type": "boolean"
          },
          "signing_implemented": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "deposit_live",
              "planned",
              "disabled"
            ]
          },
          "default_for_new_merchants": {
            "type": "boolean",
            "description": "True for mainstream assets automatically enabled for newly created merchants."
          },
          "merchant_enabled": {
            "type": "boolean",
            "description": "Authoritative per-merchant capability flag. Only enabled assets may be used for wallet, checkout, collection, withdrawal, and active chain monitoring."
          },
          "merchant_source": {
            "type": "string",
            "description": "How this merchant enabled the asset."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "SweepRequest": {
        "type": "object",
        "required": [
          "from_wallet_id"
        ],
        "properties": {
          "from_wallet_id": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          }
        },
        "additionalProperties": false
      },
      "CreateDepositAddressRequest": {
        "type": "object",
        "required": [
          "external_user_id",
          "chain",
          "currency"
        ],
        "properties": {
          "external_user_id": {
            "type": "string",
            "minLength": 1
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "label": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "BatchCreateDepositAddressRequest": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateDepositAddressRequest"
            }
          },
          "external_user_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "label_prefix": {
            "type": "string"
          },
          "continue_on_error": {
            "type": "boolean",
            "default": false
          }
        },
        "additionalProperties": false
      },
      "DepositAddress": {
        "type": "object",
        "required": [
          "id",
          "external_user_id",
          "wallet_id",
          "chain",
          "currency",
          "address",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "external_user_id": {
            "type": "string"
          },
          "wallet_id": {
            "type": "string"
          },
          "network_account_id": {
            "type": "string",
            "description": "Physical network-account identifier shared by assets using the same on-chain address."
          },
          "shared_network_address": {
            "type": "boolean",
            "description": "True when this asset assignment reuses a network-level address."
          },
          "wallet_no": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "available_balance": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "DepositAddressList": {
        "type": "object",
        "required": [
          "total",
          "limit",
          "offset",
          "items"
        ],
        "properties": {
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DepositAddress"
            }
          }
        }
      },
      "Transaction": {
        "type": "object",
        "required": [
          "id",
          "type",
          "amount",
          "currency",
          "chain",
          "status",
          "tx_hash",
          "from_address",
          "to_address",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "wallet_id": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "out_trade_no": {
            "type": "string"
          },
          "attribution": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "currency": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "status": {
            "type": "string"
          },
          "tx_hash": {
            "type": "string"
          },
          "event_index": {
            "type": "string"
          },
          "from_address": {
            "type": "string"
          },
          "to_address": {
            "type": "string"
          },
          "fee": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "TransactionList": {
        "type": "object",
        "required": [
          "total",
          "items"
        ],
        "properties": {
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          }
        },
        "additionalProperties": true
      },
      "WithdrawalFeeQuoteRequest": {
        "type": "object",
        "required": [
          "chain",
          "currency",
          "amount"
        ],
        "properties": {
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          }
        },
        "additionalProperties": false
      },
      "WithdrawalFeeQuote": {
        "type": "object",
        "required": [
          "chain",
          "currency",
          "fee_currency",
          "amount",
          "platform_fee",
          "network_fee",
          "network_fee_asset",
          "network_fee_included",
          "total_fee",
          "net_amount",
          "platform_fee_bps",
          "model",
          "policy_version"
        ],
        "properties": {
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "fee_currency": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "platform_fee": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "network_fee": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "network_fee_asset": {
            "type": "string",
            "description": "Native gas asset for a currently live policy, such as TRX, BNB or SOL. POL may appear only in historical Polygon records; Polygon is disabled for new quotes and withdrawals."
          },
          "network_fee_included": {
            "type": "boolean",
            "description": "True only when network_fee is denominated in the withdrawal currency and included in total_fee."
          },
          "total_fee": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "net_amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "platform_fee_bps": {
            "type": "integer"
          },
          "model": {
            "type": "string"
          },
          "policy_version": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "CreateWithdrawalRequest": {
        "type": "object",
        "required": [
          "chain",
          "currency",
          "amount",
          "to_address"
        ],
        "properties": {
          "wallet_id": {
            "type": "string",
            "description": "Optional asset main wallet ID. AtlasPay selects the eligible main wallet when omitted."
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "to_address": {
            "type": "string"
          },
          "address_label": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "Withdrawal": {
        "type": "object",
        "required": [
          "id",
          "withdrawal_no",
          "chain",
          "currency",
          "amount",
          "fee",
          "net_amount",
          "to_address",
          "status",
          "approval_level",
          "current_level",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "withdrawal_no": {
            "type": "string"
          },
          "wallet_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "network_account_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Chain-level source account snapshot used by AtlasPay funds accounting. Additive field; clients may ignore it."
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "fee": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "net_amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "to_address": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/WithdrawalStatus"
          },
          "approval_level": {
            "type": "integer"
          },
          "current_level": {
            "type": "integer"
          },
          "tx_hash": {
            "type": [
              "string",
              "null"
            ]
          },
          "failure_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "fee_breakdown": {
            "$ref": "#/components/schemas/WithdrawalFeeQuote"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "WithdrawalList": {
        "type": "object",
        "required": [
          "total",
          "items"
        ],
        "properties": {
          "total": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Withdrawal"
            }
          }
        }
      },
      "OrderWebhook": {
        "type": "object",
        "required": [
          "event",
          "order_id",
          "out_trade_no",
          "status",
          "amount",
          "chain",
          "currency",
          "updated_at"
        ],
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "deposit.detected",
              "deposit.confirmed",
              "order.expired"
            ],
            "description": "Current order-domain events. The transport X-FACET-EVENT header remains order.updated."
          },
          "deposit_event_id": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "out_trade_no": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Uppercase order status."
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "paid_amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "tx_hash": {
            "type": "string"
          },
          "event_index": {
            "type": "string"
          },
          "to_address": {
            "type": "string"
          },
          "kyt_level": {
            "type": "string",
            "description": "Reserved optional field. Current order webhook senders normally omit it."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "WalletDepositWebhook": {
        "type": "object",
        "required": [
          "event",
          "deposit_event_id",
          "transaction_id",
          "wallet_id",
          "wallet_no",
          "order_id",
          "out_trade_no",
          "address_scope",
          "attribution",
          "deposit_address_id",
          "external_user_id",
          "tx_hash",
          "event_index",
          "chain",
          "currency",
          "amount",
          "from_address",
          "to_address",
          "status",
          "confirmed_at"
        ],
        "properties": {
          "event": {
            "type": "string",
            "const": "wallet.deposit.confirmed"
          },
          "deposit_event_id": {
            "type": "string"
          },
          "transaction_id": {
            "type": "string"
          },
          "wallet_id": {
            "type": "string"
          },
          "wallet_no": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "out_trade_no": {
            "type": "string"
          },
          "address_scope": {
            "type": "string",
            "enum": [
              "order",
              "deposit_address",
              "wallet"
            ]
          },
          "attribution": {
            "type": "string"
          },
          "deposit_address_id": {
            "type": "string"
          },
          "external_user_id": {
            "type": "string"
          },
          "tx_hash": {
            "type": "string"
          },
          "event_index": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "from_address": {
            "type": "string"
          },
          "to_address": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "completed"
          },
          "confirmed_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "WithdrawalWebhook": {
        "type": "object",
        "required": [
          "event",
          "withdrawal_id",
          "withdrawal_no",
          "merchant_id",
          "wallet_id",
          "tx_hash",
          "chain",
          "currency",
          "amount",
          "fee",
          "net_amount",
          "to_address",
          "status",
          "failure_reason",
          "updated_at"
        ],
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "wallet.withdrawal.completed",
              "wallet.withdrawal.failed"
            ]
          },
          "withdrawal_id": {
            "type": "string"
          },
          "withdrawal_no": {
            "type": "string"
          },
          "merchant_id": {
            "type": "string"
          },
          "wallet_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "tx_hash": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/Chain"
          },
          "currency": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "fee": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "net_amount": {
            "$ref": "#/components/schemas/DecimalString"
          },
          "to_address": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "failed"
            ]
          },
          "failure_reason": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "APIChangelog": {
        "type": "object",
        "required": [
          "api",
          "current_version",
          "entries"
        ],
        "properties": {
          "api": {
            "type": "string"
          },
          "current_version": {
            "type": "string"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "version",
                "date",
                "type",
                "breaking",
                "changes"
              ],
              "properties": {
                "version": {
                  "type": "string"
                },
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "type": {
                  "type": "string"
                },
                "breaking": {
                  "type": "boolean"
                },
                "changes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "x-atlaspay-error-catalog": [
    {
      "http_status": 400,
      "category": "INVALID_REQUEST",
      "meaning": "Malformed JSON, missing required field, unsupported amount syntax or invalid address."
    },
    {
      "http_status": 401,
      "category": "AUTHENTICATION_REQUIRED",
      "meaning": "X-API-Key is missing, invalid or inactive."
    },
    {
      "http_status": 403,
      "category": "ACTION_FORBIDDEN",
      "meaning": "The authenticated actor cannot perform this operation. Human console approval may be required."
    },
    {
      "http_status": 404,
      "category": "RESOURCE_NOT_FOUND",
      "meaning": "The merchant-owned resource does not exist."
    },
    {
      "http_status": 409,
      "category": "CONFLICT",
      "meaning": "Concurrent collection, duplicate idempotency identity or incompatible resource state."
    },
    {
      "http_status": 429,
      "category": "RATE_LIMITED",
      "meaning": "Retry after bounded exponential backoff. For order or withdrawal creation, preserve the exact X-AtlasPay-Idempotency-Key and request body."
    },
    {
      "http_status": 503,
      "category": "SERVICE_UNAVAILABLE",
      "meaning": "Temporary AtlasPay dependency failure. Retry safe reads; retry order or withdrawal creation only with the exact original idempotency key and request."
    }
  ],
  "x-atlaspay-live-withdrawal-assets": [
    "TRC20-USDT",
    "TRC20-TRX",
    "BEP20-USDT",
    "BEP20-BNB",
    "BEP20-VELNX",
    "SOLANA-SOL",
    "SOLANA-USDT"
  ],
  "x-atlaspay-network-boundaries": {
    "POLYGON": "Sunset for new orders, checkout, deposit addresses, collection, fee quotes and withdrawals. POLYGON may remain in historical records, and POLYGON-USDT historical address monitoring may continue.",
    "SOLANA": "Public live scope is limited to SOLANA-SOL and SOLANA-USDT and remains subject to the authenticated merchant's wallet-asset policy and portfolio actions. SOLANA-USDC and arbitrary SPL tokens are not public-live."
  }
}
