{"components":{"schemas":{"Autopay":{"properties":{"amount_type":{"type":"string"},"autopay_config_uuid":{"type":"string"},"fixed_amount_cents":{"type":"integer"},"loan_uuid":{"type":"string"},"payment_method_uuid":{"type":"string"},"schedule_day":{"type":"integer"},"status":{"type":"string"}},"type":"object"},"FeeQuoteChangedProblem":{"allOf":[{"$ref":"#/components/schemas/Problem"},{"properties":{"amount_cents":{"description":"Fresh quote: amount that would be applied to the loan","type":"integer"},"code":{"enum":["fee_quote_changed"],"type":"string"},"fee_bearer":{"description":"Gateway fee policy for the fresh quote (the policy itself can be what moved)","enum":["customer","merchant",""],"type":"string"},"processing_fee_cents":{"description":"Fresh quote: processing fee that would be included in the charge","type":"integer"},"total_charged_cents":{"description":"Fresh quote: total the card/bank would be debited — show this and retry with it as confirmed_total_cents (new Idempotency-Key)","type":"integer"}},"type":"object"}]},"HardshipMessage":{"properties":{"body":{"type":"string"},"dt_created":{"format":"date-time","type":"string"},"is_read":{"type":"boolean"},"message_uuid":{"type":"string"},"sender_name":{"type":"string"},"sender_type":{"enum":["borrower","staff"],"type":"string"}},"type":"object"},"HardshipRequest":{"properties":{"dt_created":{"format":"date-time","type":"string"},"dt_last_message":{"format":"date-time","type":"string"},"last_message":{"type":"string"},"last_sender":{"type":"string"},"message_count":{"type":"integer"},"subject":{"type":"string"},"thread_uuid":{"type":"string"},"unread_count":{"type":"integer"}},"type":"object"},"HardshipRequestDetail":{"properties":{"dt_created":{"format":"date-time","type":"string"},"messages":{"description":"The first message is the intake itself (body blank; see request)","items":{"$ref":"#/components/schemas/HardshipMessage"},"type":"array"},"request":{"properties":{"assistance_types":{"items":{"type":"string"},"type":"array"},"description":{"description":"At least 50 characters","type":"string"},"expected_duration":{"description":"e.g. 1_month, 3_months, 6_months, unknown","type":"string"},"hardship_start_date":{"description":"YYYY-MM-DD","type":"string"},"hardship_type":{"description":"e.g. job_loss, medical, reduced_income, family_emergency, other","type":"string"},"loan_uuid":{"description":"Optional; a loan that is not the borrower's is dropped","type":"string"},"monthly_expenses_cents":{"type":"integer"},"monthly_income_cents":{"type":"integer"}},"required":["hardship_type","description","hardship_start_date","expected_duration"],"type":"object"},"subject":{"type":"string"},"thread_uuid":{"type":"string"}},"type":"object"},"Loan":{"properties":{"cab_fee_outstanding_cents":{"description":"CSO/CAB fee bucket (Texas CAB products only; omitted otherwise). Included in total_outstanding_cents.","type":"integer"},"credit_balance_cents":{"type":"integer"},"credit_limit_cents":{"type":"integer"},"currency_code":{"type":"string"},"dt_maturity":{"format":"date-time","type":"string"},"dt_opened":{"format":"date-time","type":"string"},"fees_outstanding_cents":{"type":"integer"},"interest_outstanding_cents":{"type":"integer"},"last_due_date":{"format":"date-time","type":"string"},"loan_number":{"type":"string"},"loan_uuid":{"type":"string"},"next_statement_cut_date":{"format":"date-time","type":"string"},"next_statement_due_date":{"format":"date-time","type":"string"},"principal_outstanding_cents":{"type":"integer"},"status":{"type":"string"},"total_outstanding_cents":{"type":"integer"}},"type":"object"},"Notification":{"properties":{"dt_created":{"format":"date-time","type":"string"},"is_read":{"type":"boolean"},"message":{"type":"string"},"notification_uuid":{"type":"string"},"ref_type":{"type":"string"},"ref_uuid":{"type":"string"},"title":{"type":"string"},"type":{"type":"string"}},"type":"object"},"NotificationPreferences":{"properties":{"email_due_reminders":{"type":"boolean"},"email_payments":{"type":"boolean"},"email_statements":{"type":"boolean"},"sms_due_reminders":{"type":"boolean"}},"type":"object"},"PaymentMethod":{"properties":{"account_type":{"type":"string"},"bank_name":{"type":"string"},"brand":{"type":"string"},"display_name":{"type":"string"},"eligibility_checked_at":{"description":"Cards only: when the processor last checked eligibility; empty when never","format":"date-time","type":"string"},"exp_month":{"type":"integer"},"exp_year":{"type":"integer"},"funding_type":{"description":"Cards only: the processor-reported funding type","enum":["debit","credit","prepaid","unknown"],"type":"string"},"is_default":{"type":"boolean"},"last4":{"type":"string"},"nickname":{"type":"string"},"payment_method_uuid":{"type":"string"},"push_eligible":{"description":"Cards only: true = can receive a card advance; false or null = cannot (null = never checked; still fine for payments). Verify via POST /payment-methods/{method_uuid}/verify.","nullable":true,"type":"boolean"},"status":{"type":"string"},"type":{"type":"string"}},"type":"object"},"PayoffQuote":{"properties":{"accrued_interest_cents":{"type":"integer"},"cab_fee_net_cents":{"type":"integer"},"cab_fee_rebate_cents":{"type":"integer"},"fees_cents":{"type":"integer"},"good_through_date":{"description":"The total holds through this date; add per_diem_interest_cents per day after it","format":"date","type":"string"},"loan_uuid":{"type":"string"},"payoff_date":{"format":"date","type":"string"},"per_diem_interest_cents":{"type":"integer"},"precomputed_charge_cents":{"type":"integer"},"precomputed_earned_cents":{"type":"integer"},"precomputed_rebate_cents":{"type":"integer"},"precomputed_rebate_method":{"type":"string"},"principal_cents":{"type":"integer"},"projected_cab_fee_cents":{"type":"integer"},"projected_fees_cents":{"type":"integer"},"projected_through_date":{"format":"date","type":"string"},"total_payoff_cents":{"description":"The figure to pay: principal + earned interest + fees net of the unearned-charge rebate","type":"integer"}},"type":"object"},"Problem":{"properties":{"code":{"type":"string"},"detail":{"type":"string"},"instance":{"type":"string"},"request_id":{"type":"string"},"status":{"type":"integer"},"title":{"type":"string"},"type":{"type":"string"}},"type":"object"},"Profile":{"properties":{"borrower_uuid":{"type":"string"},"email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"mobile_phone":{"type":"string"}},"type":"object"},"RewardLedgerEntry":{"properties":{"balance_after":{"type":"integer"},"description":{"type":"string"},"dt_created":{"format":"date-time","type":"string"},"entry_type":{"enum":["earn","redeem","adjust","expire","reverse"],"type":"string"},"entry_uuid":{"type":"string"},"points_delta":{"description":"Signed points movement","type":"integer"},"source":{"type":"string"}},"type":"object"},"RewardsAccount":{"properties":{"balance_cents":{"description":"Balance value at the program's CURRENT rate","type":"integer"},"balance_points":{"type":"integer"},"lifetime_earned":{"type":"integer"},"lifetime_redeemed":{"type":"integer"},"referral_code":{"description":"Shareable referral code","type":"string"},"status":{"enum":["active","frozen"],"type":"string"}},"type":"object"},"RewardsOverview":{"properties":{"account":{"$ref":"#/components/schemas/RewardsAccount"},"enabled":{"description":"false = no rewards program; program/account are absent","type":"boolean"},"program":{"$ref":"#/components/schemas/RewardsProgram"}},"type":"object"},"RewardsProgram":{"description":"Company-branded program rules. Render program_name/points_name verbatim wherever points appear.","properties":{"expiry_months":{"description":"Points expire after N months of inactivity; 0 = never","type":"integer"},"min_redeem_points":{"type":"integer"},"ontime_enabled":{"type":"boolean"},"ontime_min_amount_cents":{"type":"integer"},"ontime_mode":{"enum":["fixed","per_dollar"],"type":"string"},"ontime_points":{"type":"integer"},"ontime_points_per_dollar":{"type":"integer"},"points_name":{"type":"string"},"program_name":{"type":"string"},"rate_cents":{"type":"integer"},"rate_points":{"description":"Conversion: rate_points points == rate_cents cents","type":"integer"},"redeem_scope":{"enum":["amount_due","total_balance"],"type":"string"},"redemption_mode":{"description":"enabled = redeem immediately; approval = POST /rewards/redeem returns 202 pending_approval and applies on staff sign-off; disabled = 422 redemptions_disabled (earning continues)","enum":["enabled","disabled","approval"],"type":"string"},"referral_enabled":{"type":"boolean"},"referral_points":{"type":"integer"}},"type":"object"},"RewardsQuote":{"properties":{"amount_due_cents":{"type":"integer"},"balance_cents":{"type":"integer"},"balance_points":{"type":"integer"},"cap_cents":{"description":"Most the loan can absorb right now under the redeem scope","type":"integer"},"loan_uuid":{"type":"string"},"max_cents":{"type":"integer"},"max_points":{"description":"Most points usable right now (min of cap and balance)","type":"integer"},"min_redeem_points":{"type":"integer"},"points_name":{"type":"string"},"program_name":{"type":"string"},"rate_cents":{"type":"integer"},"rate_points":{"type":"integer"},"total_outstanding_cents":{"type":"integer"}},"type":"object"},"RewardsRedemption":{"properties":{"balance_cents":{"type":"integer"},"balance_points":{"description":"Points balance after the redemption","type":"integer"},"cents_value":{"description":"Dollar value applied to the loan (integer cents)","type":"integer"},"loan_uuid":{"type":"string"},"points":{"description":"Points deducted","type":"integer"},"points_name":{"type":"string"},"program_name":{"type":"string"},"redemption_uuid":{"type":"string"},"replayed":{"description":"true when an Idempotency-Key retry returned the original result","type":"boolean"},"status":{"enum":["redeemed"],"type":"string"}},"type":"object"},"ScheduledPayment":{"properties":{"amount_cents":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"executed_at":{"format":"date-time","type":"string"},"failure_reason":{"type":"string"},"loan_uuid":{"type":"string"},"payment_method_uuid":{"type":"string"},"scheduled_date":{"format":"date","type":"string"},"scheduled_payment_uuid":{"type":"string"},"status":{"type":"string"}},"type":"object"},"Settings":{"properties":{"languages":{"items":{"type":"string"},"type":"array"},"notifications":{"$ref":"#/components/schemas/NotificationPreferences"},"passkey_enabled":{"type":"boolean"},"password_change_available":{"description":"false for SSO-only borrowers","type":"boolean"},"preferred_language":{"type":"string"},"profile":{"$ref":"#/components/schemas/Profile"},"totp_enabled":{"type":"boolean"},"two_fa_method":{"type":"string"}},"type":"object"},"StatementDetail":{"allOf":[{"$ref":"#/components/schemas/StatementSummary"},{"properties":{"current_min_due_cents":{"type":"integer"},"html":{"type":"string"},"new_charges_cents":{"type":"integer"},"past_due_cents":{"type":"integer"},"payments_applied_cents":{"type":"integer"},"prior_balance_cents":{"type":"integer"},"total_min_due_cents":{"type":"integer"}},"type":"object"}]},"StatementSummary":{"properties":{"due_date":{"format":"date-time","type":"string"},"loan_uuid":{"type":"string"},"min_payment_cents":{"description":"Minimum payment due: past due + this period's minimum (equals total_min_due_cents)","type":"integer"},"period_end":{"format":"date-time","type":"string"},"period_start":{"format":"date-time","type":"string"},"statement_uuid":{"type":"string"},"status":{"type":"string"},"total_due_cents":{"type":"integer"}},"type":"object"},"TaxDocument":{"properties":{"detail_url":{"type":"string"},"download_url":{"type":"string"},"title":{"type":"string"},"year":{"type":"integer"}},"type":"object"},"TaxSummary":{"properties":{"disclaimer":{"type":"string"},"download_url":{"type":"string"},"loans":{"items":{"$ref":"#/components/schemas/TaxSummaryLoan"},"type":"array"},"total_fees_paid_cents":{"type":"integer"},"total_interest_paid_cents":{"type":"integer"},"total_payments_cents":{"type":"integer"},"total_principal_paid_cents":{"type":"integer"},"total_year_end_balance_cents":{"type":"integer"},"year":{"type":"integer"}},"type":"object"},"TaxSummaryLoan":{"properties":{"dt_opened":{"format":"date","type":"string"},"fees_paid_cents":{"type":"integer"},"interest_paid_cents":{"type":"integer"},"loan_number":{"type":"string"},"loan_type_name":{"type":"string"},"loan_uuid":{"type":"string"},"principal_paid_cents":{"type":"integer"},"total_paid_cents":{"type":"integer"},"year_end_balance_cents":{"type":"integer"}},"type":"object"},"TokenResponse":{"properties":{"absolute_expires_at":{"format":"date-time","type":"string"},"access_token":{"type":"string"},"expires_at":{"format":"date-time","type":"string"},"token_type":{"type":"string"}},"type":"object"},"Transaction":{"properties":{"amount_cents":{"type":"integer"},"bucket":{"type":"string"},"description":{"type":"string"},"dt_effective":{"format":"date-time","type":"string"},"payment_method_label":{"type":"string"},"transaction_uuid":{"type":"string"},"type":{"type":"string"},"type_label":{"description":"Display name of type","type":"string"}},"type":"object"}},"securitySchemes":{"bearerAuth":{"description":"Opaque bearer token issued by /auth/verify.","scheme":"bearer","type":"http"},"companyHeader":{"description":"Tenant scope for pre-auth endpoints. Public identifier, not a secret.","in":"header","name":"X-Company-UUID","type":"apiKey"}}},"info":{"description":"Public, borrower-token API for building a white-label borrower portal (browser SPA or mobile app). Pre-auth endpoints are scoped by the non-secret `X-Company-UUID` header; everything borrower-scoped uses an opaque bearer token issued on 2FA verify. All money is integer cents. Money POSTs accept an `Idempotency-Key` header so retries never double-charge.\n\nThe separate server-to-server Partner/Staff API (`/api/v1`, company API key) — awarding rewards points, posting register payments, origination — has its own spec at `/api/v1/openapi.json`, rendered at /developers/partner-api.","title":"Vector Loan — Customer Portal API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/addresses":{"get":{"parameters":[{"description":"Include retired addresses","in":"query","name":"history","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Addresses"}},"security":[{"bearerAuth":[]}],"summary":"Borrower addresses","tags":["Profile"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"address_line1":{"type":"string"},"city":{"type":"string"},"make_primary":{"type":"boolean"},"state":{"type":"string"},"zip_code":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Created"}},"security":[{"bearerAuth":[]}],"summary":"Add an address","tags":["Profile"]}},"/addresses/{address_uuid}":{"delete":{"parameters":[{"description":"Address UUID","in":"path","name":"address_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Retired"}},"security":[{"bearerAuth":[]}],"summary":"Retire an address","tags":["Profile"]},"put":{"parameters":[{"description":"Address UUID","in":"path","name":"address_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Updated"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Update an address","tags":["Profile"]}},"/addresses/{address_uuid}/primary":{"post":{"parameters":[{"description":"Address UUID","in":"path","name":"address_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"OK"}},"security":[{"bearerAuth":[]}],"summary":"Set primary address","tags":["Profile"]}},"/applications":{"get":{"parameters":[{"description":"","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Applications page"}},"security":[{"bearerAuth":[]}],"summary":"List your applications","tags":["Applications"]},"post":{"description":"Pre-auth lead intake: resolves-or-creates the borrower by email, submits an application, and records source attribution (source_code/campaign/sub_id/…) that carries through to the funded loan. No bearer token — scoped by X-Company-UUID.","requestBody":{"content":{"application/json":{"schema":{"properties":{"applicant":{"properties":{"address_line1":{"type":"string"},"address_line2":{"type":"string"},"city":{"type":"string"},"date_of_birth":{"type":"string"},"email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"phone":{"type":"string"},"state":{"type":"string"},"zip_code":{"type":"string"}},"required":["first_name","last_name","email"],"type":"object"},"attribution":{"properties":{"campaign":{"type":"string"},"click_id":{"type":"string"},"landing_page":{"type":"string"},"referrer_url":{"type":"string"},"source_code":{"type":"string"},"sub_id":{"type":"string"}},"type":"object"},"loan_type_uuid":{"type":"string"},"requested_cents":{"type":"integer"}},"required":["loan_type_uuid","requested_cents","applicant"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"application":{"type":"object"},"borrower_uuid":{"type":"string"},"resolved_affiliate":{"type":"string"}},"type":"object"}}},"description":"Application submitted"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Intake unavailable"}},"security":[{"companyHeader":[]}],"summary":"Submit a lead/affiliate application (public intake)","tags":["Applications"]}},"/applications/{application_uuid}":{"get":{"parameters":[{"description":"Application UUID","in":"path","name":"application_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Application"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Get an application","tags":["Applications"]}},"/applications/{application_uuid}/decision-letter":{"get":{"parameters":[{"description":"Application UUID","in":"path","name":"application_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"PDF or HTML letter"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"No letter"}},"security":[{"bearerAuth":[]}],"summary":"Decision / adverse-action letter (PDF or HTML)","tags":["Applications"]}},"/applications/{application_uuid}/withdraw":{"post":{"parameters":[{"description":"Application UUID","in":"path","name":"application_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"reason":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Withdrawn"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Cannot withdraw"}},"security":[{"bearerAuth":[]}],"summary":"Withdraw an application","tags":["Applications"]}},"/auth/login":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"email":{"type":"string"},"password":{"type":"string"}},"required":["email","password"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"challenge_uuid":{"type":"string"},"masked":{"type":"string"},"method":{"type":"string"}},"type":"object"}}},"description":"2FA challenge issued"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid credentials"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Password login disabled — SSO required (code: sso_required); redirect the borrower to single sign-on"},"429":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Too many attempts"}},"security":[{"companyHeader":[]}],"summary":"Start login — returns a 2FA challenge","tags":["Auth"]}},"/auth/logout":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Logged out"}},"security":[{"bearerAuth":[]}],"summary":"Revoke the session","tags":["Auth"]}},"/auth/refresh":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Refreshed"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"Roll idle expiry forward","tags":["Auth"]}},"/auth/resend":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"challenge_uuid":{"type":"string"}},"required":["challenge_uuid"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Resent"}},"security":[{"companyHeader":[]}],"summary":"Resend the 2FA code","tags":["Auth"]}},"/auth/session":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Session"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"Current session (whoami)","tags":["Auth"]}},"/auth/verify":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"challenge_uuid":{"type":"string"},"code":{"type":"string"}},"required":["challenge_uuid","code"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}},"description":"Bearer token"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Verification failed"}},"security":[{"companyHeader":[]}],"summary":"Verify 2FA code — issues a bearer token","tags":["Auth"]}},"/autopay":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"items":{"$ref":"#/components/schemas/Autopay"},"type":"array"}},"type":"object"}}},"description":"Autopay"}},"security":[{"bearerAuth":[]}],"summary":"List autopay configs","tags":["Autopay"]},"post":{"description":"The configured amount (fixed_amount_cents / minimum due / full balance) is the amount APPLIED to the loan on each autopay run. When the GATEWAY's fee-bearer policy passes processing fees to the customer, each card charge is grossed up by the then-current processing fee (the card is debited amount + fee, itemized on the borrower's receipt email). CFPB-1041 covered loans are never grossed up — they are debited exactly the noticed amount.","requestBody":{"content":{"application/json":{"schema":{"properties":{"ach_authorization_accepted":{"description":"REQUIRED true when payment_method_uuid is a bank account: the borrower checked the recurring ACH debit authorization. Enrolling without it answers 400 ach_authorization_required.","type":"boolean"},"ach_authorization_text":{"description":"The exact authorization wording the borrower saw (stored verbatim as the NACHA dispute record). Omit to store the platform's standard wording.","type":"string"},"amount_type":{"enum":["minimum_due","fixed_amount","full_balance"],"type":"string"},"fixed_amount_cents":{"type":"integer"},"loan_uuid":{"type":"string"},"payment_method_uuid":{"type":"string"},"schedule_day":{"maximum":31,"minimum":1,"type":"integer"}},"required":["loan_uuid","payment_method_uuid","amount_type","schedule_day"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Autopay"}}},"description":"Autopay"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Enable autopay","tags":["Autopay"]}},"/branding":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Branding"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Company not found"}},"security":[{"companyHeader":[]}],"summary":"Public branding for the login screen","tags":["Discovery"]}},"/disbursements/{disbursement_uuid}":{"get":{"description":"Returns the advance's current state: pending | succeeded | failed, with amount, fee, net, the processor's processed_at and the posted loan_transaction_uuid once succeeded.","parameters":[{"description":"Disbursement UUID (from the draw response)","in":"path","name":"disbursement_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Disbursement"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Disbursement not found"}},"security":[{"bearerAuth":[]}],"summary":"Status of one card advance (the 202 polling fallback)","tags":["Payments"]}},"/disputes":{"get":{"parameters":[{"description":"","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Disputes page"}},"security":[{"bearerAuth":[]}],"summary":"List your disputes / complaints","tags":["Servicing"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"description":{"type":"string"},"loan_uuid":{"type":"string"},"reason":{"type":"string"},"transaction_uuid":{"type":"string"},"type":{"enum":["transaction","fee","interest","payment","other"],"type":"string"}},"required":["type","reason","description"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Filed"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Referenced loan/txn not found"}},"security":[{"bearerAuth":[]}],"summary":"File a dispute / complaint","tags":["Servicing"]}},"/disputes/{dispute_uuid}":{"get":{"parameters":[{"description":"Dispute UUID","in":"path","name":"dispute_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Dispute"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Get a dispute","tags":["Servicing"]}},"/document-requests":{"get":{"parameters":[{"description":"Only open requests","in":"query","name":"open","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Requests page"}},"security":[{"bearerAuth":[]}],"summary":"List document requests","tags":["Documents"]}},"/document-requests/{request_uuid}/fulfill":{"post":{"parameters":[{"description":"Request UUID","in":"path","name":"request_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"category":{"type":"string"},"file":{"format":"binary","type":"string"},"loan_uuid":{"type":"string"}},"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Uploaded + linked"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Bad upload / request"}},"security":[{"bearerAuth":[]}],"summary":"Fulfill a document request (multipart upload)","tags":["Documents"]}},"/documents":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Documents page"}},"security":[{"bearerAuth":[]}],"summary":"List uploaded documents","tags":["Documents"]}},"/documents/{document_uuid}/download":{"get":{"parameters":[{"description":"Document UUID","in":"path","name":"document_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File stream"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Download a document","tags":["Documents"]}},"/hardship":{"get":{"parameters":[{"description":"Page size (default 25, max 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Offset","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/HardshipRequest"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"type":"object"}}},"description":"Requests"}},"security":[{"bearerAuth":[]}],"summary":"Hardship requests","tags":["Hardship"]},"post":{"description":"Files the request as a staff-reviewed secure-message thread and notifies the borrower it was received (review within 3-5 business days). Not allowed on an impersonated session.","requestBody":{"content":{"application/json":{"schema":{"properties":{"assistance_types":{"items":{"type":"string"},"type":"array"},"description":{"description":"At least 50 characters","type":"string"},"expected_duration":{"description":"e.g. 1_month, 3_months, 6_months, unknown","type":"string"},"hardship_start_date":{"description":"YYYY-MM-DD","type":"string"},"hardship_type":{"description":"e.g. job_loss, medical, reduced_income, family_emergency, other","type":"string"},"loan_uuid":{"description":"Optional; a loan that is not the borrower's is dropped","type":"string"},"monthly_expenses_cents":{"type":"integer"},"monthly_income_cents":{"type":"integer"}},"required":["hardship_type","description","hardship_start_date","expected_duration"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"message":{"type":"string"},"status":{"type":"string"},"thread_uuid":{"type":"string"}},"type":"object"}}},"description":"Submitted"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Impersonated session"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Validation failed"}},"security":[{"bearerAuth":[]}],"summary":"Submit a hardship assistance request","tags":["Hardship"]}},"/hardship/{thread_uuid}":{"get":{"parameters":[{"description":"Request thread UUID","in":"path","name":"thread_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HardshipRequestDetail"}}},"description":"Request"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"A hardship request with its conversation","tags":["Hardship"]}},"/hardship/{thread_uuid}/reply":{"post":{"parameters":[{"description":"Request thread UUID","in":"path","name":"thread_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"type":"string"}},"required":["body"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HardshipMessage"}}},"description":"Reply"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Empty body"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Impersonated session"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Reply on a hardship request","tags":["Hardship"]}},"/loans":{"get":{"description":"Loans on a product configured as portal_access=none (serviced in store only) are omitted here and answer 404 everywhere else.","parameters":[{"description":"Page size (max 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Offset","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/Loan"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"type":"object"}}},"description":"Loans page"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"List loans","tags":["Loans"]}},"/loans/{loan_uuid}":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Loan"}}},"description":"Loan"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Get a loan","tags":["Loans"]}},"/loans/{loan_uuid}/autopay/disable":{"post":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Disabled"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Disable autopay","tags":["Autopay"]}},"/loans/{loan_uuid}/autopay/pause":{"post":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Paused"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Pause autopay (keeps config; resume to reactivate)","tags":["Autopay"]}},"/loans/{loan_uuid}/autopay/resume":{"post":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Active"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Resume a paused autopay","tags":["Autopay"]}},"/loans/{loan_uuid}/credit-limit/eligibility":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Eligibility"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Credit-limit-increase eligibility (LOC products)","tags":["Loans"]}},"/loans/{loan_uuid}/credit-limit/request":{"post":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Request created"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"A request is already open"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not eligible"}},"security":[{"bearerAuth":[]}],"summary":"Request a credit-limit increase","tags":["Loans"]}},"/loans/{loan_uuid}/documents":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"type":"array"}},"type":"object"}}},"description":"Loan documents"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Generated / signed loan documents (contracts, agreements)","tags":["Documents"]}},"/loans/{loan_uuid}/documents/{document_uuid}/download":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Document (instance) UUID","in":"path","name":"document_uuid","required":true,"schema":{"type":"string"}},{"description":"signed (default) or original","in":"query","name":"version","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Document PDF stream"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Download a loan document (signed by default; ?version=original)","tags":["Documents"]}},"/loans/{loan_uuid}/draws":{"post":{"description":"403 draws_not_available_online when the product is portal_access=servicing_only (advances are taken in store). Pushes amount_cents to the borrower's saved, verified DEBIT card through the payment gateway; the loan principal advances by the full amount_cents (the borrower absorbs the processing fee, so the card receives amount_cents minus the fee). There is no ledger-only draw. An Idempotency-Key header is REQUIRED and must be reused verbatim on any retry: the advance's identity derives from it, so a retried POST lands on the same advance instead of pushing twice. 200 = funded and posted; 202 = the processor has not confirmed yet — poll GET /disbursements/{disbursement_uuid} or wait for the email, and NEVER retry with a new key; 402 = declined, nothing moved; 422 = a draw gate refused (available credit, past-due, documents, card not eligible), nothing moved; 502 = the outcome could not be confirmed — do not retry, contact support.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Required. Reuse the same value on retries of this advance. Keys are scoped to the signed-in borrower.","in":"header","name":"Idempotency-Key","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"description":"Amount applied to the loan (principal advances by this). The card receives this minus the processing fee.","type":"integer"},"description":{"type":"string"},"payment_method_uuid":{"description":"A saved DEBIT card UUID verified for advances (push_eligible).","type":"string"}},"required":["amount_cents","payment_method_uuid"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Advance funded and posted to the loan"},"202":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Advance pending the processor's confirmation (poll /disbursements/{disbursement_uuid})"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Idempotency-Key or payment_method_uuid missing"},"402":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Card declined — no funds moved. failure_code is one of card_declined, insufficient_funds, invalid_card_data, invalid_expiration, invalid_amount, invalid_card_token, card_not_push_eligible, payouts_disabled, payouts_not_configured, processor_config_error, duplicate_same_day (same amount to the same card today — choose a different amount or try tomorrow), not_processed, generic_failure; detail carries the borrower-facing sentence"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Idempotency-Key reused for a different advance"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Draw not allowed (limit / past-due / gate / card not eligible) — code exceeds_available_credit when the amount is above the line's available credit (credit_limit_cents less principal_outstanding_cents and any advance in flight; detail quotes the figure), or code duplicate_same_day: an advance of the same amount was already sent to this card today and the processor would refuse it — nothing was sent; choose a different amount or try tomorrow"},"502":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Advance could not be confirmed — do not retry"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Card advances are not available"}},"security":[{"bearerAuth":[]}],"summary":"Take an advance to a saved debit card (push-to-card)","tags":["Payments"]}},"/loans/{loan_uuid}/modification-eligibility":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"days_past_due":{"type":"integer"},"eligible":{"type":"boolean"},"eligible_after_dpd":{"type":"integer"},"loan_uuid":{"type":"string"},"program_enabled":{"type":"boolean"},"requestable_types":{"items":{"type":"string"},"type":"array"}},"type":"object"}}},"description":"Eligibility"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Eligibility could not be determined (product configuration unavailable) — retry"}},"security":[{"bearerAuth":[]}],"summary":"Workout / modification eligibility for a loan (product days-past-due rule; informational, never auto-applies; 503 when the product configuration cannot be read)","tags":["Servicing"]}},"/loans/{loan_uuid}/modification-requests":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Requests"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"List hardship / modification requests for a loan","tags":["Servicing"]},"post":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"reason":{"type":"string"},"requested_value":{"type":"string"},"type":{"enum":["payment_deferral","term_extension"],"type":"string"}},"required":["type","reason"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Submitted"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Request a hardship modification (staff-reviewed; never auto-applied)","tags":["Servicing"]}},"/loans/{loan_uuid}/payment-schedule":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Schedule (projected)"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Projected amortization / payment schedule","tags":["Loans"]}},"/loans/{loan_uuid}/payments":{"post":{"description":"amount_cents is the amount to APPLY to the loan. When the GATEWAY's fee-bearer policy passes processing fees to the customer (configured on the gateway's Config \u0026 fees page per company), the charge is grossed up: the card/bank is debited total_charged_cents (= amount_cents + processing_fee_cents). Disclose the total BEFORE charging: call the fee-quote endpoint, show the borrower total_charged_cents, and pass it as confirmed_total_cents — a quote that moved since confirmation is then refused with 409 fee_quote_changed (nothing charged) carrying the fresh split. Under the merchant fee bearer, processing_fee_cents is 0 and total_charged_cents equals amount_cents.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Client-generated key; a retry with the same key replays the first response","in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"allocation":{"description":"Omit for the normal allocation. principal_only applies the whole amount to principal when the loan's product allows it (422 principal_only_not_allowed / principal_only_not_current / principal_only_exceeds_principal otherwise; refused before anything is charged). Not a scheduled payment: the next due stays due.","enum":["principal_only"],"type":"string"},"amount_cents":{"description":"Amount in cents to apply to the loan (positive)","type":"integer"},"confirmed_total_cents":{"description":"Optional but recommended: the total_charged_cents the borrower confirmed (from the fee-quote endpoint). If the fresh quote's total differs, the request fails 409 with the new split and nothing is charged.","type":"integer"},"payment_method_uuid":{"type":"string"}},"required":["amount_cents","payment_method_uuid"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"description":"Amount applied to the loan (always the requested amount)","type":"integer"},"confirmation_number":{"type":"string"},"loan":{"$ref":"#/components/schemas/Loan"},"payment_method":{"type":"string"},"previous_balance_cents":{"type":"integer"},"processing_fee_cents":{"description":"Processing fee passed to the borrower and included in the charge; 0 under the merchant fee bearer","type":"integer"},"remaining_balance_cents":{"type":"integer"},"status":{"type":"string"},"total_charged_cents":{"description":"Total debited from the card/bank (what the statement shows) = amount_cents + processing_fee_cents","type":"integer"}},"type":"object"}}},"description":"Payment applied"},"402":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Payment declined"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Problem"},{"$ref":"#/components/schemas/FeeQuoteChangedProblem"}]}}},"description":"Loan paid off (generic Problem), or fee_quote_changed: the processing fee moved since confirmed_total_cents was confirmed — nothing charged; the body carries the fresh amount/fee/total split and its fee_bearer (same field names as the fee-quote endpoint)"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Payment method not chargeable"},"502":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Processing-fee quote failed — nothing was charged"}},"security":[{"bearerAuth":[]}],"summary":"Make a payment","tags":["Payments"]}},"/loans/{loan_uuid}/payments/fee-quote":{"post":{"description":"Pre-charge disclosure: returns the borrower-pays processing-fee split for charging amount_cents against a stored payment method — amount applied / processing fee / TOTAL the card or bank will be debited. Nothing is charged. Show the borrower total_charged_cents, then pass it back as confirmed_total_cents on the payment request so a moved quote is refused (409) instead of debiting an unconfirmed total. Whether fees are passed through is the GATEWAY's fee-bearer policy (configured on the gateway's Config \u0026 fees page per company): fee_bearer \"merchant\" means processing_fee_cents is 0 and total equals amount.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"description":"Amount in cents to apply to the loan (positive)","type":"integer"},"payment_method_uuid":{"type":"string"}},"required":["amount_cents","payment_method_uuid"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"description":"Amount that would be applied to the loan (always the requested amount)","type":"integer"},"fee_bearer":{"description":"Gateway fee policy: \"customer\" grosses the fee into the charge; \"merchant\" absorbs it company-side (fee 0 here); empty for methods that never touch the gateway","enum":["customer","merchant",""],"type":"string"},"processing_fee_cents":{"description":"Processing fee that would be included in the charge; 0 under the merchant fee bearer","type":"integer"},"total_charged_cents":{"description":"Total the card/bank would be debited = amount_cents + processing_fee_cents","type":"integer"}},"type":"object"}}},"description":"Fee disclosure"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan or payment method not found"},"502":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Fee quote unavailable — nothing charged"}},"security":[{"bearerAuth":[]}],"summary":"Quote the processing-fee split before charging (read-only)","tags":["Payments"]}},"/loans/{loan_uuid}/payoff":{"get":{"description":"principal + accrued interest + fees (+ CAB fee) net of any unearned-charge rebate the payoff posts, with the good-through date the figure holds for. Precomputed products report the frozen charge, the share earned through the date and the rebate of the remainder; projected_* report charges the engine will post before the date if nothing is paid first.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Payoff date YYYY-MM-DD (default today)","in":"query","name":"date","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoffQuote"}}},"description":"Payoff quote"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Lease account — no loan payoff / quote must be prepared by servicing"}},"security":[{"bearerAuth":[]}],"summary":"Authoritative pay-in-full quote (as-of date, per-diem, good-through)","tags":["Loans"]},"post":{"description":"Issues a payoff quote for today and, when confirmed_payoff_cents equals its total_payoff_cents, charges the stored method for that total (processing-fee gross-up, pre-charge screening, Idempotency-Key) and posts it through the counter payoff flow: the interest the quote charges through today is posted, the quoted total is applied, and the posting is accepted only when the loan is at $0 with no held credit or refund — otherwise nothing posts. Before the card is touched: a moved figure answers 409 payoff_changed with the fresh quote; a credit balance on the account answers 409 held_credit; a product whose interest cannot be posted before the payoff answers 409 payoff_unavailable. Not allowed on an impersonated session.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Client-generated key; reuse the same value on retries so a payoff is never charged twice.","in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"confirmed_payoff_cents":{"description":"total_payoff_cents from the quote the borrower confirmed","type":"integer"},"confirmed_total_cents":{"description":"Optional grossed total (payoff + processing fee) the borrower confirmed; a moved fee refuses with 409 fee_quote_changed","type":"integer"},"payment_method_uuid":{"type":"string"}},"required":["payment_method_uuid","confirmed_payoff_cents"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Payment applied (same shape as POST /loans/{loan_uuid}/payments)"},"402":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Card declined"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Impersonated session"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"payoff_changed (fresh quote in `quote`), held_credit, payoff_unavailable, fee_quote_changed, loan_paid_off, lease_no_payoff; payoff_posting_failed when the posting refused after the charge (nothing posted; charge refunded)"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Method not chargeable / review required"}},"security":[{"bearerAuth":[]}],"summary":"Pay the loan off in full today","tags":["Loans"]}},"/loans/{loan_uuid}/product":{"get":{"description":"family picks the block that applies: single_pay (maturity, payoff, renewal/rollover standing with the reason when unavailable, extended-payment-plan standing and schedule), title (vehicle with VIN masked to the last 4, lien status, lien-release status after payoff, the open repossession case with cure / redemption amounts and deadlines), pawn (ticket, maturity, grace end, forfeiture date and position, renewal charge and redemption amount, renewal statements), line_of_credit (available credit, minimum due vs statement balance, draw gate with its reason, allowed rails, draw history) and lease (schedule, payments made vs term, percent owned, early-purchase quote). payoff_cents is today's payoff: the redemption amount on a pawn, the early-purchase total on a lease. A block the server could not read carries unavailable=true.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"family":{"enum":["installment","single_pay","title","pawn","line_of_credit","lease"],"type":"string"},"family_label":{"type":"string"},"lease":{"description":"status, cycle, payment_cents, term_payments, payments_made, remaining_payments, progress_pct, cash_price_cents, total_of_payments_cents, items, schedule[{number, due_date, total_cents, cumulative_cents, billed, next}], epo{available, reason, total_cents, buyout_base_cents, tax_cents, same_as_cash_deadline, pending, pending_total_cents, can_void, can_exercise}","type":"object"},"line_of_credit":{"description":"credit_limit_cents, available_credit_cents, minimum_due_cents, statement_balance_cents, statement_due_date, past_due_cents, draw_allowed, draw_block_reason, draw_blocked_past_due, rails[{rail, label}], draws[{date, amount_cents, method}], disbursements","type":"object"},"loan_uuid":{"type":"string"},"pawn":{"description":"ticket_number, status, forfeiture_status (active|in_grace|grace_closed|forfeited|redeemed), pledge_date, maturity_date, grace_end_date, forfeiture_date, renewal_charge_cents, redemption_cents, can_renew, renew_refusal, can_redeem, redeem_refusal, renewals_used, max_renewals, items, renewal_statements","type":"object"},"payoff_available":{"type":"boolean"},"payoff_cents":{"description":"Payoff today (redemption on a pawn, early-purchase total on a lease)","type":"integer"},"payoff_good_through":{"format":"date-time","type":"string"},"single_pay":{"description":"maturity_date, days_to_maturity, principal_cents, finance_charge_cents, total_due_cents, payoff_cents, rollover{eligible, reason, fee_cents, min_buydown_cents, remaining_rollovers, can_request_online, online_refusal}, epp{offered, eligible, mandatory_offer, reason, installments, term_days, fee_cents, election, schedule, can_elect_online}, renewal_statements","type":"object"},"title":{"description":"vehicle{year, make, model, vin_masked, plate}, lien{status, label, perfected_date, released_date, custody}, paid_off, lien_release_status (released|requested|pending|not_applicable), repossession{has_open_case, status, label, cure_amount_cents, redemption_total_cents, cure_notice_date, redemption_deadline_date, sale_scheduled_date, notices}, documents","type":"object"}},"type":"object"}}},"description":"Product summary"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Product details not available"}},"security":[{"bearerAuth":[]}],"summary":"Product-family figures for the loan (single-pay, title, pawn, line of credit, lease)","tags":["Loans"]}},"/loans/{loan_uuid}/repayment-plan":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Open offer / plan, installments, history, can_accept"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Post-default repayment plan offer / plan on the loan","tags":["Loans"]}},"/loans/{loan_uuid}/repayment-plan/decline":{"post":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Offer declined"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"repayment_plan_no_offer"}},"security":[{"bearerAuth":[]}],"summary":"Decline the open repayment-plan offer","tags":["Loans"]}},"/loans/{loan_uuid}/repayment-plan/elect":{"post":{"description":"Converts the balance into equal installments over at least the plan term with no additional interest or fees. 409 when no offer is open or it has expired.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"auto_draft":{"type":"boolean"},"payment_method_uuid":{"type":"string"}},"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Plan active"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"repayment_plan_no_offer | repayment_plan_offer_expired"}},"security":[{"bearerAuth":[]}],"summary":"Accept the open repayment-plan offer","tags":["Loans"]}},"/loans/{loan_uuid}/statements":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Page size","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Offset","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/StatementSummary"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"type":"object"}}},"description":"Statements page"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Loan statements","tags":["Loans"]}},"/loans/{loan_uuid}/transactions":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"YYYY-MM-DD start (inclusive)","in":"query","name":"from","required":false,"schema":{"type":"string"}},{"description":"YYYY-MM-DD end (inclusive)","in":"query","name":"to","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"items":{"$ref":"#/components/schemas/Transaction"},"type":"array"}},"type":"object"}}},"description":"Transactions"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found"}},"security":[{"bearerAuth":[]}],"summary":"Loan transactions","tags":["Loans"]}},"/loans/{loan_uuid}/transactions/{txn_uuid}":{"get":{"parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Transaction UUID","in":"path","name":"txn_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}},"description":"Transaction"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Single transaction","tags":["Loans"]}},"/loans/{loan_uuid}/transactions/{txn_uuid}/receipt":{"get":{"description":"Every receipt surface renders one shared view: the store block (point-of-receipt store, else the loan's home store, else the company default — name, store number, address, phone, legal entity, licence), the loan block (loan number, product, account holder, payment date in ET, tender incl. MoneyGram / Western Union reference), how the payment was applied by bucket, the balance after the payment (principal / interest / fees / total / account credit, paid-in-full flag) and the next obligation (next due date and amount, or maturity and payoff at maturity for single-pay). A payment receipted at a Store Operations register returns JSON with issued_by=store_operations and the register's receipt number (the counter receipt is the original; the LMS never mints a second number). LMS receipts carry issued_by=lms and the stable LMS receipt number.","parameters":[{"description":"Loan UUID","in":"path","name":"loan_uuid","required":true,"schema":{"type":"string"}},{"description":"Transaction UUID","in":"path","name":"txn_uuid","required":true,"schema":{"type":"string"}},{"description":"pdf (default), html, or json (the ReceiptView: issued_by, receipt_number, store{...}, counter_line, loan_number, product_name, allocation[], *_after_cents, paid_in_full, next_due_date, next_amount_due_cents, maturity_date, payoff_at_maturity_cents)","in":"query","name":"format","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Receipt PDF/HTML stream, or JSON {receipt: lms|external, issued_by, receipt_number, transaction_uuid, view}"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Transaction not found"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Transaction type has no receipt"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"PDF rendering unavailable — retry with ?format=html; or receipt_view_unavailable for ?format=json — retry with html/pdf"}},"security":[{"bearerAuth":[]}],"summary":"Per-transaction payment/refund receipt (PDF, ?format=html, or ?format=json)","tags":["Documents"]}},"/messages":{"get":{"parameters":[{"description":"","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Threads page"}},"security":[{"bearerAuth":[]}],"summary":"Secure-inbox threads","tags":["Servicing"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"type":"string"},"category":{"enum":["general","payments","loan","account","documents","technical"],"type":"string"},"subject":{"type":"string"}},"required":["subject","body"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Sent"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"}},"security":[{"bearerAuth":[]}],"summary":"Start a new message thread","tags":["Servicing"]}},"/messages/unread-count":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"unread":{"type":"integer"}},"type":"object"}}},"description":"Unread count"}},"security":[{"bearerAuth":[]}],"summary":"Unread (staff) message count","tags":["Servicing"]}},"/messages/{thread_uuid}":{"get":{"parameters":[{"description":"Thread UUID","in":"path","name":"thread_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Thread"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Thread not found"}},"security":[{"bearerAuth":[]}],"summary":"Get a thread's messages (marks staff messages read)","tags":["Servicing"]}},"/messages/{thread_uuid}/reply":{"post":{"parameters":[{"description":"Thread UUID","in":"path","name":"thread_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"type":"string"}},"required":["body"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Sent"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Thread not found"}},"security":[{"bearerAuth":[]}],"summary":"Reply to a thread","tags":["Servicing"]}},"/notifications":{"get":{"parameters":[{"description":"Only unread","in":"query","name":"unread","required":false,"schema":{"type":"boolean"}},{"description":"","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/Notification"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"type":"object"}}},"description":"Notifications page"}},"security":[{"bearerAuth":[]}],"summary":"List notifications","tags":["Notifications"]}},"/notifications/read-all":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"All read"}},"security":[{"bearerAuth":[]}],"summary":"Mark all read","tags":["Notifications"]}},"/notifications/unread-count":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"unread":{"type":"integer"}},"type":"object"}}},"description":"Unread count"}},"security":[{"bearerAuth":[]}],"summary":"Unread count","tags":["Notifications"]}},"/notifications/{notification_uuid}/read":{"post":{"parameters":[{"description":"Notification UUID","in":"path","name":"notification_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Read"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Mark one read","tags":["Notifications"]}},"/openapi.json":{"get":{"responses":{"200":{"description":"OpenAPI 3.0 document"}},"security":[],"summary":"This OpenAPI document","tags":["Discovery"]}},"/payment-methods":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"items":{"$ref":"#/components/schemas/PaymentMethod"},"type":"array"}},"type":"object"}}},"description":"Payment methods"}},"security":[{"bearerAuth":[]}],"summary":"List payment methods","tags":["Payments"]}},"/payment-methods/hosted-add":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"type":{"enum":["card"],"type":"string"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"checkout_form_id":{"type":"string"},"hosted_url":{"type":"string"}},"type":"object"}}},"description":"Hosted URL"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Processor not configured"}},"security":[{"bearerAuth":[]}],"summary":"Mint a hosted card-vault URL","tags":["Payments"]}},"/payment-methods/sync":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"added":{"type":"integer"},"eligibility_checked_at":{"description":"RFC3339 instant of the latest push-to-card eligibility check across the borrower's cards; empty when none was checked","type":"string"}},"type":"object"}}},"description":"Added count plus the latest eligibility check instant (the verify flow's completion signal)"}},"security":[{"bearerAuth":[]}],"summary":"Sync vault tokens","tags":["Payments"]}},"/payment-methods/{method_uuid}":{"delete":{"parameters":[{"description":"Payment method UUID","in":"path","name":"method_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Deleted"}},"security":[{"bearerAuth":[]}],"summary":"Remove a payment method","tags":["Payments"]}},"/payment-methods/{method_uuid}/default":{"post":{"parameters":[{"description":"Payment method UUID","in":"path","name":"method_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Default set"}},"security":[{"bearerAuth":[]}],"summary":"Set default payment method","tags":["Payments"]}},"/payment-methods/{method_uuid}/verify":{"post":{"description":"Mints a hosted page that re-runs the processor's funding-eligibility check on the saved card. Embed it like hosted-add, then poll /payment-methods/sync until eligibility_checked_at changes (card verified in place) or added \u003e 0 (the processor issued a replacement card, swapped in with the same default flag). Only cards with push_eligible = true can receive advances; null means never checked.","parameters":[{"in":"path","name":"method_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"eligibility_checked_at":{"type":"string"},"hosted_url":{"type":"string"},"session_id":{"type":"string"}},"type":"object"}}},"description":"Hosted verify URL"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Card cannot be verified (bank account, manual entry, inactive)"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Processor not configured"}},"security":[{"bearerAuth":[]}],"summary":"Verify a saved card for advances (push-to-card eligibility)","tags":["Payments"]}},"/phones":{"get":{"parameters":[{"description":"Include retired phones","in":"query","name":"history","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Phones"}},"security":[{"bearerAuth":[]}],"summary":"Borrower phones","tags":["Profile"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"label":{"type":"string"},"number":{"type":"string"},"phone_type":{"type":"string"}},"required":["number"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Created"}},"security":[{"bearerAuth":[]}],"summary":"Add a phone","tags":["Profile"]}},"/phones/{phone_uuid}":{"delete":{"parameters":[{"description":"Phone UUID","in":"path","name":"phone_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Retired"}},"security":[{"bearerAuth":[]}],"summary":"Retire a phone","tags":["Profile"]},"put":{"parameters":[{"description":"Phone UUID","in":"path","name":"phone_uuid","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Updated"}},"security":[{"bearerAuth":[]}],"summary":"Update a phone","tags":["Profile"]}},"/products":{"get":{"parameters":[{"description":"Filter by name","in":"query","name":"q","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"type":"array"}},"type":"object"}}},"description":"Products"}},"security":[{"companyHeader":[]}],"summary":"Company loan products (what a borrower can apply for)","tags":["Discovery"]}},"/profile":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Profile"}}},"description":"Profile"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"Borrower profile","tags":["Profile"]}},"/reference":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Reference enums"}},"security":[],"summary":"Enumerations (statuses, types)","tags":["Discovery"]}},"/rewards":{"get":{"description":"The company-branded program (names, conversion rate, earning rules) plus your account: balance in points and its dollar value at the CURRENT rate, lifetime tallies, and your shareable referral code. Returns {\"enabled\": false} when the company runs no rewards program — hide the whole surface.","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RewardsOverview"}}},"description":"Rewards overview"},"401":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Unauthorized"}},"security":[{"bearerAuth":[]}],"summary":"Rewards program + your points balance","tags":["Rewards"]}},"/rewards/ledger":{"get":{"parameters":[{"description":"Page size (max 200)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Offset","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/RewardLedgerEntry"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"},"points_name":{"type":"string"},"program_name":{"type":"string"},"total":{"type":"integer"}},"type":"object"}}},"description":"Ledger page"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Rewards not enabled"}},"security":[{"bearerAuth":[]}],"summary":"Points history (paged, newest first)","tags":["Rewards"]}},"/rewards/quote":{"get":{"description":"How many points can apply to this loan RIGHT NOW: the loan-side cap under the program's redeem scope (amount due or total balance), your usable maximum (min of cap and balance), and the conversion rate. The redeem endpoint executes the SAME math — quote first, then redeem.","parameters":[{"description":"Loan UUID","in":"query","name":"loan_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RewardsQuote"}}},"description":"Redemption quote"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"loan_uuid missing"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found, or rewards not enabled"}},"security":[{"bearerAuth":[]}],"summary":"Redemption quote for a loan (read-only)","tags":["Rewards"]}},"/rewards/redeem":{"post":{"description":"Deducts points and applies their converted dollar value against the loan as a NON-CASH credit, atomically — an abort anywhere rolls everything back (points untouched). mode \"exact\" applies precisely `points` or fails; mode \"max\" applies the most the loan's cap and your balance allow at execution. A redemption is not a cash payment: it never earns on-time points and never creates refundable credit. Honors Idempotency-Key (max 128 chars): a retry with the same key replays the original result instead of redeeming twice.","parameters":[{"description":"Client-generated key (max 128 chars); reuse the same value on retries.","in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"loan_uuid":{"type":"string"},"mode":{"description":"exact (default): apply precisely `points` or fail. max: apply the most possible right now.","enum":["exact","max"],"type":"string"},"points":{"description":"Points to redeem (required unless mode is \"max\")","type":"integer"}},"required":["loan_uuid"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RewardsRedemption"}}},"description":"Redemption applied (replayed=true when an Idempotency-Key retry returned the original result)"},"202":{"content":{"application/json":{"schema":{"properties":{"loan_uuid":{"type":"string"},"message":{"type":"string"},"request_uuid":{"type":"string"},"status":{"enum":["pending_approval"],"type":"string"}},"type":"object"}}},"description":"Submitted for review (program redemption_mode=approval): points stay on the account until staff sign off; nothing has been applied yet"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Rewards account frozen, or impersonated session"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan not found, or rewards not enabled"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Idempotency-Key reused for a different redemption; the loan's balance changed mid-redemption (quote_changed — nothing applied; re-quote and retry); or redemption_request_pending — an equivalent request is already awaiting review (nothing new was queued)"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"insufficient_points / nothing_due / exceeds_amount_due / too_few_points / below_minimum_redemption / redemptions_disabled (program redemption_mode=disabled)"}},"security":[{"bearerAuth":[]}],"summary":"Pay with points","tags":["Rewards"]}},"/scheduled-payments":{"get":{"parameters":[{"description":"","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"","in":"query","name":"offset","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/ScheduledPayment"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"type":"object"}}},"description":"Scheduled page"}},"security":[{"bearerAuth":[]}],"summary":"List scheduled payments","tags":["Scheduled"]},"post":{"description":"amount_cents is the amount to APPLY to the loan on the scheduled date. When the GATEWAY's fee-bearer policy passes processing fees to the customer, the charge on that date is grossed up by the then-current processing fee (the card/bank is debited amount + fee, itemized on the borrower's receipt email). Use the fee-quote endpoint to preview today's fee for disclosure when scheduling.","parameters":[{"in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"type":"integer"},"description":{"type":"string"},"loan_uuid":{"type":"string"},"payment_method_uuid":{"type":"string"},"scheduled_date":{"format":"date","type":"string"}},"required":["loan_uuid","payment_method_uuid","amount_cents","scheduled_date"],"type":"object"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledPayment"}}},"description":"Scheduled"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid request"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Loan or method not found"}},"security":[{"bearerAuth":[]}],"summary":"Schedule a future payment","tags":["Scheduled"]}},"/scheduled-payments/{scheduled_uuid}/cancel":{"post":{"parameters":[{"description":"Scheduled payment UUID","in":"path","name":"scheduled_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Canceled"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Cancel a scheduled payment","tags":["Scheduled"]}},"/settings":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Settings"}}},"description":"Settings"}},"security":[{"bearerAuth":[]}],"summary":"Settings: profile, notification preferences, language, 2FA state","tags":["Settings"]}},"/settings/language":{"put":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"preferred_language":{"description":"A code from GET /settings languages","type":"string"}},"required":["preferred_language"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Updated"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Impersonated session"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Unsupported language"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Language preference not available on this deployment"}},"security":[{"bearerAuth":[]}],"summary":"Update the preferred document / communication language","tags":["Settings"]}},"/settings/notifications":{"put":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"notifications":{"$ref":"#/components/schemas/NotificationPreferences"},"status":{"type":"string"}},"type":"object"}}},"description":"Updated"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Impersonated session"}},"security":[{"bearerAuth":[]}],"summary":"Update notification preferences","tags":["Settings"]}},"/settings/password":{"post":{"description":"The current-password check is throttled per borrower and per IP like the login (429 with Retry-After when locked).","requestBody":{"content":{"application/json":{"schema":{"properties":{"current_password":{"type":"string"},"new_password":{"type":"string"}},"required":["current_password","new_password"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Updated"},"403":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Current password incorrect / impersonated session"},"422":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Password policy"},"429":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Too many failed attempts"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Password change not available: SSO-only borrower (no password on file) or the service is not wired"}},"security":[{"bearerAuth":[]}],"summary":"Change password (current password required)","tags":["Settings"]}},"/signature-requests":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"Signature requests"}},"security":[{"bearerAuth":[]}],"summary":"Documents awaiting your signature","tags":["Documents"]}},"/statements/{statement_uuid}":{"get":{"parameters":[{"description":"Statement UUID","in":"path","name":"statement_uuid","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatementDetail"}}},"description":"Statement"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Statement not found"}},"security":[{"bearerAuth":[]}],"summary":"Statement detail (with rendered HTML)","tags":["Loans"]}},"/statements/{statement_uuid}/download":{"get":{"parameters":[{"description":"Statement UUID","in":"path","name":"statement_uuid","required":true,"schema":{"type":"string"}},{"description":"pdf (default) or html","in":"query","name":"format","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Statement PDF/HTML stream"},"404":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Statement not found"},"503":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"PDF rendering unavailable — retry with ?format=html"}},"security":[{"bearerAuth":[]}],"summary":"Download a statement (PDF, or ?format=html)","tags":["Documents"]}},"/stores":{"get":{"parameters":[{"description":"Filter by name / city / store number","in":"query","name":"q","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"type":"array"}},"type":"object"}}},"description":"Stores"}},"security":[{"companyHeader":[]}],"summary":"Company stores / branches (for a store picker)","tags":["Discovery"]}},"/tax-documents":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"items":{"items":{"$ref":"#/components/schemas/TaxDocument"},"type":"array"}},"type":"object"}}},"description":"Available documents"}},"security":[{"bearerAuth":[]}],"summary":"Tax years with a year-end interest summary","tags":["Tax Documents"]}},"/tax-documents/{year}":{"get":{"parameters":[{"description":"Four-digit tax year","in":"path","name":"year","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxSummary"}}},"description":"Year-end summary"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid year"}},"security":[{"bearerAuth":[]}],"summary":"Year-end interest summary figures","tags":["Tax Documents"]}},"/tax-documents/{year}/download":{"get":{"parameters":[{"description":"Four-digit tax year","in":"path","name":"year","required":true,"schema":{"type":"string"}},{"description":"html (default) or pdf","in":"query","name":"format","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/pdf":{"schema":{"format":"binary","type":"string"}},"text/html":{"schema":{"type":"string"}}},"description":"The document"},"400":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"Invalid year"},"409":{"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}},"description":"PDF rendering not available"}},"security":[{"bearerAuth":[]}],"summary":"Printable Tax Interest Summary (HTML, or PDF with format=pdf)","tags":["Tax Documents"]}}},"security":[{"bearerAuth":[]}],"servers":[{"description":"Customer portal API","url":"https://vectralms.com/api/v1/portal"}],"tags":[{"description":"Login, 2FA verify, session lifecycle","name":"Auth"},{"description":"Borrower profile, addresses, phones","name":"Profile"},{"description":"Loans, transactions, statements","name":"Loans"},{"description":"Payment methods and making payments","name":"Payments"},{"description":"Future-dated scheduled payments","name":"Scheduled"},{"description":"Automatic recurring payments","name":"Autopay"},{"description":"Company-branded rewards points: balance, history, redemption quote, pay-with-points. Render the returned program_name/points_name verbatim wherever points appear.","name":"Rewards"},{"description":"Portal notifications","name":"Notifications"},{"description":"Uploaded documents, requests, e-signature","name":"Documents"},{"description":"Loan applications: list, get, withdraw, decision letter","name":"Applications"},{"description":"Disputes, hardship/modification requests, secure messaging","name":"Servicing"},{"description":"Branding, reference data, this spec","name":"Discovery"},{"description":"Year-end interest summaries (substitute 1098)","name":"Tax Documents"},{"description":"Hardship assistance requests (staff-reviewed message threads)","name":"Hardship"},{"description":"Notification preferences, language, password","name":"Settings"}]}