# Push approved Timesheet Portal invoices into Xero each evening

> Every weekday evening, newly approved invoices move from Timesheet Portal into Xero on their own, so finance never rekeys another one.

- Workflow type: code
- Services: Timesheet Portal, Xero, Slack Bot
- Categories: Finance, Operations
- Published: 2026-08-10

## What it does

- Checks Timesheet Portal every weekday evening for invoices that have been approved but not yet sent to your accounts.
- Pulls the full line by line detail for those invoices, including the hours, rate and amount on every line.
- Raises the matching sales invoice in Xero against the client, carrying the original invoice number, dates and every line across unchanged.
- Marks each invoice as exported once Xero confirms it, then posts a Slack summary with the count, the total value and anything that failed.

## What you'll need

- A Timesheet Portal account with administrator access
- A Xero organisation you can raise sales invoices in
- A Slack workspace and a channel for the evening summary
- Client names in Timesheet Portal that match the contact names you use in Xero

## Prompt

Every weekday at 7pm, push newly approved Timesheet Portal invoices into Xero as sales invoices, so finance stops rekeying them. Use a cron trigger, because Timesheet Portal does not send outgoing webhooks and is not available as a poll source.

Start in Timesheet Portal with List Invoices, filtered to invoices that have not yet been marked as exported. If nothing comes back, end the run without posting anything so the Slack channel stays quiet on days with no new invoices.

Pull the line level detail with Get Invoice Report V2. Timesheet Portal caps its invoice report endpoints at 24 requests per hour, so make exactly one report call per run covering every invoice in the batch, rather than one call per invoice. Group the returned rows by invoice so each invoice has its own set of lines carrying the description, hours, rate and amount.

Before creating anything, call Xero List Invoices filtered to the Timesheet Portal invoice number and check whether an invoice with that number already exists. If it does, skip that invoice and count it as already synced. This check is what makes a rerun safe, so it must happen for every invoice before any write.

For each remaining invoice, call Xero Create Invoices to raise an accounts receivable sales invoice. Identify the contact by name using the Timesheet Portal client name, since there is no contact lookup operation in the catalog to resolve it first. Carry the Timesheet Portal invoice number into the Xero invoice number field, carry the invoice date and the due date, and create one Xero line item per Timesheet Portal line with the description, the hours as the quantity, the rate as the unit amount and the line amount. Create the invoice in draft status so finance can review before it goes out.

Only once Xero has confirmed the invoice, call Mark Invoices as Exported in Timesheet Portal for that invoice, so the same invoice is never picked up twice. Timesheet Portal upserts can return HTTP 200 with success set to false, so check the success flag in the response body rather than the status code before treating the mark as done. Never mark an invoice as exported when the Xero create failed.

Handle each invoice independently. If one invoice fails at any step, record its invoice number and the reason, leave it unmarked so the next run retries it, and carry on with the rest of the batch.

Finish by posting a run summary to a finance channel in Slack with Send a Message. Include the number of invoices synced, the total value synced, the number skipped because they were already in Xero, and one line for each invoice that failed showing its invoice number and the reason.

## How to customize

- Change the timing. Seven in the evening on weekdays suits most finance teams, but you can move it later, run it once a week, or include weekends.
- Choose where the summary lands, whether that is a finance channel, an ops channel or a direct message to whoever owns billing.
- Decide how invoices arrive in Xero. They are created as drafts by default so someone can review them, but you can have them created ready to send.
- Narrow which invoices are in scope, for example only certain clients, branches or invoices above a minimum value.

## FAQ

### Will this create duplicate invoices in Xero?

No. Before it raises anything, the workflow looks in Xero for an invoice already carrying that Timesheet Portal invoice number, and skips it if one is there. On top of that, every invoice is marked as exported in Timesheet Portal once Xero confirms it, so it is never picked up a second time. Running it twice in one evening is safe.

### What happens if one invoice fails?

The rest still go through. Each invoice is handled on its own, and anything that fails is listed in the Slack summary with its invoice number and the reason, so you know exactly what to look at. A failed invoice is never marked as exported, so it will be retried on the next run.

### What if a client in Timesheet Portal does not exist in Xero yet?

The invoice is raised against the client name as it appears in Timesheet Portal. Xero will match an existing contact with that name, so it is worth keeping the two lists spelled the same. If the names differ, that invoice shows up in the failure list rather than landing quietly in the wrong place.

### Does this email the invoices to my clients?

No. The workflow creates the invoice in Xero and stops there. Invoices arrive as drafts by default so your team can review them, and sending stays a decision you make.

### Can I run it more often than once a day?

Once or twice a day is the sweet spot. Timesheet Portal limits how often invoice detail can be pulled, so the workflow deliberately gathers a whole batch in one go rather than fetching invoices one at a time. An evening run comfortably fits inside that limit.

Use this prompt in General Input: https://www.generalinput.com/prompts/push-approved-timesheet-portal-invoices-into-xero-each-evening