openapi: 3.1.0 info: title: Payouts Service API description: API for managing user registrations, authentication, and payouts via YooKassa. version: 1.0.0 servers: - url: / tags: - name: user description: User registration and authentication - name: payout description: Payout operations - name: system description: Health and version endpoints paths: /api/v1/user/register: post: tags: [user] summary: Register a new user operationId: userRegister requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserRegisterRequest' responses: '201': description: User created successfully '400': description: Invalid input (empty fields or password mismatch) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/user/login: post: tags: [user] summary: Authenticate a user and obtain a session token operationId: userLogin requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserLoginRequest' responses: '200': description: Login successful content: application/json: schema: $ref: '#/components/schemas/UserLoginResponse' '400': description: Invalid input (empty phone or password) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Invalid credentials content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/payout/sbp/banks: get: tags: [payout] summary: Get list of SBP (Fast Payment System) banks operationId: getSbpBanks responses: '200': description: List of SBP banks content: application/json: schema: $ref: '#/components/schemas/SBPBankListResponse' '400': description: Bad request (YooKassa API error) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/payout/create: post: tags: [payout] summary: Create a new payout operationId: createPayout security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PayoutRequest' responses: '200': description: Payout created successfully content: application/json: schema: $ref: '#/components/schemas/PayoutResponse' '400': description: Invalid payout data content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized (missing or invalid token) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/v1/payout/callback: post: tags: [payout] summary: Receive payout status callback from YooKassa description: | Called by YooKassa to notify of payout status changes. If IP validation is enabled, the request must originate from an allowed subnet. Status updates are processed asynchronously. operationId: payoutCallback requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PayoutResponse' responses: '200': description: Callback received and queued for processing '400': description: Invalid JSON payload content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden (IP address not in allowed subnets) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /payout/widget: get: tags: [payout] summary: Serve the payout widget HTML page operationId: getPayoutWidget responses: '200': description: Widget HTML page content: text/html: schema: type: string '500': description: Template rendering error /health: get: tags: [system] summary: Health check description: Verifies database connectivity. operationId: healthCheck responses: '200': description: Service is healthy content: application/json: schema: $ref: '#/components/schemas/HealthResponse' '503': description: Service unavailable (database connection failed) content: application/json: schema: $ref: '#/components/schemas/HealthResponse' /version: get: tags: [system] summary: Get service version operationId: getVersion responses: '200': description: Version string (optionally including git commit hash) content: text/plain: schema: type: string example: v1.2.3 components: securitySchemes: bearerAuth: type: http scheme: bearer description: UUID session token obtained from the login endpoint schemas: UserRegisterRequest: type: object required: [tin, phone, password, password_cfm] properties: tin: type: string description: Taxpayer Identification Number example: "1234567890" phone: type: string description: User phone number example: "+79001234567" password: type: string format: password description: User password password_cfm: type: string format: password description: Password confirmation (must match password) UserLoginRequest: type: object required: [phone, password] properties: phone: type: string description: Registered phone number example: "+79001234567" password: type: string format: password UserLoginResponse: type: object properties: token: type: string format: uuid description: Session token (UUID) example: "550e8400-e29b-41d4-a716-446655440000" token_ttl: type: integer format: int64 description: Token expiration as Unix timestamp example: 1711958400 SBPBankListResponse: type: object properties: type: type: string example: "list" items: type: array items: $ref: '#/components/schemas/SBPBank' SBPBank: type: object properties: bank_id: type: string description: Bank identifier example: "100000000111" name: type: string description: Human-readable bank name example: "Sberbank" bic: type: string description: Bank Identification Code example: "044525225" PayoutType: type: string enum: [spb, yoo_money, bank_card, widget] description: | Payout method: - `spb` — Fast Payment System (SBP) - `yoo_money` — YooMoney wallet - `bank_card` — bank card - `widget` — card via widget PayoutRequest: type: object required: [payout_type, amount] properties: payout_type: $ref: '#/components/schemas/PayoutType' payout_token: type: string description: Payment token (used for widget/card payouts) example: "pt_xxxxxxxxxxxxxxxxxxxx" account_number: type: string description: Account/phone number for SBP or YooMoney payouts example: "+79001234567" bank_id: type: string description: Bank identifier (required for SBP payouts) example: "100000000111" card_number: type: string description: Card number (for bank_card payout type) example: "4111111111111111" amount: type: number format: float description: Payout amount in RUB example: 1000.00 PayoutStatus: type: string enum: [created, pending, succeeded, canceled, failed] Amount: type: object properties: value: type: string description: Amount as a decimal string example: "1000.00" currency: type: string description: ISO 4217 currency code example: "RUB" PayoutDestination: type: object description: Payout destination details (structure depends on payout type) additionalProperties: true PayoutResponse: type: object properties: id: type: string description: YooKassa payout ID example: "po_1da5c87d-0984-50e8-a7f3-8de646dd9ec9" status: $ref: '#/components/schemas/PayoutStatus' amount: $ref: '#/components/schemas/Amount' payout_destination: $ref: '#/components/schemas/PayoutDestination' description: type: string example: "Payout for order #42" created_at: type: string format: date-time example: "2024-04-02T12:00:00Z" succeeded_at: type: string format: date-time example: "2024-04-02T12:01:00Z" metadata: type: object additionalProperties: true description: Arbitrary key-value metadata test: type: boolean description: Whether this is a test payout example: false HealthResponse: type: object properties: OK: type: boolean description: Whether the service is healthy Error: type: string description: Error message (only present when OK is false) ErrorResponse: type: object properties: status: type: integer description: HTTP status code example: 400 message: type: string description: Human-readable error message example: "Bad Request"