{
  "openapi": "3.0.3",
  "info": {
    "title": "UrontoPay Payment API",
    "version": "1.0.0",
    "description": "Create hosted payment links and verify payment transactions. Every API request must be sent from a trusted server and include CLIENT-ID, SECRET-KEY, and BRAND-KEY headers. Never expose SECRET-KEY in browser JavaScript, mobile applications, public repositories, logs, screenshots, or client-facing responses.",
    "contact": {
      "name": "UrontoPay Support"
    }
  },
  "externalDocs": {
    "description": "Human-readable integration documentation",
    "url": "https://urontopay.com/developers/docs"
  },
  "servers": [
    {
      "url": "https://pay1.urontopay.com",
      "description": "Production API"
    }
  ],
  "tags": [
    {
      "name": "Payments",
      "description": "Create a hosted payment URL"
    },
    {
      "name": "Verification",
      "description": "Verify a transaction before fulfilling an order"
    }
  ],
  "components": {
    "securitySchemes": {
      "ClientId": {
        "type": "apiKey",
        "in": "header",
        "name": "CLIENT-ID",
        "description": "Client ID copied from Dashboard → API Credentials."
      },
      "SecretKey": {
        "type": "apiKey",
        "in": "header",
        "name": "SECRET-KEY",
        "description": "Private server-side Secret Key. Never expose this value to a browser or client application."
      },
      "BrandKey": {
        "type": "apiKey",
        "in": "header",
        "name": "BRAND-KEY",
        "description": "Brand Key for the brand that will receive the payment."
      }
    },
    "schemas": {
      "CreatePaymentRequest": {
        "type": "object",
        "required": [
          "amount",
          "success_url",
          "cancel_url"
        ],
        "properties": {
          "amount": {
            "type": "number",
            "format": "double",
            "minimum": 0.01,
            "maximum": 1000000,
            "example": 500
          },
          "cus_name": {
            "type": "string",
            "maxLength": 255,
            "example": "Customer Name"
          },
          "cus_email": {
            "type": "string",
            "format": "email",
            "example": "customer@example.com"
          },
          "success_url": {
            "type": "string",
            "format": "uri",
            "example": "https://merchant.example/payment/success"
          },
          "cancel_url": {
            "type": "string",
            "format": "uri",
            "example": "https://merchant.example/payment/cancel"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "example": "https://merchant.example/webhooks/urontopay"
          },
          "metadata": {
            "type": "object",
            "description": "Merchant-owned order or reference data returned during verification.",
            "additionalProperties": true,
            "example": {
              "order_id": "ORDER-1001"
            }
          },
          "return_type": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ],
            "default": "GET",
            "example": "GET"
          }
        },
        "additionalProperties": false
      },
      "CreatePaymentResponse": {
        "type": "object",
        "required": [
          "status",
          "message",
          "payment_url"
        ],
        "properties": {
          "status": {
            "type": "integer",
            "example": 1
          },
          "message": {
            "type": "string",
            "example": "Payment Link"
          },
          "payment_url": {
            "type": "string",
            "format": "uri",
            "example": "https://pay1.urontopay.com/api/execute/59522f..."
          }
        }
      },
      "VerifyPaymentRequest": {
        "type": "object",
        "required": [
          "transaction_id"
        ],
        "properties": {
          "transaction_id": {
            "type": "string",
            "example": "UP123456"
          }
        },
        "additionalProperties": false
      },
      "VerifyPaymentResponse": {
        "type": "object",
        "properties": {
          "cus_name": {
            "type": "string",
            "example": "Customer Name"
          },
          "cus_email": {
            "type": "string",
            "format": "email",
            "example": "customer@example.com"
          },
          "amount": {
            "type": "string",
            "example": "500.000"
          },
          "transaction_id": {
            "type": "string",
            "example": "UP123456"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "order_id": "ORDER-1001"
            }
          },
          "payment_method": {
            "type": "string",
            "example": "bkash"
          },
          "status": {
            "type": "string",
            "description": "Mark the local order as paid only when this value is COMPLETED and the verified amount and metadata match the local order.",
            "enum": [
              "COMPLETED",
              "PENDING",
              "FAILED",
              "CANCELLED"
            ],
            "example": "COMPLETED"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "status": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ],
            "example": 0
          },
          "message": {
            "type": "string",
            "example": "Client ID, Secret Key and Brand Key are required."
          }
        }
      },
      "CallbackPayload": {
        "type": "object",
        "description": "Typical return or webhook fields. Treat this payload as untrusted until transaction_id is verified with POST /api/payment/verify.",
        "properties": {
          "paymentMethod": {
            "type": "string",
            "example": "bkash"
          },
          "transactionId": {
            "type": "string",
            "example": "UP123456"
          },
          "paymentAmount": {
            "type": "number",
            "example": 500
          },
          "paymentFee": {
            "type": "number",
            "example": 0
          },
          "status": {
            "type": "string",
            "example": "completed"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid or missing request data.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid credentials, mismatched account/brand, disabled credential, or inactive plan.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Payment or transaction was not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected server processing error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "ClientId": [],
      "SecretKey": [],
      "BrandKey": []
    }
  ],
  "paths": {
    "/api/payment/create": {
      "post": {
        "tags": [
          "Payments"
        ],
        "operationId": "createPayment",
        "summary": "Create a hosted payment link",
        "description": "Send this request from a trusted server. Save the local order as pending before redirecting the customer to payment_url.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentRequest"
              },
              "examples": {
                "standard": {
                  "summary": "Standard payment request",
                  "value": {
                    "amount": 500,
                    "cus_name": "Customer Name",
                    "cus_email": "customer@example.com",
                    "success_url": "https://merchant.example/payment/success",
                    "cancel_url": "https://merchant.example/payment/cancel",
                    "webhook_url": "https://merchant.example/webhooks/urontopay",
                    "return_type": "GET",
                    "metadata": {
                      "order_id": "ORDER-1001"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment link created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePaymentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-integration-notes": [
          "Do not call this endpoint from browser JavaScript.",
          "Load credentials from environment variables.",
          "Redirect the customer to payment_url only after a successful response.",
          "Do not mark the local order paid at this stage."
        ]
      }
    },
    "/api/payment/verify": {
      "post": {
        "tags": [
          "Verification"
        ],
        "operationId": "verifyPayment",
        "summary": "Verify a payment transaction",
        "description": "Call this endpoint from your trusted server after receiving transactionId from a browser return or webhook. Mark the local order paid only if status is COMPLETED and the verified amount and metadata match the local order.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyPaymentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transaction information returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyPaymentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "x-integration-notes": [
          "Treat browser return and webhook fields as untrusted until verification succeeds.",
          "Require status === COMPLETED.",
          "Compare verified amount with the expected local order amount.",
          "Compare metadata.order_id with the local order reference.",
          "Make order updates idempotent so duplicate callbacks cannot fulfill twice."
        ]
      }
    }
  },
  "x-ai-instructions": {
    "credentialEnvironmentVariables": [
      "URONTOPAY_BASE_URL",
      "URONTOPAY_CLIENT_ID",
      "URONTOPAY_SECRET_KEY",
      "URONTOPAY_BRAND_KEY"
    ],
    "requiredImplementation": [
      "Create a server-side payment endpoint.",
      "Redirect the customer to payment_url.",
      "Implement success, cancel, and webhook handlers.",
      "Verify transactionId server-side.",
      "Require COMPLETED status and compare amount and metadata.order_id.",
      "Use timeouts, clear error handling, and idempotent order updates."
    ],
    "prohibitedImplementation": [
      "Do not embed SECRET-KEY in HTML or browser JavaScript.",
      "Do not expose credentials in client responses, logs, screenshots, or repositories.",
      "Do not trust callback parameters without server-side verification."
    ]
  }
}
