The value of an application
Event: an application’s sections are complete and its value is wanted
right away, to report to the ad platform.
Endpoint: POST /v1/score
Status: live in dev. Replaces POST /score on the EV Worker
(vbb.beeline.team): same body, same answer, plus the fields Stitch adds.
Who sends this. Stitch does not know and does not need to. It sees a key and a payload. Today the likeliest caller is whatever holds the application’s figures at the point its sections are complete — most likely the application’s own backend; a middleware that fronts the application sends exactly the same thing. How that system knows the sections are complete is its business.
Authentication
Section titled “Authentication”Authorization: Bearer <your key>One key per emitting system, named by the owner after whatever actually sends.
A missing or wrong key is 401.
Request
Section titled “Request”| field | required | notes |
|---|---|---|
loan_amount | yes | dollars; the only field whose absence is a 400 |
property_value | strongly recommended | dollars, as the applicant typed it (purchase price for purchases); the round-number signal lives here |
credit_range | recommended | the form’s stated range, either generation ("Above 740", "Between 700 To 719", …) or a number |
fico | optional | the pulled score; when present the FICO model is used |
loan_purpose | recommended | Purchase, Refi - CO, Refi - RT; aliases accepted (cash-out refinance, rate/term) |
product_grouping | recommended | DSCR, Conv, Bank Stmt/Non-QM, Govt/Jumbo/Other; aliases accepted (conventional, bank statement, FHA) |
occupancy | optional | accepted; not used by the shipped models |
Unknown labels do not fail the request: the field falls back to its reference level and a warning is returned.
curl -s -X POST https://stitch-collector-dev.magic-blocks.workers.dev/v1/score \ -H 'content-type: application/json' -H 'authorization: Bearer <your key>' \ -d '{"loan_amount":250000,"property_value":357143,"credit_range":"Above 740","loan_purpose":"Refi - CO","product_grouping":"DSCR"}'Response
Section titled “Response”{ "prediction_id": "3f2c…", "ev": 4310.82, "conversion_value": 4310.82, "p_close": 0.4134, "rev_if_close": 10428.1, "model_used": "credit_range", "model": "app_ev_v4_5field_claimed", "trained_on": "2026-10-21", "train_window": ["2025-10", "2026-08"], "calibration_multiplier": 1, "calibration": { "manual": 1, "auto": 1, "auto_source": "off" }, "inputs_used": { "loan_amount": 250000, "property_value": 357143, "ltv": 0.7, "credit_range_group": "740+", "...": "..." }, "warnings": [], "complete": true, "ev_cents": 431082, "conversion_value_cents": 431082, "rev_if_close_cents": 1042810}Report conversion_value as the value of the application conversion you report to Google.
auto_source is always off: Stitch never recalibrates automatically; the
level correction is set by an admin on the Value model screen and recorded on
every prediction.
What is different from the EV Worker
Section titled “What is different from the EV Worker”- Nothing is logged by this endpoint. The predictions that count are the ones
Stitch writes against loans as their stage events arrive
(loan-stages.md), with their model version, calibration
and inputs; outcomes join by loan, so
prediction_idis returned for compatibility and has nothing to join to. POST /outcome,GET /drift,GET /exportandGET /calibrationhave no equivalent here: outcomes are thefundedstage events, drift is reported by channel on the Value model screen, and the refit reads Stitch’s prediction export (GET /api/export/predictions?since=YYYY-MM-DDon the app, with the export token).
What moves the value afterwards, and what does not
Section titled “What moves the value afterwards, and what does not”A loan is scored once, at the first stage event that finds it at
app_submitted or beyond, from the latest attributes the file has by then.
It is re-scored for one reason: the pulled score (fico or
credit_score) arriving on a later event, which switches to the FICO model —
and that re-score reads the other inputs as the first score read them
(recorded with it as the loan attribute ev_raw_inputs), plus the score; a
key with no score in it (fico: null) is not the score arriving. A later
loan_amount or property_value on the file is an edit to the file, not the
borrower’s entry, so it re-scores nothing and restates nothing; it is recorded
as the loan’s attributes and exported beside the scored inputs as
final_loan_amount, final_property_value and loan_amount_change for the
refit. The value reported to Google is therefore always the one computed from
what the borrower entered, adjusted afterwards only by the re-score, the
realised revenue at funding, or the $1 floor at a dead end — each a
restatement Stitch sends itself (outbound.md).