{"openapi":"3.0.0","paths":{"/checkout/sessions":{"post":{"description":"Creates a new checkout session for hosted or embedded checkout. Returns a session with a URL to redirect customers for payment.","operationId":"createCheckoutSession","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutSession"}}}},"responses":{"201":{"description":"Checkout session created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"400":{"description":"Invalid checkout session payload: missing or invalid line items, currency mismatch across line items, or both `customerId` and `customerDetails` provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"One or more referenced resources (price, product, customer, coupon) do not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such price: price_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Create a checkout session","tags":["Checkout Sessions"]}},"/checkout/sessions/{id}":{"get":{"description":"Retrieves an existing checkout session by ID. Returns full session data including clientSecret.","operationId":"getCheckoutSession","parameters":[{"name":"id","required":true,"in":"path","description":"Checkout session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Checkout session retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The checkout session ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such checkout_session: cs_test_a1b2c3d4","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Retrieve a checkout session","tags":["Checkout Sessions"]},"patch":{"description":"Updates an open checkout session. Immutable fields (mode, uiMode, submitType, currency, expiresAfterMinutes) cannot be changed after creation.","operationId":"updateMerchantCheckoutSession","parameters":[{"name":"id","required":true,"in":"path","description":"Checkout session ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMerchantCheckoutSession"}}}},"responses":{"200":{"description":"Checkout session updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"400":{"description":"Invalid update payload, or an attempt to change an immutable field (mode, uiMode, submitType, currency, expiresAfterMinutes).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The checkout session ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such checkout_session: cs_test_a1b2c3d4","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"409":{"description":"Only sessions in the `open` state can be updated. Completed or expired sessions are immutable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_invalid_state","message":"Cannot update a checkout session that is not open.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_invalid_state"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Update a checkout session","tags":["Checkout Sessions"]}},"/checkout/sessions/{id}/expire":{"post":{"description":"Expires an open checkout session. Expired sessions cannot be used for payment.","operationId":"expireCheckoutSession","parameters":[{"name":"id","required":true,"in":"path","description":"Checkout session ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Checkout session expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The checkout session ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such checkout_session: cs_test_a1b2c3d4","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"409":{"description":"Only sessions in the `open` state can be expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_invalid_state","message":"Cannot expire a checkout session that is already completed or expired.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_invalid_state"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Expire a checkout session","tags":["Checkout Sessions"]}},"/customers":{"post":{"description":"Creates a new customer record.\n\nAt least one contact method (email or phone) is required. Customers are environment-specific (test vs live database).","operationId":"createCustomer","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomer"}}}},"responses":{"201":{"description":"Customer created successfully","content":{"application/json":{"schema":{"example":{"id":"cus_abc123","merchantId":"merch_xyz789","name":"John Doe","email":"john@example.com","phone":"+201234567890","currency":"EGP","spendData":{"amountDisputeLosses":"0","amountRefunded":"0","averageOrderValue":"0","currency":"EGP","firstPurchaseAt":"","grossSpend":"0","lastPurchaseAt":"","netSpend":"0","numPayments":"0"},"balance":"0","createdAt":"2024-01-01T00:00:00.000Z"}}}}},"400":{"description":"Invalid customer payload, or no contact method (email or phone) provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"409":{"description":"Another customer in this account / mode already uses the provided email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_invalid_state","message":"A customer with this email already exists.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_invalid_state"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Create a customer","tags":["Customers"]},"get":{"description":"Lists customers with search and pagination. Returns only essential fields: id, createdAt, name, phone, email, and latestPaymentMethod. Search supports customer ID, name, email, or phone (supports comma-separated terms).","operationId":"listCustomers","parameters":[{"name":"type","required":false,"in":"query","description":"Filter by customer type: registered (merchant-created) or guest (auto-created during checkout)","schema":{"enum":["registered","guest"],"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search by customer ID, name, email, or phone (supports comma-separated terms)","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"type":"number"}},{"name":"page","required":false,"in":"query","description":"Page number (1-based)","schema":{"minimum":1,"type":"number"}}],"responses":{"200":{"description":"Customers retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCustomersResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"List customers","tags":["Customers"]}},"/customers/{id}":{"get":{"description":"Retrieves customer lifecycle information (id, type, name, email, phone, address, metadata). Response shape is identical to the `customer.*` webhook payload. For transaction counts + payment methods, call `GET /customers/:id/stats`.","operationId":"getCustomer","parameters":[{"name":"id","required":true,"in":"path","description":"Customer ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Customer retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The customer ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such customer: cus_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Get customer by ID","tags":["Customers"]}},"/payment-links":{"post":{"description":"Creates a new payment link — a shareable URL you can send to customers.\n\nFeatures:\n- Supports multiple line items with adjustable quantities\n- Custom fields for collecting additional customer information\n- After-completion settings (redirect or hosted confirmation)\n- Automatic amount calculation from line items\n- Validates currency consistency across line items","operationId":"createPaymentLink","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePaymentLink"}}}},"responses":{"201":{"description":"Payment link created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentLinkResponse"}}}},"400":{"description":"Invalid payment link payload: missing or invalid line items, currency mismatch, or after-completion misconfiguration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"One or more line-item prices do not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such price: price_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Create a payment link","tags":["Payment Links"]},"get":{"description":"Lists payment links with filtering, pagination, and search.\n\nFeatures:\n- Filter by active status\n- Search by product name, description, or unit label\n- Filter by amount (equal, between, greater, less)\n- Filter by date (last period, equal, between, after, before)\n- Pagination support","operationId":"listPaymentLinks","parameters":[{"name":"page","required":false,"in":"query","description":"Page number (1-based)","schema":{"minimum":1,"maximum":2147483647,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":20,"example":20,"type":"number"}},{"name":"active","required":false,"in":"query","description":"Filter by active status (true/false)","schema":{"example":"true","type":"string"}},{"name":"search","required":false,"in":"query","description":"Search by product name, description, or unitLabel in line items (supports comma-separated terms)","schema":{"example":"product name","type":"string"}},{"name":"amount","required":false,"in":"query","description":"Amount filter condition (serialized string format: eq:100 or bt:10,100 or gt:50 or lt:200)","schema":{"example":"gt:1000","type":"string"}},{"name":"date","required":false,"in":"query","description":"Date filter condition (serialized string format: last:7,days or between:2024-01-01,2024-12-31)","schema":{"example":"last:7,days","type":"string"}},{"name":"timezone","required":false,"in":"query","description":"Timezone for date filtering","schema":{"default":"UTC","example":"Africa/Cairo","type":"string"}}],"responses":{"200":{"description":"Payment links retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPaymentLinksResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"List payment links","tags":["Payment Links"]}},"/payment-links/{id}":{"get":{"description":"Retrieves a payment link with all related data including:\n- Line items with prices and products\n- Custom fields with dropdown options\n- After-completion settings","operationId":"getPaymentLink","parameters":[{"name":"id","required":true,"in":"path","description":"Payment link ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Payment link retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentLinkResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The payment link ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such payment_link: plink_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Get a payment link by ID","tags":["Payment Links"]},"patch":{"description":"Partially updates an existing payment link. Only provided fields will be updated.\n\nFeatures:\n- Partial updates: only send fields you want to update\n- Updates line items with adjustable quantities (if provided, replaces all existing line items)\n- Updates custom fields (if provided, replaces all existing custom fields)\n- Updates after-completion settings (if provided, replaces existing settings)\n- Recalculates amount from line items when line items are updated\n- Validates currency consistency across line items when line items are updated\n\nNotes:\n- If `lineItems` is provided, all existing line items are replaced\n- If `customFields` is provided, all existing custom fields are replaced\n- If `customFields` is an empty array, all custom fields are removed\n- `expiresAt` can be set to `null` to remove expiration","operationId":"updatePaymentLink","parameters":[{"name":"id","required":true,"in":"path","description":"Payment link ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePaymentLink"}}}},"responses":{"200":{"description":"Payment link updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentLinkResponse"}}}},"400":{"description":"Invalid update payload: validation failure, currency mismatch across new line items, or after-completion misconfiguration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The payment link, or one of the prices referenced in the update, does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such payment_link: plink_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Update a payment link","tags":["Payment Links"]}},"/products/{id}":{"get":{"description":"Retrieves product information including all associated prices. Response shape is identical to the `product.*` webhook payload. For per-price usage counts, call `GET /products/:id/stats`.","operationId":"getProduct","parameters":[{"name":"id","required":true,"in":"path","description":"Product ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Product retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The product ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such product: prod_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Get product by ID","tags":["Products"]},"patch":{"description":"Updates product information. Can update product data fields, default price, and image.\n\n- The `defaultPrice` field should be the ID of the Price object to set as the default price for this product\n- The `image` field should be a URL string (use the `/upload-url` endpoint to get a one-time upload URL first)","operationId":"updateProduct","parameters":[{"name":"id","required":true,"in":"path","description":"Product ID","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"Product data. The image field should be a URL string from Cloudflare Images.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProduct"}}}},"responses":{"200":{"description":"Product updated successfully"},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The product ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such product: prod_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Update product","tags":["Products"]},"delete":{"description":"Deletes a product and cascade-deletes all of its prices in one transaction. Fails if any of the product's prices have ever been referenced by a line item — in that case the product must be archived instead.","operationId":"deleteProduct","parameters":[{"name":"id","required":true,"in":"path","description":"Product ID","schema":{"type":"string"}}],"responses":{"204":{"description":"Product deleted successfully"},"400":{"description":"The product has one or more prices that have been referenced by a line item. Archive the product (set `active: false`) instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_invalid_state","message":"Cannot delete a product that has been used in a checkout session or payment link. Archive it instead.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_invalid_state"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The product ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such product: prod_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Delete product","tags":["Products"]}},"/products":{"get":{"description":"Lists products with search and filters.\n\nSupports:\n- Active filter (`active=true/false`)\n- Metadata filter (JSON string)\n- Search in `name`, `description`, and `unitLabel` fields\n- Pagination","operationId":"listProducts","parameters":[{"name":"metadata","required":false,"in":"query","description":"Metadata filter as JSON string (e.g., '{\"category\":\"subscription\"}')","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search in name, description, or unitLabel (supports comma-separated terms)","schema":{"type":"string"}},{"name":"active","required":false,"in":"query","description":"Filter by active status","schema":{"type":"boolean"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"type":"number"}},{"name":"page","required":false,"in":"query","description":"Page number (1-based)","schema":{"minimum":1,"type":"number"}}],"responses":{"200":{"description":"Products retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListProductsResponse"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"List products","tags":["Products"]},"post":{"description":"Creates a new product.\n\nOptionally includes:\n- An image URL (use the `/upload-url` endpoint to get a one-time upload URL first)\n- A default price object which will be set as the default price for this product","operationId":"createProduct","requestBody":{"required":true,"description":"Product data. The image field should be a URL string from Cloudflare Images.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProduct"}}}},"responses":{"201":{"description":"Product created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductListItem"}}}},"400":{"description":"Invalid product payload: missing `name`, invalid `defaultPrice`, or malformed image URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Create a product","tags":["Products"]}},"/prices":{"post":{"description":"Creates a new Price for an existing Product.","operationId":"createPrice","parameters":[{"name":"productId","required":true,"in":"query","description":"Product ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrice"}}}},"responses":{"201":{"description":"Price created successfully","content":{"application/json":{"schema":{"example":{"id":"price_abc123","productId":"prod_xyz789","merchantId":"merch_def456","currency":"EGP","unitAmount":10000,"type":"ONE_TIME","active":true,"createdAt":"2024-01-01T00:00:00.000Z"}}}}},"400":{"description":"Invalid price payload: missing/invalid currency, unit amount, or recurring configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The `productId` query parameter does not match an existing product in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such product: prod_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Create a price","tags":["Prices"]}},"/prices/{id}":{"patch":{"description":"Updates the specified price by setting the values of the parameters passed. Any parameters not provided are left unchanged.","operationId":"updatePrice","parameters":[{"name":"id","required":true,"in":"path","description":"Price ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePrice"}}}},"responses":{"200":{"description":"Price updated successfully"},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The price ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such price: price_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Update a price","tags":["Prices"]},"delete":{"description":"Deletes a price. Only prices that have never been referenced by a line item can be deleted — once a price has been used in any checkout session or payment link, archive it instead.\n\nIf the price is set as the default price for a product, the default price reference will be cleared.","operationId":"deletePrice","parameters":[{"name":"id","required":true,"in":"path","description":"Price ID","schema":{"type":"string"}}],"responses":{"204":{"description":"Price deleted successfully"},"400":{"description":"The price has been used in at least one checkout session or payment link. Archive it (set `active: false`) instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_invalid_state","message":"Cannot delete a price that has been referenced by a line item. Archive it instead.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_invalid_state"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The price ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such price: price_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Delete a price","tags":["Prices"]}},"/refunds":{"post":{"description":"Creates a full or partial refund for a successful charge.\n\nTarget: provide EXACTLY ONE of `chargeId` or `paymentIntentId`. When `paymentIntentId` is supplied the server resolves it to the unique succeeded charge under that intent; the request is rejected if the intent has zero or multiple succeeded charges.\n\nFeatures:\n- Full or partial refunds\n- Ledger reversal (double-entry bookkeeping)\n- Balance updates (debits available funds)\n- Updates `charge.amountRefunded`\n- Updates `paymentIntent.amountRefunded`\n\nRefund behaviour:\n- Hits available balance immediately (no hold period)\n- Creates negative balance transactions\n- Reverses the original charge's ledger entries\n- Platform keeps fees (business decision)","operationId":"createRefund","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRefund"}}}},"responses":{"201":{"description":"Refund created successfully","content":{"application/json":{"schema":{"example":{"id":"re_abc123","chargeId":"ch_xyz789","amount":"50000","currency":"EGP","status":"succeeded","reason":"requested_by_customer","balanceTransactionId":"bt_def456","createdAt":"2024-01-01T00:00:00.000Z"}}}}},"400":{"description":"Invalid refund payload: both `chargeId` and `paymentIntentId` supplied, neither supplied, the target intent has zero or multiple succeeded charges, or the refund amount exceeds what's refundable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"parameter_invalid","message":"Invalid value for parameter.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#parameter_invalid"},"request_id":"req_abc123def456"}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The target Charge or PaymentIntent does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such charge: ch_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"409":{"description":"Another refund for the same charge is already being processed. Refunds on a single charge are serialized to prevent over-refunding; retry in a moment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_invalid_state","message":"The resource is in a state that does not allow this operation.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_invalid_state"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Create a refund","tags":["Refunds"]},"get":{"description":"Lists refunds with optional filters for charge and pagination.","operationId":"listRefunds","parameters":[{"name":"chargeId","required":false,"in":"query","description":"Filter by charge ID","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of results (max 100)","schema":{"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Pagination offset","schema":{"type":"number"}}],"responses":{"200":{"description":"Refunds retrieved successfully","content":{"application/json":{"schema":{"example":{"data":[{"id":"re_abc123","chargeId":"ch_xyz789","amount":"50000","currency":"EGP","status":"succeeded","createdAt":"2024-01-01T00:00:00.000Z"}],"hasMore":false}}}}},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"List refunds","tags":["Refunds"]}},"/refunds/{id}":{"get":{"description":"Retrieves a refund with all details including ledger info.","operationId":"getRefund","parameters":[{"name":"id","required":true,"in":"path","description":"Refund ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Refund retrieved successfully"},"401":{"description":"Authentication is required and the request did not present a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"authentication_error","code":"authentication_required","message":"No valid API key provided.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#authentication_required"},"request_id":"req_abc123def456"}}}},"403":{"description":"The credential is valid but lacks the permission this endpoint requires. Check the API key's allowed permissions in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"permission_denied","message":"The API key does not have permission to perform this action.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#permission_denied"},"request_id":"req_abc123def456"}}}},"404":{"description":"The refund ID does not exist in this account / mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"invalid_request_error","code":"resource_missing","message":"No such refund: re_abc123","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"},"request_id":"req_abc123def456"}}}},"500":{"description":"Something went wrong on our end. Safe to retry idempotent requests; for non-idempotent calls, consult the `request_id` before resubmitting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"},"example":{"error":{"type":"api_error","code":"internal_error","message":"An unexpected error occurred. Please try again or contact support.","doc_url":"https://docs.xpay.app/integrate/errors/api-error-codes#internal_error"},"request_id":"req_abc123def456"}}}}},"security":[{"api-key":[]}],"summary":"Get refund by ID","tags":["Refunds"]}}},"info":{"title":"XPay Merchant API","description":"API for merchant server-side integrations with XPay checkout","version":"1.0","contact":{}},"tags":[{"name":"Checkout Sessions"},{"name":"Customers"},{"name":"Payment Links"},{"name":"Products"},{"name":"Prices"},{"name":"Refunds"}],"servers":[{"url":"https://api.xpay.app","description":"Production"},{"url":"http://localhost:4000","description":"Local development"}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","type":"http","description":"API key for merchant integrations. Send as `Authorization: Bearer <your key>`."}},"schemas":{"ApiErrorBody":{"type":"object","properties":{"type":{"type":"string","description":"High-level error category. Use this for branching at the top level of your error handler (e.g. retry on `api_error`, surface a card decline on `card_error`).","enum":["invalid_request_error","authentication_error","rate_limit_error","api_error","card_error","idempotency_error"],"example":"invalid_request_error"},"code":{"type":"string","description":"Stable, machine-readable code identifying the specific failure (e.g. `resource_missing`, `parameter_invalid`, `authentication_required`). Always present on documented errors. See the API Error Codes reference for the full list.","enum":["invalid_request","parameter_out_of_range","parameter_invalid","parameter_missing","parameter_unknown","parameters_exclusive","parameter_requires_another","validation_error","resource_missing","resource_invalid_state","resource_already_exists","resource_in_use","authentication_required","invalid_api_key","api_key_inactive","invalid_signature","merchant_not_activated","permission_denied","two_factor_required","checkout_session_expired","invalid_client_secret","creation_failed","payment_still_confirming","payment_already_completed","payment_link_inactive","payment_link_expired","amount_invalid","currency_invalid","product_archived","price_inactive","price_not_yet_active","price_expired","price_sold_out","price_date_range_invalid","price_stock_invalid","price_recurring_not_supported","price_immutable_while_used","line_item_missing_price","checkout_empty_cart","promotion_codes_not_allowed","promotion_code_not_found","promotion_code_inactive","promotion_code_expired","promotion_code_max_redemptions","promotion_code_customer_mismatch","promotion_code_minimum_amount","promotion_code_first_time_only","coupon_invalid","coupon_currency_mismatch","coupon_minimum_amount","coupon_customer_max_redemptions","too_many_discounts","payment_method_corrupted","payment_method_customer_mismatch","payment_intent_customer_mismatch","payment_method_mismatch","charge_not_captured","merchant_no_balance","insufficient_balance","charge_missing_balance_transaction","charge_missing_fee_data","charge_incomplete_fee_data","cannot_rename_default","must_have_enabled_method","cannot_delete_default","configuration_in_use","unsupported_currency","exchange_rate_not_found","coupon_in_use","promotion_code_exists","rate_limit","idempotency_key_in_use","internal_error","request_timeout"],"example":"resource_missing"},"message":{"type":"string","description":"Human-readable description of what went wrong. Safe to log or display, but not stable — use `code` for programmatic branching.","example":"No such checkout_session: cs_test_a1b2c3d4"},"param":{"type":"string","description":"Name of the request parameter that caused the error, when applicable (e.g. `amount`, `currency`).","example":"id"},"doc_url":{"type":"string","description":"URL to the documentation page for this specific error code. Deep-linked into the API Error Codes reference.","example":"https://docs.xpay.app/integrate/errors/api-error-codes#resource_missing"}},"description":"Structured error body. Returned inside `error` on every 4xx/5xx response. Switch on `code` to handle specific failure modes programmatically; show `message` to your end user.","required":["type","message"]},"ApiErrorResponse":{"type":"object","properties":{"error":{"description":"The structured error body. See `ApiErrorBody` for field semantics.","allOf":[{"$ref":"#/components/schemas/ApiErrorBody"}]},"request_id":{"type":"string","description":"Unique identifier for this request, propagated to logs and traces. Include it when contacting support.","example":"req_abc123def456"}},"description":"Canonical error response. Returned by every API endpoint on any 4xx or 5xx status. Always wraps a single `error` body plus a `request_id` you can quote when contacting support.","required":["error"]},"Recurring":{"type":"object","properties":{"interval":{"type":"string","description":"Billing interval","enum":["DAY","WEEK","MONTH","YEAR","CUSTOM"],"example":"MONTH"},"intervalCount":{"type":"number","description":"Number of intervals between billings","example":1}}},"CustomUnitAmount":{"type":"object","properties":{"minimum":{"type":"number","description":"Minimum amount the customer may enter","example":1000},"maximum":{"type":"number","description":"Maximum amount the customer may enter","example":100000},"preset":{"type":"number","description":"Suggested amount pre-filled at checkout","example":10000}}},"Product":{"type":"object","properties":{"id":{"type":"string","description":"Product ID","example":"prod_abc123"},"name":{"type":"string","description":"Product name","example":"Premium Plan"},"description":{"type":"string","description":"Product description","example":"Access to all premium features"},"image":{"type":"string","description":"Product image URL","example":"https://example.com/image.jpg"},"active":{"type":"boolean","description":"Whether the product is active. `false` means the merchant archived it — archiving a product cascades `active: false` to all of its catalog prices, so an archived product's prices will also surface `active: false`. Consumers should treat any line item with `price.product.active === false` as unavailable.","example":true}},"required":["id","name","active"]},"Price":{"type":"object","properties":{"id":{"type":"string","description":"Price ID","example":"price_abc123"},"unitAmount":{"type":"number","description":"Price amount in smallest currency unit","example":100000},"currency":{"type":"string","description":"Currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"type":{"type":"string","description":"Price type","enum":["ONE_TIME","RECURRING","CUSTOM"],"example":"ONE_TIME"},"recurring":{"description":"Recurring configuration (for recurring prices)","allOf":[{"$ref":"#/components/schemas/Recurring"}]},"customUnitAmount":{"description":"Custom unit amount configuration — present for CUSTOM-type prices","allOf":[{"$ref":"#/components/schemas/CustomUnitAmount"}]},"createdAt":{"type":"string","description":"Creation timestamp (ISO 8601)","example":"2024-01-01T00:00:00.000Z"},"active":{"type":"boolean","description":"Whether the price is active. `false` means the merchant archived it.","example":true},"stock":{"type":"number","description":"Remaining stock. `null` means unlimited. Decremented on PaymentIntent success. May go negative under race conditions (oversold).","example":100,"nullable":true},"startDate":{"type":"string","description":"Start date (before which the price is not usable in checkout), ISO 8601","nullable":true},"expirationDate":{"type":"string","description":"Expiration date (at/after which the price is not usable in checkout), ISO 8601","nullable":true},"product":{"description":"Product associated with this price","allOf":[{"$ref":"#/components/schemas/Product"}]}},"required":["id","currency","type","createdAt","active","product"]},"AdjustableQuantity":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether adjustable quantity is enabled","example":false},"minimum":{"type":"number","description":"Minimum quantity allowed","example":1},"maximum":{"type":"number","description":"Maximum quantity allowed","example":10}},"required":["enabled"]},"LineItemPresentmentDetails":{"type":"object","properties":{"unitAmount":{"type":"number","description":"Unit amount in presentment smallest unit","example":100000},"amountSubtotal":{"type":"number","description":"Line subtotal (unitAmount × quantity) in presentment smallest unit","example":100000},"amountDiscount":{"type":"number","description":"Line discount allocated to this item, in presentment smallest unit","example":20000},"amountTotal":{"type":"number","description":"Line total after discount + tax, in presentment smallest unit","example":80000},"currency":{"type":"string","description":"Presentment currency for this line — matches session.presentmentDetails.currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"KWD"}},"required":["unitAmount","amountSubtotal","amountDiscount","amountTotal","currency"]},"LineItem":{"type":"object","properties":{"id":{"type":"string","description":"Line item ID","example":"li_abc123"},"quantity":{"type":"number","description":"Quantity","example":1},"price":{"description":"Price information","allOf":[{"$ref":"#/components/schemas/Price"}]},"adjustableQuantity":{"description":"Adjustable quantity settings","allOf":[{"$ref":"#/components/schemas/AdjustableQuantity"}]},"amountSubtotal":{"type":"number","description":"Total before any discounts or taxes (unitAmount × quantity)","example":200000},"amountTotal":{"type":"number","description":"Total after discounts and taxes","example":200000},"amountDiscount":{"type":"number","description":"Discount amount applied to this item","example":0},"amountTax":{"type":"number","description":"Tax amount applied to this item","example":0},"currency":{"type":"string","description":"Currency for the amounts (ISO 4217)","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"description":{"type":"string","description":"Description from price/product","example":"Premium Plan - Monthly"},"presentmentDetails":{"description":"Customer-facing view of this line item. Populated on checkout-session snapshots when the merchant prices in a currency different from processing. Uses the session's locked exchange rate.","allOf":[{"$ref":"#/components/schemas/LineItemPresentmentDetails"}]}},"required":["id","quantity","price"]},"AfterCompletionRedirect":{"type":"object","properties":{"url":{"type":"string","description":"Where we hand the browser back to you. Required when afterCompletion.type is 'redirect'.\n\n- **hosted**: the customer is redirected here after a successful payment. A failed payment keeps them on the checkout page so they can retry.\n\n- **embedded**: the customer is returned here when a bank verification has to take over the whole tab. That return happens whatever the outcome, so read the session's status on arrival rather than assuming success.\n\n- **custom**: the destination `redirect: \"always\"` sends the customer to after a successful payment.\n\nInclude `{CHECKOUT_SESSION_ID}` anywhere in the URL and we substitute the session id before the customer ever reaches it.","example":"https://example.com/success?session_id={CHECKOUT_SESSION_ID}"}},"required":["url"]},"AfterCompletionHostedConfirmation":{"type":"object","properties":{"customMessage":{"type":"string","description":"Custom message displayed to the customer on the hosted confirmation page after payment. If not provided, a default message is shown: 'A payment to {merchant} will appear on your statement.' Max 500 characters.","example":"Thank you for your purchase! Your order is being processed.","maxLength":500},"returnUrl":{"type":"string","description":"Optional URL for a \"Return to {merchant}\" button on the confirmation page. If not provided, no return button is shown.","example":"https://example.com"}}},"AfterCompletion":{"type":"object","properties":{"type":{"type":"string","description":"The behavior after the purchase is complete.\n\n- **redirect**: Customer is redirected to the URL specified in `redirect.url`. The `redirect` object is required when using this type. Cannot be combined with `hostedConfirmation`.\n\n- **hosted_confirmation**: Customer sees a built-in confirmation page hosted by XPay with a success animation, thank you message, and optional custom message. The `hostedConfirmation` object is optional. Cannot be combined with `redirect`. Not available when `uiMode` is `embedded` or `custom` — those integrations run on your own page, and there is no XPay page to show the customer.","enum":["redirect","hosted_confirmation"],"default":"redirect"},"redirect":{"description":"Configuration when type=redirect. **Required** when type is 'redirect'. Must not be provided when type is 'hosted_confirmation'.","allOf":[{"$ref":"#/components/schemas/AfterCompletionRedirect"}]},"hostedConfirmation":{"description":"Configuration when type=hosted_confirmation. Optional — if not provided, a default confirmation page is shown. Must not be provided when type is 'redirect'.","allOf":[{"$ref":"#/components/schemas/AfterCompletionHostedConfirmation"}]}},"required":["type"]},"ProductData":{"type":"object","properties":{"name":{"type":"string","description":"Product name (required)"},"description":{"type":"string","description":"Product description"},"image":{"type":"string","description":"External image URL (https only — fetched server-side via the egress relay and uploaded to Cloudflare)"},"unitLabel":{"type":"string","description":"Unit label for display (e.g., 'seat', 'license', 'user')"},"metadata":{"type":"object","description":"Custom metadata"}},"required":["name"]},"RecurringData":{"type":"object","properties":{"interval":{"type":"string","description":"Billing interval","enum":["DAY","WEEK","MONTH","YEAR","CUSTOM"]},"intervalCount":{"type":"number","description":"Number of intervals between billings","default":1}},"required":["interval"]},"PriceData":{"type":"object","properties":{"currency":{"type":"string","description":"Currency (required)","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"]},"unitAmount":{"type":"number","description":"Unit amount in smallest currency unit (required)","maximum":2147483647},"productData":{"description":"Inline product data (required - at least name)","allOf":[{"$ref":"#/components/schemas/ProductData"}]},"recurring":{"description":"Recurring configuration (for subscriptions)","allOf":[{"$ref":"#/components/schemas/RecurringData"}]},"metadata":{"type":"object","description":"Custom metadata"}},"required":["currency","unitAmount","productData"]},"AdjustableQuantityInput":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable customer quantity adjustment"},"minimum":{"type":"number","description":"Minimum quantity. Set to 0 to make the item optional (customer can remove it).","default":1,"maximum":2147483647},"maximum":{"type":"number","description":"Maximum quantity","maximum":2147483647}},"required":["enabled"]},"LineItemInput":{"type":"object","properties":{"price":{"type":"string","description":"Existing price ID (mutually exclusive with priceData)"},"priceData":{"description":"Inline price data (mutually exclusive with price)","allOf":[{"$ref":"#/components/schemas/PriceData"}]},"quantity":{"type":"number","description":"Quantity. May be 0 only when adjustableQuantity is enabled with minimum 0 (optional item).","maximum":2147483647},"adjustableQuantity":{"description":"Adjustable quantity settings","allOf":[{"$ref":"#/components/schemas/AdjustableQuantityInput"}]}},"required":["quantity"]},"AddressInput":{"type":"object","properties":{"line1":{"type":"string","description":"Address line 1"},"line2":{"type":"string","description":"Address line 2"},"city":{"type":"string","description":"City"},"state":{"type":"string","description":"State/Province"},"postalCode":{"type":"string","description":"Postal code"},"country":{"type":"string","description":"Two-letter country code (ISO 3166-1 alpha-2)"}}},"BillingDetailsInput":{"type":"object","properties":{"name":{"type":"string","description":"Cardholder name (name on card)"},"email":{"type":"string","description":"Billing email"},"phone":{"type":"string","description":"Billing phone"},"address":{"description":"Billing address","allOf":[{"$ref":"#/components/schemas/AddressInput"}]}}},"ShippingInput":{"type":"object","properties":{"name":{"type":"string","description":"Recipient name"},"phone":{"type":"string","description":"Recipient phone"},"address":{"description":"Shipping address","allOf":[{"$ref":"#/components/schemas/AddressInput"}]}}},"CustomerDetailsInput":{"type":"object","properties":{"name":{"type":"string","description":"Customer name"},"email":{"type":"string","description":"Customer email"},"phone":{"type":"string","description":"Customer phone"},"billingDetails":{"description":"Billing details including cardholder name and address","allOf":[{"$ref":"#/components/schemas/BillingDetailsInput"}]},"shipping":{"description":"Shipping details (if different from billing)","allOf":[{"$ref":"#/components/schemas/ShippingInput"}]}}},"CustomerUpdate":{"type":"object","properties":{"address":{"type":"string","description":"Whether to save billing address to customer.address. Defaults to 'never'.","enum":["auto","never"],"default":"never"},"name":{"type":"string","description":"Whether to save name to customer.name. Defaults to 'never'.","enum":["auto","never"],"default":"never"},"shipping":{"type":"string","description":"Whether to save shipping info to customer.shipping. Defaults to 'never'.","enum":["auto","never"],"default":"never"}}},"CheckoutDiscountInput":{"type":"object","properties":{"coupon":{"type":"string","description":"Coupon ID to apply directly. Mutually exclusive with promotionCode."},"promotionCode":{"type":"string","description":"Promotion code ID to apply. Mutually exclusive with coupon."}}},"DropdownOptionInput":{"type":"object","properties":{"label":{"type":"string","description":"Option label","example":"Option 1"}},"required":["label"]},"CustomFieldInput":{"type":"object","properties":{"label":{"type":"string","description":"Field label"},"type":{"type":"string","description":"Field type","enum":["TEXT","NUMBER","DROPDOWN","CHECKBOX"],"example":"TEXT"},"isOptional":{"type":"boolean","description":"Whether the field is optional","default":false},"hasLimits":{"type":"boolean","description":"Whether validation limits are enabled"},"limitType":{"type":"string","description":"Type of validation limit","enum":["AT_MOST","BETWEEN","AT_LEAST","EXACTLY"],"example":"BETWEEN"},"minCharacters":{"type":"number","description":"Minimum number of characters"},"maxCharacters":{"type":"number","description":"Maximum number of characters"},"dropdownOptions":{"description":"Dropdown options (only for DROPDOWN type)","type":"array","items":{"$ref":"#/components/schemas/DropdownOptionInput"}}},"required":["label","type"]},"FeeConfigInput":{"type":"object","properties":{"feesPassThrough":{"type":"boolean","description":"Whether customer pays platform fee instead of merchant. When true, platform fee is added to customer payment.","example":false},"vatCollectionEnabled":{"type":"boolean","description":"Whether to collect merchant's product VAT from customer. When enabled, VAT is added to customer payment.","example":false},"vatCollectionRate":{"type":"number","description":"VAT collection rate in basis points (e.g., 1400 = 14%). Required when vatCollectionEnabled is true.","example":1400,"minimum":0,"maximum":10000}},"required":["feesPassThrough","vatCollectionEnabled"]},"ColorCustomizationInput":{"type":"object","properties":{"primary":{"type":"string","description":"Primary brand color (buttons, links, accents). Hex only, e.g. `#635bff`."},"primaryForeground":{"type":"string","description":"Primary foreground (text on primary background). Hex only."},"background":{"type":"string","description":"Page background color. Hex only."},"foreground":{"type":"string","description":"Main text color. Hex only."},"border":{"type":"string","description":"Border color. Hex only."},"input":{"type":"string","description":"Input, button, and dropdown border color. Hex only."},"ring":{"type":"string","description":"Focus ring color. Hex only."},"muted":{"type":"string","description":"Muted/secondary background. Hex only."},"mutedForeground":{"type":"string","description":"Muted text color. Hex only."},"accent":{"type":"string","description":"Accent background. Hex only."},"accentForeground":{"type":"string","description":"Accent text color. Hex only."},"destructive":{"type":"string","description":"Destructive/error color. Hex only."}}},"BrandingSettingsInput":{"type":"object","properties":{"colorMode":{"type":"string","description":"Dark mode preference","enum":["light","dark","system"],"default":"system"},"borderStyle":{"type":"string","description":"Border style for inputs, buttons, cards","enum":["rounded","sharp","pill"],"default":"rounded"},"spacing":{"type":"string","description":"Spacing density","enum":["condensed","normal","spacious"],"default":"normal"},"inputSize":{"type":"string","description":"Input field size","enum":["small","medium","large"],"default":"medium"},"inputStyle":{"type":"string","description":"Input field style","enum":["flat","outlined","filled"],"default":"outlined"},"formLayout":{"type":"string","description":"Form layout density","enum":["compact","spacious"],"default":"spacious"},"colors":{"description":"Color customization options","allOf":[{"$ref":"#/components/schemas/ColorCustomizationInput"}]},"fontFamily":{"type":"string","description":"Font family override (CSS font-family value, e.g. 'Inter, sans-serif')","maxLength":512}}},"CreateCheckoutSession":{"type":"object","properties":{"afterCompletion":{"description":"Behavior after the purchase is complete.\n\n**type=redirect** (default): Redirect customer to your URL after payment. Requires `afterCompletion.redirect.url`.\n\n**type=hosted_confirmation**: Show a built-in XPay-hosted success page. Optionally provide `afterCompletion.hostedConfirmation.customMessage` and `afterCompletion.hostedConfirmation.returnUrl`.\n\nExample (redirect): `{ type: 'redirect', redirect: { url: 'https://example.com/success' } }`\n\nExample (hosted): `{ type: 'hosted_confirmation', hostedConfirmation: { customMessage: 'Thanks!' } }`","example":{"type":"redirect","redirect":{"url":"https://example.com/success?session_id={CHECKOUT_SESSION_ID}"}},"allOf":[{"$ref":"#/components/schemas/AfterCompletion"}]},"mode":{"type":"string","description":"Session mode: payment, subscription, or setup","enum":["payment","setup","subscription"],"default":"payment"},"uiMode":{"type":"string","description":"The UI mode of the Session. Defaults to hosted.\n\n- **hosted**: Customer is redirected to XPay's hosted checkout page.\n- **embedded**: Full checkout embedded in merchant's site via SDK drop-in modal.\n- **custom**: Merchant builds their own checkout form using the Elements SDK (Payment Element, Card Element).","enum":["hosted","embedded","custom"],"default":"hosted"},"submitType":{"type":"string","description":"Describes the type of transaction to customize button text (e.g., 'Pay', 'Subscribe'). You can't set this parameter if uiMode is custom.","enum":["PAY","SUBSCRIBE","BOOK","DONATE"],"default":"PAY"},"currency":{"type":"string","description":"ISO 4217 currency code","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"]},"lineItems":{"description":"Line items for the checkout","type":"array","items":{"$ref":"#/components/schemas/LineItemInput"}},"cancelUrl":{"type":"string","description":"URL to redirect if customer cancels (back button during checkout). This parameter is not allowed if uiMode is embedded or custom."},"customerId":{"type":"string","description":"Existing customer ID. If provided, customer data will be used to prefill checkout fields.\n\n    IMPORTANT: Cannot be used together with customerDetails - you must choose one:\n    - Use customerId to checkout with an existing customer\n    - Use customerDetails to provide prefill data for a new customer"},"customerDetails":{"description":"Customer details for prefill and collection. Used to:\n    - Prefill checkout form fields\n    - Create a new customer (if customerCreation is 'always')\n\n    IMPORTANT: Cannot be used together with customerId - you must choose one.","allOf":[{"$ref":"#/components/schemas/CustomerDetailsInput"}]},"customerUpdate":{"description":"Controls which customer fields to update when customerId is provided.\n\n    IMPORTANT: Only valid when customerId is provided. Will be ignored otherwise.\n\n    Each field can be 'auto' (update customer) or 'never' (don't update, default).","allOf":[{"$ref":"#/components/schemas/CustomerUpdate"}]},"customerCreation":{"type":"string","description":"When to create customer","enum":["always","if_required"],"default":"if_required"},"allowPromotionCodes":{"type":"boolean","description":"Allow promotion codes"},"discounts":{"description":"Discounts to apply to this session. Each must reference either a coupon ID or promotion code ID. Max 1 discount per session.","type":"array","items":{"$ref":"#/components/schemas/CheckoutDiscountInput"}},"nameCollection":{"type":"boolean","description":"Collect customer name. You can't set this parameter if uiMode is custom."},"billingAddressCollection":{"type":"boolean","description":"Collect billing address. You can't set this parameter if uiMode is custom."},"shippingAddressCollection":{"type":"boolean","description":"Collect shipping address. You can't set this parameter if uiMode is custom."},"phoneNumberCollection":{"type":"boolean","description":"Collect phone number. You can't set this parameter if uiMode is custom."},"customFields":{"description":"Custom fields to collect","type":"array","items":{"$ref":"#/components/schemas/CustomFieldInput"}},"metadata":{"type":"object","description":"Custom key-value metadata"},"feeConfig":{"description":"Fee configuration override for this session.\n    If not provided, merchant's default fee config will be used.\n\n    - feesPassThrough: Customer pays platform fee instead of merchant\n    - vatCollectionEnabled: Collect merchant's product VAT from customer\n    - vatCollectionRate: VAT rate in basis points (e.g., 1400 = 14%)","allOf":[{"$ref":"#/components/schemas/FeeConfigInput"}]},"brandingSettings":{"description":"UI customization settings for the checkout page.\n    Allows customization of colors, spacing, border styles, input styles, etc.\n    Merged server-side with the merchant's `defaultBrandingSettings` — anything set here wins.","allOf":[{"$ref":"#/components/schemas/BrandingSettingsInput"}]},"locale":{"type":"string","description":"Language the checkout page is displayed in.\n    Falls back to your account's `defaultLocale` when omitted, then to `en`.","enum":["en","ar"]},"paymentMethodTypes":{"type":"array","description":"Restrict this session to specific payment method types.\n    Most integrations omit this and manage methods from the dashboard under Settings > Payment methods.\n    Every type must already be enabled on your account, or the request is rejected.\n    Mutually exclusive with paymentMethodConfigurationId. Omit both to use your default configuration.\n\n    Example: [\"card\", \"valu\"]","items":{"type":"string","enum":["card","fawry","aman","valu","sympl","tabby","tamara","vodafone_cash","etisalat_cash","orange_cash","we_pay","apple_pay","google_pay","samsung_pay","instapay","bank_transfer","cash_on_delivery"]}},"paymentMethodConfigurationId":{"type":"string","description":"ID of a payment method configuration to use for this session.\n    Find IDs in your dashboard under Settings > Payment methods.\n    Preferred over `paymentMethodTypes`: the list stays editable in the dashboard.\n    Mutually exclusive with `paymentMethodTypes`. Omit both to use your default configuration.","example":"pmc_abc123"},"expiresAfterMinutes":{"type":"number","description":"Session expiration in minutes (default: 1440 = 24 hours)"}},"required":["afterCompletion"]},"TotalDetailsResponse":{"type":"object","properties":{"amountDiscount":{"type":"number","description":"Discount amount"},"amountShipping":{"type":"number","description":"Shipping amount"},"amountTax":{"type":"number","description":"Tax amount"},"amountPlatformFee":{"type":"number","description":"Platform fee amount (only when feesPassThrough is enabled)"},"amountCollectedVat":{"type":"number","description":"Collected VAT amount (only when vatCollectionEnabled is enabled)"}},"required":["amountDiscount","amountTax"]},"SessionPresentmentDetails":{"type":"object","properties":{"amount":{"type":"number","description":"Amount in the customer's currency (smallest unit — e.g. fils for KWD, cents for USD)","example":80000},"currency":{"type":"string","description":"Customer's currency code (ISO 4217)","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"KWD"},"exchangeRate":{"type":"number","description":"Locked exchange rate: presentment_major × rate = processing_major. Reused for refunds/disputes. Stored as numeric(15,6) — frontend can call `.toFixed(6)` to render the full 6-decimal string when needed.","example":168.21},"exchangeRateId":{"type":"string","description":"Reference to the immutable ExchangeRate record used — audit trail for FX reconciliation","example":"exr_3gQWCqaDsihr09Fi5MfwXL"},"amountSubtotal":{"type":"number","description":"Subtotal before discounts/fees, in presentment smallest unit","example":100000},"amountTotal":{"type":"number","description":"Final total the customer sees, in presentment smallest unit","example":80000},"amountDiscount":{"type":"number","description":"Discount applied, in presentment smallest unit (0 when no discount)","example":20000},"amountCollectedVat":{"type":"number","description":"Collected VAT in presentment smallest unit (only when VAT collection is enabled)","example":11200},"amountPlatformFee":{"type":"number","description":"Platform fee in presentment smallest unit (only when feesPassThrough is enabled)"},"amountTax":{"type":"number","description":"Tax in presentment smallest unit (only when tax is charged)"}},"required":["amount","currency","exchangeRate","exchangeRateId","amountSubtotal","amountTotal","amountDiscount"]},"AddressResponse":{"type":"object","properties":{"line1":{"type":"string","description":"Address line 1"},"line2":{"type":"string","description":"Address line 2"},"city":{"type":"string","description":"City"},"state":{"type":"string","description":"State/Province"},"postalCode":{"type":"string","description":"Postal code"},"country":{"type":"string","description":"Country code"}}},"ShippingResponse":{"type":"object","properties":{"name":{"type":"string","description":"Recipient name"},"phone":{"type":"string","description":"Recipient phone"},"address":{"description":"Shipping address","allOf":[{"$ref":"#/components/schemas/AddressResponse"}]}}},"CheckoutSessionCustomer":{"type":"object","properties":{"id":{"type":"string","description":"Customer ID"},"type":{"type":"string","description":"Customer type. `registered` is a permanent merchant-managed record; `guest` is a session-scope dedup unit created automatically when `customerCreation` is `if_required`.","enum":["guest","registered"]},"name":{"type":"string","description":"Customer name"},"email":{"type":"string","description":"Customer email"},"phone":{"type":"string","description":"Customer phone"},"address":{"description":"Customer address","allOf":[{"$ref":"#/components/schemas/AddressResponse"}]},"shipping":{"description":"Customer shipping details","allOf":[{"$ref":"#/components/schemas/ShippingResponse"}]},"metadata":{"type":"object","description":"Customer metadata"}},"required":["id","type"]},"BillingDetailsResponse":{"type":"object","properties":{"name":{"type":"string","description":"Cardholder name (name on card)"},"email":{"type":"string","description":"Billing email"},"phone":{"type":"string","description":"Billing phone"},"address":{"description":"Billing address","allOf":[{"$ref":"#/components/schemas/AddressResponse"}]}}},"CustomerDetailsResponse":{"type":"object","properties":{"name":{"type":"string","description":"Customer name"},"email":{"type":"string","description":"Customer email"},"phone":{"type":"string","description":"Customer phone"},"billingDetails":{"description":"Billing details including cardholder name and address","allOf":[{"$ref":"#/components/schemas/BillingDetailsResponse"}]},"shipping":{"description":"Shipping details","allOf":[{"$ref":"#/components/schemas/ShippingResponse"}]}}},"Address":{"type":"object","properties":{"city":{"type":"string"},"country":{"type":"string"},"line1":{"type":"string"},"line2":{"type":"string"},"postalCode":{"type":"string"},"state":{"type":"string"}},"required":["city","country","line1","line2","postalCode","state"]},"Shipping":{"type":"object","properties":{"address":{"description":"Shipping address.","allOf":[{"$ref":"#/components/schemas/Address"}]},"name":{"type":"string","description":"Recipient name as provided by the customer.","nullable":true,"example":"Mohamed Ali"},"phone":{"type":"string","description":"Recipient phone number as provided by the customer.","nullable":true,"example":"+20 100 123 4567"}},"required":["address"]},"AmountDetailsTax":{"type":"object","properties":{"amount":{"type":"number","description":"Tax amount charged on this payment, in the smallest currency unit (e.g. piasters for EGP).","example":1400},"rateBps":{"type":"number","description":"Tax rate applied, in basis points (1% = 100 bps). For example, `1400` means 14%.","example":1400}},"required":["amount","rateBps"]},"AmountDetailsPlatformFees":{"type":"object","properties":{"amount":{"type":"number","description":"Platform fee charged by XPay on this payment, in the smallest currency unit.","example":500},"vatAmount":{"type":"number","description":"VAT charged on the platform fee itself, in the smallest currency unit.","example":70}},"required":["amount","vatAmount"]},"AmountDetails":{"type":"object","properties":{"productAmount":{"type":"number","description":"Amount that pays for the product/service itself, in the smallest currency unit. Excludes tax, platform fees, tip, and discount.","example":10000},"tax":{"description":"Tax breakdown for this payment. `null` if no tax was collected.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/AmountDetailsTax"}]},"platformFees":{"description":"Platform fee breakdown for this payment. `null` if not surfaced to the customer.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/AmountDetailsPlatformFees"}]},"tip":{"type":"number","description":"Tip amount included in this payment, in the smallest currency unit. `null` if no tip.","example":1000,"nullable":true},"discount":{"type":"number","description":"Discount amount applied, in the smallest currency unit. `null` if no discount.","example":500,"nullable":true}},"required":["productAmount"]},"PresentmentDetails":{"type":"object","properties":{"amount":{"type":"number","description":"Amount in the customer's currency (smallest unit — e.g. fils for KWD, cents for USD)","example":80000},"currency":{"type":"string","description":"Customer's currency code (ISO 4217)","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"KWD"},"exchangeRate":{"type":"number","description":"Locked exchange rate: presentment_major × rate = processing_major. Reused for refunds/disputes. Stored as numeric(15,6) — frontend can call `.toFixed(6)` to render the full 6-decimal string when needed.","example":168.21},"exchangeRateId":{"type":"string","description":"Reference to the immutable ExchangeRate record used — audit trail for FX reconciliation","example":"exr_3gQWCqaDsihr09Fi5MfwXL"}},"required":["amount","currency","exchangeRate","exchangeRateId"]},"BillingDetails":{"type":"object","properties":{"address":{"$ref":"#/components/schemas/Address"},"email":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"}},"required":["address","email","name","phone"]},"ThreeDSecure":{"type":"object","properties":{"authenticationFlow":{"type":"string"},"electronicCommerceIndicator":{"type":"string"},"exemptionIndicator":{"type":"string"},"result":{"type":"string"},"resultReason":{"type":"string"},"transactionId":{"type":"string"},"version":{"type":"string"}},"required":["authenticationFlow","electronicCommerceIndicator","exemptionIndicator","result","resultReason","transactionId","version"]},"Wallet":{"type":"object","properties":{"type":{"type":"string"},"dynamicLast4":{"type":"string"}},"required":["type","dynamicLast4"]},"ChargeCardDetails":{"type":"object","properties":{"brand":{"type":"string"},"country":{"type":"string"},"expMonth":{"type":"number"},"expYear":{"type":"number"},"funding":{"type":"string"},"last4":{"type":"string"},"network":{"type":"string","description":"Payment rails the transaction rode (e.g. mastercard for a Meeza card). Null until the charge is processed by the gateway.","nullable":true},"fingerprint":{"type":"string","description":"Card fingerprint for identifying the same card across customers"},"threeDSecure":{"$ref":"#/components/schemas/ThreeDSecure"},"wallet":{"$ref":"#/components/schemas/Wallet"}},"required":["brand","country","expMonth","expYear","funding","last4","network","fingerprint","threeDSecure","wallet"]},"ValuDetails":{"type":"object","properties":{"loanNumber":{"type":"string","description":"Loan number from the provider","nullable":true},"tenure":{"type":"number","description":"Loan tenure in months","nullable":true},"emi":{"type":"string","description":"Monthly installment amount","nullable":true},"downPayment":{"type":"string","description":"Down payment amount","nullable":true},"financedAmount":{"type":"string","description":"Total financed amount","nullable":true},"firstEmiDueDate":{"type":"string","description":"First EMI due date","nullable":true},"lastInstallmentDate":{"type":"string","description":"Last installment date","nullable":true}}},"PaymentMethodDetails":{"type":"object","properties":{"type":{"type":"string","description":"Concrete PaymentMethodType value: 'card', 'valu', etc."},"card":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ChargeCardDetails"}]},"valu":{"nullable":true,"description":"ValU details (if type is 'valu')","type":"object","allOf":[{"$ref":"#/components/schemas/ValuDetails"}]}},"required":["type"]},"Outcome":{"type":"object","properties":{"networkStatus":{"type":"string"},"reason":{"type":"string"},"riskLevel":{"type":"string"},"riskScore":{"type":"number"},"sellerMessage":{"type":"string"},"type":{"type":"string"}},"required":["networkStatus","reason","riskLevel","riskScore","sellerMessage","type"]},"BalanceTransactionFeeDetail":{"type":"object","properties":{"amount":{"type":"number"},"currency":{"type":"string","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"description":{"type":"string"},"type":{"type":"string","description":"Fee type. PROCESSOR_COST entries are internal (platform COGS) and are filtered out of merchant-facing payloads."},"application":{"type":"string","nullable":true}},"required":["amount","currency","description","type","application"]},"BalanceTransactionPayoutBatch":{"type":"object","properties":{"id":{"type":"string","description":"PayoutBatch ID","example":"pb_xxx"},"object":{"type":"string","example":"payout_batch"},"amount":{"type":"number","description":"Total disbursement amount (batch total)"},"currency":{"type":"string","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"status":{"type":"string","enum":["open","processing","in_transit","paid","partial_failed","failed","canceled"],"example":"paid","description":"Batch lifecycle status. Merchant-facing status equals the batch status (not the individual payout status)."},"arrivalDate":{"type":"string","description":"Expected / actual arrival date (ISO date, merchant business calendar). Null while batch is still OPEN / PROCESSING.","nullable":true},"createdAt":{"type":"string","description":"Batch created timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Batch last-updated timestamp (ISO 8601)"}},"required":["id","object","amount","currency","status","createdAt","updatedAt"]},"BalanceTransactionResponse":{"type":"object","properties":{"id":{"type":"string","description":"Balance transaction ID","example":"txn_abc123"},"object":{"type":"string","description":"Object type","example":"balance_transaction"},"amount":{"type":"number","description":"Gross amount (positive for money in, negative for money out) in smallest currency unit","example":22604},"availableOn":{"type":"string","description":"Timestamp when funds become available in balance (ISO 8601)","nullable":true},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"currency":{"type":"string","description":"Currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"description":{"type":"string","description":"Human-readable description","nullable":true},"fee":{"type":"number","description":"Total fees in smallest currency unit","example":912},"net":{"type":"number","description":"Net amount after fees in smallest currency unit","example":21692},"feeDetails":{"description":"Breakdown of the `fee`. Platform COGS entries (PROCESSOR_COST) are stripped before emission — merchants only see the fees they care about.","type":"array","items":{"$ref":"#/components/schemas/BalanceTransactionFeeDetail"}},"status":{"type":"string","description":"Transaction status","enum":["AVAILABLE","PENDING"]},"type":{"type":"string","description":"Transaction type","enum":["CHARGE","PAYMENT","PAYMENT_FAILURE_REFUND","PAYMENT_REFUND","PAYMENT_REVERSAL","REFUND","REFUND_FAILURE","ADJUSTMENT","ADVANCE","ADVANCE_FUNDING","PAYOUT","PAYOUT_CANCEL","PAYOUT_FAILURE","PAYOUT_MINIMUM_BALANCE_HOLD","PAYOUT_MINIMUM_BALANCE_RELEASE","RESERVED_FUNDS","RESERVE_HOLD","RESERVE_RELEASE","RECOVERY_FROM_FUTURE_FUNDS","XPAY_FEE","XPAY_FX_FEE","TAX_FEE","TOPUP","TOPUP_REVERSAL"]},"reportingCategory":{"type":"string","description":"Reporting category for accounting/analytics. Falls back to `type` when the entity has no explicit override."},"exchangeRate":{"type":"number","description":"Exchange rate when currency conversion occurred","nullable":true},"source":{"type":"string","description":"Source resource id (charge, refund, payout, topup, dispute). Scalar id only — merchants query the source explicitly."},"payoutBatch":{"nullable":true,"description":"The PayoutBatch this balance transaction was included in, or null until it's batched.","type":"object","allOf":[{"$ref":"#/components/schemas/BalanceTransactionPayoutBatch"}]},"paymentIntentId":{"type":"string","description":"Associated payment intent ID (if applicable)","nullable":true},"merchantId":{"type":"string","description":"Merchant ID owning this balance transaction"}},"description":"A Balance Transaction records every movement of money in or out of your xpay balance: successful charges, refunds, payouts, processing fees, and adjustments. Each Balance Transaction links back to its `source` (the Charge, Refund, or Payout that produced it) and breaks down `gross`, `fee`, and `net` amounts. Use Balance Transactions to reconcile what was paid into your account against what was settled to your bank.","required":["id","object","amount","createdAt","currency","fee","net","feeDetails","status","type","reportingCategory","source","payoutBatch","merchantId"]},"CardDestinationDetails":{"type":"object","properties":{"reference":{"type":"string","description":"Acquirer reference number (ARN)"},"referenceStatus":{"type":"string","enum":["pending","available","unavailable"]},"referenceType":{"type":"string"},"type":{"type":"string","enum":["pending","refund","reversal"]}}},"WalletDestinationDetails":{"type":"object","properties":{"reference":{"type":"string","description":"Wallet transaction reference"},"provider":{"type":"string","description":"Wallet provider (e.g., vodafone_cash, fawry)"}}},"BankTransferDestinationDetails":{"type":"object","properties":{"reference":{"type":"string"},"referenceStatus":{"type":"string","enum":["pending","available","unavailable"]}}},"KioskDestinationDetails":{"type":"object","properties":{"reference":{"type":"string"},"provider":{"type":"string"}}},"RefundDestinationDetails":{"type":"object","properties":{"type":{"type":"string","enum":["card","wallet","bank_transfer","kiosk"]},"card":{"$ref":"#/components/schemas/CardDestinationDetails"},"wallet":{"$ref":"#/components/schemas/WalletDestinationDetails"},"bankTransfer":{"$ref":"#/components/schemas/BankTransferDestinationDetails"},"kiosk":{"$ref":"#/components/schemas/KioskDestinationDetails"}},"required":["type"]},"RefundNextActionDisplayDetails":{"type":"object","properties":{"emailSentAt":{"type":"string","description":"Email sent timestamp (ISO 8601)"},"emailSentTo":{"type":"string"},"expiresAt":{"type":"string","description":"Expiration timestamp (ISO 8601)"}}},"RefundNextAction":{"type":"object","properties":{"type":{"type":"string"},"displayDetails":{"$ref":"#/components/schemas/RefundNextActionDisplayDetails"}},"required":["type"]},"RefundResponse":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the refund","example":"re_abc123"},"object":{"type":"string","description":"Object type","example":"refund"},"amount":{"type":"number","description":"Refund amount in smallest currency unit","example":50000},"chargeId":{"type":"string","description":"ID of the charge being refunded","example":"ch_xyz789"},"paymentIntentId":{"type":"string","description":"ID of the PaymentIntent being refunded","example":"pi_xyz789"},"balanceTransactionId":{"type":"string","description":"ID of the balance transaction for the refund, null until settled","nullable":true},"failureBalanceTransactionId":{"type":"string","description":"Balance transaction for failed refund reversal, null unless the refund failed","nullable":true},"externalRefundId":{"type":"string","description":"Processor-side refund id, null when not yet reconciled","nullable":true},"createdAt":{"type":"string","description":"Time at which the refund was created (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"currency":{"type":"string","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"description":"Three-letter ISO currency code"},"presentmentDetails":{"description":"Customer-facing view of the refund — amount in the original charge's presentment currency using the charge's LOCKED exchange rate. Populated only when the charge had a presentment currency different from processing.","allOf":[{"$ref":"#/components/schemas/PresentmentDetails"}]},"status":{"type":"string","enum":["PENDING","REQUIRES_ACTION","SUCCEEDED","FAILED","CANCELED"],"description":"Status of the refund (pending, requires_action, succeeded, failed, canceled)"},"reason":{"type":"string","enum":["DUPLICATE","FRAUDULENT","REQUESTED_BY_CUSTOMER","RISK_HOLD_CAPTURE"],"description":"Reason for the refund"},"failureReason":{"type":"string","enum":["lost_or_stolen_card","expired_or_canceled_card","charge_for_pending_refund_disputed","insufficient_funds","declined","merchant_request","unknown"],"description":"Reason for refund failure"},"pendingReason":{"type":"string","enum":["processing","insufficient_funds","charge_pending"],"description":"Reason for pending status"},"description":{"type":"string","description":"Description for non-card refunds"},"destinationDetails":{"description":"Payment method-specific refund details","allOf":[{"$ref":"#/components/schemas/RefundDestinationDetails"}]},"nextAction":{"description":"Next action if requires_action","allOf":[{"$ref":"#/components/schemas/RefundNextAction"}]},"instructionsEmail":{"type":"string","description":"Email for refund instructions"},"receiptNumber":{"type":"string","description":"Receipt number for email receipts"},"feeAmount":{"type":"number","description":"Original platform fee (NOT refunded - kept by platform)"}},"description":"A Refund returns funds from a successful Charge back to the customer's original payment method. Refunds can be full or partial, and a single Charge can be refunded multiple times up to its original amount. The Refund's `status` reflects the processor's progress as the money makes its way back: `pending` while in flight, `succeeded` once the funds have been returned, or `failed` if the processor rejected the request.","required":["id","object","amount","chargeId","paymentIntentId","balanceTransactionId","failureBalanceTransactionId","externalRefundId","createdAt","currency","status"]},"ChargeConfig":{"type":"object","properties":{"vatCollectionEnabled":{"type":"boolean"},"vatCollectionRate":{"type":"number"},"collectedVatAmount":{"type":"number"},"platformFeePassThrough":{"type":"boolean"},"merchantFeeDeduction":{"type":"number"}},"required":["vatCollectionEnabled","vatCollectionRate","collectedVatAmount","platformFeePassThrough","merchantFeeDeduction"]},"ChargeGeocodingLocation":{"type":"object","properties":{"countryCode":{"type":"string","description":"ISO 3166-1 alpha-2 country code","example":"US"},"countryName":{"type":"string","description":"English country name","example":"United States"},"regionCode":{"type":"string","description":"ISO 3166-2 region code","example":"CA"},"regionName":{"type":"string","description":"English region/state name","example":"California"},"cityName":{"type":"string","description":"English city name","example":"Los Angeles"}}},"ChargeGeocoding":{"type":"object","properties":{"ipAddress":{"type":"string","description":"The IP address that was resolved"},"location":{"$ref":"#/components/schemas/ChargeGeocodingLocation"}},"required":["ipAddress"]},"ChargeSession":{"type":"object","properties":{"browser":{"type":"string"},"browserVersion":{"type":"string"},"platform":{"type":"string"},"device":{"type":"string"},"deviceVendor":{"type":"string"},"deviceModel":{"type":"string"}}},"ProcessorCapabilities":{"type":"object","properties":{"supportsRefund":{"type":"boolean","description":"Whether this processor supports refunds"},"supportsPartialRefund":{"type":"boolean","description":"Whether partial refunds are supported"}},"required":["supportsRefund","supportsPartialRefund"]},"ChargeResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","example":"charge"},"amount":{"type":"number"},"amountCaptured":{"type":"number"},"amountRefunded":{"type":"number"},"currency":{"type":"string","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"status":{"type":"string"},"paid":{"type":"boolean"},"refunded":{"type":"boolean"},"captured":{"type":"boolean"},"capturedAt":{"type":"string","description":"Captured timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"failureCode":{"type":"string"},"failureMessage":{"type":"string"},"receiptUrl":{"type":"string"},"receiptEmail":{"type":"string"},"billingDetails":{"$ref":"#/components/schemas/BillingDetails"},"paymentMethodDetails":{"$ref":"#/components/schemas/PaymentMethodDetails"},"outcome":{"$ref":"#/components/schemas/Outcome"},"balanceTransaction":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/BalanceTransactionResponse"}]},"presentmentDetails":{"description":"Present when customer paid in a different currency than settlement (EGP)","allOf":[{"$ref":"#/components/schemas/PresentmentDetails"}]},"refunds":{"description":"Refunds issued against this charge, ordered newest-first.","type":"array","items":{"$ref":"#/components/schemas/RefundResponse"}},"paymentIntentId":{"type":"string"},"paymentMethodId":{"type":"string"},"calculatedStatementDescriptor":{"type":"string"},"disputed":{"type":"boolean"},"externalChargeId":{"type":"string"},"config":{"$ref":"#/components/schemas/ChargeConfig"},"geocoding":{"$ref":"#/components/schemas/ChargeGeocoding"},"session":{"$ref":"#/components/schemas/ChargeSession"},"merchantOrigin":{"type":"string","description":"Origin of the page where this checkout ran — the merchant's site for embedded integrations (SDK Elements / drop-in), or our hosted checkout domain for hosted checkout and payment links. Null for merchant-initiated charges (recurring / MOTO).","example":"https://shop.merchant.com","nullable":true},"merchantDomain":{"type":"string","description":"Registrable domain (eTLD+1) derived from merchantOrigin.","example":"merchant.com","nullable":true},"processorCapabilities":{"$ref":"#/components/schemas/ProcessorCapabilities"},"activeHoldId":{"type":"string","description":"ID of the currently-active risk hold on this charge, if any","example":"hld_xxx","nullable":true},"settlementModel":{"type":"string","description":"Settlement model snapshotted at charge time","enum":["aggregated","direct"],"example":"aggregated"}},"description":"A Charge represents a single attempt to move money from a customer's payment method to your account. It records what was paid, by whom, through which processor, and the final outcome: `succeeded`, `failed`, or `refunded`. A single PaymentIntent may produce multiple Charges if earlier attempts fail; only the most recent successful Charge actually moves funds, and any subsequent Refunds reference it directly.","required":["id","object","amount","amountCaptured","amountRefunded","currency","createdAt","status","paid","refunded","captured","capturedAt","failureCode","failureMessage","receiptUrl","receiptEmail","billingDetails","paymentMethodDetails","outcome","balanceTransaction","refunds","paymentIntentId","paymentMethodId","calculatedStatementDescriptor","disputed","externalChargeId","config","settlementModel"]},"ThreeDSecureUsage":{"type":"object","properties":{"supported":{"type":"boolean"}},"required":["supported"]},"PaymentMethodCard":{"type":"object","properties":{"brand":{"type":"string"},"country":{"type":"string"},"displayBrand":{"type":"string"},"expMonth":{"type":"number"},"expYear":{"type":"number"},"fingerprint":{"type":"string"},"funding":{"type":"string"},"last4":{"type":"string"},"networks":{"type":"object"},"regulatedStatus":{"type":"string"},"threeDSecureUsage":{"$ref":"#/components/schemas/ThreeDSecureUsage"},"wallet":{"$ref":"#/components/schemas/Wallet"}},"required":["brand","country","displayBrand","expMonth","expYear","fingerprint","funding","last4","networks","regulatedStatus","threeDSecureUsage","wallet"]},"PaymentMethodObject":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string"},"card":{"nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PaymentMethodCard"}]},"valu":{"nullable":true,"description":"ValU details (if type is 'valu')","type":"object","allOf":[{"$ref":"#/components/schemas/ValuDetails"}]},"billingDetails":{"$ref":"#/components/schemas/BillingDetails"},"type":{"type":"string","enum":["card","fawry","aman","valu","sympl","tabby","tamara","vodafone_cash","etisalat_cash","orange_cash","we_pay","apple_pay","google_pay","samsung_pay","instapay","bank_transfer","cash_on_delivery"],"example":"card"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"}},"required":["id","object","card","billingDetails","type","createdAt"]},"Customer":{"type":"object","properties":{"id":{"type":"string","description":"ID of the Customer associated with this payment.","example":"cus_abc123"},"name":{"type":"string","description":"Customer's name as captured for this payment. Prefers the billing-details snapshot from the latest charge (immutable) over the Customer entity's current name.","nullable":true,"example":"Mohamed Ali"},"email":{"type":"string","description":"Customer's email captured for this payment. Falls back to the Customer entity's email if no billing-details email was provided.","nullable":true,"example":"customer@example.com"},"phone":{"type":"string","description":"Customer's phone captured for this payment, in E.164 format when available.","nullable":true,"example":"+20 100 123 4567"}},"required":["id"]},"NextActionRedirect":{"type":"object","properties":{"url":{"type":"string","description":"URL to redirect the customer to in order to complete the next step (typically 3-D Secure).","example":"https://hooks.xpay.app/3ds/redirect/abc123"},"returnUrl":{"type":"string","description":"URL the customer is sent back to after completing the redirect step. `null` if no return URL was configured.","nullable":true,"example":"https://example.com/checkout/return"}},"required":["url"]},"NextActionDetail":{"type":"object","properties":{"type":{"type":"string","description":"Kind of action the customer must take next. Today the only value is `redirect_to_url`; future payment methods may add new types.","example":"redirect_to_url"},"redirectToUrl":{"description":"Redirect details when `type` is `redirect_to_url`. `null` for any other action type.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/NextActionRedirect"}]}},"required":["type"]},"LastPaymentErrorDetail":{"type":"object","properties":{"code":{"type":"string","description":"Short machine-readable error code describing what failed (e.g. `card_declined`, `expired_card`, `incorrect_cvc`). `null` if no code applies.","nullable":true,"example":"card_declined"},"declineCode":{"type":"string","description":"More specific reason for a decline (e.g. `insufficient_funds`, `generic_decline`). Present when `code` is `card_declined`; otherwise `null`.","nullable":true,"example":"insufficient_funds"},"networkDeclineCode":{"type":"string","description":"Decline code returned by the card network itself, when different from `declineCode`. `null` if the network did not provide one.","nullable":true},"docUrl":{"type":"string","description":"Link to documentation explaining this error and how to recover from it.","nullable":true,"example":"https://docs.xpay.app/integrate/errors/decline-codes#insufficient_funds"},"message":{"type":"string","description":"Customer-safe message describing what went wrong. Safe to display in your UI.","example":"Your card has insufficient funds. Please try a different card."},"merchantMessage":{"type":"string","description":"Internal message for the merchant with more detail than `message`. Do NOT show this to customers. `null` if no merchant-only context is available.","nullable":true},"adviceCode":{"type":"string","description":"Advice on whether and how to retry. One of `confirm_card_data`, `do_not_try_again`, `try_again_later`. `null` if no specific advice applies.","nullable":true,"enum":["confirm_card_data","do_not_try_again","try_again_later"]},"param":{"type":"string","description":"Name of the request parameter that caused the error (e.g. `amount`, `payment_method`). `null` when the failure isn't tied to a specific parameter.","nullable":true},"chargeId":{"type":"string","description":"ID of the failed Charge that triggered this error. `null` if no charge was created.","nullable":true,"example":"ch_3MqAaCB4Ot..."},"paymentMethod":{"type":"object","description":"Snapshot of the payment method as it existed at the time of failure (brand, last 4, billing details, etc.). `null` if no payment method was attached when the error occurred.","nullable":true},"paymentMethodType":{"type":"string","description":"Type of the payment method that failed (e.g. `card`, `valu`, `fawry`). `null` if unknown.","nullable":true,"example":"card"},"type":{"type":"string","description":"Error category. One of `card_error`, `payment_method_error`, `api_error`, `invalid_request_error`. Use this for high-level branching in your error handling.","enum":["card_error","payment_method_error","api_error","invalid_request_error"],"example":"card_error"},"processorCode":{"type":"string","description":"Raw error code returned by the upstream processor, unmapped. Useful for support tickets and processor-specific debugging. Most applications should rely on `code` and `declineCode` instead.","nullable":true},"processorMessage":{"type":"string","description":"Raw error message returned by the upstream processor, unmapped. Useful for support tickets and processor-specific debugging. Most applications should rely on `message` instead.","nullable":true}},"required":["message","type"]},"NestedPaymentIntentResponse":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for this PaymentIntent. Always prefixed with `pi_`.","example":"pi_3MqAaCB4Otk1z2A30vXyz9aB"},"object":{"type":"string","description":"String identifying the object type. Always `payment_intent` for this resource.","example":"payment_intent"},"checkoutSessionId":{"type":"string","description":"ID of the CheckoutSession that created this PaymentIntent. `null` for PaymentIntents created directly via the API without a session.","nullable":true,"example":"cs_test_a1b2c3d4"},"amount":{"type":"number","description":"Amount the customer is being charged, in the smallest currency unit of `currency` (e.g. piasters for EGP — `10000` = 100 EGP).","example":10000},"amountCapturable":{"type":"number","description":"Amount that can still be captured for this PaymentIntent, in the smallest currency unit. Non-zero only when `captureMethod` is `manual` and the payment has been authorized but not yet captured. Drops to `0` once captured (fully or partially).","example":0},"amountReceived":{"type":"number","description":"Amount actually received from the customer so far, in the smallest currency unit. Equals `amount` after a successful capture; `0` for payments that haven't reached SUCCEEDED.","example":10000},"currency":{"type":"string","description":"ISO 4217 currency code this payment is denominated in.","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"status":{"type":"string","description":"Lifecycle status. Combines the raw processor state with refund state, so values like `REFUNDED`, `PARTIALLY_REFUNDED`, `UNCAPTURED`, and `FAILED` may appear in addition to the base processor states.","enum":["REQUIRES_PAYMENT_METHOD","REQUIRES_CONFIRMATION","REQUIRES_ACTION","PROCESSING","UNCAPTURED","CANCELED","SUCCEEDED","FAILED","REFUNDED","PARTIALLY_REFUNDED","AMOUNT_CAPTURABLE_UPDATED"],"example":"SUCCEEDED"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"clientSecret":{"type":"string","description":"Secret used by the SDK to confirm the payment from the customer's browser. Do NOT log this or share it with any party other than the customer. Each PaymentIntent has one client secret for its lifetime.","example":"pi_3MqAaCB4Otk1z2A30vXyz9aB_secret_xyz"},"captureMethod":{"type":"string","description":"When to capture funds from the customer. `automatic` (default) captures immediately on successful confirmation. `manual` only authorizes — call the capture endpoint later (within 7 days) to actually move the money.","enum":["automatic","manual"],"example":"automatic"},"confirmationMethod":{"type":"string","description":"How the PaymentIntent moves out of `REQUIRES_CONFIRMATION`. `automatic` (default) confirms as soon as a payment method is attached. `manual` requires you to call confirm explicitly.","enum":["automatic","manual"],"example":"automatic"},"description":{"type":"string","description":"Arbitrary description you can attach when creating the PaymentIntent. Shown in the dashboard and useful for reconciling with your own systems. `null` if not provided.","nullable":true,"example":"Order #1234"},"receiptEmail":{"type":"string","description":"Email to send the receipt to once the payment succeeds. `null` if no receipt email was set.","nullable":true,"example":"customer@example.com"},"canceledAt":{"type":"string","description":"ISO 8601 timestamp of when this PaymentIntent was canceled. `null` if it was never canceled.","nullable":true,"example":"2025-03-25T12:00:00.000Z"},"shipping":{"description":"Shipping address and recipient details for this payment. `null` if no shipping was collected.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/Shipping"}]},"amountDetails":{"description":"Breakdown of `amount` into product amount, tax, platform fees, tip, and discount. `null` for legacy payments without itemized breakdown.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/AmountDetails"}]},"presentmentDetails":{"description":"Mirror of `amount` / `currency` in the currency the customer actually saw at checkout, when different from the settlement currency. `null` when customer paid in the same currency.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PresentmentDetails"}]},"latestCharge":{"description":"The most recent Charge attempt for this PaymentIntent. `null` if no Charge has been attempted yet.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ChargeResponse"}]},"charges":{"description":"All Charge attempts for this PaymentIntent, sorted by creation time ascending (oldest first). Each retry adds a new Charge. Empty array if no attempts have been made yet.","type":"array","items":{"$ref":"#/components/schemas/ChargeResponse"}},"paymentMethod":{"description":"Payment method attached to this PaymentIntent. `null` before a method is attached or after a failure clears it.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PaymentMethodObject"}]},"customer":{"description":"The Customer this payment belongs to. `null` if no Customer is associated.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/Customer"}]},"nextAction":{"description":"Action the customer must take to advance the payment (e.g. complete 3-D Secure). `null` when no further action is needed.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/NextActionDetail"}]},"metadata":{"type":"object","description":"Custom key/value pairs you attached when creating or updating the PaymentIntent. Useful for reconciling with your own systems. Empty object if none.","example":{"orderId":"1234","channel":"web"}},"lastPaymentError":{"description":"Details of the most recent failed payment attempt for this PaymentIntent. `null` if no attempts have failed.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/LastPaymentErrorDetail"}]}},"description":"A PaymentIntent embedded inside a CheckoutSession. Same fields as PaymentIntent, but without the `checkoutSession` back-reference (you are already reading this from the enclosing CheckoutSession).","required":["id","object","amount","amountCapturable","amountReceived","currency","status","createdAt","updatedAt","clientSecret","captureMethod","confirmationMethod","charges","metadata"]},"DropdownOptionResponse":{"type":"object","properties":{"label":{"type":"string","description":"Option label"}},"required":["label"]},"CustomFieldTextValue":{"type":"object","properties":{"value":{"type":"string","description":"Text value"}},"required":["value"]},"CustomFieldNumericValue":{"type":"object","properties":{"value":{"type":"string","description":"Numeric value"}},"required":["value"]},"CustomFieldDropdownValue":{"type":"object","properties":{"value":{"type":"string","description":"Selected dropdown value"}},"required":["value"]},"CustomFieldResponse":{"type":"object","properties":{"key":{"type":"string","description":"Unique key for the field"},"label":{"type":"string","description":"Field label"},"type":{"type":"string","description":"Field type","enum":["TEXT","NUMBER","DROPDOWN","CHECKBOX"]},"isOptional":{"type":"boolean","description":"Whether the field is optional"},"hasLimits":{"type":"boolean","description":"Whether validation limits are enabled"},"limitType":{"type":"string","description":"Type of validation limit","enum":["AT_MOST","BETWEEN","AT_LEAST","EXACTLY"]},"minCharacters":{"type":"number","description":"Minimum number of characters"},"maxCharacters":{"type":"number","description":"Maximum number of characters"},"dropdownOptions":{"description":"Dropdown options","type":"array","items":{"$ref":"#/components/schemas/DropdownOptionResponse"}},"text":{"description":"Text value (populated after collection)","allOf":[{"$ref":"#/components/schemas/CustomFieldTextValue"}]},"numeric":{"description":"Numeric value (populated after collection)","allOf":[{"$ref":"#/components/schemas/CustomFieldNumericValue"}]},"dropdown":{"description":"Dropdown value (populated after collection)","allOf":[{"$ref":"#/components/schemas/CustomFieldDropdownValue"}]}},"required":["key","label","type","isOptional"]},"CouponResponse":{"type":"object","properties":{"id":{"type":"string","description":"Coupon ID"},"object":{"type":"string","description":"Object type","example":"coupon"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"discountType":{"type":"string","description":"Discount type","enum":["percentage","fixed_amount"]},"percentOff":{"type":"number","description":"Percentage off (0.01-100)"},"amountOff":{"type":"number","description":"Fixed amount off in smallest currency unit"},"currency":{"type":"string","description":"Currency for amountOff","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"]},"duration":{"type":"string","description":"Duration","enum":["once","repeating","forever"]},"durationInMonths":{"type":"number","description":"Number of months for repeating duration"},"name":{"type":"string","description":"Display name"},"maxDiscountAmount":{"type":"number","description":"Maximum discount amount for percentage coupons (caps the discount)"},"minValue":{"type":"number","description":"Minimum order subtotal required to use this coupon"},"maxRedemptions":{"type":"number","description":"Maximum total redemptions"},"customerMaxRedemptions":{"type":"number","description":"Maximum times a single customer can redeem"},"timesRedeemed":{"type":"number","description":"Number of times redeemed"},"redeemBy":{"type":"string","description":"Redemption deadline (ISO 8601)"},"valid":{"type":"boolean","description":"Whether the coupon is currently valid (computed)"},"active":{"type":"boolean","description":"Whether the coupon is active"},"appliesToProductIds":{"description":"Product IDs this coupon applies to","type":"array","items":{"type":"string"}},"metadata":{"type":"object","description":"Custom metadata"},"merchantId":{"type":"string","description":"Merchant ID"},"livemode":{"type":"boolean","description":"Whether this is live mode"}},"description":"A Coupon defines a reusable discount you can apply to Checkout Sessions and PaymentIntents. Coupons can grant either a percentage off (`percentOff`) or a fixed amount off (`amountOff`), and can apply once, forever, or repeating for a number of billing cycles. You can also cap how many times a Coupon may be redeemed and when it expires.\n\nCoupons are the reusable template. Each concrete application of a Coupon to a customer's purchase is recorded as a Discount. To give customers a redeemable code (e.g. `SUMMER25`) instead of applying the Coupon directly, create one or more Promotion Codes that map to this Coupon — a single Coupon can have many Promotion Codes, each with its own per-code restrictions. You receive `coupon.*` and `promotion_code.*` webhook events for each as they are created or changed.","required":["id","object","createdAt","discountType","duration","timesRedeemed","valid","active","merchantId","livemode"]},"DiscountResponse":{"type":"object","properties":{"id":{"type":"string","description":"Discount ID"},"object":{"type":"string","description":"Object type","example":"discount"},"coupon":{"description":"The coupon that was applied","allOf":[{"$ref":"#/components/schemas/CouponResponse"}]},"promotionCodeId":{"type":"string","description":"Promotion code ID used (null if direct coupon application)"},"promotionCodeCode":{"type":"string","description":"Customer-facing promotion code string (e.g. SUMMER25)"},"checkoutSessionId":{"type":"string","description":"Checkout session this discount was applied to"},"customerId":{"type":"string","description":"Customer who received the discount"},"start":{"type":"string","description":"When the discount became active (ISO 8601)"},"end":{"type":"string","description":"When the discount ends (ISO 8601)"}},"description":"A Discount records a single application of a Coupon to a specific Checkout Session, PaymentIntent, or Customer. Where a Coupon is the reusable template, a Discount captures the concrete redemption: which Coupon was applied, when it became active, when it expires, and (when applicable) which Promotion Code the customer entered to claim it.","required":["id","object","coupon","checkoutSessionId","start"]},"FeeConfigResponse":{"type":"object","properties":{"feesPassThrough":{"type":"boolean","description":"Whether customer pays platform fee (false = merchant pays)"},"vatCollectionEnabled":{"type":"boolean","description":"Whether to collect VAT from customer"},"vatCollectionRate":{"type":"number","description":"VAT collection rate in basis points (e.g., 1400 = 14%)"},"source":{"type":"string","description":"Where this config came from","enum":["session","merchant","system"]}},"required":["feesPassThrough","vatCollectionEnabled","source"]},"ColorCustomizationResponse":{"type":"object","properties":{"primary":{"type":"string","description":"Primary brand color (buttons, links, accents). Hex only, e.g. `#635bff`."},"primaryForeground":{"type":"string","description":"Primary foreground (text on primary background). Hex only."},"background":{"type":"string","description":"Page background color. Hex only."},"foreground":{"type":"string","description":"Main text color. Hex only."},"border":{"type":"string","description":"Border color. Hex only."},"input":{"type":"string","description":"Input, button, and dropdown border color. Hex only."},"ring":{"type":"string","description":"Focus ring color. Hex only."},"muted":{"type":"string","description":"Muted/secondary background. Hex only."},"mutedForeground":{"type":"string","description":"Muted text color. Hex only."},"accent":{"type":"string","description":"Accent background. Hex only."},"accentForeground":{"type":"string","description":"Accent text color. Hex only."},"destructive":{"type":"string","description":"Destructive/error color. Hex only."}}},"BrandingSettingsResponse":{"type":"object","properties":{"colorMode":{"type":"string","description":"Dark mode preference","enum":["light","dark","system"]},"borderStyle":{"type":"string","description":"Border style for inputs, buttons, cards","enum":["rounded","sharp","pill"]},"spacing":{"type":"string","description":"Spacing density","enum":["condensed","normal","spacious"]},"inputSize":{"type":"string","description":"Input field size","enum":["small","medium","large"]},"inputStyle":{"type":"string","description":"Input field style","enum":["flat","outlined","filled"]},"formLayout":{"type":"string","description":"Form layout density","enum":["compact","spacious"]},"colors":{"description":"Color customization options","allOf":[{"$ref":"#/components/schemas/ColorCustomizationResponse"}]},"fontFamily":{"type":"string","description":"Font family override"}}},"PaymentMethodTypeResponse":{"type":"object","properties":{"type":{"type":"string","description":"Concrete payment method type (e.g., 'card', 'fawry', 'valu')"},"displayName":{"type":"string","description":"Display name for the payment method"},"category":{"type":"string","description":"UI grouping category (e.g., 'card', 'bnpl', 'kiosk')"},"minTransactionAmount":{"type":"string","description":"Minimum transaction amount in piasters","nullable":true},"maxTransactionAmount":{"type":"string","description":"Maximum transaction amount in piasters","nullable":true},"requiredCustomerFields":{"description":"Required customer fields for this payment method","nullable":true,"type":"array","items":{"type":"string"}},"supportsRefund":{"type":"boolean","description":"Whether this payment method supports refunds"},"supportsPartialRefund":{"type":"boolean","description":"Whether partial refunds are supported"},"supportsPartialCapture":{"type":"boolean","description":"Whether partial capture is supported"},"paymentConfirmation":{"type":"string","description":"Whether payment resolves immediately or asynchronously","example":"immediate"}},"required":["type","displayName"]},"CardInfoResponse":{"type":"object","properties":{"brand":{"type":"string","description":"Card brand (e.g., Visa, Mastercard)"},"isOnUs":{"type":"boolean","description":"Whether this is an on-us transaction (same bank)"},"isInternational":{"type":"boolean","description":"Whether this is an international card"}},"required":["brand","isOnUs","isInternational"]},"FeesResponse":{"type":"object","properties":{"paymentMethodType":{"type":"string","description":"Payment method type (e.g., card, fawry, valu)"},"feeAmount":{"type":"number","description":"Platform fee amount (only if feesPassThrough is true)"},"feePercentage":{"type":"number","description":"Fee percentage"},"vatAmount":{"type":"number","description":"VAT amount (only if vatCollectionEnabled is true)"},"totalAmount":{"type":"number","description":"Total amount customer will pay"},"cardInfo":{"description":"Card info (only for card payments with BIN)","allOf":[{"$ref":"#/components/schemas/CardInfoResponse"}]}},"required":["paymentMethodType","feeAmount","feePercentage","totalAmount"]},"CustomerUpdateResponse":{"type":"object","properties":{"address":{"type":"string","description":"Whether to save address to customer.address","enum":["auto","never"]},"name":{"type":"string","description":"Whether to save name to customer.name","enum":["auto","never"]},"shipping":{"type":"string","description":"Whether to save shipping to customer.shipping","enum":["auto","never"]}}},"CheckoutSessionResponse":{"type":"object","properties":{"id":{"type":"string","description":"Checkout session ID. Absent on the SSR hosted-view payload derived from a payment link (before the first mutation materializes the session)."},"object":{"type":"string","description":"Object type","example":"checkout.session"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)"},"mode":{"type":"string","description":"Session mode","enum":["payment","setup","subscription"]},"uiMode":{"type":"string","description":"UI mode","enum":["hosted","embedded","custom"]},"submitType":{"type":"string","description":"Submit type","enum":["PAY","SUBSCRIBE","BOOK","DONATE"]},"customerCreation":{"type":"string","description":"Customer creation mode","enum":["always","if_required"]},"status":{"type":"string","description":"Session status","enum":["open","complete","expired"]},"paymentStatus":{"type":"string","description":"Payment status","enum":["paid","unpaid","no_payment_required"],"example":"unpaid"},"currency":{"type":"string","description":"Currency code (ISO 4217)","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"amountSubtotal":{"type":"number","description":"Subtotal before discounts/taxes"},"amountTotal":{"type":"number","description":"Total amount due"},"totalDetails":{"description":"Amount breakdown","allOf":[{"$ref":"#/components/schemas/TotalDetailsResponse"}]},"presentmentDetails":{"description":"Customer-facing view of the session — full mirror of subtotal/total/discount/VAT/fees in the presentment currency. Populated only when the merchant prices in a currency different from processing. Uses a rate locked at session creation.","allOf":[{"$ref":"#/components/schemas/SessionPresentmentDetails"}]},"afterCompletion":{"type":"object","description":"What happens after payment: redirect to merchant URL or show hosted confirmation page"},"cancelUrl":{"type":"string","description":"Cancel redirect URL (back button during checkout)"},"url":{"type":"string","description":"Checkout page URL (hosted mode)"},"clientSecret":{"type":"string","description":"Client secret for frontend access"},"expiresAt":{"type":"string","description":"Expiration timestamp (ISO 8601)"},"isExpired":{"type":"boolean","description":"Whether this session can no longer be paid because it has expired (either swept/expired by status, or past `expiresAt`). Clients MUST render from this flag and MUST NOT re-derive expiry by comparing `expiresAt` against the local clock — a customer device running fast reads a live session as dead.","example":false},"customerId":{"type":"string","description":"Customer ID (when existing customer linked)"},"customer":{"description":"Customer object (when customerId is provided). Contains existing customer data for prefill.","allOf":[{"$ref":"#/components/schemas/CheckoutSessionCustomer"}]},"customerDetails":{"description":"CustomerDetails - unified prefill/collection object. Contains name, email, phone, address (billing), shipping.","allOf":[{"$ref":"#/components/schemas/CustomerDetailsResponse"}]},"paymentIntentId":{"type":"string","description":"Payment Intent ID"},"paymentIntent":{"description":"The PaymentIntent for this session, or `null` if no payment has been started yet. The PaymentIntent's own `checkoutSession` field is not included here to keep the response self-contained.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/NestedPaymentIntentResponse"}]},"lineItems":{"description":"Line items with full price and product details","type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"customFields":{"description":"Custom fields with configuration and collected values (Stripe-aligned). Values are populated after customer submits.","type":"array","items":{"$ref":"#/components/schemas/CustomFieldResponse"}},"discounts":{"description":"Applied discounts on this session","type":"array","items":{"$ref":"#/components/schemas/DiscountResponse"}},"allowPromotionCodes":{"type":"boolean","description":"Allow promotion codes"},"nameCollection":{"type":"boolean","description":"Collect customer name"},"billingAddressCollection":{"type":"boolean","description":"Collect billing address"},"shippingAddressCollection":{"type":"boolean","description":"Collect shipping address"},"phoneNumberCollection":{"type":"boolean","description":"Collect phone number"},"feeConfig":{"description":"Fee configuration (tells checkout whether to track BIN and display fees)","allOf":[{"$ref":"#/components/schemas/FeeConfigResponse"}]},"brandingSettings":{"description":"UI customization settings for checkout (colors, spacing, borders, etc.). Fully resolved: merchant defaults merged with session-level overrides. Callers can apply this object directly — no client-side merging required.","allOf":[{"$ref":"#/components/schemas/BrandingSettingsResponse"}]},"locale":{"type":"string","description":"Language the checkout page is displayed in. Resolved from `session.locale`, falling back to your account's `defaultLocale`, then to `en`.","enum":["en","ar"]},"paymentMethodTypes":{"description":"Available payment method types with fee estimates","type":"array","items":{"$ref":"#/components/schemas/PaymentMethodTypeResponse"}},"paymentMethodConfigurationId":{"type":"string","description":"ID of the PaymentMethodConfiguration used for this session"},"fees":{"description":"Fee breakdown (only populated when feesPassThrough or vatCollectionEnabled, and after /update with BIN for cards)","allOf":[{"$ref":"#/components/schemas/FeesResponse"}]},"customerUpdate":{"description":"Controls which customer fields to update when customerId is provided","allOf":[{"$ref":"#/components/schemas/CustomerUpdateResponse"}]},"metadata":{"type":"object","description":"Custom metadata"},"merchantId":{"type":"string","description":"Merchant ID"},"merchantName":{"type":"string","description":"Merchant display name"},"merchantLogo":{"type":"string","description":"Merchant logo URL"},"paymentLinkId":{"type":"string","description":"Payment Link ID (if created from link)"},"livemode":{"type":"boolean","description":"Whether this is a live mode session"}},"description":"A Checkout Session represents your customer's session as they pay on an xpay-hosted checkout page. Create a new Session each time a customer begins a checkout: attach line items, customer details, or a PaymentIntent, then redirect the customer to the Session's `url` to begin payment. As the customer progresses, the Session's `status` and `paymentStatus` update; once payment succeeds, the Session contains references to the resulting Customer and PaymentIntent. Sessions expire 24 hours after creation if not completed.","required":["object","createdAt","mode","uiMode","submitType","customerCreation","status","paymentStatus","afterCompletion","isExpired","paymentIntent","allowPromotionCodes","nameCollection","billingAddressCollection","shippingAddressCollection","phoneNumberCollection","merchantId","livemode"]},"UpdateMerchantCheckoutSession":{"type":"object","properties":{"afterCompletion":{"description":"Behavior after the purchase is complete.\n\n**type=redirect** (default): Redirect customer to your URL after payment. Requires `afterCompletion.redirect.url`.\n\n**type=hosted_confirmation**: Show a built-in XPay-hosted success page. Optionally provide `afterCompletion.hostedConfirmation.customMessage` and `afterCompletion.hostedConfirmation.returnUrl`.\n\nExample (redirect): `{ type: 'redirect', redirect: { url: 'https://example.com/success' } }`\n\nExample (hosted): `{ type: 'hosted_confirmation', hostedConfirmation: { customMessage: 'Thanks!' } }`","example":{"type":"redirect","redirect":{"url":"https://example.com/success?session_id={CHECKOUT_SESSION_ID}"}},"allOf":[{"$ref":"#/components/schemas/AfterCompletion"}]},"lineItems":{"description":"Line items for the checkout","type":"array","items":{"$ref":"#/components/schemas/LineItemInput"}},"cancelUrl":{"type":"string","description":"URL to redirect if customer cancels (back button during checkout). This parameter is not allowed if uiMode is embedded or custom."},"customerId":{"type":"string","description":"Existing customer ID. If provided, customer data will be used to prefill checkout fields.\n\n    IMPORTANT: Cannot be used together with customerDetails - you must choose one:\n    - Use customerId to checkout with an existing customer\n    - Use customerDetails to provide prefill data for a new customer"},"customerDetails":{"description":"Customer details for prefill and collection. Used to:\n    - Prefill checkout form fields\n    - Create a new customer (if customerCreation is 'always')\n\n    IMPORTANT: Cannot be used together with customerId - you must choose one.","allOf":[{"$ref":"#/components/schemas/CustomerDetailsInput"}]},"customerUpdate":{"description":"Controls which customer fields to update when customerId is provided.\n\n    IMPORTANT: Only valid when customerId is provided. Will be ignored otherwise.\n\n    Each field can be 'auto' (update customer) or 'never' (don't update, default).","allOf":[{"$ref":"#/components/schemas/CustomerUpdate"}]},"customerCreation":{"type":"string","description":"When to create customer","enum":["always","if_required"],"default":"if_required"},"allowPromotionCodes":{"type":"boolean","description":"Allow promotion codes"},"discounts":{"description":"Discounts to apply to this session. Each must reference either a coupon ID or promotion code ID. Max 1 discount per session.","type":"array","items":{"$ref":"#/components/schemas/CheckoutDiscountInput"}},"nameCollection":{"type":"boolean","description":"Collect customer name. You can't set this parameter if uiMode is custom."},"billingAddressCollection":{"type":"boolean","description":"Collect billing address. You can't set this parameter if uiMode is custom."},"shippingAddressCollection":{"type":"boolean","description":"Collect shipping address. You can't set this parameter if uiMode is custom."},"phoneNumberCollection":{"type":"boolean","description":"Collect phone number. You can't set this parameter if uiMode is custom."},"customFields":{"description":"Custom fields to collect","type":"array","items":{"$ref":"#/components/schemas/CustomFieldInput"}},"metadata":{"type":"object","description":"Custom key-value metadata"},"feeConfig":{"description":"Fee configuration override for this session.\n    If not provided, merchant's default fee config will be used.\n\n    - feesPassThrough: Customer pays platform fee instead of merchant\n    - vatCollectionEnabled: Collect merchant's product VAT from customer\n    - vatCollectionRate: VAT rate in basis points (e.g., 1400 = 14%)","allOf":[{"$ref":"#/components/schemas/FeeConfigInput"}]},"brandingSettings":{"description":"UI customization settings for the checkout page.\n    Allows customization of colors, spacing, border styles, input styles, etc.\n    Merged server-side with the merchant's `defaultBrandingSettings` — anything set here wins.","allOf":[{"$ref":"#/components/schemas/BrandingSettingsInput"}]},"locale":{"type":"string","description":"Language the checkout page is displayed in.\n    Falls back to your account's `defaultLocale` when omitted, then to `en`.","enum":["en","ar"]},"paymentMethodTypes":{"type":"array","description":"Restrict this session to specific payment method types.\n    Most integrations omit this and manage methods from the dashboard under Settings > Payment methods.\n    Every type must already be enabled on your account, or the request is rejected.\n    Mutually exclusive with paymentMethodConfigurationId. Omit both to use your default configuration.\n\n    Example: [\"card\", \"valu\"]","items":{"type":"string","enum":["card","fawry","aman","valu","sympl","tabby","tamara","vodafone_cash","etisalat_cash","orange_cash","we_pay","apple_pay","google_pay","samsung_pay","instapay","bank_transfer","cash_on_delivery"]}},"paymentMethodConfigurationId":{"type":"string","description":"ID of a payment method configuration to use for this session.\n    Find IDs in your dashboard under Settings > Payment methods.\n    Preferred over `paymentMethodTypes`: the list stays editable in the dashboard.\n    Mutually exclusive with `paymentMethodTypes`. Omit both to use your default configuration.","example":"pmc_abc123"}}},"PromotionCodeResponse":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for this Promotion Code. Always prefixed with `promo_`.","example":"promo_abc123"},"object":{"type":"string","description":"String identifying the object type. Always `promotion_code` for this resource.","example":"promotion_code"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"code":{"type":"string","description":"The customer-facing code merchants share and customers enter at checkout.","example":"SUMMER25"},"active":{"type":"boolean","description":"Whether the code can currently be redeemed. Set to `false` to disable a code without deleting it."},"coupon":{"description":"The Coupon this code redeems. Multiple Promotion Codes can map to the same Coupon.","allOf":[{"$ref":"#/components/schemas/CouponResponse"}]},"customerId":{"type":"string","description":"ID of the specific Customer this code is bound to. When set, only that Customer can redeem the code.","example":"cus_abc123"},"maxRedemptions":{"type":"number","description":"Maximum number of times this specific code can be redeemed across all customers. Independent from the parent Coupon's `maxRedemptions`.","example":100},"timesRedeemed":{"type":"number","description":"Number of times this code has already been redeemed."},"expiresAt":{"type":"string","description":"When this code stops being redeemable (ISO 8601). Independent from the parent Coupon's `redeemBy`.","example":"2026-12-31T23:59:59.000Z"},"restrictions":{"type":"object","description":"Per-code restrictions (e.g. minimum order amount, first-time customers only)."},"metadata":{"type":"object","description":"Custom key/value metadata you attached to the code."},"merchantId":{"type":"string","description":"Merchant ID this Promotion Code belongs to."},"livemode":{"type":"boolean","description":"Whether the Promotion Code exists in live mode (vs. test mode)."}},"description":"A Promotion Code is a customer-facing alphanumeric code (for example `SUMMER25`) that maps to a single Coupon. One Coupon can have many Promotion Codes, letting you run different campaigns (email vs. social, customer-specific codes, regional codes, …) against the same underlying discount. Customers enter the code at checkout to redeem the Coupon's discount. Promotion Codes can carry their own restrictions on top of the Coupon — a per-code redemption cap, an expiry date, or a binding to a specific Customer. You receive `promotion_code.created` and `promotion_code.updated` webhook events whenever a code is created or modified.","required":["id","object","createdAt","code","active","coupon","timesRedeemed","merchantId","livemode"]},"CreateCustomer":{"type":"object","properties":{"name":{"type":"string","description":"Customer name","example":"John Doe"},"email":{"type":"string","description":"Customer email","example":"john@example.com"},"phone":{"type":"string","description":"Customer phone number. Canonicalized to E.164 when it parses; stored as given otherwise.","example":"+201007972983"},"currency":{"type":"string","description":"Customer currency","example":"EGP"},"address":{"type":"object","description":"Customer address","example":{"line1":"123 Main St","city":"Cairo","country":"EG"}},"metadata":{"type":"object","description":"Custom metadata","example":{"source":"simulation"}}},"required":["name","email","phone","currency","address","metadata"]},"CustomerResponse":{"type":"object","properties":{"id":{"type":"string","description":"Customer ID","example":"cus_abc123xyz"},"object":{"type":"string","description":"Object type","example":"customer"},"type":{"type":"string","description":"Customer type: registered (merchant-created) or guest (auto-created during checkout)","enum":["registered","guest"],"example":"registered"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)"},"name":{"type":"string","description":"Customer name","nullable":true},"email":{"type":"string","description":"Customer email","nullable":true},"phone":{"type":"string","description":"Customer phone number","nullable":true},"address":{"type":"object","description":"Customer address","nullable":true},"guestFingerprint":{"type":"object","description":"Guest fingerprint (only populated for `type=guest`). Captures the set of emails/phones/card fingerprints used during checkout so the same shopper is recognizable across sessions.","nullable":true},"metadata":{"type":"object","description":"Merchant-supplied custom metadata","nullable":true},"merchantId":{"type":"string","description":"Merchant ID owning this customer"}},"description":"A Customer represents a buyer you do business with. Use Customers to save payment methods for reuse, track lifetime spend, attach metadata for your CRM, and group related Charges, Refunds, and Checkout Sessions under a single record. You can identify a Customer by their email or by a stable external ID from your own system and reference them on any future payment.","required":["id","object","type","createdAt","updatedAt","merchantId"]},"TransactionCardDetails":{"type":"object","properties":{"brand":{"type":"string","description":"Card brand/network","example":"visa"},"last4":{"type":"string","description":"Last 4 digits of card","example":"4242"},"expMonth":{"type":"number","description":"Card expiration month","example":12},"expYear":{"type":"number","description":"Card expiration year","example":2025},"cardholderName":{"type":"string","description":"Cardholder name","nullable":true},"funding":{"type":"string","description":"Card funding type","nullable":true},"country":{"type":"string","description":"Card country","nullable":true},"fingerprint":{"type":"string","description":"Card fingerprint","nullable":true}},"required":["brand","last4","expMonth","expYear"]},"TransactionPaymentMethod":{"type":"object","properties":{"id":{"type":"string","description":"Payment method ID","example":"pm_xyz789"},"type":{"type":"string","description":"Payment method type","enum":["card","fawry","aman","valu","sympl","tabby","tamara","vodafone_cash","etisalat_cash","orange_cash","we_pay","apple_pay","google_pay","samsung_pay","instapay","bank_transfer","cash_on_delivery"],"example":"card"},"card":{"description":"Card details (if type is CARD)","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/TransactionCardDetails"}]},"valu":{"description":"ValU details (if type is 'valu')","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ValuDetails"}]}},"required":["id","type"]},"SpendData":{"type":"object","properties":{"amountDisputeLosses":{"type":"number","description":"Total amount lost to disputes (in smallest currency unit)","example":0},"amountRefunded":{"type":"number","description":"Total amount refunded to customer (in smallest currency unit)","example":100},"averageOrderValue":{"type":"number","description":"Average order value (grossSpend / numPayments)","example":500},"currency":{"type":"string","description":"Customer's default currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"firstPurchaseAt":{"type":"string","description":"Date of first purchase (ISO 8601 date string, empty string if none)","example":"2024-01-15T10:30:00.000Z"},"grossSpend":{"type":"number","description":"Total amount charged (before refunds, in smallest currency unit)","example":1000},"lastPurchaseAt":{"type":"string","description":"Date of most recent purchase (ISO 8601 date string, empty string if none)","example":"2024-03-20T14:45:00.000Z"},"netSpend":{"type":"number","description":"Total amount after refunds (grossSpend - amountRefunded)","example":900},"numPayments":{"type":"number","description":"Total number of successful payments","example":5}},"required":["amountDisputeLosses","amountRefunded","averageOrderValue","currency","firstPurchaseAt","grossSpend","lastPurchaseAt","netSpend","numPayments"]},"ListCustomer":{"type":"object","properties":{"id":{"type":"string","description":"Customer ID","example":"cus_abc123"},"type":{"type":"string","description":"Customer type","enum":["registered","guest"],"example":"registered"},"createdAt":{"format":"date-time","type":"string","description":"Customer creation date","example":"2024-01-01T00:00:00.000Z"},"name":{"type":"string","description":"Customer name","example":"John Doe"},"email":{"type":"string","description":"Customer email","example":"john@example.com"},"phone":{"type":"string","description":"Customer phone number","example":"+201234567890"},"country":{"type":"string","description":"Customer country (ISO 3166-1 alpha-2 code)","example":"EG","nullable":true},"latestPaymentMethod":{"description":"Latest payment method (most recently created)","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/TransactionPaymentMethod"}]},"spendData":{"description":"Customer spend data","allOf":[{"$ref":"#/components/schemas/SpendData"}]}},"required":["id","type","createdAt","spendData"]},"ListCustomersResponse":{"type":"object","properties":{"data":{"description":"Array of customers","type":"array","items":{"$ref":"#/components/schemas/ListCustomer"}},"totalCount":{"type":"number","description":"Total count of matching records (for pagination)","example":42}},"required":["data","totalCount"]},"CreateLineItem":{"type":"object","properties":{"priceId":{"type":"string","description":"Price ID","example":"price_abc123"},"quantity":{"type":"number","description":"Quantity. May be 0 only when adjustableQuantity is enabled with minimum 0 (optional item).","example":1,"minimum":0,"maximum":2147483647},"adjustableQuantity":{"description":"Adjustable quantity settings","allOf":[{"$ref":"#/components/schemas/AdjustableQuantity"}]}},"required":["priceId","quantity","adjustableQuantity"]},"CreateDropdownOption":{"type":"object","properties":{"label":{"type":"string","description":"Option label","example":"Option 1"}},"required":["label"]},"CreateCustomField":{"type":"object","properties":{"label":{"type":"string","description":"Field label","example":"Company Name"},"type":{"type":"string","description":"Field type","enum":["TEXT","NUMBER","DROPDOWN","CHECKBOX"],"example":"TEXT"},"isOptional":{"type":"boolean","description":"Whether the field is optional","example":false},"hasLimits":{"type":"boolean","description":"Whether validation limits are enabled","example":false},"limitType":{"type":"string","description":"Type of validation limit","enum":["AT_MOST","BETWEEN","AT_LEAST","EXACTLY"],"example":"BETWEEN"},"minCharacters":{"type":"number","description":"Minimum number of characters","example":5},"maxCharacters":{"type":"number","description":"Maximum number of characters","example":100},"dropdownOptions":{"description":"Dropdown options (only for DROPDOWN type)","type":"array","items":{"$ref":"#/components/schemas/CreateDropdownOption"}}},"required":["label","type","isOptional"]},"CreatePaymentLink":{"type":"object","properties":{"lineItems":{"description":"Line items for the payment link","minItems":1,"type":"array","items":{"$ref":"#/components/schemas/CreateLineItem"}},"nameCollection":{"type":"boolean","description":"Whether to collect customer name","default":false},"billingAddressCollection":{"type":"boolean","description":"Whether to collect billing address","default":false},"shippingAddressCollection":{"type":"boolean","description":"Whether to collect shipping address","default":false},"phoneNumberCollection":{"type":"boolean","description":"Whether to collect phone number","default":false},"allowPromotionCodes":{"type":"boolean","description":"Whether to allow promotion codes","default":false},"submitType":{"type":"string","description":"Submit button type","enum":["PAY","SUBSCRIBE","BOOK","DONATE"],"default":"PAY"},"customerCreation":{"type":"string","description":"When to create customer","enum":["always","if_required"],"default":"if_required"},"afterCompletion":{"description":"Behavior after the purchase is complete.\n\n**type=redirect** (default): Redirect customer to your URL after payment. Requires `afterCompletion.redirect.url`.\n\n**type=hosted_confirmation**: Show a built-in XPay-hosted success page. Optionally provide `afterCompletion.hostedConfirmation.customMessage` and `afterCompletion.hostedConfirmation.returnUrl`.\n\nExample (redirect): `{ type: 'redirect', redirect: { url: 'https://example.com/success' } }`\n\nExample (hosted): `{ type: 'hosted_confirmation', hostedConfirmation: { customMessage: 'Thanks!' } }`","example":{"type":"redirect","redirect":{"url":"https://example.com/success"}},"allOf":[{"$ref":"#/components/schemas/AfterCompletion"}]},"customFields":{"description":"Custom fields (max 3)","maxItems":3,"type":"array","items":{"$ref":"#/components/schemas/CreateCustomField"}},"expiresAt":{"type":"string","description":"Expiration date","example":"2024-12-31T23:59:59Z"},"metadata":{"type":"object","description":"Custom key-value metadata"},"feeConfig":{"description":"Fee configuration override. If not provided, merchant's default fee config will be used.","allOf":[{"$ref":"#/components/schemas/FeeConfigInput"}]},"brandingSettings":{"description":"UI customization settings for the checkout page","allOf":[{"$ref":"#/components/schemas/BrandingSettingsInput"}]},"paymentMethodConfigurationId":{"type":"string","description":"ID of a PaymentMethodConfiguration to use. Omit to use the merchant's default configuration."}},"required":["lineItems","afterCompletion"]},"AfterCompletionRedirectResponse":{"type":"object","properties":{"url":{"type":"string","description":"Redirect URL"}},"required":["url"]},"AfterCompletionHostedConfirmationResponse":{"type":"object","properties":{"customMessage":{"type":"string","description":"Custom message"},"returnUrl":{"type":"string","description":"Return URL"}}},"AfterCompletionResponse":{"type":"object","properties":{"type":{"type":"string","description":"After completion type","enum":["redirect","hosted_confirmation"]},"redirect":{"description":"Redirect configuration","allOf":[{"$ref":"#/components/schemas/AfterCompletionRedirectResponse"}]},"hostedConfirmation":{"description":"Hosted confirmation configuration","allOf":[{"$ref":"#/components/schemas/AfterCompletionHostedConfirmationResponse"}]}},"required":["type"]},"DropdownOption":{"type":"object","properties":{"label":{"type":"string","description":"Option label","example":"Option 1"}},"required":["label"]},"CustomField":{"type":"object","properties":{"label":{"type":"string","description":"Field label","example":"Company Name"},"type":{"type":"string","description":"Field type","enum":["TEXT","NUMBER","DROPDOWN","CHECKBOX"],"example":"TEXT"},"isOptional":{"type":"boolean","description":"Whether the field is optional","example":false},"hasLimits":{"type":"boolean","description":"Whether validation limits are enabled","example":false},"limitType":{"type":"string","description":"Type of validation limit","enum":["AT_MOST","BETWEEN","AT_LEAST","EXACTLY"],"example":"BETWEEN"},"minCharacters":{"type":"number","description":"Minimum number of characters","example":5},"maxCharacters":{"type":"number","description":"Maximum number of characters","example":100},"dropdownOptions":{"description":"Dropdown options (only for DROPDOWN type)","type":"array","items":{"$ref":"#/components/schemas/DropdownOption"}}},"required":["label","type","isOptional","hasLimits"]},"ResolvedFeeConfig":{"type":"object","properties":{"feesPassThrough":{"type":"boolean","description":"Whether customer pays platform fee (false = merchant pays)","example":false},"vatCollectionEnabled":{"type":"boolean","description":"Whether to collect VAT from customer","example":false},"vatCollectionRate":{"type":"number","description":"VAT collection rate in basis points (e.g., 1400 = 14%)","example":1400},"source":{"type":"string","description":"Where this config came from","enum":["session","merchant","system"],"example":"merchant"}},"required":["feesPassThrough","vatCollectionEnabled","source"]},"PaymentLinkResponse":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for this Payment Link. Always prefixed with `plink_`.","example":"plink_abc123"},"object":{"type":"string","description":"String identifying the object type. Always `payment_link` for this resource.","example":"payment_link"},"merchantId":{"type":"string","description":"Merchant ID","example":"mer_xyz789"},"active":{"type":"boolean","description":"Whether the payment link is active","example":true},"expiresAt":{"type":"string","description":"Expiration timestamp (ISO 8601)"},"currency":{"type":"string","description":"Currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"computedAmount":{"type":"number","description":"Computed total amount from line items","example":100000},"nameCollection":{"type":"boolean","description":"Whether to collect customer name","example":false},"billingAddressCollection":{"type":"boolean","description":"Whether to collect billing address","example":false},"shippingAddressCollection":{"type":"boolean","description":"Whether to collect shipping address","example":false},"phoneNumberCollection":{"type":"boolean","description":"Whether to collect phone number","example":false},"allowPromotionCodes":{"type":"boolean","description":"Whether to allow promotion codes","example":false},"submitType":{"type":"string","description":"Submit type","enum":["PAY","SUBSCRIBE","BOOK","DONATE"],"example":"PAY"},"customerCreation":{"type":"string","description":"When to create customer","enum":["always","if_required"]},"afterCompletion":{"description":"After completion settings","allOf":[{"$ref":"#/components/schemas/AfterCompletionResponse"}]},"lineItems":{"description":"Line items","type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"customFields":{"description":"Custom fields","type":"array","items":{"$ref":"#/components/schemas/CustomField"}},"feeConfig":{"description":"Fee configuration","allOf":[{"$ref":"#/components/schemas/ResolvedFeeConfig"}]},"metadata":{"type":"object","description":"Custom metadata"},"brandingSettings":{"description":"Branding settings","allOf":[{"$ref":"#/components/schemas/BrandingSettingsResponse"}]},"paymentMethodConfigurationId":{"type":"string","description":"Payment method configuration ID"},"createdAt":{"type":"string","description":"Creation timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Last update timestamp (ISO 8601)"}},"description":"A Payment Link is a shareable URL you can send to a customer to collect a single payment or set up a subscription, without writing any checkout code. Open the URL in any browser and we render the hosted checkout, collect payment details, and process the payment. Use Payment Links for one-off invoices, social-media checkout, in-person QR codes, or anywhere you need a checkout page without integrating the SDK.","required":["id","object","merchantId","active","currency","computedAmount","nameCollection","billingAddressCollection","shippingAddressCollection","phoneNumberCollection","allowPromotionCodes","submitType","lineItems","createdAt","updatedAt"]},"ListPaymentLink":{"type":"object","properties":{"id":{"type":"string","description":"Payment link ID","example":"plink_abc123"},"merchantId":{"type":"string","description":"Merchant ID","example":"mer_xyz789"},"active":{"type":"boolean","description":"Whether the payment link is active","example":true},"expiresAt":{"type":"string","description":"Expiration timestamp (ISO 8601)"},"currency":{"type":"string","description":"Currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"computedAmount":{"type":"number","description":"Computed total amount from line items","example":100000},"submitType":{"type":"string","description":"Submit type","enum":["PAY","SUBSCRIBE","BOOK","DONATE"],"example":"PAY"},"afterCompletion":{"description":"After completion settings","allOf":[{"$ref":"#/components/schemas/AfterCompletionResponse"}]},"lineItems":{"description":"Line items","type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"createdAt":{"type":"string","description":"Creation timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Last update timestamp (ISO 8601)"}},"required":["id","merchantId","active","currency","computedAmount","submitType","lineItems","createdAt","updatedAt"]},"ListPaymentLinksResponse":{"type":"object","properties":{"data":{"description":"Array of payment links","type":"array","items":{"$ref":"#/components/schemas/ListPaymentLink"}},"totalCount":{"type":"number","description":"Total count of matching records (for pagination)","example":42}},"required":["data","totalCount"]},"UpdatePaymentLink":{"type":"object","properties":{"lineItems":{"description":"Line items for the payment link (if provided, replaces all existing line items)","minItems":1,"type":"array","items":{"$ref":"#/components/schemas/CreateLineItem"}},"nameCollection":{"type":"boolean","description":"Whether to collect customer name"},"billingAddressCollection":{"type":"boolean","description":"Whether to collect billing address"},"shippingAddressCollection":{"type":"boolean","description":"Whether to collect shipping address"},"phoneNumberCollection":{"type":"boolean","description":"Whether to collect phone number"},"allowPromotionCodes":{"type":"boolean","description":"Whether to allow promotion codes"},"submitType":{"type":"string","description":"Submit type","enum":["PAY","SUBSCRIBE","BOOK","DONATE"]},"customerCreation":{"type":"string","description":"When to create customer","enum":["always","if_required"]},"afterCompletion":{"description":"After completion settings (if provided, replaces existing settings)","allOf":[{"$ref":"#/components/schemas/AfterCompletion"}]},"customFields":{"description":"Custom fields (max 3, if provided, replaces all existing custom fields)","maxItems":3,"type":"array","items":{"$ref":"#/components/schemas/CreateCustomField"}},"expiresAt":{"type":"string","description":"Expiration date (set to null to remove expiration)","example":"2024-12-31T23:59:59Z"},"active":{"type":"boolean","description":"Whether the payment link is active"},"metadata":{"type":"object","description":"Custom key-value metadata"},"feeConfig":{"description":"Fee configuration override. Pass null to clear and use merchant defaults.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/FeeConfigInput"}]},"brandingSettings":{"description":"UI customization settings for the checkout page","allOf":[{"$ref":"#/components/schemas/BrandingSettingsInput"}]},"paymentMethodConfigurationId":{"type":"string","description":"ID of a PaymentMethodConfiguration to use. Send null to reset to default.","nullable":true}}},"RecurringConfig":{"type":"object","properties":{"interval":{"type":"string","description":"Interval type for recurring prices","enum":["DAY","WEEK","MONTH","YEAR","CUSTOM"],"example":"MONTH"},"intervalCount":{"type":"number","description":"Number of intervals between each billing cycle","example":1}}},"CustomUnitAmountResponse":{"type":"object","properties":{"minimum":{"type":"number","description":"Minimum amount the customer may enter (minor units).","nullable":true},"maximum":{"type":"number","description":"Maximum amount the customer may enter (minor units).","nullable":true},"preset":{"type":"number","description":"Suggested amount pre-filled for the customer (minor units).","nullable":true}}},"PriceResponse":{"type":"object","properties":{"id":{"type":"string","description":"Price ID","example":"price_abc123"},"object":{"type":"string","description":"Object type","example":"price"},"name":{"type":"string","description":"Price name","nullable":true},"description":{"type":"string","description":"Price description","nullable":true},"currency":{"type":"string","description":"Currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"unitAmount":{"type":"number","description":"Unit amount in smallest currency unit (e.g., piasters for EGP)","nullable":true},"type":{"type":"string","description":"Price type","enum":["ONE_TIME","RECURRING","CUSTOM"],"example":"ONE_TIME"},"recurring":{"description":"Recurring configuration (interval + intervalCount), null for one-time prices","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/RecurringConfig"}]},"customUnitAmount":{"description":"Custom unit amount configuration — present for CUSTOM-type prices. Bounds and preset are in minor units.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/CustomUnitAmountResponse"}]},"stock":{"type":"number","description":"Remaining stock. `null` means unlimited. Decremented on PaymentIntent success. May become negative under race conditions — treat negative as oversold.","nullable":true},"startDate":{"type":"string","description":"Start date (ISO 8601)","nullable":true},"expirationDate":{"type":"string","description":"Expiration date (ISO 8601)","nullable":true},"active":{"type":"boolean","description":"Whether the price is active","example":true},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)"},"productId":{"type":"string","description":"Product ID this price belongs to"}},"description":"A Price defines what a Product costs: the unit amount, currency, and (for subscriptions) billing interval. A single Product can have many Prices, letting you offer the same item in multiple currencies, tiers, or billing models without duplicating your catalog. Reference a Price by ID when creating Checkout Sessions, Payment Links, or line items, and the customer is charged according to what the Price defines.","required":["id","object","currency","type","active","createdAt","updatedAt","productId"]},"ProductResponse":{"type":"object","properties":{"id":{"type":"string","description":"Product ID","example":"prod_abc123"},"object":{"type":"string","description":"Object type","example":"product"},"name":{"type":"string","description":"Product name","example":"Premium Plan"},"description":{"type":"string","description":"Product description","nullable":true},"image":{"type":"string","description":"Product image URL","nullable":true},"unitLabel":{"type":"string","description":"Unit label","nullable":true},"active":{"type":"boolean","description":"Whether the product is active","example":true},"isSystemCreated":{"type":"boolean","description":"Whether the product was created automatically by the system","example":false},"metadata":{"type":"object","description":"Custom metadata","nullable":true},"defaultPriceId":{"type":"string","description":"Default price ID","nullable":true},"merchantId":{"type":"string","description":"Merchant ID","example":"merch_xyz789"},"prices":{"description":"Prices attached to this product. Lifecycle fields only — for per-price usage counts, see `GET /products/:id/stats`.","type":"array","items":{"$ref":"#/components/schemas/PriceResponse"}},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)"}},"description":"A Product represents a good or service you sell. Products carry only descriptive information (name, description, images), while their pricing is described separately by Price objects. A single Product can have many Prices: for example, the same digital course offered in EGP and USD, or at different tiers. Use Products to model your catalog and Prices to model how each is sold.","required":["id","object","name","active","isSystemCreated","merchantId","prices","createdAt","updatedAt"]},"PriceListItem":{"type":"object","properties":{"id":{"type":"string","description":"Price ID","example":"price_abc123"},"unitAmount":{"type":"number","description":"Unit amount in smallest currency unit (e.g., cents for EGP)","example":10000,"nullable":true},"currency":{"type":"string","description":"Currency","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"type":{"type":"string","description":"Price type","enum":["ONE_TIME","RECURRING","CUSTOM"],"example":"ONE_TIME"},"recurring":{"description":"Recurring configuration (`interval` + `intervalCount`). Present only when `type` is `RECURRING`; `null` for `ONE_TIME` and `CUSTOM` prices.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/RecurringConfig"}]},"customUnitAmount":{"description":"Custom unit amount configuration — present for CUSTOM-type prices. Bounds and preset are in minor units.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/CustomUnitAmountResponse"}]},"stock":{"type":"number","description":"Remaining stock. `null` means unlimited. Decremented on PaymentIntent success. May become negative under race conditions — treat negative as oversold.","example":100,"nullable":true},"createdAt":{"type":"string","description":"Creation timestamp (ISO 8601)","example":"2024-01-01T00:00:00.000Z"}},"required":["id","currency","type","createdAt"]},"ProductListItem":{"type":"object","properties":{"id":{"type":"string","description":"Product ID","example":"prod_abc123"},"name":{"type":"string","description":"Product name","example":"Premium Plan"},"description":{"type":"string","description":"Product description","example":"Premium subscription plan","nullable":true},"image":{"type":"string","description":"Product image URL","example":"https://example.com/image.jpg","nullable":true},"unitLabel":{"type":"string","description":"Unit label","example":"month","nullable":true},"active":{"type":"boolean","description":"Whether the product is active","example":true},"isSystemCreated":{"type":"boolean","description":"Whether the product was created automatically by the system","example":false},"metadata":{"type":"object","description":"Custom metadata","example":{"category":"subscription"},"nullable":true},"prices":{"description":"Product prices","type":"array","items":{"$ref":"#/components/schemas/PriceListItem"}},"createdAt":{"type":"string","description":"Creation timestamp (ISO 8601)","example":"2024-01-01T00:00:00.000Z"},"updatedAt":{"type":"string","description":"Last update timestamp (ISO 8601)","example":"2024-01-01T00:00:00.000Z"}},"required":["id","name","active","isSystemCreated","prices","createdAt","updatedAt"]},"ListProductsResponse":{"type":"object","properties":{"data":{"description":"Array of products","type":"array","items":{"$ref":"#/components/schemas/ProductListItem"}},"totalCount":{"type":"number","description":"Total count of matching records (for pagination)","example":42},"page":{"type":"number","description":"Current page number (1-based)","example":1},"limit":{"type":"number","description":"Number of items per page","example":20},"totalPages":{"type":"number","description":"Total number of pages","example":3}},"required":["data","totalCount","page","limit","totalPages"]},"CustomUnitAmountInput":{"type":"object","properties":{"minimum":{"type":"number","description":"Minimum amount the customer may enter (minor units).","example":1000},"maximum":{"type":"number","description":"Maximum amount the customer may enter (minor units).","example":100000},"preset":{"type":"number","description":"Suggested amount pre-filled for the customer (minor units). Must fall within [minimum, maximum] when both bounds are set.","example":10000}}},"CreateProductDefaultPrice":{"type":"object","properties":{"name":{"type":"string","description":"Price name","example":"Price name"},"description":{"type":"string","description":"Price description","example":"Price description"},"currency":{"type":"string","description":"Currency","example":"EGP","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"default":"EGP"},"unitAmount":{"type":"number","description":"Unit amount in smallest currency unit (e.g., piasters for EGP). Required unless `type` is CUSTOM. May be 0.","example":10000,"maximum":2147483647},"type":{"type":"string","description":"Price type","example":"ONE_TIME","enum":["ONE_TIME","RECURRING","CUSTOM"],"default":"ONE_TIME"},"recurring":{"type":"object","description":"Recurring configuration (required for RECURRING type)","example":{"interval":"MONTH","intervalCount":1}},"customUnitAmount":{"description":"When set, provides configuration for the amount to be adjusted by the customer during Checkout Sessions and Payment Links. Required unless unit_amount is provided","allOf":[{"$ref":"#/components/schemas/CustomUnitAmountInput"}]},"stock":{"type":"number","description":"Remaining stock for the default price. Omit or set `null` for unlimited.","example":100,"nullable":true,"maximum":2147483647},"startDate":{"type":"string","description":"Start date (before which the price is not usable in checkout)","example":"2024-01-01T00:00:00Z"},"expirationDate":{"type":"string","description":"Expiration date (at/after which the price is not usable in checkout)","example":"2024-12-31T23:59:59Z"},"active":{"type":"boolean","description":"Whether the price is active","example":true,"default":true},"metadata":{"type":"object","description":"Custom metadata","example":{"source":"api"}}}},"CreateProduct":{"type":"object","properties":{"name":{"type":"string","description":"Product name","example":"Premium Plan"},"description":{"type":"string","description":"Product description","example":"Premium subscription plan with all features"},"image":{"type":"string","description":"Product image URL","example":"https://example.com/image.jpg"},"unitLabel":{"type":"string","description":"Unit label (e.g., 'user', 'GB', 'month')","example":"month"},"active":{"type":"boolean","description":"Whether the product is active","example":true,"default":true},"metadata":{"type":"object","description":"Custom metadata","example":{"category":"subscription","tier":"premium"}},"defaultPrice":{"description":"Default price object. This Price will be set as the default price for this product.","allOf":[{"$ref":"#/components/schemas/CreateProductDefaultPrice"}]}},"required":["name"]},"UpdateProduct":{"type":"object","properties":{"name":{"type":"string","description":"Product name","example":"Product name"},"description":{"type":"string","description":"Product description","example":"Product description"},"image":{"type":"string","description":"Product image URL","example":"https://example.com/image.jpg"},"unitLabel":{"type":"string","description":"Unit label (e.g., 'user', 'GB', 'month')","example":"month"},"active":{"type":"boolean","description":"Whether the product is active","example":true},"metadata":{"type":"object","description":"Custom metadata","example":{"category":"product category","tier":"product tier"}},"defaultPrice":{"type":"string","description":"The ID of the Price object that is the default price for this product. Set to empty string to clear the default price.","example":"price_abc123"}}},"CreatePrice":{"type":"object","properties":{"name":{"type":"string","description":"Price name","example":"Monthly Subscription"},"description":{"type":"string","description":"Price description","example":"Monthly subscription price"},"currency":{"type":"string","description":"Currency","example":"EGP","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"default":"EGP"},"unitAmount":{"type":"number","description":"Unit amount in smallest currency unit (e.g., piasters for EGP). Required for ONE_TIME and RECURRING prices, and must be omitted for CUSTOM prices (whose amount the customer enters at checkout). May be 0.","example":10000,"maximum":2147483647},"type":{"type":"string","description":"Price type","example":"ONE_TIME","enum":["ONE_TIME","RECURRING","CUSTOM"],"default":"ONE_TIME"},"recurring":{"description":"Recurring configuration (required for RECURRING type)","allOf":[{"$ref":"#/components/schemas/RecurringConfig"}]},"customUnitAmount":{"description":"Custom unit amount configuration — required to scope customer-entered amounts for CUSTOM prices. Only allowed when type is CUSTOM.","allOf":[{"$ref":"#/components/schemas/CustomUnitAmountInput"}]},"stock":{"type":"number","description":"Remaining stock. Omit or set `null` for unlimited. When set, checkout blocks new sales once stock reaches 0.","example":100,"nullable":true,"maximum":2147483647},"startDate":{"type":"string","description":"Start date","example":"2024-01-01T00:00:00Z"},"expirationDate":{"type":"string","description":"Expiration date","example":"2024-12-31T23:59:59Z"},"active":{"type":"boolean","description":"Whether the price is active","example":true,"default":true},"metadata":{"type":"object","description":"Custom metadata","example":{"source":"api"}}}},"UpdatePrice":{"type":"object","properties":{"name":{"type":"string","description":"Price name","example":"Monthly Subscription"},"description":{"type":"string","description":"Price description","example":"Monthly subscription price"},"currency":{"type":"string","description":"Currency","example":"EGP","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"]},"unitAmount":{"type":"number","description":"Unit amount in smallest currency unit (e.g., piasters for EGP). Must be omitted when updating to type CUSTOM. Required when this update switches the price away from CUSTOM, since a CUSTOM price stores no amount of its own. Frozen once the price has been used by a line item.","example":10000,"maximum":2147483647},"type":{"type":"string","description":"Price type","example":"ONE_TIME","enum":["ONE_TIME","RECURRING","CUSTOM"]},"recurring":{"description":"Recurring configuration (required for RECURRING type)","allOf":[{"$ref":"#/components/schemas/RecurringConfig"}]},"customUnitAmount":{"description":"Custom unit amount configuration — scopes customer-entered amounts for CUSTOM prices. Only allowed when type is CUSTOM.","allOf":[{"$ref":"#/components/schemas/CustomUnitAmountInput"}]},"stock":{"type":"number","description":"Remaining stock. Set `null` to mark unlimited. When set, checkout blocks new sales once stock reaches 0.","example":100,"nullable":true,"maximum":2147483647},"startDate":{"type":"string","description":"Start date (before which the price is not usable in checkout)","example":"2024-01-01T00:00:00Z","nullable":true},"expirationDate":{"type":"string","description":"Expiration date (at/after which the price is not usable in checkout)","example":"2024-12-31T23:59:59Z","nullable":true},"active":{"type":"boolean","description":"Whether the price is active","example":true},"metadata":{"type":"object","description":"Custom metadata","example":{"source":"api"}}}},"NestedCheckoutSessionResponse":{"type":"object","properties":{"id":{"type":"string","description":"Checkout session ID. Absent on the SSR hosted-view payload derived from a payment link (before the first mutation materializes the session)."},"object":{"type":"string","description":"Object type","example":"checkout.session"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)"},"mode":{"type":"string","description":"Session mode","enum":["payment","setup","subscription"]},"uiMode":{"type":"string","description":"UI mode","enum":["hosted","embedded","custom"]},"submitType":{"type":"string","description":"Submit type","enum":["PAY","SUBSCRIBE","BOOK","DONATE"]},"customerCreation":{"type":"string","description":"Customer creation mode","enum":["always","if_required"]},"status":{"type":"string","description":"Session status","enum":["open","complete","expired"]},"paymentStatus":{"type":"string","description":"Payment status","enum":["paid","unpaid","no_payment_required"],"example":"unpaid"},"currency":{"type":"string","description":"Currency code (ISO 4217)","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"amountSubtotal":{"type":"number","description":"Subtotal before discounts/taxes"},"amountTotal":{"type":"number","description":"Total amount due"},"totalDetails":{"description":"Amount breakdown","allOf":[{"$ref":"#/components/schemas/TotalDetailsResponse"}]},"presentmentDetails":{"description":"Customer-facing view of the session — full mirror of subtotal/total/discount/VAT/fees in the presentment currency. Populated only when the merchant prices in a currency different from processing. Uses a rate locked at session creation.","allOf":[{"$ref":"#/components/schemas/SessionPresentmentDetails"}]},"afterCompletion":{"type":"object","description":"What happens after payment: redirect to merchant URL or show hosted confirmation page"},"cancelUrl":{"type":"string","description":"Cancel redirect URL (back button during checkout)"},"url":{"type":"string","description":"Checkout page URL (hosted mode)"},"clientSecret":{"type":"string","description":"Client secret for frontend access"},"expiresAt":{"type":"string","description":"Expiration timestamp (ISO 8601)"},"isExpired":{"type":"boolean","description":"Whether this session can no longer be paid because it has expired (either swept/expired by status, or past `expiresAt`). Clients MUST render from this flag and MUST NOT re-derive expiry by comparing `expiresAt` against the local clock — a customer device running fast reads a live session as dead.","example":false},"customerId":{"type":"string","description":"Customer ID (when existing customer linked)"},"customer":{"description":"Customer object (when customerId is provided). Contains existing customer data for prefill.","allOf":[{"$ref":"#/components/schemas/CheckoutSessionCustomer"}]},"customerDetails":{"description":"CustomerDetails - unified prefill/collection object. Contains name, email, phone, address (billing), shipping.","allOf":[{"$ref":"#/components/schemas/CustomerDetailsResponse"}]},"paymentIntentId":{"type":"string","description":"Payment Intent ID"},"lineItems":{"description":"Line items with full price and product details","type":"array","items":{"$ref":"#/components/schemas/LineItem"}},"customFields":{"description":"Custom fields with configuration and collected values (Stripe-aligned). Values are populated after customer submits.","type":"array","items":{"$ref":"#/components/schemas/CustomFieldResponse"}},"discounts":{"description":"Applied discounts on this session","type":"array","items":{"$ref":"#/components/schemas/DiscountResponse"}},"allowPromotionCodes":{"type":"boolean","description":"Allow promotion codes"},"nameCollection":{"type":"boolean","description":"Collect customer name"},"billingAddressCollection":{"type":"boolean","description":"Collect billing address"},"shippingAddressCollection":{"type":"boolean","description":"Collect shipping address"},"phoneNumberCollection":{"type":"boolean","description":"Collect phone number"},"feeConfig":{"description":"Fee configuration (tells checkout whether to track BIN and display fees)","allOf":[{"$ref":"#/components/schemas/FeeConfigResponse"}]},"brandingSettings":{"description":"UI customization settings for checkout (colors, spacing, borders, etc.). Fully resolved: merchant defaults merged with session-level overrides. Callers can apply this object directly — no client-side merging required.","allOf":[{"$ref":"#/components/schemas/BrandingSettingsResponse"}]},"locale":{"type":"string","description":"Language the checkout page is displayed in. Resolved from `session.locale`, falling back to your account's `defaultLocale`, then to `en`.","enum":["en","ar"]},"paymentMethodTypes":{"description":"Available payment method types with fee estimates","type":"array","items":{"$ref":"#/components/schemas/PaymentMethodTypeResponse"}},"paymentMethodConfigurationId":{"type":"string","description":"ID of the PaymentMethodConfiguration used for this session"},"fees":{"description":"Fee breakdown (only populated when feesPassThrough or vatCollectionEnabled, and after /update with BIN for cards)","allOf":[{"$ref":"#/components/schemas/FeesResponse"}]},"customerUpdate":{"description":"Controls which customer fields to update when customerId is provided","allOf":[{"$ref":"#/components/schemas/CustomerUpdateResponse"}]},"metadata":{"type":"object","description":"Custom metadata"},"merchantId":{"type":"string","description":"Merchant ID"},"merchantName":{"type":"string","description":"Merchant display name"},"merchantLogo":{"type":"string","description":"Merchant logo URL"},"paymentLinkId":{"type":"string","description":"Payment Link ID (if created from link)"},"livemode":{"type":"boolean","description":"Whether this is a live mode session"}},"description":"A CheckoutSession embedded inside a PaymentIntent. Same fields as CheckoutSession, but without the `paymentIntent` back-reference (you are already reading this from the enclosing PaymentIntent).","required":["object","createdAt","mode","uiMode","submitType","customerCreation","status","paymentStatus","afterCompletion","isExpired","allowPromotionCodes","nameCollection","billingAddressCollection","shippingAddressCollection","phoneNumberCollection","merchantId","livemode"]},"PaymentIntentResponse":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for this PaymentIntent. Always prefixed with `pi_`.","example":"pi_3MqAaCB4Otk1z2A30vXyz9aB"},"object":{"type":"string","description":"String identifying the object type. Always `payment_intent` for this resource.","example":"payment_intent"},"checkoutSessionId":{"type":"string","description":"ID of the CheckoutSession that created this PaymentIntent. `null` for PaymentIntents created directly via the API without a session.","nullable":true,"example":"cs_test_a1b2c3d4"},"checkoutSession":{"description":"The CheckoutSession that created this payment, or `null` if the payment was not created via a session. The session's own `paymentIntent` field is not included here to keep the response self-contained.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/NestedCheckoutSessionResponse"}]},"amount":{"type":"number","description":"Amount the customer is being charged, in the smallest currency unit of `currency` (e.g. piasters for EGP — `10000` = 100 EGP).","example":10000},"amountCapturable":{"type":"number","description":"Amount that can still be captured for this PaymentIntent, in the smallest currency unit. Non-zero only when `captureMethod` is `manual` and the payment has been authorized but not yet captured. Drops to `0` once captured (fully or partially).","example":0},"amountReceived":{"type":"number","description":"Amount actually received from the customer so far, in the smallest currency unit. Equals `amount` after a successful capture; `0` for payments that haven't reached SUCCEEDED.","example":10000},"currency":{"type":"string","description":"ISO 4217 currency code this payment is denominated in.","enum":["EGP","USD","EUR","GBP","SAR","AED","QAR","KWD","JOD","OMR","BHD","LYD","AUD","CAD","CNY"],"example":"EGP"},"status":{"type":"string","description":"Lifecycle status. Combines the raw processor state with refund state, so values like `REFUNDED`, `PARTIALLY_REFUNDED`, `UNCAPTURED`, and `FAILED` may appear in addition to the base processor states.","enum":["REQUIRES_PAYMENT_METHOD","REQUIRES_CONFIRMATION","REQUIRES_ACTION","PROCESSING","UNCAPTURED","CANCELED","SUCCEEDED","FAILED","REFUNDED","PARTIALLY_REFUNDED","AMOUNT_CAPTURABLE_UPDATED"],"example":"SUCCEEDED"},"createdAt":{"type":"string","description":"Created timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"updatedAt":{"type":"string","description":"Updated timestamp (ISO 8601)","example":"2025-03-25T12:00:00.000Z"},"clientSecret":{"type":"string","description":"Secret used by the SDK to confirm the payment from the customer's browser. Do NOT log this or share it with any party other than the customer. Each PaymentIntent has one client secret for its lifetime.","example":"pi_3MqAaCB4Otk1z2A30vXyz9aB_secret_xyz"},"captureMethod":{"type":"string","description":"When to capture funds from the customer. `automatic` (default) captures immediately on successful confirmation. `manual` only authorizes — call the capture endpoint later (within 7 days) to actually move the money.","enum":["automatic","manual"],"example":"automatic"},"confirmationMethod":{"type":"string","description":"How the PaymentIntent moves out of `REQUIRES_CONFIRMATION`. `automatic` (default) confirms as soon as a payment method is attached. `manual` requires you to call confirm explicitly.","enum":["automatic","manual"],"example":"automatic"},"description":{"type":"string","description":"Arbitrary description you can attach when creating the PaymentIntent. Shown in the dashboard and useful for reconciling with your own systems. `null` if not provided.","nullable":true,"example":"Order #1234"},"receiptEmail":{"type":"string","description":"Email to send the receipt to once the payment succeeds. `null` if no receipt email was set.","nullable":true,"example":"customer@example.com"},"canceledAt":{"type":"string","description":"ISO 8601 timestamp of when this PaymentIntent was canceled. `null` if it was never canceled.","nullable":true,"example":"2025-03-25T12:00:00.000Z"},"shipping":{"description":"Shipping address and recipient details for this payment. `null` if no shipping was collected.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/Shipping"}]},"amountDetails":{"description":"Breakdown of `amount` into product amount, tax, platform fees, tip, and discount. `null` for legacy payments without itemized breakdown.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/AmountDetails"}]},"presentmentDetails":{"description":"Mirror of `amount` / `currency` in the currency the customer actually saw at checkout, when different from the settlement currency. `null` when customer paid in the same currency.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PresentmentDetails"}]},"latestCharge":{"description":"The most recent Charge attempt for this PaymentIntent. `null` if no Charge has been attempted yet.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/ChargeResponse"}]},"charges":{"description":"All Charge attempts for this PaymentIntent, sorted by creation time ascending (oldest first). Each retry adds a new Charge. Empty array if no attempts have been made yet.","type":"array","items":{"$ref":"#/components/schemas/ChargeResponse"}},"paymentMethod":{"description":"Payment method attached to this PaymentIntent. `null` before a method is attached or after a failure clears it.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/PaymentMethodObject"}]},"customer":{"description":"The Customer this payment belongs to. `null` if no Customer is associated.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/Customer"}]},"nextAction":{"description":"Action the customer must take to advance the payment (e.g. complete 3-D Secure). `null` when no further action is needed.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/NextActionDetail"}]},"metadata":{"type":"object","description":"Custom key/value pairs you attached when creating or updating the PaymentIntent. Useful for reconciling with your own systems. Empty object if none.","example":{"orderId":"1234","channel":"web"}},"lastPaymentError":{"description":"Details of the most recent failed payment attempt for this PaymentIntent. `null` if no attempts have failed.","nullable":true,"type":"object","allOf":[{"$ref":"#/components/schemas/LastPaymentErrorDetail"}]}},"description":"A PaymentIntent tracks the full lifecycle of collecting one payment from your customer: from creation, through authorization and 3-D Secure, to capture and final outcome. We recommend creating one PaymentIntent per order: you can inspect its history of Charge attempts, watch its `status` as it transitions, and reference the successful Charge it ultimately produces. PaymentIntents are the object that the hosted Checkout and xpay.js drive on the client to complete a payment.","required":["id","object","amount","amountCapturable","amountReceived","currency","status","createdAt","updatedAt","clientSecret","captureMethod","confirmationMethod","charges","metadata"]},"CreateRefund":{"type":"object","properties":{"chargeId":{"type":"string","description":"Charge ID to refund. Mutually exclusive with `paymentIntentId` — provide exactly one.","example":"ch_abc123"},"paymentIntentId":{"type":"string","description":"PaymentIntent ID to refund. The server resolves it to the unique succeeded charge. Mutually exclusive with `chargeId` — provide exactly one. Rejected if the PaymentIntent has zero or multiple succeeded charges.","example":"pi_abc123"},"amount":{"type":"number","description":"Amount to refund in smallest currency unit (e.g. piasters). Defaults to full remaining refundable amount.","example":50000},"reason":{"type":"string","description":"Reason for refund","enum":["DUPLICATE","FRAUDULENT","REQUESTED_BY_CUSTOMER","RISK_HOLD_CAPTURE"],"example":"REQUESTED_BY_CUSTOMER"},"description":{"type":"string","description":"An arbitrary string attached to the object. Available on non-card refunds only.","maxLength":500},"instructionsEmail":{"type":"string","description":"Email address for refund instructions (for payment methods without native refund support)."},"metadata":{"type":"object","description":"Custom metadata"}}}}}}