Scoring

Underwrite a list of properties

Send a list of addresses to get one result per property in submission order.

Batch answers carry the core numbers only, with no comps list. Use Score a property by address or property identifier to get those sales.

Send the list

Each item in properties accepts the single-call inputs. The envelope accepts only that array; options belong inside each item. Duplicate addresses are allowed, and each is charged.

Save your API key, the credential identifying you, in INVESTORLIFT_API_KEY. Your account is the record owning your keys and the money you add. Use a client timeout of at least 30 seconds.

The second address is a placeholder; the captured answer shows its real failure.

curl https://api.investorliftdata.com/v1/predict/batch \ --request POST --max-time 30 \ --header "Authorization: Bearer $INVESTORLIFT_API_KEY" \ --header "Content-Type: application/json" \ --data '{"properties": [{"address": "1026 N Beckley Ave, Dallas, TX 75203"}, {"address": "100 Sample Street, Dallas, TX 75203", "condition": "major_rehab"}]}'

Read each result

Show the full response (100 lines)
JSONFull response
{ "results": [ { "comp_band": { "low": 388634, "high": 942020, "median": 571412 }, "cost_stack": { "loan": 331200, "points": 6624, "interest": 6533, "hold_days": 60, "down_payment": 82800, "closing_costs": 29562, "target_profit": 114282 }, "rehab_budget": 0, "target_margin": 0.2, "valuation_mean": 1016099, "subject_property": { "facts": { "bathrooms": { "value": 2, "source": "county-record" }, "year_built": { "value": 1935, "source": "county-record" }, "square_feet": { "value": 2047, "source": "county-record" }, "property_type": { "value": "Single Family", "source": "county-record" }, "lot_size_square_feet": { "value": 7100, "source": "county-record" } }, "address": { "zip": "75203", "city": "Dallas", "state": "TX", "street": "1026 N Beckley Ave" }, "property_id": "00000000000000000000000000000001", "address_quality": { "code": "zip-confirmed", "statement": "The house number matched exactly one county record, and that record sits in the same ZIP code your address resolved to. Check the address and property facts in this block before relying on these numbers." }, "outside_model_range": { "flagged": false, "reasons": [] } }, "as_is_similar_band": { "basis": "all-comparable-sales", "statement": "Too few comparable sales passed the size, age and recency filter this service applies to state a similar-sales range, so this price-per-square-foot range covers every comparable sale below that carries a usable sale price and square footage. `qualifying_sales` is how many passed the filter and fell short.", "qualifying_sales": 1, "price_per_square_foot": { "low": 190, "high": 460, "median": 279 } }, "rehab_adjusted_arv": 571000, "max_allowable_offer": { "amount": 414000, "clamped": false }, "valuation_quantiles": { "0.02": 191787, "0.10": 345336, "0.20": 476815, "0.30": 598093, "0.40": 733771, "0.50": 878872, "0.60": 1110818, "0.70": 1417051, "0.80": 1988162, "0.90": 3615373, "0.98": 15505619 }, "effective_sample_size": 51.04950714111328, "model_estimate_available": true, "pricing_model_arv_estimate": 1417000 }, { "type": "https://docs.investorliftdata.com/errors/unscorable-address", "title": "Address cannot be scored", "detail": "The submitted address could not be scored. The Credit for this call has been returned to the Account as a Refund.", "status": 422, "trace_id": "00000000-0000-4000-8000-000000000000" } ] }

results preserves submission order, with none omitted or reordered. Each position answers the input at that position. Only error entries carry results[].status and results[].type; branch on the type to choose a fix.

An underwritten entry uses the single-call member names and meanings, including max_allowable_offer. When max_allowable_offer.clamped is true, no price clears the target margin: do not show the amount as an offer. Conditional members can still be absent.

Read Maximum allowable offer before using the ceiling in your workflow.

effective_sample_size measures evidence supporting the model, and is absent when that estimate is withheld. as_is_similar_band.qualifying_sales counts sales passing its filter, including when the range falls back to all comparable sales. These are different counts.

Keep subject_property.property_id for property history; use an address when underwriting again. Read the call's Trace ID, its call identifier, from the trace-id response header when contacting support. Every entry shares the call's identifier; the captured error also includes results[].trace_id.

Understand charges and refunds

Each submitted property is charged the batch call's price from your balance; see Per-call prices. A covered property failure returns that property's charge to your balance as a refund.

The whole batch is charged before any property is underwritten. If your balance, the money available on your account, cannot cover it, the entire batch is rejected without charging or splitting it. After adding funds, you can retry unchanged; batches are never partially accepted.

The reference publishes the batch limit as maxItems. Exceeding it returns 413 before charging, with limit and submitted counts.

Covered failures use the single call's error body and refund reasons.

A covered failure leaves an error entry, refunds its share and still attempts later properties. The response remains 200. Covered reasons are an ambiguous address, an address outside coverage, an unscorable address, a service failure or a service timeout; see errors.

An uncovered refusal stops processing: later properties are not attempted, no results array returns, and the request answers 503 spend-indeterminate. Every recorded charge is returned to your balance, including already underwritten properties whose answers are not returned. The request is retryable; you pay only for properties that produced an answer.

Retry safely

Send Idempotency-Key and follow Retry safely. Using one key for the same body on the single and batch endpoints is a conflict, never a replay.

Next steps

Last modified on