Google Sheets to invoice, in four steps
Keep one row per invoice line, import the sheet, and get numbered invoices with PDFs and hosted pages.
To create invoice from Google Sheets rows with ASHDOCS, keep one row per invoice line, download the sheet as a CSV file and import it. ASHDOCS groups the rows into invoices, numbers each one, renders its PDF and creates a hosted invoice page your customer can open. ASHDOCS has no published Google Sheets add-on; the template and the import do the work.
If rows should become invoices the moment they are added, a Zapier or Make step can create each invoice from the new row, using the same fields shown in the table below. Both routes end in the same invoices, numbered in the same sequence.
curl -X POST https://www.ashdocs.com/api/v1/invoices/batch \
-H "X-API-Key: ash_test_..." \
-F "file=@ashdocs-invoice-rows.csv" \
-F 'mapping={"customer_name":"customer name","customer_email":"customer email","description":"description","quantity":"quantity","unit_price":"unit price","tax_rate":"tax rate","unit":"unit","currency":"currency","due_terms":"due terms","reference":"reference","po_number":"po number","notes":"notes","template":"template","group":"group"}' \
-F "mode=issue"import { readFile } from "node:fs/promises";
// Each API field maps to the template column of the same name, with spaces.
const fields = ["customer_name", "customer_email", "description", "quantity", "unit_price", "tax_rate", "unit",
"currency", "due_terms", "reference", "po_number", "notes", "template", "group"];
const mapping = Object.fromEntries(fields.map((f) => [f, f.replace(/_/g, " ")]));
const form = new FormData();
form.append("file", new Blob([await readFile("ashdocs-invoice-rows.csv")], { type: "text/csv" }), "ashdocs-invoice-rows.csv");
form.append("mapping", JSON.stringify(mapping));
form.append("mode", "issue");
const res = await fetch("https://www.ashdocs.com/api/v1/invoices/batch", {
method: "POST",
headers: { "X-API-Key": "ash_test_..." },
body: form,
});
const batch = await res.json();
console.log(res.status, batch.id, batch.rows);import json
import requests
# Each API field maps to the template column of the same name, with spaces.
fields = ["customer_name", "customer_email", "description", "quantity", "unit_price", "tax_rate", "unit",
"currency", "due_terms", "reference", "po_number", "notes", "template", "group"]
mapping = {f: f.replace("_", " ") for f in fields}
with open("ashdocs-invoice-rows.csv", "rb") as f:
r = requests.post(
"https://www.ashdocs.com/api/v1/invoices/batch",
headers={"X-API-Key": "ash_test_..."},
files={"file": ("ashdocs-invoice-rows.csv", f, "text/csv")},
data={"mapping": json.dumps(mapping), "mode": "issue"},
)
batch = r.json()
print(r.status_code, batch["id"], batch["rows"]){
"id": "bat_4c1e9a7d2b8f40e6a913",
"state": "queued",
"mode": "issue",
"rows": 2,
"results": [],
"zip_url": null,
"created_at": "2026-10-09T10:00:00"
}The import answers 202 Accepted; values illustrative. rows counts invoices after grouping, so the template's three rows make two.
A template built from the importer
The CSV and Excel templates use the importer's own 14 field names as column headers, so the dashboard import matches them for you. Three sample rows show two invoices.
Group rows into one invoice
Rows with the same group value become one invoice with several lines, and the customer comes from the group's first row. An empty group makes one invoice per row.
Drafts or issued invoices
Import as drafts to review first, at no cost, or as issued invoices to number them now; issuing uses 1 credit per invoice. One failed row never stops the rest of the batch.
Create invoice from Google Sheets: the four steps
Download the template as CSV (/invoice-templates/ashdocs-invoice-rows.csv) or Excel (/invoice-templates/ashdocs-invoice-rows.xlsx). Both hold the same columns and three example rows.
- 1. Open the template in Google Sheets with File → Import, or paste your own rows under the same headers. customer name, description and unit price are required.
- 2. Fill one row per invoice line, and give every row of the same invoice the same group value, for example a customer and month such as northwind-oct.
- 3. Download the sheet as a CSV file, then in ASHDOCS open Invoices, choose Import CSV, pick the file and check the column matches.
- 4. Create the invoices as Drafts or as issued invoices and import. Each issued invoice gets a number, a PDF and a hosted page; send it from the dashboard or with POST /api/v1/invoices/{id}/send.
Multiple line items on one invoice: the group column
The importer reads the sheet top to bottom. The first row with a new group value starts an invoice and supplies the customer name and email, currency, due terms, reference, PO number, notes and template. Every later row with the same group adds one line: description, quantity (1 when empty), unit price, tax rate and unit. In the template, the two Northwind Studio rows share northwind-oct, so they become one invoice with two lines, and the Globex row becomes a second invoice.
The same import is available from code: send the CSV to POST /api/v1/invoices/batch with a mapping from API fields to your column headers and a mode of draft or issue, as in the sample above. The call returns 202 straight away; GET /api/v1/invoices/batch/{id} then lists each invoice's row, status, number and error, and GET /api/v1/invoices/batch/{id}/zip downloads the PDFs with a manifest.csv. One batch holds up to 200 invoices.
Template columns and Zapier fields
Each template column is an API field. When a Zap or Make scenario creates the invoice from a row instead, the same values go into these Create Invoice fields (Make uses the same words in sentence case).
| Template column | API field | Zapier Create Invoice field | Required |
|---|---|---|---|
| customer name | customer.name | Customer Name | Yes |
| customer email | customer.email | Customer Email | No |
| description | line_items[].description | Line Items → Line item description | Yes |
| quantity | line_items[].quantity | Line Items → Quantity | No (default 1) |
| unit price | line_items[].unit_price | Line Items → Unit Price | Yes |
| tax rate | line_items[].tax_rate | Line Items → Tax Rate (%) | No |
| unit | line_items[].unit | Line Items → Unit | No |
| currency | currency | Currency | No |
| due terms | due_terms | Due Terms | No |
| reference | reference | Reference | No |
| po number | po_number | PO Number | No |
| notes | notes | Notes | No |
| template | template | Template | No |
| group | group (import only) | None: map several rows into Line Items instead | No |
Automate it with Zapier or Make
For invoices made one at a time, start a Zap or scenario with a Google Sheets new-row trigger and add a step that sends the row to POST /api/v1/invoices, mapped as in the table: a Webhooks by Zapier Custom Request step in Zapier, or the HTTP "Make a request" module in Make. A single row makes a one-line invoice; to put several rows on one invoice, pass them to Line Items as a list, as the Zapier and Make pages explain.
If you would rather use a packaged app, the ASHDOCS Zapier app is available by invite while Zapier reviews the public listing, and the ASHDOCS community node runs on self-hosted n8n. There is no ASHDOCS Make app yet. The HTTP step on each platform calls POST /api/v1/invoices directly with your API key. Build the sheet automation with a test key, which uses no credits, and once it is live the free plan's 100 credits per month cover up to 100 issued invoices.
Frequently asked questions
How do I turn a Google Sheet into invoices?
Download the sheet as a CSV file and import it in ASHDOCS with Import CSV. Each group of rows becomes one invoice with its own PDF and hosted page.
How do I number invoices automatically?
Import the CSV and choose issued invoices. ASHDOCS gives each invoice the next number in your sequence when it is issued, so the sheet itself never has to count.
Can several rows go on one invoice?
Yes. Give the rows the same value in the group column and they become one invoice with one line per row. Rows with an empty group each become their own invoice.
Can I send invoices from a spreadsheet?
Yes, after the import. Send each issued invoice from the dashboard, or call POST /api/v1/invoices/{id}/send, and ASHDOCS emails it to the customer email from its row.
Plans
- 100 credits per month
- 1 seat
- No webhooks
- 1,500 credits per month
- 1 seat
- Webhooks
- 10,000 credits per month
- 3 seats
- Webhooks
- 30,000 credits per month
- 5 seats
- Webhooks
- 100,000 credits per month
- 10 seats
- Webhooks
Test keys are free, never expire and never use credits; plan rate limits apply. Webhooks are on paid plans. Issuing an invoice uses 1 credit. No per-seat fees. See full pricing.