Defensible pricing on lock day
Pinning the ratesheet version means a lock cannot be 'lost' to a later activation. The price you locked is the price the engine reproduces, forever.
End-to-end rate-lock lifecycle: create, extend, cancel, fund. Exception Inbox with SSE push and AI-suggested resolutions. Sell-side pricing with per-investor audit. Per-organization desk configuration with effective-dated inheritance. ShedLock-guarded expiry sweeper that runs safely across replicas.
Overview
Locks pin a specific ratesheet version + investor + rate at lock time. Every state transition (create → extend → cancel → fund) writes a journal entry with the actor, the timestamp, and the prior + next state, all hashed into the platform-wide audit chain. Sell-side pricing runs alongside loan-level pricing so the secondary desk sees the same numbers as the LO. The Exception Inbox surfaces detected anomalies (pricing drift, pullthrough confidence drop, missed fills) with AI-suggested resolutions, streaming via SSE for live triage. Lock-desk policy (cutoff times, max extension days, free-extension grace, fee curves) lives per-organization with effective-dated inheritance.
Lock captures the ratesheet version, the investor, the program, the noteRate, and the computed price. Repricing later uses exactly that pin.
Pricing drift, pullthrough drop, sell-side mismatch — exceptions stream via SSE with an AI-drafted resolution. Resolve, dismiss, embed, or recompute.
Sell-side pricing returns alongside loan-level pricing. The secondary desk and the LO see the same investor, the same trace, the same numbers.
Cutoff time, max extension days, fee curves, free-extension windows, allowed lock periods — all configured per organization with effective-dated inheritance from the platform default.
Every state transition writes a journal entry with the actor, the prior state, the next state, and the reason. Hash-chained into common_audit_log.
ShedLock-guarded job runs on every replica; only one acquires the lock per minute and rolls eligible locks into EXPIRED, emitting locks.expired for downstream.
How it works
Numbered steps from input to output. Each step maps to a specific subsystem you can inspect via OpenTelemetry.
Operator (LO or autopilot) selects a quote and submits a CreateLockRequest. The server re-prices to validate, captures the pin, and writes the lock + initial journal entry transactionally.
ExtendLockRequest applies the org's extension fee curve, validates against the max-extension cap, and writes a journal entry. The lock's expiry timestamp slides forward.
Detectors over pricing, pullthrough, and sell-side compare expected vs. observed; deviations fire to the Exception Inbox with an AI-drafted resolution and the cited source events.
RequestSellSide fires the sell-side ladder against the same input + pin. CompleteSellSide marks the executed investor and writes a SellSidePricingView row.
FundLockRequest transitions the lock to FUNDED; locks.funded fires; the lock becomes immutable except for audit-only annotations.
Every minute, the ShedLock-guarded sweeper queries locks past their expiry, transitions them to EXPIRED, and emits locks.expired. Replicas race; one wins; everyone observes the result.
Hands on
Live cURL sample — copy, paste, ship.
# Create a lock — server pins ratesheet version + computed price
curl -X POST https://api.ratestack.com/v1/locks?actorUserId=$ME \
-H "X-API-Key: $RATESTACK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"loanId": "loan_8a7c4f",
"investorCode": "INV_42",
"noteRate": 6.625,
"lockPeriodDays": 30,
"executionMode": "BEST_EX",
"comment": "Borrower confirmed rate, locking through 2026-06-02"
}'Why this matters
Pinning the ratesheet version means a lock cannot be 'lost' to a later activation. The price you locked is the price the engine reproduces, forever.
The Exception Inbox is a single named surface — SSE push, AI suggestions, audit-chained actions. Triage is a workflow, not a fire drill.
Retail LO, hedge desk, and secondary all operate against the same lock row, the same audit chain, the same sell-side bid history.
Frequently asked
Yes. The lock pins the ratesheet version it was priced against. Rolling back a ratesheet does not affect existing locks; it affects future pricing only.
The desk config carries a grace-window curve (e.g., 'first 7 days extend free'). The extend endpoint applies the curve at request time and journals the fee as $0.00 with the rule that fired.
Pricing drift (Stage-1 vs Stage-2 disagreement), pullthrough confidence drop, sell-side mismatch (sell-side completion doesn't reconcile to the lock), and missed fills (locks expiring with no fund event). See the Exception Inbox feature for the full catalog.
The lock row uses optimistic locking. The second writer gets a 409 Conflict with the current version; the operator retries with the new state visible.
Indefinitely by default. Retention policy is configurable per environment but the recommended posture for compliance is no expiration on lock journals.
How we compare
Specific angles, not generic feature checklists. Each row links to a longer side-by-side; we're transparent about where competitors are the better choice.
Lock-desk policy lives in version-pinned config, not a UI dialog — your audit can replay any policy at any prior moment.
See the side-by-sideSell-side pricing returns alongside loan-level pricing in the same call — the secondary desk and the LO read identical numbers.
See the side-by-sideHash-chained audit on every state change. Tampering is detectable, not just discouraged.
See the side-by-sideComparisons reflect each vendor's public positioning. Where a fact is unverifiable, we mark it "Depends" or "Unknown" instead of guessing.
Related capabilities
Ready to see it on your data?
We'll spin you a sandbox, load your actual ratesheets, and walk you through this capability against your top scenarios.