# POST Loans

Создание займов и продвижение loan lifecycle в Sandbox.

## POST /api/sandbox/loans/flow

> Продвигает один шаг cabinet-compatible flow выдачи займа. Это основной endpoint для интеграций, которые хотят повторить у себя тот же путь, что пользователь проходит в клиентском кабинете Fundora.\
> \
> Порядок действий строгий:\
> \
> 1\. \`start\_collateral\_transfer\` — создать draft заявки, рассчитать параметры и получить sandbox-кошельки.\
> 2\. \`confirm\_btc\` — подтвердить тестовое зачисление BTC-залога через \`tx\_hash\` и \`confirmations\`.\
> 3\. \`run\_kyt\` — симулировать KYT-проверку.\
> 4\. \`complete\_payout\` — завершить выдачу займа и перевести заявку в активный займ.\
> \
> Нельзя выполнить шаг раньше времени: API вернет \`409 FLOW\_CONFLICT\`. Для восстановления состояния вызовите \`GET /api/sandbox/state\`.\
> \
> Кошельки в ответе находятся в \`sandboxFlow\.loanApplications\[].wallets\`. Это тестовые deterministic addresses: \`collateralDeposit\` для залога, \`loanPayout\` для выдачи и \`collateralReturn\` для будущего возврата залога. В production реальные сделки будут отслеживаться по on-chain зачислениям, но в Sandbox внешний chain polling не требуется: подтверждение имитируется POST-действием \`confirm\_btc\`.\
> \
> Для POST обязательно передавайте \`Idempotency-Key\`, чтобы retry не создал второй draft или второй переход состояния.\
> \
> Пример:\
> \`\`\`bash\
> curl <https://partner.fundora.capital/api/sandbox/loans/flow> \\\
> &#x20; -H "Authorization: Bearer sk\_sandbox\_YOUR\_KEY" \\\
> &#x20; -H "Content-Type: application/json" \\\
> &#x20; -H "Idempotency-Key: 0d66a118-e544-4a82-94de-35c9f28a0f38" \\\
> &#x20; -d '{"action":"start\_collateral\_transfer","collateral\_btc":0.1,"loan\_amount":3000,"loan\_currency":"USDT","external\_client\_id":"client-42"}'\
> \`\`\`

````json
{"openapi":"3.0.3","info":{"title":"Fundora API","version":"0.3.0"},"tags":[{"name":"post-loans","description":"Создание займов и продвижение loan lifecycle в Sandbox."}],"servers":[{"url":"https://partner.fundora.capital","description":"Production-домен партнерского API"}],"security":[{"SandboxBearer":[]}],"components":{"securitySchemes":{"SandboxBearer":{"type":"http","scheme":"bearer","bearerFormat":"sk_sandbox"}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Обязательный уникальный ключ POST-операции, обычно UUID. Повтор того же POST с тем же endpoint-ом и телом вернет сохраненный результат с idempotency_replayed=true. Тот же ключ с другим телом или endpoint-ом вернет IDEMPOTENCY_KEY_CONFLICT. Отсутствующий ключ вернет IDEMPOTENCY_KEY_REQUIRED.","schema":{"type":"string","maxLength":255}}},"schemas":{"SandboxLoanFlowRequest":{"type":"object","properties":{"action":{"type":"string","enum":["start_collateral_transfer","confirm_btc","run_kyt","complete_payout"],"description":"Действие loan flow. Порядок: start_collateral_transfer -> confirm_btc -> run_kyt -> complete_payout."},"collateral_btc":{"type":"number","description":"BTC-залог. Нужен для start_collateral_transfer."},"loan_amount":{"type":"number","description":"Сумма займа. Нужна для start_collateral_transfer."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа. Если не передать, используется RUB."},"partner_link_slug":{"type":"string","nullable":true,"description":"Slug партнерской ссылки. Используется для расчета партнерской маржи/вознаграждения."},"external_client_id":{"type":"string","nullable":true,"description":"Внешний идентификатор клиента в системе партнера. Используется для группировки Sandbox-займов в админке."},"client_reference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента или сделку в системе партнера."},"tx_hash":{"type":"string","nullable":true,"description":"Тестовый hash транзакции. Передавайте на confirm_btc для имитации зачисления BTC."},"confirmations":{"type":"number","description":"Количество тестовых подтверждений. Для confirm_btc обычно достаточно 1."},"kyt_report":{"type":"object","nullable":true,"additionalProperties":true,"description":"Произвольный KYT payload для run_kyt. В Sandbox сохраняется как тестовый отчет."}},"description":"Тело запроса для одного шага loan flow. action можно не передавать: по умолчанию используется start_collateral_transfer."},"SandboxLoansStateResponse":{"type":"object","properties":{"request_id":{"type":"string","description":"Идентификатор запроса для поддержки и поиска в Logs."},"idempotency_replayed":{"type":"boolean","description":"true, если POST-ответ возвращен из кеша Idempotency-Key. Для GET отсутствует."},"success":{"type":"boolean","description":"Признак успешного ответа."},"activatedScenarios":{"type":"object","description":"Какие sandbox-сценарии активированы для текущего пользователя/API-ключа.","properties":{"miner":{"type":"boolean","description":"Активирован borrower/miner сценарий."},"investor":{"type":"boolean","description":"Активирован investor сценарий."}}},"wallet":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/SandboxWalletState"}],"description":"Тестовый кошелек симулятора."},"activeLoans":{"type":"array","description":"Активные Sandbox-займы.","items":{"$ref":"#/components/schemas/SandboxLoanRecord"}},"loanHistory":{"type":"array","description":"Закрытые или исторические Sandbox-займы.","items":{"$ref":"#/components/schemas/SandboxLoanRecord"}},"loanHistoryEvents":{"type":"array","description":"События истории по займам для UI/таймлайна.","items":{"$ref":"#/components/schemas/SandboxLoanHistoryEvent"}},"loanDraft":{"$ref":"#/components/schemas/SandboxLoanDraft"},"sandboxFlow":{"$ref":"#/components/schemas/SandboxLoanFlowState"}},"required":["request_id","success"]},"SandboxWalletState":{"type":"object","properties":{"id":{"type":"string","description":"ID sandbox-кошелька симулятора."},"virtualBtcBalance":{"type":"string","description":"Доступный тестовый BTC-баланс."},"virtualUsdBalance":{"type":"string","description":"Доступный тестовый USD/USDT-баланс."},"virtualRubBalance":{"type":"string","description":"Доступный тестовый RUB-баланс."},"lockedBtcBalance":{"type":"string","description":"BTC, заблокированный в залоге."},"investedRubBalance":{"type":"string","description":"RUB, задействованный в инвестиционном сценарии."}}},"SandboxLoanRecord":{"type":"object","properties":{"id":{"type":"string","description":"ID Sandbox-займа."},"status":{"type":"string","description":"Статус займа."},"collateral_btc":{"type":"number","description":"Общий BTC-залог."},"collateral_received":{"type":"number","description":"Фактически подтвержденный BTC-залог."},"collateral_address":{"type":"string","nullable":true,"description":"Адрес залога в симуляторе."},"external_client_id":{"type":"string","nullable":true,"description":"ID клиента в системе партнера."},"client_reference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента или сделку."},"loan_amount":{"type":"number","description":"Исходная сумма займа."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа."},"debt_amount":{"type":"number","description":"Исходный основной долг."},"annual_rate":{"type":"number","description":"Годовая ставка займа в процентах."},"btc_rate":{"type":"number","description":"BTC rate, зафиксированный на момент создания."},"usd_rub_rate":{"type":"number","description":"USD/RUB rate, зафиксированный на момент создания."},"current_collateral_usd":{"type":"number","description":"Текущая стоимость залога в USD."},"current_collateral_rub":{"type":"number","description":"Текущая стоимость залога в RUB."},"current_debt":{"type":"number","description":"Текущий долг с учетом операций."},"health_factor":{"type":"number","description":"Индикатор здоровья займа: чем выше, тем безопаснее."},"accrued_interest":{"type":"number","description":"Начисленные проценты."},"max_ltv":{"type":"number","description":"Максимальный LTV для займа."},"liquidation_threshold":{"type":"number","description":"Порог ликвидации для займа."},"created_at":{"type":"string","format":"date-time","description":"Время создания займа."},"funded_at":{"type":"string","format":"date-time","description":"Время выдачи займа."},"interest_due_at":{"type":"string","nullable":true,"format":"date-time","description":"Дата ближайшего процентного платежа."},"principal_due_at":{"type":"string","nullable":true,"format":"date-time","description":"Дата платежа основного долга."}}},"SandboxLoanHistoryEvent":{"type":"object","properties":{"id":{"type":"string","description":"ID события истории."},"type":{"type":"string","enum":["opened","collateral","loan","interest_paid","closed"],"description":"Тип события."},"title":{"type":"string","description":"Название события для UI."},"amountLabel":{"type":"string","description":"Основная сумма для отображения."},"amountSubLabel":{"type":"string","nullable":true,"description":"Дополнительная сумма для отображения."},"rateLabel":{"type":"string","nullable":true,"description":"Ставка или курс для отображения."},"createdAt":{"type":"string","format":"date-time","description":"Время события."},"loanId":{"type":"string","description":"ID связанного займа."},"canRemoveCollateral":{"type":"boolean","description":"Можно ли снять часть залога после этого события."}}},"SandboxLoanDraft":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"ID draft-заявки."},"status":{"type":"string","enum":["active","completed","discarded"],"description":"Статус draft-заявки."},"currentStep":{"type":"string","enum":["contract","kyt","collateral","cfa"],"description":"Текущий шаг draft в legacy simulator flow."},"loanId":{"type":"string","nullable":true,"description":"ID созданного займа, если draft уже завершен."},"loanParams":{"type":"object","properties":{"collateral_btc":{"type":"number","description":"BTC-залог draft-заявки."},"loan_amount":{"type":"number","description":"Сумма займа draft-заявки."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа draft-заявки."}}},"contractAddress":{"type":"string","nullable":true,"description":"Тестовый contract/collateral address."},"kytReport":{"type":"object","nullable":true,"additionalProperties":true,"description":"KYT payload, переданный в run_kyt."},"collateralPosted":{"type":"boolean","description":"Подтвержден ли залог."},"cfaIssued":{"type":"boolean","description":"Завершена ли выдача займа."},"collateralPostedAt":{"type":"string","nullable":true,"format":"date-time"},"cfaIssuedAt":{"type":"string","nullable":true,"format":"date-time"},"completedAt":{"type":"string","nullable":true,"format":"date-time"},"discardedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SandboxLoanFlowState":{"type":"object","properties":{"loanApplications":{"type":"array","description":"Все активные и завершенные loan application flows.","items":{"$ref":"#/components/schemas/SandboxLoanApplicationFlow"}},"repaymentOperations":{"type":"array","description":"Все repayment flows по займам.","items":{"$ref":"#/components/schemas/SandboxRepaymentOperationFlow"}}}},"SandboxLoanApplicationFlow":{"type":"object","description":"Текущий loan application flow для выдачи займа.","properties":{"id":{"type":"string","description":"Идентификатор draft/application flow."},"loanId":{"type":"string","nullable":true,"description":"Идентификатор созданного займа. До complete_payout может быть null."},"externalClientId":{"type":"string","nullable":true,"description":"ID клиента в системе партнера."},"clientReference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента/сделку."},"status":{"type":"string","enum":["pending","completed"],"description":"Статус loan application flow."},"currentStepId":{"type":"string","nullable":true,"enum":["calculator","collateral_transfer","btc_confirmation","kyt","payout"],"description":"Следующий или текущий шаг, который нужно завершить."},"collateralRequiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm_btc."},"payoutRequiredConfirmations":{"type":"integer","description":"Сколько подтверждений ожидается для тестовой выдачи."},"wallets":{"type":"object","description":"Тестовые кошельки loan flow.","properties":{"collateralDeposit":{"$ref":"#/components/schemas/SandboxTestWallet"},"loanPayout":{"$ref":"#/components/schemas/SandboxTestWallet"},"collateralReturn":{"$ref":"#/components/schemas/SandboxTestWallet"}}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SandboxFlowStep"}}}},"SandboxTestWallet":{"type":"object","description":"Тестовый deterministic wallet/address для Sandbox flow. Не является реальным custody-кошельком.","properties":{"purpose":{"type":"string","enum":["collateral_deposit","loan_payout","repayment","collateral_return"],"description":"Назначение тестового кошелька в flow."},"asset":{"type":"string","enum":["BTC","USDT"],"description":"Актив кошелька."},"network":{"type":"string","enum":["sandbox"],"description":"Всегда sandbox: адрес не предназначен для реального blockchain-перевода."},"chainCode":{"type":"string","enum":["SANDBOX_BTC","SANDBOX_USDT"],"description":"Код тестовой сети."},"address":{"type":"string","description":"Тестовый адрес, который партнер показывает клиенту или использует в симуляции."},"isRealWallet":{"type":"boolean","enum":[false],"description":"Всегда false: в Sandbox не создается реальный custody wallet."},"confirmationMode":{"type":"string","enum":["api_simulated"],"description":"Подтверждение выполняется через API action, а не через внешний blockchain polling."},"requiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm action."}},"required":["purpose","asset","network","chainCode","address","isRealWallet","confirmationMode","requiredConfirmations"]},"SandboxFlowStep":{"type":"object","properties":{"id":{"type":"string","description":"Машинный идентификатор шага flow."},"title":{"type":"string","description":"Название шага для отображения."},"status":{"type":"string","enum":["pending","processing","completed"],"description":"Текущий статус шага."}}},"SandboxRepaymentOperationFlow":{"type":"object","description":"Repayment operation flow для процентов, частичного или полного погашения.","properties":{"id":{"type":"string","description":"Идентификатор repayment operation. Передавайте его как operation_id на следующих шагах."},"loanId":{"type":"string","nullable":true,"description":"ID займа, к которому относится repayment operation."},"kind":{"type":"string","enum":["interest","partial_principal","full_principal"],"description":"Тип погашения."},"status":{"type":"string","enum":["pending","completed"],"description":"Статус repayment flow."},"currentStepId":{"type":"string","nullable":true,"enum":["payment","usdt_confirmation","kyt","interest_settlement","debt_update","collateral_return"],"description":"Следующий или текущий шаг repayment flow."},"requiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm_usdt."},"wallets":{"type":"object","description":"Тестовые кошельки repayment flow.","properties":{"repayment":{"$ref":"#/components/schemas/SandboxTestWallet"},"collateralReturn":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/SandboxTestWallet"}],"description":"Кошелек возврата залога. Заполняется для полного погашения."}}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SandboxFlowStep"}},"createdAt":{"type":"string","format":"date-time","description":"Время создания repayment operation."}}},"ErrorResponse":{"type":"object","properties":{"request_id":{"type":"string","description":"Идентификатор запроса для поддержки и поиска в Logs."},"error_code":{"type":"string","description":"Формализованный код ошибки для интеграционной логики.","enum":["SANDBOX_API_KEY_REQUIRED","SANDBOX_API_KEY_INVALID","SANDBOX_API_KEY_DATABASE_REQUIRED","SANDBOX_SESSION_REQUIRED","SANDBOX_RATE_LIMIT_EXCEEDED","INVALID_REQUEST","INVALID_ACTION","INVALID_SCOPE","LOAN_NOT_FOUND","WALLET_NOT_FOUND","FLOW_CONFLICT","LIMIT_EXCEEDED","INSUFFICIENT_BALANCE","IDEMPOTENCY_KEY_REQUIRED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_KEY_IN_PROGRESS","DATABASE_UNAVAILABLE","INTERNAL_ERROR"]},"error":{"type":"string","description":"Человекочитаемое описание ошибки. Не используйте его для интеграционной логики, для этого есть error_code."}},"required":["request_id","error_code","error"]}},"responses":{"BadRequest":{"description":"Некорректный запрос: неверное тело, отсутствует Idempotency-Key для POST, неизвестное действие или невалидная сумма","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Sandbox API-ключ отсутствует или недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Займ не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"Flow нельзя продолжить из текущего состояния, не хватает баланса/лимита или конфликтует Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"Превышен Sandbox API rate limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/api/sandbox/loans/flow":{"post":{"operationId":"runSandboxLoanFlow","tags":["post-loans"],"summary":"POST /api/sandbox/loans/flow","description":"Продвигает один шаг cabinet-compatible flow выдачи займа. Это основной endpoint для интеграций, которые хотят повторить у себя тот же путь, что пользователь проходит в клиентском кабинете Fundora.\n\nПорядок действий строгий:\n\n1. `start_collateral_transfer` — создать draft заявки, рассчитать параметры и получить sandbox-кошельки.\n2. `confirm_btc` — подтвердить тестовое зачисление BTC-залога через `tx_hash` и `confirmations`.\n3. `run_kyt` — симулировать KYT-проверку.\n4. `complete_payout` — завершить выдачу займа и перевести заявку в активный займ.\n\nНельзя выполнить шаг раньше времени: API вернет `409 FLOW_CONFLICT`. Для восстановления состояния вызовите `GET /api/sandbox/state`.\n\nКошельки в ответе находятся в `sandboxFlow.loanApplications[].wallets`. Это тестовые deterministic addresses: `collateralDeposit` для залога, `loanPayout` для выдачи и `collateralReturn` для будущего возврата залога. В production реальные сделки будут отслеживаться по on-chain зачислениям, но в Sandbox внешний chain polling не требуется: подтверждение имитируется POST-действием `confirm_btc`.\n\nДля POST обязательно передавайте `Idempotency-Key`, чтобы retry не создал второй draft или второй переход состояния.\n\nПример:\n```bash\ncurl https://partner.fundora.capital/api/sandbox/loans/flow \\\n  -H \"Authorization: Bearer sk_sandbox_YOUR_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: 0d66a118-e544-4a82-94de-35c9f28a0f38\" \\\n  -d '{\"action\":\"start_collateral_transfer\",\"collateral_btc\":0.1,\"loan_amount\":3000,\"loan_currency\":\"USDT\",\"external_client_id\":\"client-42\"}'\n```","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLoanFlowRequest"}}}},"responses":{"200":{"description":"Обновленное состояние Sandbox-займа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLoansStateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}}}}
````

## POST /api/sandbox/loans

> Создает Sandbox-займ напрямую, без пошагового cabinet-compatible flow. Endpoint полезен для быстрых backend-тестов, но для имитации реального кабинета используйте \`POST /api/sandbox/loans/flow\`.\
> \
> Тело запроса задает BTC-залог, сумму займа, валюту займа и опциональные идентификаторы клиента партнера. \`external\_client\_id\` и \`client\_reference\` помогают группировать сделки в админке и сопоставлять их с клиентом в системе партнера.\
> \
> Для POST обязательно передавайте \`Idempotency-Key\`, чтобы retry не создал второй займ.

```json
{"openapi":"3.0.3","info":{"title":"Fundora API","version":"0.3.0"},"tags":[{"name":"post-loans","description":"Создание займов и продвижение loan lifecycle в Sandbox."}],"servers":[{"url":"https://partner.fundora.capital","description":"Production-домен партнерского API"}],"security":[{"SandboxBearer":[]}],"components":{"securitySchemes":{"SandboxBearer":{"type":"http","scheme":"bearer","bearerFormat":"sk_sandbox"}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Обязательный уникальный ключ POST-операции, обычно UUID. Повтор того же POST с тем же endpoint-ом и телом вернет сохраненный результат с idempotency_replayed=true. Тот же ключ с другим телом или endpoint-ом вернет IDEMPOTENCY_KEY_CONFLICT. Отсутствующий ключ вернет IDEMPOTENCY_KEY_REQUIRED.","schema":{"type":"string","maxLength":255}}},"schemas":{"CreateSandboxLoanRequest":{"type":"object","properties":{"collateral_btc":{"type":"number","description":"BTC-залог."},"loan_amount":{"type":"number","description":"Сумма займа."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа. Если не передать, используется RUB."},"partner_link_slug":{"type":"string","nullable":true,"description":"Slug партнерской ссылки для расчета партнерской маржи/вознаграждения."},"external_client_id":{"type":"string","nullable":true,"description":"Внешний идентификатор клиента в системе партнера. Используется для группировки Sandbox-займов в админке."},"client_reference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента или сделку в системе партнера."}},"description":"Тело прямого создания Sandbox-займа без пошагового flow.","required":["collateral_btc","loan_amount"]},"SandboxLoansStateResponse":{"type":"object","properties":{"request_id":{"type":"string","description":"Идентификатор запроса для поддержки и поиска в Logs."},"idempotency_replayed":{"type":"boolean","description":"true, если POST-ответ возвращен из кеша Idempotency-Key. Для GET отсутствует."},"success":{"type":"boolean","description":"Признак успешного ответа."},"activatedScenarios":{"type":"object","description":"Какие sandbox-сценарии активированы для текущего пользователя/API-ключа.","properties":{"miner":{"type":"boolean","description":"Активирован borrower/miner сценарий."},"investor":{"type":"boolean","description":"Активирован investor сценарий."}}},"wallet":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/SandboxWalletState"}],"description":"Тестовый кошелек симулятора."},"activeLoans":{"type":"array","description":"Активные Sandbox-займы.","items":{"$ref":"#/components/schemas/SandboxLoanRecord"}},"loanHistory":{"type":"array","description":"Закрытые или исторические Sandbox-займы.","items":{"$ref":"#/components/schemas/SandboxLoanRecord"}},"loanHistoryEvents":{"type":"array","description":"События истории по займам для UI/таймлайна.","items":{"$ref":"#/components/schemas/SandboxLoanHistoryEvent"}},"loanDraft":{"$ref":"#/components/schemas/SandboxLoanDraft"},"sandboxFlow":{"$ref":"#/components/schemas/SandboxLoanFlowState"}},"required":["request_id","success"]},"SandboxWalletState":{"type":"object","properties":{"id":{"type":"string","description":"ID sandbox-кошелька симулятора."},"virtualBtcBalance":{"type":"string","description":"Доступный тестовый BTC-баланс."},"virtualUsdBalance":{"type":"string","description":"Доступный тестовый USD/USDT-баланс."},"virtualRubBalance":{"type":"string","description":"Доступный тестовый RUB-баланс."},"lockedBtcBalance":{"type":"string","description":"BTC, заблокированный в залоге."},"investedRubBalance":{"type":"string","description":"RUB, задействованный в инвестиционном сценарии."}}},"SandboxLoanRecord":{"type":"object","properties":{"id":{"type":"string","description":"ID Sandbox-займа."},"status":{"type":"string","description":"Статус займа."},"collateral_btc":{"type":"number","description":"Общий BTC-залог."},"collateral_received":{"type":"number","description":"Фактически подтвержденный BTC-залог."},"collateral_address":{"type":"string","nullable":true,"description":"Адрес залога в симуляторе."},"external_client_id":{"type":"string","nullable":true,"description":"ID клиента в системе партнера."},"client_reference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента или сделку."},"loan_amount":{"type":"number","description":"Исходная сумма займа."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа."},"debt_amount":{"type":"number","description":"Исходный основной долг."},"annual_rate":{"type":"number","description":"Годовая ставка займа в процентах."},"btc_rate":{"type":"number","description":"BTC rate, зафиксированный на момент создания."},"usd_rub_rate":{"type":"number","description":"USD/RUB rate, зафиксированный на момент создания."},"current_collateral_usd":{"type":"number","description":"Текущая стоимость залога в USD."},"current_collateral_rub":{"type":"number","description":"Текущая стоимость залога в RUB."},"current_debt":{"type":"number","description":"Текущий долг с учетом операций."},"health_factor":{"type":"number","description":"Индикатор здоровья займа: чем выше, тем безопаснее."},"accrued_interest":{"type":"number","description":"Начисленные проценты."},"max_ltv":{"type":"number","description":"Максимальный LTV для займа."},"liquidation_threshold":{"type":"number","description":"Порог ликвидации для займа."},"created_at":{"type":"string","format":"date-time","description":"Время создания займа."},"funded_at":{"type":"string","format":"date-time","description":"Время выдачи займа."},"interest_due_at":{"type":"string","nullable":true,"format":"date-time","description":"Дата ближайшего процентного платежа."},"principal_due_at":{"type":"string","nullable":true,"format":"date-time","description":"Дата платежа основного долга."}}},"SandboxLoanHistoryEvent":{"type":"object","properties":{"id":{"type":"string","description":"ID события истории."},"type":{"type":"string","enum":["opened","collateral","loan","interest_paid","closed"],"description":"Тип события."},"title":{"type":"string","description":"Название события для UI."},"amountLabel":{"type":"string","description":"Основная сумма для отображения."},"amountSubLabel":{"type":"string","nullable":true,"description":"Дополнительная сумма для отображения."},"rateLabel":{"type":"string","nullable":true,"description":"Ставка или курс для отображения."},"createdAt":{"type":"string","format":"date-time","description":"Время события."},"loanId":{"type":"string","description":"ID связанного займа."},"canRemoveCollateral":{"type":"boolean","description":"Можно ли снять часть залога после этого события."}}},"SandboxLoanDraft":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"ID draft-заявки."},"status":{"type":"string","enum":["active","completed","discarded"],"description":"Статус draft-заявки."},"currentStep":{"type":"string","enum":["contract","kyt","collateral","cfa"],"description":"Текущий шаг draft в legacy simulator flow."},"loanId":{"type":"string","nullable":true,"description":"ID созданного займа, если draft уже завершен."},"loanParams":{"type":"object","properties":{"collateral_btc":{"type":"number","description":"BTC-залог draft-заявки."},"loan_amount":{"type":"number","description":"Сумма займа draft-заявки."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа draft-заявки."}}},"contractAddress":{"type":"string","nullable":true,"description":"Тестовый contract/collateral address."},"kytReport":{"type":"object","nullable":true,"additionalProperties":true,"description":"KYT payload, переданный в run_kyt."},"collateralPosted":{"type":"boolean","description":"Подтвержден ли залог."},"cfaIssued":{"type":"boolean","description":"Завершена ли выдача займа."},"collateralPostedAt":{"type":"string","nullable":true,"format":"date-time"},"cfaIssuedAt":{"type":"string","nullable":true,"format":"date-time"},"completedAt":{"type":"string","nullable":true,"format":"date-time"},"discardedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SandboxLoanFlowState":{"type":"object","properties":{"loanApplications":{"type":"array","description":"Все активные и завершенные loan application flows.","items":{"$ref":"#/components/schemas/SandboxLoanApplicationFlow"}},"repaymentOperations":{"type":"array","description":"Все repayment flows по займам.","items":{"$ref":"#/components/schemas/SandboxRepaymentOperationFlow"}}}},"SandboxLoanApplicationFlow":{"type":"object","description":"Текущий loan application flow для выдачи займа.","properties":{"id":{"type":"string","description":"Идентификатор draft/application flow."},"loanId":{"type":"string","nullable":true,"description":"Идентификатор созданного займа. До complete_payout может быть null."},"externalClientId":{"type":"string","nullable":true,"description":"ID клиента в системе партнера."},"clientReference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента/сделку."},"status":{"type":"string","enum":["pending","completed"],"description":"Статус loan application flow."},"currentStepId":{"type":"string","nullable":true,"enum":["calculator","collateral_transfer","btc_confirmation","kyt","payout"],"description":"Следующий или текущий шаг, который нужно завершить."},"collateralRequiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm_btc."},"payoutRequiredConfirmations":{"type":"integer","description":"Сколько подтверждений ожидается для тестовой выдачи."},"wallets":{"type":"object","description":"Тестовые кошельки loan flow.","properties":{"collateralDeposit":{"$ref":"#/components/schemas/SandboxTestWallet"},"loanPayout":{"$ref":"#/components/schemas/SandboxTestWallet"},"collateralReturn":{"$ref":"#/components/schemas/SandboxTestWallet"}}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SandboxFlowStep"}}}},"SandboxTestWallet":{"type":"object","description":"Тестовый deterministic wallet/address для Sandbox flow. Не является реальным custody-кошельком.","properties":{"purpose":{"type":"string","enum":["collateral_deposit","loan_payout","repayment","collateral_return"],"description":"Назначение тестового кошелька в flow."},"asset":{"type":"string","enum":["BTC","USDT"],"description":"Актив кошелька."},"network":{"type":"string","enum":["sandbox"],"description":"Всегда sandbox: адрес не предназначен для реального blockchain-перевода."},"chainCode":{"type":"string","enum":["SANDBOX_BTC","SANDBOX_USDT"],"description":"Код тестовой сети."},"address":{"type":"string","description":"Тестовый адрес, который партнер показывает клиенту или использует в симуляции."},"isRealWallet":{"type":"boolean","enum":[false],"description":"Всегда false: в Sandbox не создается реальный custody wallet."},"confirmationMode":{"type":"string","enum":["api_simulated"],"description":"Подтверждение выполняется через API action, а не через внешний blockchain polling."},"requiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm action."}},"required":["purpose","asset","network","chainCode","address","isRealWallet","confirmationMode","requiredConfirmations"]},"SandboxFlowStep":{"type":"object","properties":{"id":{"type":"string","description":"Машинный идентификатор шага flow."},"title":{"type":"string","description":"Название шага для отображения."},"status":{"type":"string","enum":["pending","processing","completed"],"description":"Текущий статус шага."}}},"SandboxRepaymentOperationFlow":{"type":"object","description":"Repayment operation flow для процентов, частичного или полного погашения.","properties":{"id":{"type":"string","description":"Идентификатор repayment operation. Передавайте его как operation_id на следующих шагах."},"loanId":{"type":"string","nullable":true,"description":"ID займа, к которому относится repayment operation."},"kind":{"type":"string","enum":["interest","partial_principal","full_principal"],"description":"Тип погашения."},"status":{"type":"string","enum":["pending","completed"],"description":"Статус repayment flow."},"currentStepId":{"type":"string","nullable":true,"enum":["payment","usdt_confirmation","kyt","interest_settlement","debt_update","collateral_return"],"description":"Следующий или текущий шаг repayment flow."},"requiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm_usdt."},"wallets":{"type":"object","description":"Тестовые кошельки repayment flow.","properties":{"repayment":{"$ref":"#/components/schemas/SandboxTestWallet"},"collateralReturn":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/SandboxTestWallet"}],"description":"Кошелек возврата залога. Заполняется для полного погашения."}}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SandboxFlowStep"}},"createdAt":{"type":"string","format":"date-time","description":"Время создания repayment operation."}}},"ErrorResponse":{"type":"object","properties":{"request_id":{"type":"string","description":"Идентификатор запроса для поддержки и поиска в Logs."},"error_code":{"type":"string","description":"Формализованный код ошибки для интеграционной логики.","enum":["SANDBOX_API_KEY_REQUIRED","SANDBOX_API_KEY_INVALID","SANDBOX_API_KEY_DATABASE_REQUIRED","SANDBOX_SESSION_REQUIRED","SANDBOX_RATE_LIMIT_EXCEEDED","INVALID_REQUEST","INVALID_ACTION","INVALID_SCOPE","LOAN_NOT_FOUND","WALLET_NOT_FOUND","FLOW_CONFLICT","LIMIT_EXCEEDED","INSUFFICIENT_BALANCE","IDEMPOTENCY_KEY_REQUIRED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_KEY_IN_PROGRESS","DATABASE_UNAVAILABLE","INTERNAL_ERROR"]},"error":{"type":"string","description":"Человекочитаемое описание ошибки. Не используйте его для интеграционной логики, для этого есть error_code."}},"required":["request_id","error_code","error"]}},"responses":{"BadRequest":{"description":"Некорректный запрос: неверное тело, отсутствует Idempotency-Key для POST, неизвестное действие или невалидная сумма","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Sandbox API-ключ отсутствует или недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"Flow нельзя продолжить из текущего состояния, не хватает баланса/лимита или конфликтует Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"Превышен Sandbox API rate limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/api/sandbox/loans":{"post":{"operationId":"createSandboxLoan","tags":["post-loans"],"summary":"POST /api/sandbox/loans","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSandboxLoanRequest"}}}},"responses":{"200":{"description":"Sandbox-займ создан","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLoansStateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"description":"Создает Sandbox-займ напрямую, без пошагового cabinet-compatible flow. Endpoint полезен для быстрых backend-тестов, но для имитации реального кабинета используйте `POST /api/sandbox/loans/flow`.\n\nТело запроса задает BTC-залог, сумму займа, валюту займа и опциональные идентификаторы клиента партнера. `external_client_id` и `client_reference` помогают группировать сделки в админке и сопоставлять их с клиентом в системе партнера.\n\nДля POST обязательно передавайте `Idempotency-Key`, чтобы retry не создал второй займ."}}}}
```

## POST /api/sandbox/loans/{id}/action

> Выполняет прямое действие по активному Sandbox-займу. Это низкоуровневый shortcut для операций после выдачи займа: погашение процентов, погашение основного долга, довнесение или снятие части залога, увеличение займа.\
> \
> Для cabinet-compatible repayment path используйте \`POST /api/sandbox/loans/{id}/repayment-flow\`. Этот endpoint оставлен для простых тестов бизнес-логики и балансов.\
> \
> Для POST обязательно передавайте \`Idempotency-Key\`, чтобы retry не применил одно действие дважды.

```json
{"openapi":"3.0.3","info":{"title":"Fundora API","version":"0.3.0"},"tags":[{"name":"post-loans","description":"Создание займов и продвижение loan lifecycle в Sandbox."}],"servers":[{"url":"https://partner.fundora.capital","description":"Production-домен партнерского API"}],"security":[{"SandboxBearer":[]}],"components":{"securitySchemes":{"SandboxBearer":{"type":"http","scheme":"bearer","bearerFormat":"sk_sandbox"}},"parameters":{"LoanId":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Идентификатор Sandbox-займа из activeLoans[].id или loanHistory[].id."},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Обязательный уникальный ключ POST-операции, обычно UUID. Повтор того же POST с тем же endpoint-ом и телом вернет сохраненный результат с idempotency_replayed=true. Тот же ключ с другим телом или endpoint-ом вернет IDEMPOTENCY_KEY_CONFLICT. Отсутствующий ключ вернет IDEMPOTENCY_KEY_REQUIRED.","schema":{"type":"string","maxLength":255}}},"schemas":{"SandboxLoanActionRequest":{"type":"object","properties":{"action":{"type":"string","enum":["repay_interest","repay_principal","add_collateral","remove_collateral","borrow_more"],"description":"Прямое действие по активному Sandbox-займу."},"amount":{"type":"number","description":"Сумма операции. Для full repayment может быть не нужна."},"fullRepayment":{"type":"boolean","description":"true для полного погашения основного долга в shortcut action."}}},"SandboxLoansStateResponse":{"type":"object","properties":{"request_id":{"type":"string","description":"Идентификатор запроса для поддержки и поиска в Logs."},"idempotency_replayed":{"type":"boolean","description":"true, если POST-ответ возвращен из кеша Idempotency-Key. Для GET отсутствует."},"success":{"type":"boolean","description":"Признак успешного ответа."},"activatedScenarios":{"type":"object","description":"Какие sandbox-сценарии активированы для текущего пользователя/API-ключа.","properties":{"miner":{"type":"boolean","description":"Активирован borrower/miner сценарий."},"investor":{"type":"boolean","description":"Активирован investor сценарий."}}},"wallet":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/SandboxWalletState"}],"description":"Тестовый кошелек симулятора."},"activeLoans":{"type":"array","description":"Активные Sandbox-займы.","items":{"$ref":"#/components/schemas/SandboxLoanRecord"}},"loanHistory":{"type":"array","description":"Закрытые или исторические Sandbox-займы.","items":{"$ref":"#/components/schemas/SandboxLoanRecord"}},"loanHistoryEvents":{"type":"array","description":"События истории по займам для UI/таймлайна.","items":{"$ref":"#/components/schemas/SandboxLoanHistoryEvent"}},"loanDraft":{"$ref":"#/components/schemas/SandboxLoanDraft"},"sandboxFlow":{"$ref":"#/components/schemas/SandboxLoanFlowState"}},"required":["request_id","success"]},"SandboxWalletState":{"type":"object","properties":{"id":{"type":"string","description":"ID sandbox-кошелька симулятора."},"virtualBtcBalance":{"type":"string","description":"Доступный тестовый BTC-баланс."},"virtualUsdBalance":{"type":"string","description":"Доступный тестовый USD/USDT-баланс."},"virtualRubBalance":{"type":"string","description":"Доступный тестовый RUB-баланс."},"lockedBtcBalance":{"type":"string","description":"BTC, заблокированный в залоге."},"investedRubBalance":{"type":"string","description":"RUB, задействованный в инвестиционном сценарии."}}},"SandboxLoanRecord":{"type":"object","properties":{"id":{"type":"string","description":"ID Sandbox-займа."},"status":{"type":"string","description":"Статус займа."},"collateral_btc":{"type":"number","description":"Общий BTC-залог."},"collateral_received":{"type":"number","description":"Фактически подтвержденный BTC-залог."},"collateral_address":{"type":"string","nullable":true,"description":"Адрес залога в симуляторе."},"external_client_id":{"type":"string","nullable":true,"description":"ID клиента в системе партнера."},"client_reference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента или сделку."},"loan_amount":{"type":"number","description":"Исходная сумма займа."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа."},"debt_amount":{"type":"number","description":"Исходный основной долг."},"annual_rate":{"type":"number","description":"Годовая ставка займа в процентах."},"btc_rate":{"type":"number","description":"BTC rate, зафиксированный на момент создания."},"usd_rub_rate":{"type":"number","description":"USD/RUB rate, зафиксированный на момент создания."},"current_collateral_usd":{"type":"number","description":"Текущая стоимость залога в USD."},"current_collateral_rub":{"type":"number","description":"Текущая стоимость залога в RUB."},"current_debt":{"type":"number","description":"Текущий долг с учетом операций."},"health_factor":{"type":"number","description":"Индикатор здоровья займа: чем выше, тем безопаснее."},"accrued_interest":{"type":"number","description":"Начисленные проценты."},"max_ltv":{"type":"number","description":"Максимальный LTV для займа."},"liquidation_threshold":{"type":"number","description":"Порог ликвидации для займа."},"created_at":{"type":"string","format":"date-time","description":"Время создания займа."},"funded_at":{"type":"string","format":"date-time","description":"Время выдачи займа."},"interest_due_at":{"type":"string","nullable":true,"format":"date-time","description":"Дата ближайшего процентного платежа."},"principal_due_at":{"type":"string","nullable":true,"format":"date-time","description":"Дата платежа основного долга."}}},"SandboxLoanHistoryEvent":{"type":"object","properties":{"id":{"type":"string","description":"ID события истории."},"type":{"type":"string","enum":["opened","collateral","loan","interest_paid","closed"],"description":"Тип события."},"title":{"type":"string","description":"Название события для UI."},"amountLabel":{"type":"string","description":"Основная сумма для отображения."},"amountSubLabel":{"type":"string","nullable":true,"description":"Дополнительная сумма для отображения."},"rateLabel":{"type":"string","nullable":true,"description":"Ставка или курс для отображения."},"createdAt":{"type":"string","format":"date-time","description":"Время события."},"loanId":{"type":"string","description":"ID связанного займа."},"canRemoveCollateral":{"type":"boolean","description":"Можно ли снять часть залога после этого события."}}},"SandboxLoanDraft":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"ID draft-заявки."},"status":{"type":"string","enum":["active","completed","discarded"],"description":"Статус draft-заявки."},"currentStep":{"type":"string","enum":["contract","kyt","collateral","cfa"],"description":"Текущий шаг draft в legacy simulator flow."},"loanId":{"type":"string","nullable":true,"description":"ID созданного займа, если draft уже завершен."},"loanParams":{"type":"object","properties":{"collateral_btc":{"type":"number","description":"BTC-залог draft-заявки."},"loan_amount":{"type":"number","description":"Сумма займа draft-заявки."},"loan_currency":{"type":"string","enum":["RUB","USDT"],"description":"Валюта займа draft-заявки."}}},"contractAddress":{"type":"string","nullable":true,"description":"Тестовый contract/collateral address."},"kytReport":{"type":"object","nullable":true,"additionalProperties":true,"description":"KYT payload, переданный в run_kyt."},"collateralPosted":{"type":"boolean","description":"Подтвержден ли залог."},"cfaIssued":{"type":"boolean","description":"Завершена ли выдача займа."},"collateralPostedAt":{"type":"string","nullable":true,"format":"date-time"},"cfaIssuedAt":{"type":"string","nullable":true,"format":"date-time"},"completedAt":{"type":"string","nullable":true,"format":"date-time"},"discardedAt":{"type":"string","nullable":true,"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"SandboxLoanFlowState":{"type":"object","properties":{"loanApplications":{"type":"array","description":"Все активные и завершенные loan application flows.","items":{"$ref":"#/components/schemas/SandboxLoanApplicationFlow"}},"repaymentOperations":{"type":"array","description":"Все repayment flows по займам.","items":{"$ref":"#/components/schemas/SandboxRepaymentOperationFlow"}}}},"SandboxLoanApplicationFlow":{"type":"object","description":"Текущий loan application flow для выдачи займа.","properties":{"id":{"type":"string","description":"Идентификатор draft/application flow."},"loanId":{"type":"string","nullable":true,"description":"Идентификатор созданного займа. До complete_payout может быть null."},"externalClientId":{"type":"string","nullable":true,"description":"ID клиента в системе партнера."},"clientReference":{"type":"string","nullable":true,"description":"Человекочитаемая ссылка на клиента/сделку."},"status":{"type":"string","enum":["pending","completed"],"description":"Статус loan application flow."},"currentStepId":{"type":"string","nullable":true,"enum":["calculator","collateral_transfer","btc_confirmation","kyt","payout"],"description":"Следующий или текущий шаг, который нужно завершить."},"collateralRequiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm_btc."},"payoutRequiredConfirmations":{"type":"integer","description":"Сколько подтверждений ожидается для тестовой выдачи."},"wallets":{"type":"object","description":"Тестовые кошельки loan flow.","properties":{"collateralDeposit":{"$ref":"#/components/schemas/SandboxTestWallet"},"loanPayout":{"$ref":"#/components/schemas/SandboxTestWallet"},"collateralReturn":{"$ref":"#/components/schemas/SandboxTestWallet"}}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SandboxFlowStep"}}}},"SandboxTestWallet":{"type":"object","description":"Тестовый deterministic wallet/address для Sandbox flow. Не является реальным custody-кошельком.","properties":{"purpose":{"type":"string","enum":["collateral_deposit","loan_payout","repayment","collateral_return"],"description":"Назначение тестового кошелька в flow."},"asset":{"type":"string","enum":["BTC","USDT"],"description":"Актив кошелька."},"network":{"type":"string","enum":["sandbox"],"description":"Всегда sandbox: адрес не предназначен для реального blockchain-перевода."},"chainCode":{"type":"string","enum":["SANDBOX_BTC","SANDBOX_USDT"],"description":"Код тестовой сети."},"address":{"type":"string","description":"Тестовый адрес, который партнер показывает клиенту или использует в симуляции."},"isRealWallet":{"type":"boolean","enum":[false],"description":"Всегда false: в Sandbox не создается реальный custody wallet."},"confirmationMode":{"type":"string","enum":["api_simulated"],"description":"Подтверждение выполняется через API action, а не через внешний blockchain polling."},"requiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm action."}},"required":["purpose","asset","network","chainCode","address","isRealWallet","confirmationMode","requiredConfirmations"]},"SandboxFlowStep":{"type":"object","properties":{"id":{"type":"string","description":"Машинный идентификатор шага flow."},"title":{"type":"string","description":"Название шага для отображения."},"status":{"type":"string","enum":["pending","processing","completed"],"description":"Текущий статус шага."}}},"SandboxRepaymentOperationFlow":{"type":"object","description":"Repayment operation flow для процентов, частичного или полного погашения.","properties":{"id":{"type":"string","description":"Идентификатор repayment operation. Передавайте его как operation_id на следующих шагах."},"loanId":{"type":"string","nullable":true,"description":"ID займа, к которому относится repayment operation."},"kind":{"type":"string","enum":["interest","partial_principal","full_principal"],"description":"Тип погашения."},"status":{"type":"string","enum":["pending","completed"],"description":"Статус repayment flow."},"currentStepId":{"type":"string","nullable":true,"enum":["payment","usdt_confirmation","kyt","interest_settlement","debt_update","collateral_return"],"description":"Следующий или текущий шаг repayment flow."},"requiredConfirmations":{"type":"integer","description":"Сколько подтверждений нужно передать в confirm_usdt."},"wallets":{"type":"object","description":"Тестовые кошельки repayment flow.","properties":{"repayment":{"$ref":"#/components/schemas/SandboxTestWallet"},"collateralReturn":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/SandboxTestWallet"}],"description":"Кошелек возврата залога. Заполняется для полного погашения."}}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/SandboxFlowStep"}},"createdAt":{"type":"string","format":"date-time","description":"Время создания repayment operation."}}},"ErrorResponse":{"type":"object","properties":{"request_id":{"type":"string","description":"Идентификатор запроса для поддержки и поиска в Logs."},"error_code":{"type":"string","description":"Формализованный код ошибки для интеграционной логики.","enum":["SANDBOX_API_KEY_REQUIRED","SANDBOX_API_KEY_INVALID","SANDBOX_API_KEY_DATABASE_REQUIRED","SANDBOX_SESSION_REQUIRED","SANDBOX_RATE_LIMIT_EXCEEDED","INVALID_REQUEST","INVALID_ACTION","INVALID_SCOPE","LOAN_NOT_FOUND","WALLET_NOT_FOUND","FLOW_CONFLICT","LIMIT_EXCEEDED","INSUFFICIENT_BALANCE","IDEMPOTENCY_KEY_REQUIRED","IDEMPOTENCY_KEY_CONFLICT","IDEMPOTENCY_KEY_IN_PROGRESS","DATABASE_UNAVAILABLE","INTERNAL_ERROR"]},"error":{"type":"string","description":"Человекочитаемое описание ошибки. Не используйте его для интеграционной логики, для этого есть error_code."}},"required":["request_id","error_code","error"]}},"responses":{"BadRequest":{"description":"Некорректный запрос: неверное тело, отсутствует Idempotency-Key для POST, неизвестное действие или невалидная сумма","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Sandbox API-ключ отсутствует или недействителен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Займ не найден","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"Flow нельзя продолжить из текущего состояния, не хватает баланса/лимита или конфликтует Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"Превышен Sandbox API rate limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/api/sandbox/loans/{id}/action":{"post":{"operationId":"runSandboxLoanAction","tags":["post-loans"],"summary":"POST /api/sandbox/loans/{id}/action","parameters":[{"$ref":"#/components/parameters/LoanId"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLoanActionRequest"}}}},"responses":{"200":{"description":"Обновленное состояние Sandbox-займа","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLoansStateResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"}},"description":"Выполняет прямое действие по активному Sandbox-займу. Это низкоуровневый shortcut для операций после выдачи займа: погашение процентов, погашение основного долга, довнесение или снятие части залога, увеличение займа.\n\nДля cabinet-compatible repayment path используйте `POST /api/sandbox/loans/{id}/repayment-flow`. Этот endpoint оставлен для простых тестов бизнес-логики и балансов.\n\nДля POST обязательно передавайте `Idempotency-Key`, чтобы retry не применил одно действие дважды."}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fundora.capital/api-sandbox/post-loans.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
