1
Create the vendor config JSON
Create a new file at Place the file in the subdirectory that matches the
vendor_configs/{sub_type}/{vendor_id}.json. The vendor_id must be lowercase and unique across all vendors — it is used as the DynamoDB partition key and as the S3 path segment.invoice_sub_type value (e.g. vendor_configs/clothing/ for clothing vendors).2
Upload the config to DynamoDB
Run the upload script from the Example output:The script exits with code
vendor_configs/ directory. The script iterates over all */*.json files and uploads each one using aws dynamodb put-item with a attribute_not_exists(vendor_id) condition, so existing records are never overwritten.1 if any upload fails.3
Add a prompt config (optional)
To improve parsing accuracy, add an entry to The
lambda_layers/gemini_parsers/python/vendor_prompt_configs/{sub_type}.py.vendor_id key must exactly match the vendor_id value in the JSON config. This step can be skipped — the parser will still run, but with less context.4
Test the new vendor
Trigger a retail invoice fetch for your account by calling the ingest endpoint. You can scope the request to a specific date range to avoid re-fetching old data:A successful response looks like:Check CloudWatch Logs at
/aws/lambda/fetch_retail_invoices for per-email processing details and any errors.Vendor config field reference
The upload_vendors.sh script
attribute_not_exists(vendor_id)) so running it multiple times is safe — existing records are never silently overwritten. If you need to update an existing vendor’s configuration, use aws dynamodb update-item or delete and re-upload the record.
Real vendor examples
These are the current vendor configs in the repository.Dominos (food-delivery)
Dominos (food-delivery)
Foodora (food-delivery)
Foodora (food-delivery)
Zalando (clothing)
Zalando (clothing)
Jack & Jones (clothing)
Jack & Jones (clothing)
Anthropic (subscriptions)
Anthropic (subscriptions)
Mevlana Moské (subscriptions)
Mevlana Moské (subscriptions)
Notes and warnings
Set
active to false to disable a vendor without deleting its record. The get_active_vendors() function filters on active = true, so the vendor will be excluded from all fetch runs until you re-enable it.