Extract Invoice Data into Google Sheets with Make.com
Build a Make.com scenario: Drive Watch Files → Cryvis Invoice API → Google Sheets. Map invoice_number, dates, seller, and totals.
What we're building
A Drive folder drops PDFs or images. Make downloads each file, posts it to Cryvis, and appends one Sheets row with header fields — number, dates, vendor, totals. No line-item expansion; one document → one row.
Google Drive: Watch Files (folder)
|
v
Google Drive: Download a File
|
v
HTTP: Make a Request
POST https://api.cryvis.com/v1/documents/invoice
multipart field: file
|
v
JSON: Parse JSON
|
v
Google Sheets: Add a Row
invoice_number | invoice_date | due_date | currency
seller.name | buyer.name | subtotal | tax_total
total_amount | amount_due | file nameWhat you need
- Make.com account
- Google Drive folder for inbound invoices (shared with the Make connection)
- Google Sheet with a header row (columns listed in step 7)
- Cryvis API key — Invoice API, docs at /docs/api/extractInvoice
- Sample invoice PDF or JPEG/PNG/WebP
Credits: 1 per PDF page or image. See Credits.
Create the scenario
New scenario → add modules in this order:
- Google Drive — Watch Files (Trigger)
- Google Drive — Download a File (Action)
- HTTP — Make a Request (Action)
- JSON — Parse JSON (Action)
- Google Sheets — Add a Row (Action)
Optional later: Error Handler on the HTTP module, Filter after Watch Files for MIME type.
Configure source
Watch Files
- Connection: your Google account
- Select the inbound folder
- Watch for: all files, or limit to
application/pdfif your Drive connection exposes MIME filters - Limit: start with 1–2 files while testing
Download a File
- File ID: map from Watch Files →
File ID - Output: binary data Make can attach as multipart
Edge case: Drive sometimes delivers Google Docs mime types. Stick to uploaded PDFs/images. If a file is a Docs export, convert to PDF first or filter it out.
Configure Cryvis HTTP
HTTP — Make a Request
| Setting | Value |
|---|---|
| URL | https://api.cryvis.com/v1/documents/invoice |
| Method | POST |
| Body type | Multipart/form-data |
| Request content | Field name file, map binary from Download a File |
| Headers | Authorization = Bearer <API_KEY> |
Do not set Content-Type manually — Make sets the multipart boundary. Forcing application/json will break the upload.
Accepted MIME: pdf, jpeg, png, webp. Up to 20 files per request if you batch later; this tutorial sends one file per run.
Timeout: set the HTTP module timeout high enough for multi-page PDFs (60–120s is safer than the default on large scans). Parse response as JSON when Make offers the option; otherwise keep JSON — Parse JSON as the next step.
If the module returns a string body, Confirm success is boolean true, not the string "true", before you trust the mapper.
Process response
Cryvis returns roughly:
{
"success": true,
"data": {
"invoice_number": "INV-2024-00142",
"invoice_date": "2024-03-15",
"due_date": "2024-04-14",
"currency": "USD",
"seller": { "name": "Acme Cloud Services", "tax_id": "US12-3456789" },
"buyer": { "name": "Globex Corporation" },
"line_items": [],
"subtotal": 1148.98,
"tax_total": 94.79,
"total_amount": 1193.77,
"amount_due": 1193.77
},
"meta": {}
}JSON — Parse JSON: feed Data / body string from HTTP if Make did not already parse it. Then map:
data.invoice_numberdata.invoice_datedata.due_datedata.currencydata.seller.namedata.buyer.namedata.subtotaldata.tax_totaldata.total_amountdata.amount_due
Nested objects (seller, buyer) need dotted paths. Do not write the whole seller object into a single cell unless you want raw JSON.
Configure destination
Sheet headers (row 1):
Invoice Number | Invoice Date | Due Date | Currency | Vendor | Buyer | Subtotal | Tax | Total | Amount Due | Source File | Processed At
Add a Row mapping:
| Column | Source |
|---|---|
| Invoice Number | data.invoice_number |
| Invoice Date | data.invoice_date |
| Due Date | data.due_date |
| Currency | data.currency |
| Vendor | data.seller.name |
| Buyer | data.buyer.name |
| Subtotal | data.subtotal |
| Tax | data.tax_total |
| Total | data.total_amount |
| Amount Due | data.amount_due |
| Source File | Drive file name |
| Processed At | now (Make formula) |
Leave line_items for a dedicated flow — see Extract invoice line items.
Filters and error handling
Filter after Watch Files (recommended):
- Continue only if file name ends with
.pdf,.jpg,.jpeg,.png, or.webp
Error Handler on HTTP:
- On
4xx/5xx, write a row to an “Errors” sheet: file name, status code, response body snippet - Or break the scenario and notify Slack (pattern in Automate accounts payable)
Check success === true with a Filter before Add a Row so failed extractions do not create blank finance rows.
Test
- Drop one known invoice into the Drive folder.
- Run once (or wait for the Watch interval).
- Confirm HTTP status 200 and
success: true. - Verify Sheets columns match the PDF header — especially currency and
amount_duevstotal_amount. - Re-run the same file only if you accept duplicate rows; otherwise move processed files to an archive folder as a second Drive module.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 / 403 | Bad or missing Bearer token | Recreate the key; header must be Authorization: Bearer … with a single space |
| 415 / validation error | Wrong body type | Multipart field name must be file, not document or attachment |
| Empty Sheets row | Mapping from top-level instead of data | Use data.invoice_number, not invoice_number on the envelope |
| Duplicate rows | Watch re-fires on same file | Move to Processed after success; add Data Store dedupe |
| Credits higher than expected | Multi-page PDF | Each page = 1 credit — see Credits |
Run the HTTP module in isolation with “Run this module only” and inspect the raw JSON before wiring Sheets. That separates API issues from mapping bugs.
Production considerations
- Archive after success: Google Drive — Move a File to
/Invoices/Processedso Watch Files does not re-pick the same PDF. - Scheduling: shorten Watch interval only if credit burn and API rate limits are fine.
- Multi-page PDFs: each page costs 1 credit; huge statements will add up.
- Idempotency: store
invoice_number+ vendor in a Data Store and Filter duplicates before Sheets.
Next steps
Need AP status fields and Gmail intake instead of Drive? Use Automate invoice processing. For Notion as the destination: Extract invoice data from PDFs.
API reference: extractInvoice · Product page: Invoice · Hub: Make.com + Cryvis.