Written by: JJ Tan, Founder, Jelly | Last updated: 13 August 2026
Key Takeaways for Restaurant Operators
- UK restaurant operators can reclaim 20–40 hours of monthly admin by posting a single daily summary journal to Xero instead of per-order transactions.
- The daily-summary method aggregates sales, taxes, and fees into one journal entry per site, keeping kitchen-level detail in the POS while matching net bank payouts.
- Successful integration relies on OAuth2 granular scopes, tracking categories for Location and Department, a clearing account for card revenue, and idempotency keys that prevent duplicates.
- Production-ready integrations should hit clear benchmarks such as daily posting before 09:00, zero duplicates over 30 days, real-time gross-profit visibility, automatic rate-limit handling, and correct 20% / 0% VAT splits.
- Ready to automate Xero integration without writing code? See one-click Xero setup in action and discover how Jelly delivers daily summaries and margin visibility automatically.
Phase 1: Pick Daily-Summary Posting for Most Restaurants
The core architectural decision is whether to post one aggregated journal per day or one invoice per transaction. For most UK restaurant operators, the summary method aggregates daily sales, taxes, and fees into a single journal entry that matches the net bank payout, which avoids thousands of individual transactions in the ledger. Per-order posting suits wholesale or audit-heavy scenarios that require invoice-level customer traceability. Typical restaurant operations rarely need that level of detail inside Xero.
The table below maps key restaurant data fields to their corresponding Xero objects under the daily-summary approach.
| Data Point | Xero Object | Tracking Category | Notes |
|---|---|---|---|
| Gross food sales | Manual Journal (credit revenue account) | Location → Site name | Split by VAT rate: 20% standard on prepared meals |
| Gross beverage sales | Manual Journal (credit revenue account) | Location → Site name | Separate line to preserve sales-mix visibility |
| Card payments received | Bank Transaction (debit clearing account) | Department → F&B | Net of processor fees, gross posted to clearing |
| Cash payments received | Bank Transaction (debit bank account) | Department → F&B | Matched against end-of-day cash count |
| Supplier invoices | Bill (Accounts Payable) | Location → Site name | Line-item detail retained in Jelly, summary pushed to Xero |
| Refunds / voids | Credit Note against Manual Journal | Location → Site name | Must net against gross before VAT calculation |
Troubleshooting: If POS admin rights are missing, the export API returns a 401. Confirm admin credentials before connecting. VAT rounding differences of ±£0.01 per line are normal. Resolve them with a rounding adjustment line on the journal instead of editing individual amounts.
Phase 2: Set Up OAuth2 Authentication for Xero
Create an app at developer.xero.com, set the redirect URI to your server endpoint, and request the following granular scopes. Xero replaced broad scopes with ten granular scopes for all apps created on or after 2 March 2026. Apps created before that date must migrate by 13 September 2027, when the deprecated accounting.transactions scope stops working.
Required scopes for a restaurant daily-summary integration:
accounting.invoicesaccounting.paymentsaccounting.banktransactionsaccounting.manualjournalsoffline_access
After the OAuth flow completes, call GET https://api.xero.com/connections to retrieve the tenantId for each connected organisation. Supply that value in the Xero-tenant-id header on every subsequent Accounting API request.
Access tokens expire after 30 minutes, and refresh tokens rotate on every use and expire after 60 days if unused. Persist the newest refresh token atomically after every rotation. A race condition here can lock the integration out entirely.
Troubleshooting: A 403 response almost always means the Xero-tenant-id header is missing or contains a stale value. When this occurs, re-fetch connections via GET /connections and update the stored tenantId before retrying the request.
Want to skip building this yourself? See how Jelly handles OAuth automatically, with one-click connection, no token management, and no tenant mapping headaches.
Phase 3: Configure Tracking Categories and Clearing Accounts in Xero
Xero permits a maximum of two active tracking categories per organisation, each with up to 100 options. For multi-site restaurant groups, the recommended pairing is Location (one option per site) and Department (for example, Food, Beverage, Events). This structure lets the Profit & Loss by Tracking Category report display revenue, cost of sales, and gross profit as separate columns per site without adding sub-accounts to the chart of accounts.
Set up a dedicated clearing account with Current Asset type, not a bank account, to hold gross card revenue. When processor payouts are netted before reaching the bank, a clearing account holds gross revenue so fees and refunds can be recorded separately. The net deposit is then matched against clearing entries during reconciliation.
Operators who want to automate this configuration can let Jelly handle it. Jelly ingests supplier invoices via email or photo, scans every line item automatically, maps POS sales to individual dishes in minutes, and pushes a single daily summary directly into Xero with tracking categories pre-applied. The Price Alert feature flags every ingredient price movement the same week it happens, which gives operators time to negotiate credits before margin damage compounds. At a flat £129 per site per month, Jelly replaces the configuration work described in Phases 1–3 with a setup that usually completes within a week.
Troubleshooting: Post refunds as credit notes against the original journal, not as negative sales lines, to avoid double-counting VAT. For multi-site groups approaching the 100-option limit on a tracking category, archive inactive site options instead of deleting them so historical reports remain intact.
Phase 4: Implement Idempotency and Audit Logging
Every POST to the Xero API should carry a stable, deterministic idempotency key, typically a hash of site_id + business_date, stored in a local audit table before the request is sent. If the API returns a 2xx response, mark the row as posted. If it returns a 5xx or times out, the next scheduled run re-attempts using the same key, and Xero deduplicates the entry server-side.
A minimal audit table schema:
idempotency_key(VARCHAR, primary key)site_id(VARCHAR)business_date(DATE)xero_manual_journal_id(UUID, nullable)status(ENUM: pending, posted, failed)attempted_at(TIMESTAMP)
Troubleshooting: Hitting rate limits returns a 429 Too Many Requests response with a Retry-After header that integrations must respect with exponential backoff. As mentioned in Phase 2, monitoring the rate limit headers on every response helps you detect approaching limits before a 429 occurs.
Phase 5: Push the Daily Summary via the Xero API
The following minimal Python example posts a daily food-sales summary as a manual journal. Extend it for beverage lines, payments, and supplier bills using the same pattern.
import requests, hashlib, datetime TENANT_ID = "your-tenant-id" ACCESS_TOKEN = "your-access-token" SITE_ID = "site-london-bridge" BUSINESS_DATE = datetime.date.today().isoformat() idempotency_key = hashlib.sha256( f"{SITE_ID}:{BUSINESS_DATE}".encode() ).hexdigest() headers = { "Authorization": f"Bearer {ACCESS_TOKEN}", "Xero-tenant-id": TENANT_ID, "Content-Type": "application/json", "Idempotency-Key": idempotency_key, } payload = { "Date": BUSINESS_DATE, "Narration": f"Daily sales summary - {SITE_ID} - {BUSINESS_DATE}", "JournalLines": [ { "Description": "Gross food sales", "LineAmount": 2450.00, "AccountCode": "200", "TaxType": "OUTPUT2", "Tracking": [{"Name": "Location", "Option": "London Bridge"}], }, { "Description": "Sales clearing account", "LineAmount": -2450.00, "AccountCode": "825", "TaxType": "NONE", }, ], } response = requests.post( "https://api.xero.com/api.xro/2.0/ManualJournals", headers=headers, json=payload, ) print(response.status_code, response.json())
Troubleshooting: Sandbox and VAT New Xero apps created after 2 March 2026 must use granular scopes and can be tested against a Demo Company in the developer portal. For UK VAT, hospitality sales such as restaurant meals are subject to the 20% standard VAT rate, while most unprepared food items sold for home consumption qualify for the 0% zero rate. Correctly distinguishing these in POS data is essential to avoid MTD penalties. Making Tax Digital compliance mandates a direct digital link from source systems to the VAT return, and manual re-keying is prohibited.
Measurable Success Criteria for Your Integration
A production-ready integration should meet all of the following benchmarks by the end of Week 6.
- Daily summaries posted to Xero before 09:00 each morning with zero manual intervention
- Zero duplicate entries in the audit log across a rolling 30-day window
- Gross-profit visibility updated within five minutes of a sale completing in the POS
- All 429 responses handled automatically with exponential backoff, with no manual retries required
- VAT output split correctly between 20% standard and 0% zero-rated lines on every journal
Advanced Next Steps for Growing Groups
Once the single-site daily summary is stable, the next phase focuses on scale and deeper automation.
- Multi-location roll-outs: Replicate the tracking category mapping for each new site. Given Xero’s tracking category limits discussed earlier, location naming conventions must be agreed before scaling beyond 100 sites.
- Supplier-statement reconciliation: Match Jelly’s scanned invoice line items against supplier statements automatically and flag discrepancies before payment runs.
- Delivery-commission adjustments: Add a separate journal line per delivery platform, such as Deliveroo or Uber Eats, to net commission before posting net revenue and preserve true gross margin per channel.
Ready to automate all of this without writing a line of code? Watch Jelly’s Xero integration in action, including multi-location roll-outs, supplier reconciliation, and delivery-commission adjustments.
Frequently Asked Questions
What are the current Xero API rate limits in 2026?
Xero enforces per-organisation rate limits of 5 concurrent requests, 60 calls per minute, and 5,000 daily calls (identical across all apps and tiers). Each limit is tracked independently. Exceeding any limit returns an HTTP 429 response with an X-Rate-Limit-Problem header that identifies which limit was breached and a Retry-After header for minute and daily limits. Best practice is to log the X-DayLimit-Remaining header on every response and pause posting if it drops below a safe threshold, typically 50 calls, to avoid blocking the morning summary run.
Does Xero have a sandbox environment for testing restaurant integrations?
Xero provides a Demo Company environment accessible from the developer portal at developer.xero.com. Apps created after 2 March 2026 default to granular scopes and can be tested against the Demo Company. The Demo Company contains a pre-populated chart of accounts, contacts, and transactions, which makes it suitable for validating daily-summary journal posting, tracking category assignment, and VAT code mapping before connecting a live organisation. Sandbox rate limits mirror production limits, so idempotency and retry logic should be tested here as well. The Demo Company resets periodically, so do not rely on it for persistent audit-log testing. Use a dedicated test Xero organisation on a paid plan for that purpose.
How should UK VAT be treated when posting daily restaurant summaries?
UK restaurant operators must split daily sales into at least two VAT buckets on every manual journal. Use the 20% standard rate for prepared food and all alcoholic and soft drinks consumed on-premises, and the 0% zero rate for any unprepared food sold for home consumption. The tax type codes in Xero are OUTPUT2 for 20% standard and ZERORATEDINPUT, or the equivalent output code, for zero-rated lines. Under Making Tax Digital, every digital record from the POS through to the Xero VAT return must maintain a direct digital link, and no manual re-keying is permitted at any step. Retail schemes, such as point of sale, apportionment, or direct calculation, allow multi-site restaurants to calculate output VAT from daily gross takings rather than individual transactions, which aligns neatly with the daily-summary posting pattern described in this guide. Operators with turnover under £1.35 million may also use the cash accounting scheme, which defers VAT liability until payment is received rather than when the sale is invoiced.
What is the limit of Xero API calls for high-volume POS imports?
The practical ceiling for a restaurant group using the daily-summary method sits well within Xero’s limits. A single daily journal post per site consumes one API call. A group with 20 sites posting simultaneously uses 20 calls, which is a fraction of the 60-per-minute allowance. The daily cap of 1,000 calls (Starter) or 5,000 calls (Core and above) becomes relevant only if the integration also performs incremental syncs, reads tracking categories, fetches bank transactions for reconciliation, or retries failed posts. To stay within budget, use the If-Modified-Since header for incremental reads, set pageSize to 1,000 on any list endpoint, and cache tenantId and tracking category option IDs locally instead of fetching them on every run. For groups with more than 50 connected sites, the Core tier at $35 AUD per month provides 5,000 daily calls per organisation and is the minimum recommended tier for production use.
Conclusion: Automate Xero and Focus on Margin
Without POS-Xero integration, restaurants face data entry errors, missing transactions, incorrect tax calculations, delayed financial reporting, and difficulty tracking profitability as transaction volume grows. The phased approach above resolves every one of those problems, but it requires OAuth configuration, tracking category design, idempotency engineering, and ongoing rate-limit management.
Jelly removes that entire build burden. Invoices arrive by email or photo and are scanned automatically. POS sales from integration partners flow into Jelly in real time. A single daily summary lands in Xero before your team arrives each morning. Price Alerts flag supplier increases the same week they happen. Gross profit updates within minutes of every sale. One operator moved from 65% to 72% gross profit within 12 weeks on £500,000 in revenue. Cairn Lodge Hotel cut food costs by 5% in a single month. Amber restaurant saves £3,000–£4,000 every month, all at a flat £129 per site per month with no variable user fees or hidden implementation costs.
Ready to stop drowning your ledger in transactions? See how Jelly eliminates manual data entry with automated daily summaries, real-time margin visibility, and flat £129 per site pricing.