← Back to blog

Automate Expense Tracking with Make.com

Parse Gmail receipt attachments with the Cryvis Receipt API and log expenses into Airtable — merchant, date, tax, and total without manual entry.

Most expense leakage is not fraud — it is delayed entry. Receipts sit in Gmail for weeks, then get typed into a tracker from memory. This scenario watches Gmail for receipt-like mail, extracts structured fields with Cryvis, and creates Airtable Expense records the same day.

Browse other Make recipes in the Make.com hub. Drive-based ingestion is covered in extract receipt data with Make.com. For approval gates before the ledger, see employee expense workflow.

Workflow

[Gmail: Watch Emails]
   criteria: has:attachment newer_than:7d
        |
        v
[Iterator: Attachments]
        |
        v
[Filter: pdf|jpeg|png|webp]
        |
        v
[HTTP: Make a Request]
   Cryvis POST /v1/documents/receipt
        |
        v
[Airtable: Create a Record]
   Expenses table
        |
        v
[Gmail: optional label "Expense/Logged"]

Modules

StepModuleRole
1Gmail — Watch EmailsTrigger on new matching messages
2IteratorWalk each attachment
3FilterKeep receipt MIME types only
4HTTP — Make a RequestCryvis Receipt extraction
5Airtable — Create a RecordWrite the expense row
6Gmail — Add Label (optional)Mark mail as processed
7Router (optional)Split retail vs travel by receipt_type

Gmail search that works well for expense inboxes:

has:attachment (receipt OR invoice OR "order confirmation") -label:Expense/Logged

Start with -label:Expense/Logged so reprocessing is controlled. Invoice PDFs from vendors may belong in a separate Cryvis Invoice scenario — see extract invoice data with Make.com — because invoice schemas differ from receipts.

Cryvis HTTP configuration

SettingValue
URLhttps://api.cryvis.com/v1/documents/receipt
MethodPOST
Auth headerAuthorization: Bearer <API_KEY>
BodyMultipart/form-data
fileAttachment binary from Iterator

One attachment = one HTTP call = one Airtable record. Do not bundle all attachments into a single multipart batch unless you also add an Iterator over results[]. Batch envelopes are documented in convert receipts to JSON.

Credits: 1 per page/image. A four-page PDF attachment costs four credits. Prefer single-page scans for email receipts.

API docs: extractReceipt. Product: Receipt API.

Fields you will map from data

data.receipt_number
data.transaction_date
data.transaction_time
data.merchant.name
data.location.city
data.payment.method
data.currency
data.subtotal
data.tax_total
data.total_amount
data.amount_paid
data.receipt_type
data.notes
data.line_items[]   (optional linked table)

Response mapping to Airtable

Suggested Expenses table:

Airtable fieldTypeMapping
Receipt NumberSingle line textdata.receipt_number
MerchantSingle line textdata.merchant.name
DateDatedata.transaction_date
AmountCurrency / Numberdata.total_amount
TaxNumberdata.tax_total
SubtotalNumberdata.subtotal
CurrencySingle select or textdata.currency
PaymentSingle selectdata.payment.method
CategorySingle selectMap from receipt_type or leave blank for humans
Source EmailURL / textGmail message link or Message-ID
Attachment NameTextIterator filename
StatusSingle selectDefault Logged
EmployeeCollaborator / textParse from From: if you use a shared alias

Airtable currency fields are single-currency per base in many setups. If you process multi-currency mail, store Amount as Number and keep Currency as text, then convert in a reporting view.

Line items

If you need SKU-level detail (rare for expense reimbursement, common for card reconciliation):

  1. After HTTP success, add Iterator on data.line_items.
  2. Airtable — Create a Record in a Line Items table with a link to the parent Expense.
  3. Map description, quantity, unit_price, amount.

Skip this until the parent Expense flow is stable. Empty line_items arrays are normal for faded thermal receipts; parent totals still populate.

Destination specifics: Airtable

  • Use Create a Record, not Update, for first-write expense logs.
  • Add a unique formula or automations later; for Make-side dedupe, query Airtable for existing Receipt Number + Date before Create. If both match, route to Update or Skip.
  • Views: This week, Missing receipt number, Foreign currency, Needs category.
  • Attach the original file to an Airtable Attachment field by re-uploading the Gmail binary — useful when auditors ask for proof without digging through mail.

Employee identity: if expenses arrive from expenses+alex@company.com, parse the local-part into Employee. If everyone forwards to one inbox, require a Google Form instead (employee expense workflow).

Filters and edge cases

Filter after Iterator:

  • Content-Type in application/pdf, image/jpeg, image/png, image/webp
  • Filename not matching smime|signature|logo|banner

Edge cases:

  • HTML-only receipts: many retailers email HTML without a PDF. This attachment path will miss them. Add a parallel branch that saves the email as PDF via a converter, or ask vendors for PDF receipts.
  • Password-protected PDFs: Cryvis cannot open them; send those to a Failures view.
  • Multiple receipts in one PDF: you get one extraction pass over the document; prefer one receipt per file for clean total_amount.
  • Tips: restaurant tips may appear in notes or fold into total_amount. Compare amount_paid vs total_amount when both exist.
  • Forwarded threads: Watch Emails can fire on replies. Prefer is:inbox + label gating, or filter on Attachment count > 0 and subject keywords.

Errors

FailureHandling
No attachmentsEnd branch silently
HTTP 401Break + notify admin
Soft success: falseCreate Airtable record in Failures with subject + filename
Airtable RATE_LIMITIncomplete execution / retry
Duplicate receiptFilter after Airtable Search; skip Create

Wire a Slack Error Handler only for auth and sustained 5xx — not for every logo PNG that fails the MIME filter.

Test plan

  1. Send yourself an email with a single JPEG receipt attached.
  2. Confirm Iterator yields one bundle and Filter passes.
  3. Inspect HTTP output: data.merchant.name and data.total_amount.
  4. Confirm Airtable row exists with Source Email populated.
  5. Re-run with a PNG logo attachment — Filter should drop it.
  6. Send a 2-page PDF; verify credit usage is 2 and totals still look right.

Gmail-specific operational notes

Shared inboxes (expenses@company.com) need a single Make connection with permission to read mail and apply labels. Avoid personal OAuth connections that break when an employee leaves.

Threading: if vendors send “receipt attached” follow-ups without new files, your Watch criteria should require attachments. Pair with filename:(pdf OR jpg OR jpeg OR png OR webp) when the provider search supports it.

When finance still wants human categorization, leave Category empty and build an Airtable Interface with a single-select. Do not invent categories from receipt_type unless you have validated mappings (e.g. fuel → Travel, grocery → Meals only if policy says so).

For approval before Airtable becomes the system of record, insert Slack between HTTP and Create a Record — same pattern as employee expense workflow, swapping Sheets for Airtable.

Production checklist

  • Dedicated Gmail label workflow so humans can see what automation touched.
  • Airtable interface for finance review (Status = LoggedApproved).
  • API key rotation documented; Make scenario cloning for staging inbox.
  • Credit alerts for mail storms (travel weeks).
  • Retention: decide whether to keep Gmail originals after Airtable attachment upload.
  • Separate Failures view with Subject, From, Filename, HTTP status for weekly triage.

CTA

Replace weekend expense entry with an API call. The Cryvis Receipt API accepts multipart receipt files and returns merchant, tax, totals, and line items as JSON. Read the extractReceipt documentation and wire it into Make with Bearer auth.