Recipe catalog / offer-terms-facets
Label what a property offer states
Which of these does offer state: a price, financing, contingencies, a closing or move-in date, an earnest money or security deposit?
You need several independent presence checks on a purchase or lease offer in one call, to spot missing terms before it is countersigned, countered, or entered into a transaction system.
Explore this recipe interactively ยท Source and implementation guide
Use offer-terms-facets in TypeScript
Install with npm install jev-recipes. Requires Node.js 22.9 or newer and ES modules. Set TYPESAFE_API_KEY in your server environment for live calls, which send input to TypeSafe and use API quota. See the installation guide.
import { offerTermsFacets } from 'jev-recipes/offer-terms-facets';
const result = await offerTermsFacets({
"offer": "Offer to purchase 118 Linden Court\n\nBuyers: Marcus and Dana Reyes\nPurchase price: $412,000\nFinancing: conventional 30-year loan, 20% down; pre-approval letter from Summit Federal attached.\nContingencies: home inspection within 10 days of acceptance; financing contingency through closing.\nClosing: on or before November 15, 2026, with possession at closing.\nInclusions: kitchen appliances and washer/dryer.\n\nThis offer expires at 6:00 PM on September 26, 2026.",
"minConfidence": 0.8
});
console.log(result);
Input contract
| Field | Type | Needed |
|---|---|---|
| offer | string | Required |
| minConfidence | number | Optional |
Full input and result schemas
{
"input": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"offer": {
"type": "string"
},
"minConfidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"offer"
]
},
"result": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"model": {
"type": "string"
},
"usage": {
"type": "object",
"properties": {
"input_tokens": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"output_tokens": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"input_tokens",
"output_tokens"
],
"additionalProperties": false
},
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"detected": {
"type": "array",
"items": {
"type": "string",
"enum": [
"statesPrice",
"statesFinancing",
"statesContingencies",
"statesClosingDate",
"statesDeposit"
]
}
},
"labels": {
"type": "object",
"properties": {
"statesPrice": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesFinancing": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesContingencies": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesClosingDate": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
},
"statesDeposit": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"verdict": {
"type": "string",
"enum": [
"present",
"absent"
]
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"status",
"verdict",
"probability",
"confidence"
],
"additionalProperties": false
}
},
"required": [
"statesPrice",
"statesFinancing",
"statesContingencies",
"statesClosingDate",
"statesDeposit"
],
"additionalProperties": false
}
},
"required": [
"model",
"usage",
"status",
"detected",
"labels"
],
"additionalProperties": false
}
}Saved example result
This hand-authored response demonstrates the contract. It is not a model accuracy measurement. Run it without an API key: npx jev-recipes demo offer-terms-facets.
{
"model": "demo-fixture",
"usage": {
"input_tokens": 0,
"output_tokens": 0
},
"status": "ready",
"detected": [
"statesPrice",
"statesFinancing",
"statesContingencies",
"statesClosingDate"
],
"labels": {
"statesPrice": {
"status": "ready",
"verdict": "present",
"probability": 0.98,
"confidence": 0.98
},
"statesFinancing": {
"status": "ready",
"verdict": "present",
"probability": 0.95,
"confidence": 0.95
},
"statesContingencies": {
"status": "ready",
"verdict": "present",
"probability": 0.94,
"confidence": 0.94
},
"statesClosingDate": {
"status": "ready",
"verdict": "present",
"probability": 0.93,
"confidence": 0.93
},
"statesDeposit": {
"status": "ready",
"verdict": "absent",
"probability": 0.06,
"confidence": 0.94
}
}
}
Evaluation evidence
No verified live accuracy measurement is available. Evaluate representative cases before using this decision in your workflow.
Use the evaluation guide to measure this decision on your own labeled cases.
Limitations
- Each label reports whether the offer text states the term, not whether the stated value is reasonable, complete, or acceptable.
- Amounts, percentages, and dates are not validated or compared to a listing. Parse and check them in code.
- Labels are independent, so an offer can carry several, all, or none.
Related recipes
- clarify: Use clarify to decide whether a buyer's or tenant's request is too ambiguous to act on, rather than which terms a written offer states.
- invoice-facets: Use invoice-facets for the same presence-check pattern over invoice text instead of offer terms.