Extract line items and totals from receipt text.
What you will build
Extract a list of items and a nullable total from receipt text. Create a Canary project first. You need an OpenAI API key to run the model call; the TypeScript option also needs Node.js.
1. Model the result
Add these types to baml_src/main.baml. The example uses floating-point prices for extraction; validate and convert them to your application’s money representation before financial calculations.
extract-receipt.bamlclass ReceiptItem {
name: string,
quantity: int,
price: float,
}
class Receipt {
items: ReceiptItem[],
total: float?,
}class ReceiptItem {
name: string,
quantity: int,
price: float,
}
class Receipt {
items: ReceiptItem[],
total: float?,
}2. Add the function
Add this function below the types. It configures an OpenAI client, puts instructions and the output format in the system message, and puts receipt text in the user message.
extract-receipt.bamlfunction extract_receipt(text: string) -> Receipt {
client: openai.ResponsesClient.new(model = "gpt-4.1-mini", api_key = env.OPENAI_API_KEY)
prompt: `
${role("system")}
Extract the items and total from the receipt. Use null if the total is missing.
${ctx.output_format()}
${role("user")}
${text}
`
}function extract_receipt(text: string) -> Receipt {
client: openai.ResponsesClient.new(model = "gpt-4.1-mini", api_key = env.OPENAI_API_KEY)
prompt: `
${role("system")}
Extract the items and total from the receipt. Use null if the total is missing.
${ctx.output_format()}
${role("user")}
${text}
`
}ctx.output_format inserts instructions based on the return type. You don't need to repeat the schema in the prompt.
3. Call the client
Set the API key and try the function from the project root:
To call it from Node.js, generate the TypeScript SDK, then use the async export from server-side application code:
4. Add tests and handle missing data
- Add representative tests for clean, noisy, and incomplete receipts.
- Decide whether a missing total is acceptable before making it optional.
- Keep credentials and model calls in server-only modules.
- Regenerate the client whenever the result model changes.
Review the TypeScript bridge for host-language details, or open the function reference for the syntax.