{"openapi":"3.1.0","info":{"title":"POST /api/v1/credit/loans/{loan_id}/adjustments","version":"1.0.0","description":"Adjust a loan"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/credit/loans/{loan_id}/adjustments":{"post":{"tags":["credit"],"summary":"Adjust a loan","description":"Waive part of a loan's unpaid fee (`waive_fee`) or accrued interest (`waive_interest`), or credit its unpaid principal as goodwill (`goodwill_credit`). The amount may not exceed what is outstanding in that bucket. Posts an `adjustment` ledger entry with the reason as its memo and, when the program posts to the GL, a journal entry to Fee Waivers, Interest Waivers or Goodwill Credits. A loan brought to zero is paid on `effective_on` and emits `credit.loan.paid`. Operator action: API tokens receive 403.","operationId":"create_loan_adjustment","parameters":[{"name":"loan_id","in":"path","required":true,"schema":{"type":"string","title":"Loan Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditLoanAdjustmentRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_CreditLoanAdjustmentResult_"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: due_date: Input should be a valid date","errors":{"due_date":"Input should be a valid date"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Resource does not exist","content":{"application/json":{"example":{"error":"not_found","message":"Resource not found","code":"NOT_FOUND_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"}}}}},"x-fastapi-operation-id":"create_loan_adjustment_api_v1_credit_loans__loan_id__adjustments_post"}}},"components":{"schemas":{"CreditLoanAdjustmentRequest":{"properties":{"type":{"type":"string","enum":["waive_fee","waive_interest","goodwill_credit"],"title":"Type","description":"waive_fee reduces the unpaid disbursement fee, waive_interest the unpaid accrued interest, goodwill_credit the unpaid principal."},"amount_cents":{"type":"integer","exclusiveMinimum":0.0,"title":"Amount Cents","description":"At most what is outstanding in that bucket; more is refused."},"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason","description":"Why. Recorded on the adjustment and as the ledger memo."},"effective_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Effective On","description":"The date the reduction counts from. Defaults to today; not before the loan was originated, and not in the future."}},"additionalProperties":false,"type":"object","required":["type","amount_cents","reason"],"title":"CreditLoanAdjustmentRequest","description":"Waive part of a loan's fee or interest, or credit its principal."},"CreditLoanAdjustmentResponse":{"properties":{"id":{"type":"string","title":"Id"},"loan_id":{"type":"string","title":"Loan Id"},"credit_line_id":{"type":"string","title":"Credit Line Id"},"type":{"type":"string","enum":["waive_fee","waive_interest","goodwill_credit"],"title":"Type"},"amount_cents":{"type":"integer","title":"Amount Cents","description":"What the adjustment took off the loan. Less than requested_amount_cents when a pending debit settled at an earlier date and left less in the bucket."},"requested_amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested Amount Cents","description":"What was asked for, when it differs from amount_cents (see amount_cents). Null when the adjustment took effect in full."},"reason":{"type":"string","title":"Reason"},"effective_on":{"type":"string","format":"date","title":"Effective On"},"actor_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor User Id","description":"The operator who recorded it."},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","loan_id","credit_line_id","type","amount_cents","reason","effective_on"],"title":"CreditLoanAdjustmentResponse","description":"One adjustment recorded against a loan."},"CreditLoanAdjustmentResult":{"properties":{"adjustment":{"$ref":"#/components/schemas/CreditLoanAdjustmentResponse"},"loan":{"$ref":"#/components/schemas/CreditLoanResponse"}},"type":"object","required":["adjustment","loan"],"title":"CreditLoanAdjustmentResult","description":"The adjustment, and the loan as it stands after it."},"CreditLoanResponse":{"properties":{"id":{"type":"string","title":"Id"},"credit_line_id":{"type":"string","title":"Credit Line Id"},"cycle_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cycle Id"},"settlement_id":{"type":"string","title":"Settlement Id"},"external_settlement_id":{"type":"string","title":"External Settlement Id"},"status":{"$ref":"#/components/schemas/LoanStatusEnum"},"transaction_date":{"type":"string","format":"date","title":"Transaction Date","description":"Issuer posting date. The term runs from here (D-12)."},"merchant_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Name"},"card_last_four":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Last Four"},"term_days":{"type":"integer","title":"Term Days"},"due_date":{"type":"string","format":"date","title":"Due Date"},"rate_bps":{"type":"integer","title":"Rate Bps"},"principal_cents":{"type":"integer","title":"Principal Cents","description":"Principal advanced: the settled amount."},"disbursement_fee_cents":{"type":"integer","title":"Disbursement Fee Cents"},"principal_paid_cents":{"type":"integer","title":"Principal Paid Cents"},"fee_paid_cents":{"type":"integer","title":"Fee Paid Cents"},"interest_paid_cents":{"type":"integer","title":"Interest Paid Cents"},"credit_applied_cents":{"type":"integer","title":"Credit Applied Cents"},"interest_accrued_cents":{"type":"integer","title":"Interest Accrued Cents","description":"Accrued to date. Zero until the loan passes its due date (D-07)."},"principal_outstanding_cents":{"type":"integer","title":"Principal Outstanding Cents"},"fee_outstanding_cents":{"type":"integer","title":"Fee Outstanding Cents"},"interest_outstanding_cents":{"type":"integer","title":"Interest Outstanding Cents"},"outstanding_cents":{"type":"integer","title":"Outstanding Cents","description":"Unpaid principal + unpaid fee + accrued interest."},"last_accrued_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Last Accrued On"},"past_due_since":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Past Due Since"},"paid_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Paid On","description":"The date the balance reached zero: the date of the payment, refund or adjustment that cleared it. Null while anything is owed, and null again if that money is returned."},"written_off_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Written Off On"},"written_off_cents":{"type":"integer","title":"Written Off Cents","default":0},"fee_waived_cents":{"type":"integer","title":"Fee Waived Cents","description":"Fee an operator waived. Not a payment.","default":0},"interest_waived_cents":{"type":"integer","title":"Interest Waived Cents","description":"Interest an operator waived. Not a payment.","default":0},"goodwill_credit_cents":{"type":"integer","title":"Goodwill Credit Cents","description":"Principal an operator credited as goodwill. Not a payment.","default":0},"on_hold":{"type":"boolean","title":"On Hold","description":"On hold for a dispute or a void: accruing nothing, out of amount due, days past due and AutoPay until resolved.","default":false},"hold_status":{"type":"string","enum":["none","disputed","voided"],"title":"Hold Status","default":"none"},"hold_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hold Reason"},"hold_started_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hold Started On","description":"First day of the latest hold."},"hold_resolved_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hold Resolved On"},"hold_outcome":{"anyOf":[{"type":"string","enum":["merchant_won","lender_won","voided","released"]},{"type":"null"}],"title":"Hold Outcome"},"principal_reversed_cents":{"type":"integer","title":"Principal Reversed Cents","description":"Principal a dispute resolution took off the loan.","default":0},"fee_reversed_cents":{"type":"integer","title":"Fee Reversed Cents","description":"Fee a dispute resolution took off the loan.","default":0},"interest_reversed_cents":{"type":"integer","title":"Interest Reversed Cents","description":"Interest a dispute resolution took off the loan.","default":0},"pricing_terms":{"anyOf":[{"$ref":"#/components/schemas/LoanPricingTermsResponse"},{"type":"null"}],"description":"The program's pricing rules as they stood when this loan was originated or imported. The loan accrues, caps and is quoted under them for its whole life; a later change to the program's rules reaches only loans originated after it."}},"type":"object","required":["id","credit_line_id","settlement_id","external_settlement_id","status","transaction_date","term_days","due_date","rate_bps","principal_cents","disbursement_fee_cents","principal_paid_cents","fee_paid_cents","interest_paid_cents","credit_applied_cents","interest_accrued_cents","principal_outstanding_cents","fee_outstanding_cents","interest_outstanding_cents","outstanding_cents"],"title":"CreditLoanResponse","description":"One row of the Transactions tab: one card transaction, one loan.\n\nEvery figure is served, never derived. ``status`` is authoritative —\na client must not compute it from dates or balances (§10.5)."},"LoanPricingTermsResponse":{"properties":{"terms_version":{"type":"integer","title":"Terms Version","description":"Layout of this record. `1` today."},"source":{"type":"string","enum":["origination","import","backfill"],"title":"Source","description":"How the loan got its terms: `origination` (copied when the card transaction posted), `import` (copied when the loan was imported from a previous system), or `backfill` (a loan that existed before loans carried their terms, given its program's rules on that day)."},"captured_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Captured At","description":"When the terms were copied onto the loan (UTC)."},"lending_model":{"type":"string","enum":["per_transaction","cycle_draw"],"title":"Lending Model","description":"The program's lending model when the loan was written."},"interest_accrual_start":{"type":"string","enum":["due_date","origination"],"title":"Interest Accrual Start","description":"When daily interest starts: the day after the due date (`due_date`) or the day after the transaction posted (`origination`)."},"late_terms":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Late Terms","description":"The program's late rule as it stood: its `grace_days`, `day_count`, `cap_cents` and `cap_pct_of_principal_bps` shape this loan's daily accrual. Null means the FRD defaults: no grace, actual/365, no cap."},"early_payoff_terms":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Early Payoff Terms","description":"The program's early-payoff rule as it stood. A per-transaction loan has nothing to rebate (D-13); it is kept for the record."},"interest_cap_pct_of_principal_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Interest Cap Pct Of Principal Bps","description":"The program's ceiling on this loan's total interest, as a share of its principal. Null means uncapped (unless the late rule caps it)."}},"type":"object","required":["terms_version","source","lending_model","interest_accrual_start"],"title":"LoanPricingTermsResponse","description":"The program's pricing rules as they stood when this loan joined the books.\n\nThe loan accrues, caps and is quoted under these for its whole life; a\nlater change to the program reaches only loans originated after it."},"LoanStatusEnum":{"type":"string","enum":["active","past_due","paid","written_off"],"title":"LoanStatusEnum","description":"Per-transaction loan state (FRD v2 §10.5 status vocabulary).\n\nThe API status is authoritative; a client must not compute it from\ndates or balances."},"SuccessEnvelope_CreditLoanAdjustmentResult_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/CreditLoanAdjustmentResult"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[CreditLoanAdjustmentResult]"},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}