App guides
The Xero app sends your Swell orders to Xero as invoices, with their payments, and your refunds as credit notes. When an order is paid, the app creates its invoice in Xero for the customer's contact. Once the invoice is approved, each payment is recorded on the Xero account you name, so the invoice is marked as paid. When a payment is refunded, the app creates a credit note for the refunded amount and pays it out from the same account. Xero numbers the invoices, and the layout and branding are your organisation's.
Each invoice's total is the order's total to the cent, with the Xero tax rate that matches the tax Swell charged on each line. Invoices are created as drafts to review in Xero, or approved with their payments at once. Each one is listed on its order in Swell, and its page has the number, the status in Xero, what was paid and a link into Xero. The app connects through a Xero custom connection that you create for your organisation.
| When | What the app does |
| An order is paid | Creates its invoice in Xero, if Send paid orders and refunds to Xero is on. |
| An invoice is approved | Records the order's payments on the accounts set under Payments. With Create invoices as set to approved invoices, this happens right after the invoice is created. For a draft you approve in Xero, it happens when you read it again. |
| A payment of an invoiced order is refunded | Creates a credit note for the refunded amount for the invoice's contact, if Create credit notes for refunds is on too, and pays it out from the account of the refund's payment method. |
| An order is paid after its invoice was created | Records the payment on the invoice, if Send paid orders and refunds to Xero is on. |
| Xero refuses a document, or no invoice can be built for the order | Lists the document under Needs attention with the reason, and e-mails the store's administrators. |
| Xero can't be reached, is offline or limits the calls | Tries again for about ten minutes, then every half hour. After a day, lists the document under Needs attention. |
| You choose Create Xero invoice on an order, or Create Xero invoices on selected orders | Creates the invoice now, whether or not the order is paid. |
| You choose Retry, or Retry failed documents | Tries again, without creating a document that's already in Xero a second time. |
- A Xero organisation in Australia, New Zealand, the United Kingdom or the United States. Xero offers custom connections only there.
- A custom connection for the organisation. Xero charges the organisation a monthly fee for each custom connection, and the person who buys it needs the Connected apps permission in Xero. Connecting the Xero Demo Company is free, which suits your test environment.
- An income account in Xero for sales, such as Sales, and optionally another for shipping.
- A bank account in Xero for shop payments, usually a clearing account for your payment provider. Without one, payments aren't recorded and invoices stay awaiting payment in Xero.
- For orders in other currencies than the organisation's base currency, a Xero plan with multi-currency and the currency added under Accounting > Advanced > Currencies.
- Swell taxes that match what you owe. The app doesn't calculate tax. It uses the rate Swell charged on each line and picks the Xero sales tax rate with the same percentage.
Install Xero from the Swell App Store, and set it up in your test environment before the live one.
Create a custom connection
Sign in at developer.xero.com with your Xero login, go to My Apps and click New app. Enter a name, such as Swell, choose Custom connection and create the app.
Select the scopes accounting.contacts, accounting.invoices, accounting.payments and accounting.settings.read, and choose the user who authorises the connection. Xero e-mails that user a link: open it, click Connect and choose the organisation. For the test environment, choose the Demo Company.
Back on the app's page, copy the Client id and click Generate a secret to get the Client secret.
Connect Xero
In Swell, go to Apps > Xero > Settings, enter Client ID and Client secret, and click Save settings. Then click Test connection. The message names your organisation, its country and base currency, and Connected organisation shows its name. The message also says what's still missing in the settings.
Choose the accounts
Under Invoices, enter the code or name of your sales account in Account for sales, such as Sales, and optionally an account for shipping. Under Payments, enter the code or name of the bank account for shop payments. For each payment method whose money doesn't arrive there, add a row under Payment method exceptions with the method's ID in Swell, such as paypal, and another account, or no account to record nothing for it. Click Save settings, then Test connection again: it lists the accounts it found.
Choose the tax rates
If Test connection says that orders with a percentage need a choice, add a row under Tax rates for that percentage, such as 0, with the name of the Xero tax rate to use, such as Zero Rated Income. US organisations enter the account for sales tax instead, such as your Sales Tax Payable account. Click Save settings.
Choose how invoices are created
Under Invoices, keep Create invoices as set to Drafts, to review and approve while you test, and choose whether to create credit notes for refunds. Click Save settings.
Turn on automatic documents
Under Connection, turn on Send paid orders and refunds to Xero and click Save settings. From then on, paid orders and refunds get their documents. Orders paid before this aren't invoiced automatically.
Test with an order
Place and pay a test order. Open the order's Xero tab: it lists the invoice with the status In Xero and Status in Xero set to Draft. Open the document and choose View in Xero to check the lines, the tax and the total there.
To test the rest, choose Actions > Approve draft on the document, then Approve. Status in Xero becomes Paid, and Payments says what was recorded, such as Paid in Xero. To test a credit note, refund part of the payment in Swell after the invoice is approved.
Go live
Settings are saved separately for each environment. In the live environment, create a custom connection for your real organisation, repeat steps 2 to 6, and choose drafts or approved invoices for your live orders.
The app has no test mode. Test orders create real contacts, invoices and payments in the organisation the connection belongs to. Use the Demo Company for the test environment, or keep it on drafts and delete the test drafts in Xero.
To invoice orders placed before you installed the app, select them in the order list and choose Create Xero invoices.
When an order is paid and Send paid orders and refunds to Xero is on, the app creates its invoice in Xero. The invoice is for the customer's contact and has:
- The order number in Xero's Reference field, such as 1042.
- One line per item, with the product and variant name or its options, the SKU, the quantity and the unit price. A discount is on the line it belongs to, so the unit price is the one the customer saw.
- One line for shipping, named after the shipping service, such as Shipping: NZ Post Courier.
- Each line on Account for sales, or shipping on Account for shipping, with the Xero tax rate that matches the percentage Swell charged on it.
- The order's currency.
The invoice is dated the day the order was placed, in the organisation's time zone. A paid order's invoice is due on its date. An unpaid order's invoice gets the default sales payment terms from your organisation's invoice settings in Xero. Xero gives the invoice its number from your invoice settings when it's created, and the app shows it in Swell.
The invoice's total is the order's total to the cent. Xero calculates the tax of each line itself and rounds it to the cent, while Swell calculates tax per item and rounds only the order total, so the app repeats Xero's calculation before it sends anything. When store prices exclude tax, the invoice's amounts are tax exclusive if that gives the order's total, and tax inclusive otherwise. When store prices include tax, they're tax inclusive. The app then compares Xero's own total on the draft with the order. If a tax-exclusive draft is a cent off, the app deletes it and sends the same lines tax inclusive. If the total still differs, the draft is deleted and the document is listed under Needs attention.
Every Xero invoice needs a contact. The app uses the contact it used for the same customer before, or the Xero contact whose Contact Code is the Swell customer's ID or whose e-mail address is the customer's. Otherwise it creates a contact with the billing address, e-mail address, phone and the Swell customer ID as its Contact Code, named after the company or the customer. Xero needs unique contact names, so when another contact has the name, the new one gets the e-mail address in brackets, such as Olivia Moore (olivia@example.com). Existing contacts aren't changed.
Each line gets an active Xero sales tax rate with the percentage Swell charged on it. A row under Tax rates for the percentage decides first. Otherwise the app takes the one sales tax rate Xero has with that percentage, such as 15% GST on Income. A free line with no tax rule of its own, such as a free gift, takes the order's highest rate.
When Xero has several sales tax rates with the same percentage, the document is listed under Needs attention until you add a row for it. That's common for 0 %: a UK organisation has Zero Rated Income, Exempt Income and No VAT, and a New Zealand one Zero Rated and No GST. Test connection lists the percentages that need a row. The document's Xero tax rates shows the rates the invoice uses.
US organisations. Xero's US sales tax rates can't be used for transactions sent through the API. For a US organisation, the item and shipping lines carry no tax, and the order's sales tax is one more line, such as Sales tax: CA Sales Tax, on the account set in Account for sales tax (US organisations). An order that was charged sales tax needs attention until that account is set. Rows under Tax rates aren't used.
When an invoice is approved, the app records its payments in Xero, so the invoice is marked as paid. Xero takes payments on a bank account, or on an account with Enable payments to this account turned on in the chart of accounts.
- Each successful payment of the order is recorded on Account for shop payments, with its own amount and date and the reference Swell order 1042, card, up to what's still due on the invoice.
- A payment method with a row under Payment method exceptions is recorded on that row's account, or not at all when the row has no account. No account is right for payments you reconcile from your bank feed, such as bank transfers.
- Gift cards (giftcard) and store credit (account) are recorded only when they have a row with an account.
- With no account entered anywhere, nothing is recorded and invoices stay awaiting payment in Xero.
The document's Payments says what was done, such as Paid in Xero., 31.75 of 51.75 NZD recorded as paid in Xero. or Not recorded: 20.00 NZD paid by giftcard, which has no Xero account in the app's settings. A clearing account then holds the shop's payments until you transfer each payout from your payment provider to your bank account in Xero. The app doesn't record payouts or the provider's fees.
When an order is paid after its invoice was created, for example an invoice you created on demand, the app records the payment on the invoice.
If an account isn't found in Xero, or doesn't take payments, the invoice is still approved, and it's listed under Needs attention. Correct the account and choose Retry to record the payment.
Status in Xero shows Draft, Awaiting approval, Awaiting payment or Paid as it was when the app last read the document. Payments you record in Xero later aren't shown in Swell.
When a payment is refunded, and Send paid orders and refunds to Xero and Create credit notes for refunds are on, the app creates a credit note for the refunded amount if the order has a Xero invoice. Each refund gets its own credit note, for the invoice's contact, with a reference such as Order 1042, refund 100023.
- A refund of the whole invoice repeats the invoice's lines.
- A partial refund becomes one line per account and tax rate of the invoice, split in proportion to what the invoice holds on each, and adds up to the refunded amount exactly.
- Refunds that would add up to more than the invoice aren't sent.
- The credit note is a draft or approved as Create invoices as says.
Once the credit note is approved, the app pays out the refund from the account of the refund's payment method, by the same rules as payments, so the credit note is marked as paid. That happens only when the app recorded the order's payments. Otherwise the credit note stays open in Xero, to reconcile with the refund from your bank feed, and Payments on the document says so. The app doesn't allocate credit notes to invoices.
The app creates a credit note only for an approved invoice. While the invoice is a draft, the credit note is listed under Needs attention. Approve the invoice, then retry the credit note.
Refunds of orders the app has no invoice for are ignored. There's no action to create a credit note for a refund made while automatic documents or credit notes were off. Create it in Xero instead.
Every document starts as a draft in Xero. Create invoices as decides what happens next:
- Drafts, to review and approve stops at the draft. You can edit or delete a draft in Xero. Its payments aren't recorded until it's approved. New installs create drafts.
- Approved invoices, with their payments approves each document at once and records its payments. An approved invoice can't be deleted in Xero, only voided.
To approve a draft from Swell, open the document and choose Actions > Approve draft, then Approve. To approve several, select them on the Drafts tab of Orders > Xero documents and choose Approve drafts. Documents that aren't drafts are left as they are.
The app doesn't check Xero for drafts you approve there. After you approve one in Xero, open the document in Swell and choose Actions > Read again from Xero. The app records its payments. To read several at once, select them on the Drafts tab and choose Retry.
If a draft was deleted in Xero, reading it again lists it under Needs attention. Choose Retry to create it again, or Mark as resolved to leave it.
Xero's Starter plan approves a limited number of invoices a month. Beyond that limit, the invoice stays a draft and is listed under Needs attention. Approve it in Xero once your plan allows it, then choose Retry on the document.
To invoice an order that the automation doesn't cover, such as an unpaid bank transfer order or an order from before you installed the app, open the order and choose Actions > Create Xero invoice, then Create invoice. To invoice several, select them in the order list and choose Create Xero invoices, then Create invoices. These work whether or not automatic documents are on, and create drafts or approved invoices as Create invoices as says.
An order that already has an invoice gets no second one. If a payment came after its invoice, the action records it. When an unpaid order is paid later while automatic documents are on, the payment is recorded on its invoice. If they were off, choose Create Xero invoice on the order again to record it.
Documents the app couldn't create or finish are listed under Orders > Xero documents > Needs attention, with the reason in Problem. Correct the cause first, for example the connection, an account or a tax rate. Then:
- To retry one document, open it and choose Actions > Retry.
- To retry several, select them under Orders > Xero documents and choose Retry.
- To retry every document under Needs attention, and finish the ones that are in progress, choose Actions > Retry failed documents in the app settings.
A document that's already in Xero is never created twice. Each order has one invoice record and each refund one credit note record in Swell, written before anything is sent to Xero. If Xero's answer was lost, the app sends the same request again with the same idempotency key, which Xero answers without creating anything twice, and looks for its draft by the reference before it creates another. Before it records a payment, it reads the payments it already recorded on the invoice, which carry the reference Swell order and the order number. A retry of a document that's in Xero only finishes it: approving it if Create invoices as says so, and recording its payments.
If Xero can't be reached, is offline for maintenance, limits the calls or doesn't answer in time, the app tries again for about ten minutes. Then a check every half hour tries the document again. After a day of waiting, it's listed under Needs attention with The document could not be finished within a day.
Every action on orders and documents except Mark as resolved, and Retry failed documents, runs in the background, five documents at a time for a selection. The result is on the document. The runs are listed under Apps > Xero > Workflows. If Xero refuses the connection, a run over several documents stops at the first one.
When documents need attention, or Xero refuses the connection, the app e-mails the store's administrators with the problem and a link to the app. The subject starts with Action needed:. You get one e-mail when documents start needing attention, and one when Xero refuses the connection, not one per order or per problem. No new e-mail is sent until the problems are cleared, or a day passes without a new one. The e-mail is the notification Xero needs attention, which you can edit or turn off under Settings > Notifications.
To stop the app from creating a document, for example after you created it in Xero by hand or decided none is needed, open it and choose Actions > Mark as resolved. Optionally enter the Document number in Xero (optional), then click Mark as resolved. The document's status becomes Resolved by hand, and it's no longer listed under Needs attention.
A document that's in Xero but couldn't be finished, for example because its payment couldn't be recorded, is marked as In Xero instead and left as it is in Xero. When an order's invoice was resolved by hand, the app can't build credit notes for it, so its refunds need attention and their credit notes have to be created in Xero by hand too.
| Where | What it's for |
| Apps > Xero > Settings | The client ID and secret, Test connection, the automatic documents switch, and the invoice, tax rate and payment settings. |
| Apps > Xero > Settings, Actions menu | Retry failed documents. |
| Apps > Xero > Workflows | The background runs of the app's actions. |
| Orders > Xero documents | Every invoice and credit note, with the Needs attention, In Xero, Drafts and Skipped tabs, Open Xero, and Retry and Approve drafts for selected documents. |
| A document | Its number, status, total, currency, problem, tax rates and payments, View in Xero, and Retry, Approve draft, Read again from Xero and Mark as resolved in its Actions menu. |
| An order's Xero tab | The order's invoice and credit notes, with their status and problem. |
| An order's Actions menu | Create Xero invoice. |
| The order list, with orders selected | Create Xero invoices. |
| Settings > Notifications | The e-mail Xero needs attention. |
Settings are in Apps > Xero > Settings and are saved separately for each environment. They're in four sections, Connection, Invoices, Payments and Tax rates.
| Setting | Description | Default |
| Client ID | Connection. The Client id of your Xero custom connection. | None |
| Client secret | Connection. A Client secret of the custom connection. Masked on the settings page. | None |
| Connected organisation | Connection. Read-only. The name of the Xero organisation the connection belongs to, filled in by Test connection. | Not tested yet |
| Send paid orders and refunds to Xero | Connection. While on, an invoice is created when an order is paid, and a credit note when a payment of an invoiced order is refunded. The actions on orders and documents work either way. | Off |
| Create invoices as | Invoices. Drafts, to review and approve, or Approved invoices, with their payments. Credit notes are created the same way. | Drafts, to review and approve |
| Account for sales | Invoices. The code or name of the Xero account that item sales are posted to. Required. | None |
| Account for shipping | Invoices. The code or name of the Xero account that shipping is posted to. Empty: the account for sales. | None |
| Create credit notes for refunds | Invoices. Each refund of an order that has a Xero invoice becomes a credit note for the invoice's contact. | On |
| Account for shop payments | Payments. The code or name of the Xero bank account, or account with payments enabled, that payments are recorded on. Empty: nothing is recorded, and invoices stay awaiting payment in Xero. | None |
| Payment method exceptions | Payments. A row for each payment method that doesn't arrive on the account above. Payment method ID in Swell is the method's ID, such as card, paypal, klarna, amazon, giftcard, account (store credit) or the ID of a manual method. Xero account is the account to record it on. Leave it empty to record nothing for the method. Gift cards and store credit are recorded only with a row that has an account. Refunds are paid out by the same rules. | None |
| Tax rate choices | Tax rates. A row for each percentage charged in Swell that Xero has several sales tax rates for, or that should use another rate. Xero tax rate is the rate's name or tax type in Xero. | None |
| Account for sales tax (US organisations) | Tax rates. US organisations only. The code or name of the Xero account that the order's sales tax line is posted to, usually a liability account for sales tax payable. | None |
- Only Xero organisations in Australia, New Zealand, the United Kingdom and the United States can connect, because the app uses a custom connection. Xero bills each custom connection to the organisation every month.
- Each environment uses the organisation of its custom connection. There's no test mode, so test orders create real documents there. Use the Demo Company for the test environment.
- Xero allows an organisation 60 API calls a minute and a daily limit. A document takes about five calls, so a large backfill runs over several hours, and documents wait while the limit is reached.
- Payments are recorded only on bank accounts and accounts with payments enabled. Payouts from your payment provider and its fees aren't recorded.
- Status in Xero isn't updated when you record payments or change a document in Xero.
- Changes to an order after its invoice, such as edited or canceled items without a refund, aren't sent to Xero. Canceling an order doesn't void its invoice.
- Credit notes are for an amount, not for items, because a Swell refund names no items. They're created only automatically, for refunds of orders with a Xero invoice, and aren't allocated to invoices.
- The app doesn't follow drafts in Xero. Read a draft again after you approve it there.
- Only orders are invoiced. Subscription charges that don't create an order aren't.
- The app doesn't calculate tax. It picks Xero tax rates by the percentage Swell charged, and Xero calculates the tax from the rate, so a line's tax in Xero can differ from Swell's by a cent while the invoice total stays the order's.
- Gift card sales are posted to the account for sales like other items.
- Invoices don't use Xero's inventory items or tracking categories.
- Existing Xero contacts aren't changed, so a returning customer's new address isn't saved on their contact.
Problems with a document are shown in Problem on the document, and under Orders > Xero documents > Needs attention. The app also logs errors. In the Swell dashboard, the logs are under Developer > Console > Logs.
Enter the client ID and the client secret of your Xero custom connection means one of them isn't saved. Xero did not accept the client ID and secret means one is wrong. Copy the Client id again from the app's page in Xero's developer portal, or generate a new secret, then save and test again. Xero has not authorised the custom connection yet means the user it was sent to hasn't connected it to an organisation. The custom connection lacks a scope the app needs means a scope is missing: add it in the developer portal and have the connection authorised again. A test that connects can also name a missing scope, such as The custom connection lacks accounting.payments (for payments).
Check that Send paid orders and refunds to Xero is on and saved. Orders paid before it was turned on, and orders that never become paid, such as unpaid bank transfer orders, aren't invoiced automatically. Choose Actions > Create Xero invoice on the order. If the order's document is listed under Needs attention, Problem says why.
The custom connection was disconnected, or the organisation is no longer active. The store's administrators get an e-mail whose subject starts with Action needed: Xero is not accepting documents from. Check the connection in Xero's developer portal, then click Test connection and choose Actions > Retry failed documents.
An account under Invoices is missing, or an account under Invoices, Tax rates or Payments doesn't match an active account in Xero. Enter the account's code or name as it's shown in Xero's chart of accounts. Test connection lists the income accounts and the accounts that take payments. Then retry.
An account under Payments isn't a bank account and doesn't have payments enabled. Name a bank account, or turn on Enable payments to this account for it in Xero's chart of accounts, then retry. The invoice is already approved, so the retry only records the payment.
Add a row under Tax rates with the percentage and the name of the Xero tax rate to use, save, and retry.
The order was charged a percentage that no active Xero sales tax rate has. Add the rate in Xero under Accounting > Advanced > Tax rates, or add a row under Tax rates that names an existing rate for the percentage. Then retry.
A US organisation needs Account for sales tax (US organisations) under Tax rates. Enter the account, such as your Sales Tax Payable account, then retry.
The order's currency isn't added to your Xero organisation. Add it under Accounting > Advanced > Currencies. That needs a Xero plan with multi-currency. Then retry.
The invoice is a draft in Xero. Approve it in Xero once your plan allows it, or upgrade the plan, then choose Retry on the document.
No invoice with exactly the order's total can be built from its amounts. Nothing was kept in Xero. Create the invoice in Xero by hand and mark the document as resolved.
A refund's credit note waits for its invoice. Correct the invoice's problem and retry it, then retry the credit note.
Approve the invoice, in Swell with Actions > Approve draft or in Xero followed by Read again from Xero. Then retry the credit note.
The order's refunds add up to more than its invoice, for example after the order total was changed. Create this credit note in Xero by hand and mark it as resolved.
A draft was deleted or an invoice voided in Xero, or the connection now belongs to another organisation. Choose Retry to create the document again, or Mark as resolved to leave it. A credit note for an invoice that's gone has to be created in Xero by hand.
Xero couldn't be reached, was offline or limited the calls for a day, so the app stopped trying. The rest of the message is the last error. Choose Retry on the document, or Actions > Retry failed documents in the app settings.
Payments on the document says why. Usually no account is set under Payments, the payment method has an exception without an account, or the order was paid by gift card or store credit. Drafts aren't paid until they're approved. When the order was paid after the invoice was created while automatic documents were off, choose Create Xero invoice on the order to record the payment.
Uninstalling the app stops creating invoices and credit notes and recording payments, and removes the app's settings, its functions, the Xero documents list, the order's Xero tab and actions, and the notification. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.
The client ID and secret are deleted from Swell with the settings. Documents that are still in progress aren't finished, because the half-hourly check is removed too. The records under Xero documents are kept and come back if you reinstall, so documents already in Xero aren't created again. Contacts, invoices, credit notes and payments in Xero stay there. To stop the connection on Xero's side, disconnect the custom connection in Xero's developer portal.
| Function | Runs on | What it does |
| invoice-order | order.paid, while Send paid orders and refunds to Xero is on | Writes the order's invoice record, or marks an existing invoice for its payments, and starts a process-documents run. |
| credit-refund | payment.refund.succeeded, while the same setting is on | Writes the credit note record for a refund of an invoiced order, when credit notes are on, and starts a run. |
| process-documents | A workflow, started by the two event functions, sweep, and every action on orders and documents except Mark as resolved, including Retry failed documents | Works on one document, or on selected documents or orders five per step in id order, until each is complete or needs attention. |
| sweep | Cron, every 30 minutes | Starts a run for documents that wait for Xero and had no attempt for 15 minutes. |
| test-connection | The Test connection button | Reads the organisation, accounts, tax rates and granted scopes, saves the organisation's name and clears the connection alert. |
| resolve-document | The Mark as resolved action | Sets the record to resolved, or to created when the document is in Xero. |
The app's permissions are read_orders, read_payments and read_accounts. It writes only its own records in Swell.
Each invoice and credit note has a record in the app collection apps/xero/documents, written before anything is sent to Xero. Its key, invoice:<order id> or credit_note:<refund id>, is unique, so each order gets one invoice and each refund one credit note. status is pending, created, failed, skipped or resolved, and xero_status is draft, submitted, authorised, paid, voided or deleted. Other fields include source, number, invoice_number, order_id, refund_id, payment_method, reference, amount, currency, tax_note, xero_id, xero_url, contact_id, contact_key, booked_amount, booking_note, date_booked, problem, problem_code, attempts, date_attempted, date_submitted, date_pending and locked_until. Orders get a documents link field, expanded as $app.xero.documents. Nothing is stored on the order.
The app gets a token from https://identity.xero.com/connect/token with the client credentials grant, and keeps it until shortly before it expires after 30 minutes. It calls https://api.xero.com/api.xro/2.0 without a tenant header: GET /Organisation, /Accounts and /TaxRates, kept for five minutes per worker and read fresh by Test connection; GET /Contacts with a where on ContactNumber and EmailAddress, GET /Contacts/{id} to reuse a customer's earlier contact, and PUT /Contacts; PUT /Invoices and /CreditNotes with unitdp=4 for drafts, GET by id or with a where on the contact and Reference to find them, and POST /Invoices/{id} or /CreditNotes/{id} with Status AUTHORISED to approve or DELETED to discard; and PUT /Payments with an Invoice or a CreditNote. Every create, approval and payment carries an Idempotency-Key. Calls time out after 15 seconds. A 429 is waited out up to twice, 1 and then 2 seconds or Xero's Retry-After if that's longer, when the wait is at most 5 seconds; the daily limit isn't waited out.
A worker takes a record by raising attempts with $inc and holding locked_until for two minutes, so of two attempts only one goes on. date_submitted is set before a create call and cleared when Xero answers. A record still marked on a later attempt is looked up by its contact and reference at once. If it isn't found, it's sent again with the same idempotency key once a minute has passed since the first send; a document deleted since is created anew. Before it records a payment, the app reads the invoice's payments whose reference starts with Swell order, and records no more than the amount due. Approving an approved document changes nothing.
Amounts are integers in 1/10000 of the currency unit. The app simulates Xero's per-line tax rounding, half away from zero, and sends tax-exclusive lines only when the simulated total equals the order's and no line's tax falls on half a cent. Tax-inclusive lines settle Swell's fractions of a cent between the lines, largest remainder first. A unit price that can't multiply back to its line total with four decimals becomes one line for the lot.
A run's step for one document retries 5 times, from 20 seconds with exponential backoff; a step over a selection retries 4 times. A Xero 429, 5xx or network error sets problem_code to temporary. The sweep picks up records that are pending, or created with a temporary problem, whose date_attempted is older than 15 minutes, and marks a record failed once its date_pending is a day old. A refused token, a missing scope or a 403 sets problem_code to connection and stops a run over several records.
Open problems are records in apps/xero/alerts, one per key (connection or documents), with message, subject, count, date_last_seen and app_id. Creating one sends the admin notification, written from the workflow with $events: true and a $notify name.
Swell builds and maintains the Xero app. For help with the app, email support@swell.is. For questions about your Xero organisation or custom connections, contact Xero support.