On a schedule
Turn order rows in a sheet into Stripe invoices
Each new B2B order in your sheet becomes a finalised Stripe invoice, with the invoice link written back to the row.
- Runs
- On a schedule
- Apps
- Google Sheets, Stripe
- AI
- Not needed
- Access
- Stripe write customers/invoices; sheet editor
Send this to your assistant
Create a ClickRuntime automation: every hour, create a Stripe invoice for each new B2B order row in my sheet that has no invoice yet and write the invoice link back to the row.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
A wholesale bakery takes trade orders from cafés by phone and email, and the sales assistant records each one as a row in a shared Google Sheet. Invoicing is a separate weekly job: open Stripe, find or create the customer, add the items, send the invoice, copy the link back. Orders taken on Monday are invoiced on Friday, and cash comes in a week later than it could.
This automation turns the sheet into the invoicing tool. Every hour it picks up rows without an invoice, finds or creates the customer in Stripe, builds and finalises the invoice and writes the link back into the row. The team keeps working in the sheet they know, and every order is invoiced within the hour.
What you get out of it
Invoices go out the same day
Orders are invoiced within an hour of being added, so customers can pay sooner.
The team keeps using the sheet
Nobody has to learn Stripe; adding a row is all it takes.
The sheet shows what's been invoiced
The invoice link is written into each row, so it is clear which orders are done.
Customers are reused
Existing Stripe customers are found by email, so repeat buyers are not duplicated.
No double invoices
Rows that already have a link are skipped, so each order is invoiced once.
How it works
What happens, step by step
Every hour, ClickRuntime reads your orders sheet and picks out rows that have no invoice link yet, stopping straight away if there are none.
For each order, it finds the customer in Stripe by email, or adds them if they are new.
It adds the order's item, quantity and price to a new invoice and finalises it.
The invoice link is written back into the row, so the order is never invoiced twice.
Before it runs live
- Connect your Google Sheets account and pick the spreadsheets it may use
- Connect Stripe
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Act only on the items that match your own rules, and skip the rest
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Google Sheets and Stripe steps into one automation
Under the hood
The code that runs this automation
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
import stripe
from clickruntime import on_trigger, credentials, report_fetched
SHEET_ID = "your-sheet-id"
@on_trigger
def run(event):
sheets = build("sheets", "v4", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False).spreadsheets()
rows = sheets.values().get(spreadsheetId=SHEET_ID, range="Orders!A2:G").execute().get("values", [])
todo = [(i + 2, r) for i, r in enumerate(rows) if len(r) >= 6 and (len(r) < 7 or not r[6])]
report_fetched(len(todo))
if not todo:
return {"invoiced": 0}
stripe.api_key = credentials.secret("STRIPE_API_KEY")
for row_no, (email, company, item, qty, price, currency, *_) in todo:
found = stripe.Customer.list(email=email, limit=1).data
customer = found[0] if found else stripe.Customer.create(email=email, name=company)
inv = stripe.Invoice.create(customer=customer.id, collection_method="send_invoice", days_until_due=30, currency=currency.lower())
stripe.InvoiceItem.create(customer=customer.id, invoice=inv.id, description=item, quantity=int(qty),
unit_amount=round(float(price) * 100), currency=currency.lower())
inv = stripe.Invoice.finalize_invoice(inv.id)
sheets.values().update(spreadsheetId=SHEET_ID, range=f"Orders!G{row_no}", valueInputOption="RAW",
body={"values": [[inv.hosted_invoice_url]]}).execute()
return {"invoiced": len(todo)}FAQ
Common questions
What columns does the sheet need?
Are invoices sent to the customer?
What are the payment terms?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Log Stripe sales in a sheet and send buyers their product
Every payment becomes a row in your sales sheet, and the buyer gets the download link you keep in that sheet.
See how it worksLog every Stripe cancellation and its reason in a sheet
Each cancelled subscription is added to your churn sheet with the customer, plan, revenue lost and the reason they gave.
See how it worksMonthly Stripe tax summary by country in a sheet
On the 1st of each month, last month's paid Stripe invoices are totalled by country and tax rate in a new tab, and you're told in Slack.
See how it worksKeep exploring
Set up “Turn order rows in a sheet into Stripe invoices” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.