Skip to content

The moment it happens

Raise a draft Xero invoice when a deal closes

A won deal elsewhere creates a draft invoice for the right contact, and Slack gets a link to review it.

Runs
The moment it happens
Apps
Xero
AI
Not needed
Access
accounting.transactions, accounting.contacts

Send this to your assistant

Create a ClickRuntime automation: give me a link my CRM can call with a contact and line items. Find or create the contact in Xero, create a draft invoice, and send me the link in Slack.

Paste it into your assistant. It tells you what it will send or change before it runs live.

First time? Adding ClickRuntime to your assistant takes about two minutes.

Why use it

Why teams use this automation

When a deal closes in a CRM, a form or a booking tool, somebody has to create the invoice in Xero. That means opening Xero, checking whether the customer already exists, typing line items, copying the amount, and sending. When the sales rep is busy celebrating, the invoice is created a week late, and payment is delayed by the same week.

When the other system sends its deal-closed event to your trigger link, the automation finds the customer in Xero or creates a new contact, then creates a draft invoice with the lines from the event. A Slack message tells the finance team the draft is ready, so a person only has to check and approve.

It is practical for agencies, consultants and subscription businesses that bill straight after a sale.

What you get out of it

  • Invoices go out sooner

    A draft invoice created at the moment of the sale means billing happens the same day, which shortens the time between winning work and getting paid. Quicker invoicing is one of the simplest ways to improve cash flow without changing your prices.

  • No double entry of customers

    Finding the contact first prevents duplicate customer records in Xero, which cause messy statements and make it hard to see what one client owes in total. A clean contact list makes statements and customer reports much easier to trust.

  • Drafts keep a person in charge

    Because the invoice is created as a draft, finance reviews the amount and tax before it is sent, which stops a wrong figure from the source reaching the customer. A short human check catches the occasional wrong figure at the source.

  • Fewer typing errors

    Amounts, descriptions and quantities come from the deal itself, so there is no retyping a figure from one screen to another and getting a digit wrong. Retyping is where small mistakes sneak in, and mistakes in invoices cost trust.

  • Sales and finance share one trigger

    The deal closing is the only signal required, and both teams see the Slack message, which ends the back-and-forth asking whether an invoice has been raised. That ends the question of whether a sale has been billed yet, which finance hears constantly.

How it works

What happens, step by step

  1. When a deal is won in your other tool, it sends the customer and amount to ClickRuntime's link.

  2. ClickRuntime finds the matching contact in Xero, or creates one if they are new.

  3. It creates a draft invoice for that contact, so nothing is sent before you check it.

  4. Your Slack channel gets the customer, amount and a link to review the draft in Xero.

Before it runs live

  • Connect Xero
  • Paste your automation's link into the other app's webhook settings

What you get

RunsThe moment it happens
Raise a draft Xero invoice when a deal closesjust nowSucceeded
Slack · #salesDraft invoice for Northwind Traders: 3,600.00 https://go.xero.com/AccountsReceivable/Edit.aspx?InvoiceID=8f2c…

Build your own

Need it to work differently?

This template is a starting point. Copy the prompt and change it, or describe a different automation from scratch, with your own conditions, more apps or an AI step. Your assistant writes it, tests it and runs it on ClickRuntime.
  • 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 Xero steps into one automation

Under the hood

The code that runs this automation

This is the Python script that runs each time the automation starts. Your AI assistant writes it for you when you send the prompt, and you allow each step in your assistant. To change how the automation works, describe the change to your assistant and it updates the script for you. For every function it can use, see the script reference.
create_invoice_from_a_webhook.pyexample
from clickruntime import on_event, credentials, http, notify

API = "https://api.xero.com/api.xro/2.0"

def xero_headers():
    token = credentials.connection("xero", "work")
    tenant = http.get("https://api.xero.com/connections", headers={"Authorization": f"Bearer {token}"}).json()[0]["tenantId"]
    return {"Authorization": f"Bearer {token}", "xero-tenant-id": tenant, "Accept": "application/json"}

@on_event
def handle(event):
    body = event.json
    headers = xero_headers()
    found = http.get(f"{API}/Contacts", headers=headers, params={"where": f'Name=="{body["name"]}"'}).json()["Contacts"]
    if not found:
        found = http.post(f"{API}/Contacts", headers=headers,
                          json={"Contacts": [{"Name": body["name"], "EmailAddress": body.get("email")}]}).json()["Contacts"]
    invoice = {"Type": "ACCREC", "Status": "DRAFT", "Contact": {"ContactID": found[0]["ContactID"]},
               "LineItems": [{"Description": li["description"], "Quantity": li["quantity"],
                              "UnitAmount": li["unit_amount"], "AccountCode": "200"} for li in body["line_items"]]}
    inv = http.put(f"{API}/Invoices", headers=headers, json={"Invoices": [invoice]}).json()["Invoices"][0]
    link = f"https://go.xero.com/AccountsReceivable/Edit.aspx?InvoiceID={inv['InvoiceID']}"
    notify.slack(f"Draft invoice for {body['name']}: {inv['Total']:,.2f}\n{link}", channel="#sales")
    return {"invoice_id": inv["InvoiceID"]}

FAQ

Common questions

Which fields does the other system have to send?
At minimum the customer name or email, a description and an amount, plus quantity and account code if you need them. Your AI assistant can map the fields your CRM or form provides to the matching fields on the Xero invoice.
How does it avoid creating duplicate contacts?
It first searches Xero for a contact with the same email or name. If found, the invoice is attached to that contact, and if not a new one is created. Slightly different spellings can still slip through, so a consistent email is the most reliable key.
Can it send the invoice automatically instead of leaving a draft?
It can, but most finance teams prefer drafts so a person checks amounts and tax first. If your deals always follow a fixed price list, tell your AI assistant to authorise and send, and approve the change before it applies.
What permissions does it need?
accounting.transactions, accounting.contacts. Nothing else in your accounts is used.
Does it need AI?
No. It runs without AI, so it doesn't use your plan's AI allowance.
How many runs does it use?
One run for each event the app sends.
Can I change how it works?
Yes. Describe the change to your AI assistant, for example a different schedule, channel or filter. It updates the automation, tests it and tells you what changed.

Set up “Raise a draft Xero invoice when a deal closes” from your assistant

Copy the prompt above, or connect your assistant first. Free plan, no credit card.