{
    "openapi": "3.1.0",
    "info": {
        "title": "PAYUNIT Merchant API",
        "version": "2.0.0",
        "description": "Create hosted payment sessions for Togo, Lahza, and supported EVM stablecoins. All amount fields are decimal USD strings: 1 = 1.00 USD, 1.75 = 1.75 USD, and 74 = 74.00 USD."
    },
    "servers": [
        {
            "url": "https://payunit.co"
        }
    ],
    "tags": [
        {
            "name": "Payment Intents",
            "description": "Hosted online payments"
        }
    ],
    "paths": {
        "/api/v1/payment-intents": {
            "post": {
                "tags": [
                    "Payment Intents"
                ],
                "summary": "Create a payment intent",
                "operationId": "createPaymentIntent",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 190
                        },
                        "description": "Unique per commercial operation. Reusing it with the same body returns the same intent."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CreatePaymentIntent"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaymentIntent"
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v1/payment-intents/{id}": {
            "get": {
                "tags": [
                    "Payment Intents"
                ],
                "summary": "Retrieve a payment intent",
                "operationId": "getPaymentIntent",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "^pi_live_[A-Za-z0-9_-]+$"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Current state",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PaymentIntent"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Payment intent not found"
                    }
                }
            }
        }
    },
    "webhooks": {
        "paymentIntentStatusChanged": {
            "post": {
                "summary": "Payment status event",
                "description": "PAYUNIT sends a signed JSON event to the HTTPS webhook URL configured by the merchant. Verify X-Payunit-Signature using HMAC-SHA256 over timestamp + \".\" + raw body. X-Payunit-Event contains the event type.",
                "parameters": [
                    {
                        "name": "X-Payunit-Event",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "payment_intent.succeeded"
                    },
                    {
                        "name": "X-Payunit-Signature",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "example": "t=1785146400,v1=hex_signature"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookEvent"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Acknowledged"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "PAYUNIT API key"
            }
        },
        "schemas": {
            "MoneyString": {
                "type": "string",
                "pattern": "^\\d+(?:\\.\\d{1,2})?$",
                "examples": [
                    "1",
                    "1.75",
                    "74.00"
                ],
                "description": "Decimal USD units, never cents. At most two decimal places."
            },
            "Customer": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                    "name": {
                        "type": "string",
                        "maxLength": 160
                    },
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "phone": {
                        "type": "string",
                        "example": "+970599000000"
                    },
                    "city": {
                        "type": "string",
                        "maxLength": 120
                    },
                    "country": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 2,
                        "example": "PS"
                    }
                }
            },
            "CreatePaymentIntent": {
                "type": "object",
                "required": [
                    "amount",
                    "currency"
                ],
                "additionalProperties": true,
                "properties": {
                    "amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "currency": {
                        "type": "string",
                        "enum": [
                            "USD"
                        ]
                    },
                    "external_ref": {
                        "type": "string",
                        "maxLength": 120
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "success_url": {
                        "type": "string",
                        "format": "uri",
                        "pattern": "^https://"
                    },
                    "cancel_url": {
                        "type": "string",
                        "format": "uri",
                        "pattern": "^https://"
                    },
                    "methods": {
                        "type": "array",
                        "uniqueItems": true,
                        "items": {
                            "type": "string",
                            "enum": [
                                "togo",
                                "lahza",
                                "crypto"
                            ]
                        }
                    },
                    "customer": {
                        "$ref": "#/components/schemas/Customer"
                    },
                    "metadata": {
                        "type": "object",
                        "additionalProperties": true
                    },
                    "expires_in": {
                        "type": "integer",
                        "minimum": 300,
                        "maximum": 86400,
                        "default": 1800
                    }
                },
                "example": {
                    "amount": "25.00",
                    "currency": "USD",
                    "external_ref": "ORDER-1001",
                    "description": "Order payment",
                    "success_url": "https://merchant.example/payment/success",
                    "cancel_url": "https://merchant.example/payment/cancel",
                    "methods": [
                        "togo",
                        "lahza",
                        "crypto"
                    ]
                }
            },
            "CryptoState": {
                "type": "object",
                "properties": {
                    "address": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "requested_amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "received_amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "remaining_amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "overpayment_amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "txid": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                }
            },
            "PaymentIntent": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "object": {
                        "type": "string",
                        "const": "payment_intent"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "requires_payment_method",
                            "processing",
                            "succeeded",
                            "failed",
                            "cancelled",
                            "expired"
                        ]
                    },
                    "amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "currency": {
                        "type": "string",
                        "enum": [
                            "USD"
                        ]
                    },
                    "fee": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "net_amount": {
                        "$ref": "#/components/schemas/MoneyString"
                    },
                    "payment_method": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "external_ref": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "paid": {
                        "type": "boolean"
                    },
                    "available_methods": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "checkout_url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "crypto": {
                        "$ref": "#/components/schemas/CryptoState"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "paid_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "WebhookEvent": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "examples": [
                            "payment_intent.succeeded"
                        ]
                    },
                    "created": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Unix timestamp in seconds",
                        "example": 1785146400
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "object": {
                                "$ref": "#/components/schemas/PaymentIntent"
                            }
                        }
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "object",
                        "properties": {
                            "code": {
                                "type": "string"
                            },
                            "message": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "responses": {
            "BadRequest": {
                "description": "Invalid request",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Unauthorized": {
                "description": "Invalid or disabled API key",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Conflict": {
                "description": "Idempotency conflict or unavailable payment methods",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "Rate limit exceeded",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            }
        }
    }
}