Recipe catalog / invoice-facets
Label what an invoice states
Which of these does invoice state: vendor identity, an invoice number, a due date, line items, a tax or total breakdown?
You need several independent presence checks on invoice text in one call, to spot missing fields before routing it for approval or entry.
Explore this recipe interactively ยท Source and implementation guide
Use invoice-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 { invoiceFacets } from 'jev-recipes/invoice-facets';
const result = await invoiceFacets({
"invoice": "Northwind Design Studio\n412 Harbor St, Portland OR\n\nINVOICE #2024-0187\nBill to: Acme Robotics, Attn: Accounts Payable\n\n1. Landing page redesign, 24 hrs @ $120/hr ........ $2,880.00\n2. Icon set (32 icons) ................................ $640.00\n\nSubtotal: $3,520.00\nTax (0%): $0.00\nTotal due: $3,520.00\n\nThank you for your business.",
"minConfidence": 0.8
});
console.log(result);
Input contract
| Field | Type | Needed |
|---|---|---|
| invoice | string | Required |
| minConfidence | number | Optional |
Full input and result schemas
{
"input": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"invoice": {
"type": "string"
},
"minConfidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"invoice"
]
},
"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": [
"statesVendor",
"statesInvoiceNumber",
"statesDueDate",
"statesLineItems",
"statesTotals"
]
}
},
"labels": {
"type": "object",
"properties": {
"statesVendor": {
"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
},
"statesInvoiceNumber": {
"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
},
"statesDueDate": {
"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
},
"statesLineItems": {
"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
},
"statesTotals": {
"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": [
"statesVendor",
"statesInvoiceNumber",
"statesDueDate",
"statesLineItems",
"statesTotals"
],
"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 invoice-facets.
{
"model": "demo-fixture",
"usage": {
"input_tokens": 0,
"output_tokens": 0
},
"status": "ready",
"detected": [
"statesVendor",
"statesInvoiceNumber",
"statesLineItems",
"statesTotals"
],
"labels": {
"statesVendor": {
"status": "ready",
"verdict": "present",
"probability": 0.97,
"confidence": 0.97
},
"statesInvoiceNumber": {
"status": "ready",
"verdict": "present",
"probability": 0.95,
"confidence": 0.95
},
"statesDueDate": {
"status": "ready",
"verdict": "absent",
"probability": 0.12,
"confidence": 0.88
},
"statesLineItems": {
"status": "ready",
"verdict": "present",
"probability": 0.93,
"confidence": 0.93
},
"statesTotals": {
"status": "ready",
"verdict": "present",
"probability": 0.96,
"confidence": 0.96
}
}
}
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 invoice text states the item, not whether the stated value is correct, consistent, or matches a purchase order.
- Numbers, dates, and totals are not validated. Parse and check them in code.
- Labels are independent, so an invoice can carry several, all, or none.
Related recipes
- clarify: Use clarify to decide whether a request about an invoice is too ambiguous to act on, rather than what the invoice text itself states.
- field-select: Use field-select to pick which field of a record a value belongs to, rather than to check which fields the invoice text contains at all.