ReceiptScanner is a small Laravel package for extracting structured receipt data from images and PDFs using upstream AI providers.
It is a wrapper around multimodal LLM APIs. It does not host its own OCR service, database, queue, UI, or REST API.
- Laravel facade entry point:
Jake142\ReceiptScanner\Facades\ReceiptScanner - Public methods:
ReceiptScanner::scanImages(array $images): arrayReceiptScanner::scanPdf(mixed $pdf): array
- Supports multi-image receipt analysis in a single upstream request
- Supports PDF receipt analysis from one input file
- Provider selection via config/env
- Default provider models:
- OpenAI:
gpt-5.4-nano - Azure OpenAI:
gpt-5.4-nano - Gemini:
gemini-2.5-pro - Anthropic:
claude-sonnet-4-20250514
- OpenAI:
- Configurable output fields to reduce prompt size and response size
- Safe logging controls
- PHP
^8.3 - Laravel
illuminate/support^11.0|^12.0|^13.0 - Laravel
illuminate/http^11.0|^12.0|^13.0 - For development and testing:
orchestra/testbench^9.0|^10.0|^11.0
composer require jake142/receiptscannerPublish the config file:
php artisan vendor:publish --tag=receiptscanner-configReceiptScanner is configured through config/receipt-scanner.php and environment variables.
RECEIPT_SCANNER_PROVIDER=openai
RECEIPT_SCANNER_TIMEOUT=60
RECEIPT_SCANNER_MAX_RETRIES=2
RECEIPT_SCANNER_PROMPT_LANGUAGE=en
OPENAI_API_KEY=
OPENAI_MODEL=gpt-5.4-nano
AZURE_OPENAI_API_KEY=
AZURE_OPENAI_ENDPOINT=
AZURE_OPENAI_DEPLOYMENT=gpt-5.4-nano
AZURE_OPENAI_MODEL=gpt-5.4-nano
GEMINI_API_KEY=
GEMINI_MODEL=gemini-2.5-pro
ANTHROPIC_API_KEY=
ANTHROPIC_MODEL=claude-sonnet-4-20250514The package config exposes these keys:
default_providerproviders.openai.api_keyproviders.openai.modelproviders.azure_openai.api_keyproviders.azure_openai.endpointproviders.azure_openai.deploymentproviders.azure_openai.modelproviders.gemini.api_keyproviders.gemini.modelproviders.anthropic.api_keyproviders.anthropic.modeltimeoutmax_retriesenabled_fieldsprompt_language
By default, all fields are enabled:
merchanttotal_amountcurrencydatevat_amountmccvatsline_itemsconfidencetippurchase_countrypurchase_city
You can disable parts of the response in config to reduce prompt size and response size. For example, if you do not need VAT breakdowns, set enabled_fields.vats to false.
Use scanImages() when a receipt is split across several photos.
use Jake142\ReceiptScanner\Facades\ReceiptScanner;
$result = ReceiptScanner::scanImages([
storage_path('app/receipts/receipt-part-1.jpg'),
storage_path('app/receipts/receipt-part-2.jpg'),
]);The images are analyzed together as one receipt. This is useful when the top and bottom of a long receipt were captured in separate photos.
Use scanPdf() for a single PDF input.
use Jake142\ReceiptScanner\Facades\ReceiptScanner;
$result = ReceiptScanner::scanPdf(storage_path('app/receipts/receipt.pdf'));$result is a JSON-compatible associative array. The package asks the upstream model to return strict JSON only.
Default output shape:
[
'merchant' => null,
'total_amount' => null,
'currency' => null,
'date' => null,
'vat_amount' => null,
'mcc' => null,
'vats' => [
[
'rate' => null,
'amount' => null,
'amount_inc_vat' => null,
'amount_ex_vat' => null,
],
],
'line_items' => [
[
'description' => null,
'quantity' => null,
'unit_price' => null,
'amount' => null,
],
],
'confidence' => null,
'tip' => null,
'purchase_country' => null,
'purchase_city' => null,
]Notes:
vatsis always an array.line_itemsis always an array.- Unknown scalar values are returned as
null. - Unknown arrays are returned as
[]. - Dates are normalized to
YYYY-MM-DDwhen possible. - Numeric values are normalized to numbers, not strings, when possible.
mccis AI-estimated because receipts usually do not contain MCC directly.tipis a numeric tip/gratuity amount when visible on the receipt; otherwisenull.purchase_countryis the purchase country when inferable from receipt text, merchant/address, currency, or visible location; otherwisenull.purchase_cityis the purchase city when visible or clearly inferable from receipt text/address; otherwisenull.
Set the provider and model in env, then load them through config.
Example:
RECEIPT_SCANNER_PROVIDER=openai
OPENAI_MODEL=gpt-5.4-nanoAzure OpenAI is supported as well. When using Azure OpenAI, configure the Azure provider settings and use the OpenAI gpt-5.4-nano model/deployment.
If logging is enabled, the package may log safe diagnostics such as provider, model, mime type, retry count, duration, and failure category.
It will not log API keys, raw receipt contents, extracted JSON values, or full base64 payloads.
The package throws Jake142\ReceiptScanner\Exceptions\ReceiptScannerException for configuration, input, upstream, and parsing failures.
No tests are included in this package.
ReceiptScanner uses upstream AI providers to interpret receipts. It does not guarantee accounting accuracy. Always review critical financial data before using it in production workflows.