{
    "openapi": "3.1.0",
    "info": {
        "title": "PAYWISE API",
        "version": "1.0.0",
        "description": "Accept QRIS (IDR) and USDT (BEP20) payments and withdraw the settled funds. A sandbox key (pw_test_…) works on sandbox transactions only, a live key (pw_live_…) on live ones. Rate limit: 60 requests per minute per key. Documentation: https://paywise.asia/developers/docs"
    },
    "servers": [
        {
            "url": "https://paywise.asia/api/v1"
        }
    ],
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "paths": {
        "/transactions": {
            "post": {
                "operationId": "createTransaction",
                "summary": "Create a transaction",
                "description": "Idempotent per environment on merchant_reference: the same request again returns the original transaction (200); different details return 409 DUPLICATE_REFERENCE.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreateTransaction"
                            },
                            "examples": {
                                "qris": {
                                    "value": {
                                        "merchant_reference": "ORDER-1042",
                                        "amount": 250000,
                                        "currency": "IDR",
                                        "payment_method": "QRIS",
                                        "customer_id": "user-1042",
                                        "customer_name": "Budi Santoso"
                                    }
                                },
                                "usdt": {
                                    "value": {
                                        "merchant_reference": "ORDER-1043",
                                        "amount": 100,
                                        "currency": "USDT",
                                        "payment_method": "USDT",
                                        "network": "BEP20",
                                        "customer_id": "user-1043"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TransactionResponse"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Replay of an existing merchant_reference",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TransactionResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "DUPLICATE_REFERENCE, DUPLICATE_REQUEST, WITHDRAWAL_BUSY",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "VALIDATION_ERROR, RETURN_URL_NOT_ALLOWED, WEBSITE_NOT_FOUND, WEBSITE_REQUIRED, AMOUNT_TOO_LARGE, INSUFFICIENT_FUNDS",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "INTERNAL_ERROR",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "PROVIDER_ERROR",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "PAYMENT_METHOD_PAUSED, WITHDRAWALS_PAUSED, MAINTENANCE, PROVIDER_NOT_CONNECTED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "504": {
                        "description": "PROVIDER_TIMEOUT",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "get": {
                "operationId": "listTransactions",
                "summary": "List transactions",
                "description": "Newest first, in the key's environment.",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "description": "pending, paid, failed or expired.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "pending",
                                "paid",
                                "failed",
                                "expired"
                            ]
                        }
                    },
                    {
                        "name": "payment_method",
                        "in": "query",
                        "description": "QRIS or USDT.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "QRIS",
                                "USDT"
                            ]
                        }
                    },
                    {
                        "name": "date_from",
                        "in": "query",
                        "description": "YYYY-MM-DD. First day (UTC+7) the transaction was created.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "date_to",
                        "in": "query",
                        "description": "YYYY-MM-DD. Last day (UTC+7), inclusive.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "merchant_reference",
                        "in": "query",
                        "description": "Your order reference, exact match.",
                        "schema": {
                            "type": "string",
                            "maxLength": 100
                        }
                    },
                    {
                        "name": "customer_id",
                        "in": "query",
                        "description": "Your customer id, exact match.",
                        "schema": {
                            "type": "string",
                            "maxLength": 100
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "1–100, default 20.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "description": "Page number, default 1.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of transactions",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TransactionList"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "VALIDATION_ERROR, RETURN_URL_NOT_ALLOWED, WEBSITE_NOT_FOUND, WEBSITE_REQUIRED, AMOUNT_TOO_LARGE, INSUFFICIENT_FUNDS",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/transactions/{reference}": {
            "get": {
                "operationId": "getTransaction",
                "summary": "Retrieve a transaction",
                "parameters": [
                    {
                        "name": "reference",
                        "in": "path",
                        "required": true,
                        "description": "The PAYWISE reference returned at creation.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The transaction",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TransactionResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "NOT_FOUND",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/balance": {
            "get": {
                "operationId": "getBalance",
                "summary": "Funds per payment method",
                "description": "Available now, awaiting settlement, the largest withdrawal possible now, and the withdrawal limits and fee, in the key's environment.",
                "responses": {
                    "200": {
                        "description": "Balance per payment method",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "const": true
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "environment": {
                                                    "type": "string",
                                                    "enum": [
                                                        "live",
                                                        "sandbox"
                                                    ]
                                                },
                                                "methods": {
                                                    "type": "object",
                                                    "additionalProperties": {
                                                        "type": "object",
                                                        "properties": {
                                                            "currency": {
                                                                "type": "string"
                                                            },
                                                            "available": {
                                                                "type": "number"
                                                            },
                                                            "awaiting_settlement": {
                                                                "type": "number"
                                                            },
                                                            "next_settlement_at": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "format": "date-time"
                                                            },
                                                            "next_settlement_amount": {
                                                                "type": "number"
                                                            },
                                                            "max_withdrawal": {
                                                                "type": "number"
                                                            },
                                                            "withdrawal": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "min": {
                                                                        "type": "number"
                                                                    },
                                                                    "max": {
                                                                        "type": "number"
                                                                    },
                                                                    "fee": {
                                                                        "type": "number"
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/withdrawals": {
            "post": {
                "operationId": "createWithdrawal",
                "summary": "Request a withdrawal",
                "description": "Live keys only. The same request as Settlements → Withdraw in the dashboard (same limits, fee and available funds). amount is what arrives; the fee is added on top. Idempotent on the Idempotency-Key header: the same key with the same details returns the original withdrawal (200); different details return 409 DUPLICATE_REQUEST.",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "description": "8–64 characters (letters, digits, . _ : -), unique per withdrawal.",
                        "schema": {
                            "type": "string",
                            "minLength": 8,
                            "maxLength": 64,
                            "pattern": "^[A-Za-z0-9._:\\-]{8,64}$"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreateWithdrawal"
                            },
                            "examples": {
                                "qris": {
                                    "value": {
                                        "payment_method": "QRIS",
                                        "amount": 1500000,
                                        "bank_code": "014",
                                        "account_number": "1234567890"
                                    }
                                },
                                "usdt": {
                                    "value": {
                                        "payment_method": "USDT",
                                        "amount": 250,
                                        "wallet_address": "0xabababababababababababababababababababab",
                                        "network": "BEP20"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Requested",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WithdrawalResponse"
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Replay of an existing Idempotency-Key",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WithdrawalResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "DUPLICATE_REFERENCE, DUPLICATE_REQUEST, WITHDRAWAL_BUSY",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "VALIDATION_ERROR, RETURN_URL_NOT_ALLOWED, WEBSITE_NOT_FOUND, WEBSITE_REQUIRED, AMOUNT_TOO_LARGE, INSUFFICIENT_FUNDS",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "INTERNAL_ERROR",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "get": {
                "operationId": "listWithdrawals",
                "summary": "List withdrawals",
                "description": "Newest first, in the key's environment.",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "requested",
                                "approved",
                                "processing",
                                "completed",
                                "failed",
                                "rejected"
                            ]
                        }
                    },
                    {
                        "name": "payment_method",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "QRIS",
                                "USDT"
                            ]
                        }
                    },
                    {
                        "name": "date_from",
                        "in": "query",
                        "description": "First day (UTC+7) the withdrawal was requested.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "date_to",
                        "in": "query",
                        "description": "Last day (UTC+7), inclusive.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 20
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "default": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of withdrawals",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WithdrawalList"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "VALIDATION_ERROR, RETURN_URL_NOT_ALLOWED, WEBSITE_NOT_FOUND, WEBSITE_REQUIRED, AMOUNT_TOO_LARGE, INSUFFICIENT_FUNDS",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/withdrawals/{reference}": {
            "get": {
                "operationId": "getWithdrawal",
                "summary": "Retrieve a withdrawal",
                "parameters": [
                    {
                        "name": "reference",
                        "in": "path",
                        "required": true,
                        "description": "The PWD… reference returned when the withdrawal was requested.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The withdrawal",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/WithdrawalResponse"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "INVALID_API_KEY, API_KEY_REVOKED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "IP_NOT_ALLOWED, MERCHANT_INACTIVE, LIVE_KEY_REQUIRED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "NOT_FOUND",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "RATE_LIMITED",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "webhooks": {
        "payment.paid": {
            "post": {
                "operationId": "paymentPaidWebhook",
                "summary": "payment.paid",
                "description": "Sent to your webhook URL, signed in the X-PAYWISE-Signature header: hex HMAC-SHA256 of the raw JSON body with your webhook secret.",
                "parameters": [
                    {
                        "name": "X-PAYWISE-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentEvent"
                            },
                            "example": {
                                "event": "payment.paid",
                                "data": {
                                    "reference": "PW20261027165222DEMO",
                                    "merchant_reference": "ORDER-1001",
                                    "payment_method": "QRIS",
                                    "environment": "sandbox",
                                    "customer_id": "user-1042",
                                    "customer_name": "Budi Santoso",
                                    "amount": "25000.00",
                                    "currency": "IDR",
                                    "status": "paid",
                                    "created_at": "2026-10-27T16:49:22+00:00",
                                    "paid_at": "2026-10-27T16:52:22+00:00"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Any 2xx acknowledges the delivery; anything else is retried."
                    }
                }
            }
        },
        "payment.failed": {
            "post": {
                "operationId": "paymentFailedWebhook",
                "summary": "payment.failed",
                "description": "Sent to your webhook URL, signed in the X-PAYWISE-Signature header: hex HMAC-SHA256 of the raw JSON body with your webhook secret.",
                "parameters": [
                    {
                        "name": "X-PAYWISE-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentEvent"
                            },
                            "example": {
                                "event": "payment.failed",
                                "data": {
                                    "reference": "PW20261027165222DEMO",
                                    "merchant_reference": "ORDER-1001",
                                    "payment_method": "QRIS",
                                    "environment": "sandbox",
                                    "customer_id": "user-1042",
                                    "customer_name": "Budi Santoso",
                                    "amount": "25000.00",
                                    "currency": "IDR",
                                    "status": "failed",
                                    "created_at": "2026-10-27T16:49:22+00:00",
                                    "paid_at": null
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Any 2xx acknowledges the delivery; anything else is retried."
                    }
                }
            }
        },
        "payment.expired": {
            "post": {
                "operationId": "paymentExpiredWebhook",
                "summary": "payment.expired",
                "description": "Sent to your webhook URL, signed in the X-PAYWISE-Signature header: hex HMAC-SHA256 of the raw JSON body with your webhook secret.",
                "parameters": [
                    {
                        "name": "X-PAYWISE-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PaymentEvent"
                            },
                            "example": {
                                "event": "payment.expired",
                                "data": {
                                    "reference": "PW20261027165222DEMO",
                                    "merchant_reference": "ORDER-1001",
                                    "payment_method": "QRIS",
                                    "environment": "sandbox",
                                    "customer_id": "user-1042",
                                    "customer_name": "Budi Santoso",
                                    "amount": "25000.00",
                                    "currency": "IDR",
                                    "status": "expired",
                                    "created_at": "2026-10-27T16:49:22+00:00",
                                    "paid_at": null
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Any 2xx acknowledges the delivery; anything else is retried."
                    }
                }
            }
        },
        "withdrawal.completed": {
            "post": {
                "operationId": "withdrawalCompletedWebhook",
                "summary": "withdrawal.completed",
                "description": "Sent to your webhook URL, signed in the X-PAYWISE-Signature header: hex HMAC-SHA256 of the raw JSON body with your webhook secret.",
                "parameters": [
                    {
                        "name": "X-PAYWISE-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WithdrawalEvent"
                            },
                            "example": {
                                "event": "withdrawal.completed",
                                "data": {
                                    "reference": "PWD20261027165222DEMO",
                                    "payment_method": "QRIS",
                                    "environment": "live",
                                    "payout_method": "bank_transfer",
                                    "currency": "IDR",
                                    "network": null,
                                    "amount": 1500000,
                                    "fee": 5000,
                                    "payout_amount": 1495000,
                                    "status": "completed",
                                    "reason": null,
                                    "requested_at": "2026-10-27T16:42:22+00:00",
                                    "completed_at": "2026-10-27T16:52:22+00:00",
                                    "closed_at": null
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Any 2xx acknowledges the delivery; anything else is retried."
                    }
                }
            }
        },
        "withdrawal.failed": {
            "post": {
                "operationId": "withdrawalFailedWebhook",
                "summary": "withdrawal.failed",
                "description": "Sent to your webhook URL, signed in the X-PAYWISE-Signature header: hex HMAC-SHA256 of the raw JSON body with your webhook secret.",
                "parameters": [
                    {
                        "name": "X-PAYWISE-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WithdrawalEvent"
                            },
                            "example": {
                                "event": "withdrawal.failed",
                                "data": {
                                    "reference": "PWD20261027165222DEMO",
                                    "payment_method": "QRIS",
                                    "environment": "live",
                                    "payout_method": "bank_transfer",
                                    "currency": "IDR",
                                    "network": null,
                                    "amount": 1500000,
                                    "fee": 5000,
                                    "payout_amount": 1495000,
                                    "status": "failed",
                                    "reason": "Automatic transfer failed · account number not found",
                                    "requested_at": "2026-10-27T16:42:22+00:00",
                                    "completed_at": null,
                                    "closed_at": "2026-10-27T16:52:22+00:00"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Any 2xx acknowledges the delivery; anything else is retried."
                    }
                }
            }
        },
        "withdrawal.rejected": {
            "post": {
                "operationId": "withdrawalRejectedWebhook",
                "summary": "withdrawal.rejected",
                "description": "Sent to your webhook URL, signed in the X-PAYWISE-Signature header: hex HMAC-SHA256 of the raw JSON body with your webhook secret.",
                "parameters": [
                    {
                        "name": "X-PAYWISE-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WithdrawalEvent"
                            },
                            "example": {
                                "event": "withdrawal.rejected",
                                "data": {
                                    "reference": "PWD20261027165222DEMO",
                                    "payment_method": "QRIS",
                                    "environment": "live",
                                    "payout_method": "bank_transfer",
                                    "currency": "IDR",
                                    "network": null,
                                    "amount": 1500000,
                                    "fee": 5000,
                                    "payout_amount": 1495000,
                                    "status": "rejected",
                                    "reason": "Destination account name does not match",
                                    "requested_at": "2026-10-27T16:42:22+00:00",
                                    "completed_at": null,
                                    "closed_at": "2026-10-27T16:52:22+00:00"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Any 2xx acknowledges the delivery; anything else is retried."
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Your API key: Authorization: Bearer pw_test_… or pw_live_…"
            }
        },
        "schemas": {
            "CreateTransaction": {
                "type": "object",
                "required": [
                    "merchant_reference",
                    "amount",
                    "payment_method",
                    "customer_id"
                ],
                "properties": {
                    "merchant_reference": {
                        "type": "string",
                        "maxLength": 100,
                        "description": "Your own order ID. Doubles as the idempotency key."
                    },
                    "amount": {
                        "type": "number",
                        "description": "QRIS: whole rupiah, 1,000–10,000,000 IDR. USDT: at least 1, up to 2 decimals"
                    },
                    "payment_method": {
                        "type": "string",
                        "enum": [
                            "QRIS",
                            "USDT"
                        ],
                        "description": "QRIS (IDR) or USDT (BEP20) only"
                    },
                    "currency": {
                        "type": "string",
                        "enum": [
                            "IDR",
                            "USDT"
                        ],
                        "description": "Optional. Must match the method: IDR for QRIS, USDT for USDT. Stored as sent, without conversion."
                    },
                    "network": {
                        "type": "string",
                        "enum": [
                            "BEP20"
                        ],
                        "description": "USDT only, required: BEP20. TRC20/ERC20 are rejected. Omit for QRIS."
                    },
                    "customer_id": {
                        "type": "string",
                        "maxLength": 100,
                        "description": "Required (max 100). Your own id for the customer: user id, username or email. Shown in your dashboard, exports, API responses and webhooks, so you can see who paid. Also passed to the payment provider as the customer label, unless it contains \"@\" (emails are never sent)."
                    },
                    "customer_name": {
                        "type": "string",
                        "maxLength": 50,
                        "description": "Optional (max 50), any method. The payer's name, shown in your dashboard. Passed to the provider instead of customer_id when customer_id is an email."
                    },
                    "return_url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Optional. Overrides the website's return URL for this payment. https, on one of your active websites (Dashboard → Websites & webhook)."
                    },
                    "website": {
                        "type": "string",
                        "description": "Optional. The domain of one of your websites (e.g. shop.example.com); its return URL is used. Omit both to use your default website. A mirror domain counts as its website: the return URL and a webhook URL on the website's domain move to that mirror."
                    },
                    "expires_in": {
                        "type": "integer",
                        "minimum": 60,
                        "maximum": 600,
                        "description": "Optional, QRIS only. How long the QR code stays payable, in seconds: 60 to 1,200 (the default)."
                    }
                }
            },
            "Transaction": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string"
                    },
                    "merchant_reference": {
                        "type": "string"
                    },
                    "payment_method": {
                        "type": "string",
                        "enum": [
                            "QRIS",
                            "USDT"
                        ]
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "live",
                            "sandbox"
                        ]
                    },
                    "customer_id": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "customer_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "amount": {
                        "type": "number"
                    },
                    "currency": {
                        "type": "string"
                    },
                    "network": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "paid",
                            "failed",
                            "expired"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "paid_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "qr_string": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "QRIS: the string to render as a QR code, while pending."
                    },
                    "pay_address": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "USDT: the BEP20 deposit address, while pending."
                    },
                    "pay_amount": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "USDT: the exact amount to send, while pending."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "checkout_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri",
                        "description": "The hosted payment page, when the website uses it."
                    }
                }
            },
            "TransactionResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "const": true
                    },
                    "data": {
                        "$ref": "#/components/schemas/Transaction"
                    }
                }
            },
            "TransactionList": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "const": true
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Transaction"
                        }
                    },
                    "meta": {
                        "type": "object",
                        "properties": {
                            "page": {
                                "type": "integer"
                            },
                            "per_page": {
                                "type": "integer"
                            },
                            "total": {
                                "type": "integer"
                            },
                            "last_page": {
                                "type": "integer"
                            }
                        }
                    }
                }
            },
            "CreateWithdrawal": {
                "type": "object",
                "required": [
                    "payment_method",
                    "amount"
                ],
                "properties": {
                    "payment_method": {
                        "type": "string",
                        "enum": [
                            "QRIS",
                            "USDT"
                        ],
                        "description": "Required. Which funds to withdraw: QRIS (paid out to a bank account in IDR) or USDT (sent to a BEP20 wallet)."
                    },
                    "amount": {
                        "type": "number",
                        "description": "Required. What arrives at the destination, in the rail's currency (up to 2 decimals)."
                    },
                    "bank_code": {
                        "type": "string",
                        "enum": [
                            "002",
                            "008",
                            "009",
                            "011",
                            "013",
                            "014",
                            "016",
                            "019",
                            "022",
                            "023",
                            "028",
                            "031",
                            "032",
                            "033",
                            "036",
                            "037",
                            "040",
                            "041",
                            "042",
                            "046",
                            "047",
                            "048",
                            "050",
                            "052",
                            "054",
                            "057",
                            "059",
                            "061",
                            "067",
                            "068",
                            "069",
                            "076",
                            "087",
                            "088",
                            "089",
                            "095",
                            "097",
                            "110",
                            "111",
                            "112",
                            "113",
                            "114",
                            "115",
                            "116",
                            "117",
                            "118",
                            "119",
                            "120",
                            "121",
                            "122",
                            "123",
                            "124",
                            "125",
                            "126",
                            "127",
                            "128",
                            "129",
                            "130",
                            "131",
                            "132",
                            "133",
                            "134",
                            "135",
                            "145",
                            "146",
                            "147",
                            "151",
                            "152",
                            "153",
                            "157",
                            "161",
                            "164",
                            "167",
                            "200",
                            "212",
                            "213",
                            "405",
                            "422",
                            "425",
                            "426",
                            "427",
                            "441",
                            "451",
                            "459",
                            "466",
                            "472",
                            "484",
                            "485",
                            "490",
                            "491",
                            "494",
                            "498",
                            "501",
                            "503",
                            "506",
                            "513",
                            "517",
                            "520",
                            "521",
                            "523",
                            "526",
                            "531",
                            "535",
                            "536",
                            "542",
                            "547",
                            "548",
                            "553",
                            "555",
                            "558",
                            "559",
                            "562",
                            "564",
                            "566",
                            "567",
                            "945",
                            "947",
                            "949",
                            "950",
                            "911",
                            "DANA",
                            "OVO",
                            "GOPAY",
                            "SHOPEEPAY"
                        ],
                        "description": "QRIS only, required. A code from the list below: 3 digits for a bank, or DANA, OVO, GOPAY or SHOPEEPAY for an e-wallet (account_number is then the 08… phone number). An e-wallet takes at most IDR 10,000,000 per withdrawal and has no owner name check: a wrong number is still paid."
                    },
                    "account_number": {
                        "type": "string",
                        "pattern": "^[0-9]{5,30}$",
                        "description": "QRIS only, required. 5 to 30 digits."
                    },
                    "wallet_address": {
                        "type": "string",
                        "pattern": "^0x[a-fA-F0-9]{40}$",
                        "description": "USDT only, required. A BEP20 address: 0x followed by 40 hex characters."
                    },
                    "network": {
                        "type": "string",
                        "enum": [
                            "BEP20"
                        ],
                        "description": "USDT only, required: BEP20."
                    }
                }
            },
            "Withdrawal": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string"
                    },
                    "payment_method": {
                        "type": "string",
                        "enum": [
                            "QRIS",
                            "USDT"
                        ]
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "live",
                            "sandbox"
                        ]
                    },
                    "payout_method": {
                        "type": "string",
                        "enum": [
                            "bank_transfer",
                            "bep20_wallet"
                        ]
                    },
                    "currency": {
                        "type": "string"
                    },
                    "network": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "amount": {
                        "type": "number",
                        "description": "Taken from your available funds: payout_amount + fee."
                    },
                    "fee": {
                        "type": "number"
                    },
                    "payout_amount": {
                        "type": "number",
                        "description": "Sent to the destination."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "requested",
                            "approved",
                            "processing",
                            "completed",
                            "failed",
                            "rejected"
                        ]
                    },
                    "destination": {
                        "type": "object",
                        "description": "QRIS: bank_code, bank_name, account_number, account_holder (the name the bank holds, filled in by the account check; null until then). USDT: wallet_address, network."
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it failed or was rejected."
                    },
                    "requested_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "closed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "WithdrawalResponse": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "const": true
                    },
                    "data": {
                        "$ref": "#/components/schemas/Withdrawal"
                    }
                }
            },
            "WithdrawalList": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "const": true
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Withdrawal"
                        }
                    },
                    "meta": {
                        "type": "object",
                        "properties": {
                            "page": {
                                "type": "integer"
                            },
                            "per_page": {
                                "type": "integer"
                            },
                            "total": {
                                "type": "integer"
                            },
                            "last_page": {
                                "type": "integer"
                            }
                        }
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean",
                        "const": false
                    },
                    "error": {
                        "type": "object",
                        "required": [
                            "code",
                            "message"
                        ],
                        "properties": {
                            "code": {
                                "type": "string",
                                "enum": [
                                    "INVALID_API_KEY",
                                    "API_KEY_REVOKED",
                                    "IP_NOT_ALLOWED",
                                    "MERCHANT_INACTIVE",
                                    "VALIDATION_ERROR",
                                    "RETURN_URL_NOT_ALLOWED",
                                    "WEBSITE_NOT_FOUND",
                                    "WEBSITE_REQUIRED",
                                    "AMOUNT_TOO_LARGE",
                                    "DUPLICATE_REFERENCE",
                                    "LIVE_KEY_REQUIRED",
                                    "INSUFFICIENT_FUNDS",
                                    "DUPLICATE_REQUEST",
                                    "WITHDRAWAL_BUSY",
                                    "NOT_FOUND",
                                    "METHOD_NOT_ALLOWED",
                                    "RATE_LIMITED",
                                    "PROVIDER_ERROR",
                                    "PAYMENT_METHOD_PAUSED",
                                    "WITHDRAWALS_PAUSED",
                                    "MAINTENANCE",
                                    "PROVIDER_NOT_CONNECTED",
                                    "PROVIDER_TIMEOUT",
                                    "INTERNAL_ERROR"
                                ]
                            },
                            "message": {
                                "type": "string"
                            },
                            "available": {
                                "type": "number",
                                "description": "INSUFFICIENT_FUNDS only: the largest amount that can be withdrawn now."
                            },
                            "fields": {
                                "type": "object",
                                "description": "VALIDATION_ERROR only: messages per field.",
                                "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "PaymentEvent": {
                "type": "object",
                "properties": {
                    "event": {
                        "type": "string",
                        "enum": [
                            "payment.paid",
                            "payment.failed",
                            "payment.expired"
                        ]
                    },
                    "data": {
                        "type": "object"
                    }
                }
            },
            "WithdrawalEvent": {
                "type": "object",
                "properties": {
                    "event": {
                        "type": "string",
                        "enum": [
                            "withdrawal.completed",
                            "withdrawal.failed",
                            "withdrawal.rejected"
                        ]
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "reference": {
                                "type": "string"
                            },
                            "payment_method": {
                                "type": "string"
                            },
                            "environment": {
                                "type": "string"
                            },
                            "payout_method": {
                                "type": "string",
                                "enum": [
                                    "bank_transfer",
                                    "bep20_wallet"
                                ]
                            },
                            "currency": {
                                "type": "string"
                            },
                            "network": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "amount": {
                                "type": "number"
                            },
                            "fee": {
                                "type": "number"
                            },
                            "payout_amount": {
                                "type": "number"
                            },
                            "status": {
                                "type": "string",
                                "enum": [
                                    "completed",
                                    "failed",
                                    "rejected"
                                ]
                            },
                            "reason": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            },
                            "requested_at": {
                                "type": "string",
                                "format": "date-time"
                            },
                            "completed_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            },
                            "closed_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            }
                        }
                    }
                }
            }
        }
    }
}