<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Byte8 Xero Accounting Blog</title>
        <link>https://magento-xero.byte8.dev/blog</link>
        <description>Byte8 Xero Accounting Blog</description>
        <lastBuildDate>Thu, 30 Apr 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[v1.0.0 — initial release]]></title>
            <link>https://magento-xero.byte8.dev/blog/v1-0-0-release</link>
            <guid>https://magento-xero.byte8.dev/blog/v1-0-0-release</guid>
            <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The first public release of Byte8 Xero Accounting is out. SaaS connector for Magento 2 → Xero — invoices, credit notes, customers, products, and payments syncing within minutes, with full sync-status visibility from the Magento admin and side-by-side coexistence with Sage Accounting on the same Magento install.]]></description>
            <content:encoded><![CDATA[<p>The first public release of <strong>Byte8 Xero Accounting</strong> is out. SaaS connector for <strong>Magento 2 → Xero</strong> — invoices, credit notes, customers, products, and payments syncing within minutes, with full sync-status visibility from the Magento admin and side-by-side coexistence with Sage Accounting on the same Magento install.</p>
<h2 class="anchor anchorWithStickyNavbar_gijT" id="whats-in-v100">What's in v1.0.0<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#whats-in-v100" class="hash-link" aria-label="Direct link to What's in v1.0.0" title="Direct link to What's in v1.0.0" translate="no">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="connect-flow">Connect flow<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#connect-flow" class="hash-link" aria-label="Direct link to Connect flow" title="Direct link to Connect flow" translate="no">​</a></h3>
<ul>
<li><strong>Pairing-code Connect</strong> — generate a 30-min code in Magento admin, paste into <code>ledger.byte8.io</code>, the chassis handshakes back. No OAuth client secret on disk, no callback URL wrangling.</li>
<li><strong>Xero OAuth</strong> — fully chassis-side. Tokens encrypted at rest (AES-GCM), refreshed transparently, never seen in PHP. Single global API endpoint (<code>api.xero.com/v2</code>); sandbox available on request.</li>
<li><strong>Per-provider routing</strong> — outbox carries <code>provider</code> column; webhook URL carries <code>?provider=xero</code> query. Sage + Xero can pair on the same tenant + the same Magento install without colliding.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="outbound-sync-magento--xero">Outbound sync (Magento → Xero)<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#outbound-sync-magento--xero" class="hash-link" aria-label="Direct link to Outbound sync (Magento → Xero)" title="Direct link to Outbound sync (Magento → Xero)" translate="no">​</a></h3>
<ul>
<li><strong>Invoices</strong> (<code>invoice.created</code>) — Open AR with full line items, addresses, currency, per-line discounts, dedicated shipping line. Always carries <code>payment_terms_in_days</code> (Xero quirk #1).</li>
<li><strong>Payments</strong> (<code>invoice.paid</code>) — <code>bank_transaction_explanation</code> against the matching Xero invoice URL, routed per the per-tenant payment-method map. Invoice transitions Open → Paid in Xero.</li>
<li><strong>Credit notes</strong> (<code>creditmemo.created</code>) — refunds routed to the same contact as the original invoice, with shipping refund line and original-invoice date for accountant reporting.</li>
<li><strong>Customers</strong> (<code>customer.upserted</code>) — Magento customer → Xero contact. Lookup-by-email self-heal on duplicate POST 422.</li>
<li><strong>Products</strong> (<code>product.upserted</code>, opt-in) — simple → Xero <code>Products</code>, virtual / downloadable → <code>Services</code> by default. Per-Magento-type item-type override available. Composite types skipped intentionally.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="coexistence-with-sage-accounting">Coexistence with Sage Accounting<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#coexistence-with-sage-accounting" class="hash-link" aria-label="Direct link to Coexistence with Sage Accounting" title="Direct link to Coexistence with Sage Accounting" translate="no">​</a></h3>
<ul>
<li>Both connectors share the <code>byte8/module-client</code> chassis (outbox, JWT auth, sync-state mirror). Outbox <code>provider</code> column + per-provider grid join aliases (<code>byte8_sync_fa</code> table alias, <code>_xero</code> column suffix) keep the two from trampling each other.</li>
<li>Sales → Invoices grid renders <strong>two columns</strong> when both connectors are installed — "Sage Status" + "Xero Status" — each with its own chip and tooltip. Same on credit-memo grid + invoice / credit-memo detail pages.</li>
<li>Independent pairing + disconnect surfaces; one provider's outage doesn't block the other.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="magento-admin-visibility-pr7">Magento admin visibility (PR7)<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#magento-admin-visibility-pr7" class="hash-link" aria-label="Direct link to Magento admin visibility (PR7)" title="Direct link to Magento admin visibility (PR7)" translate="no">​</a></h3>
<ul>
<li><strong>Xero Status column</strong> on Sales → Invoices and Sales → Credit Memos grids. Sortable + filterable. Chips: ✓ Synced / ⏳ Pending / ⏸ Skipped / ✗ Failed / —. Hover for Xero invoice URL, skip-reason, or error code.</li>
<li><strong>Xero Accounting info block</strong> on every Invoice + Credit Memo detail page — chip, Xero URL, last sync timestamp, skip / error context.</li>
<li><strong>Write-through pending mirror</strong> — chip appears the moment the merchant clicks Submit Invoice, not 60 s later when the cron drain catches up.</li>
<li><strong>Dead-letter banner</strong> on the config page surfaces failed deliveries + links to the <code>byte8:client:outbox:inspect</code> triage CLI (provider-filterable via <code>--provider=xero</code>).</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="operator-surfaces">Operator surfaces<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#operator-surfaces" class="hash-link" aria-label="Direct link to Operator surfaces" title="Direct link to Operator surfaces" translate="no">​</a></h3>
<ul>
<li><strong>Console commands</strong> for outbox triage: <code>byte8:client:outbox:{inspect,requeue,cleanup}</code>. The previous <code>byte8:sage:outbox:*</code> namespace is renamed — outbox triage is provider-agnostic and lives on the shared chassis CLI.</li>
<li><strong>Settings dashboard</strong> at <code>ledger.byte8.io/dashboard/bindings/{id}/settings</code> with five cards: Sync Behaviour, Xero Defaults, Payment-method Map, Item-type Map, Commercial Knobs. Server-side validation against the live Xero reference cache; red-underline field errors before save.</li>
<li><strong>Sync history</strong> dashboard at <code>ledger.byte8.io/dashboard/sync</code> with full per-event audit + per-row retry button. Provider filter chip lets you scope to Xero rows only.</li>
<li><strong>Disconnect dialog</strong> — when disconnecting from the chassis dashboard, a structured "What gets removed" / "What stays" breakdown surfaces before the operator commits.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="catalogued-xero-quirks">Catalogued Xero quirks<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#catalogued-xero-quirks" class="hash-link" aria-label="Direct link to Catalogued Xero quirks" title="Direct link to Catalogued Xero quirks" translate="no">​</a></h3>
<p>Two non-obvious Xero v2 behaviours captured + worked around:</p>
<ul>
<li><strong>§1 — <code>payment_terms_in_days</code> required on every POST.</strong> Even on net-cash invoices, even on £0 lines. Chassis always sends a value (default 30, configurable per binding).</li>
<li><strong>§2 — Numeric fields stringified on responses.</strong> <code>exchange_rate: "1.0"</code>, <code>total_value: "100.00"</code>, etc. Chassis decodes create responses through minimal envelopes that only read <code>url</code> to dodge the asymmetric encoding.</li>
</ul>
<p>Full catalogue: <code>apps/ledger/__docs/XERO_API_QUIRKS.md</code>. New entries land any time the worker logs a 4xx that isn't an obvious operator typo.</p>
<h3 class="anchor anchorWithStickyNavbar_gijT" id="distribution">Distribution<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#distribution" class="hash-link" aria-label="Direct link to Distribution" title="Direct link to Distribution" translate="no">​</a></h3>
<ul>
<li><code>byte8/magento-xero-accounting</code> on Cargoman (Byte8 private Composer registry) for the closed-beta cohort. Public Packagist + Magento Marketplace listing follow.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_gijT" id="intentionally-not-in-v1">Intentionally NOT in v1<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#intentionally-not-in-v1" class="hash-link" aria-label="Direct link to Intentionally NOT in v1" title="Direct link to Intentionally NOT in v1" translate="no">​</a></h2>
<ul>
<li><strong>No Xero Status chip on Sales → Orders or Customers grids.</strong> Orders aren't synced directly (we sync invoices, 0..N per order); customer mirror is single-row but the chassis doesn't publish contact-resolution status as a grid signal yet. Order-rollup info block + customer-block surfacing are planned v1.1+.</li>
<li><strong>No <code>provider_reference</code></strong> (e.g. Xero's human-readable invoice number) populated on the chip yet. Column exists in the schema; chassis sends <code>null</code> today. v1.1+ — needs a getter on the provider trait so <code>reference</code> rides back with the Xero create response.</li>
<li><strong>No manual "Resync now" button on Magento detail pages.</strong> Operators use the chassis dashboard's per-row retry; no need to duplicate the surface yet.</li>
<li><strong>No standalone <code>payment.captured</code></strong> for offline payments. Magento has no API to attach an offline payment to an existing invoice — accountants reconcile manually in Xero's bank feed when the cheque / bank transfer lands.</li>
<li><strong>No Xero → Magento writeback.</strong> Enterprise on request — needs Xero webhook surface + Magento write endpoints + conflict-resolution policy. Build only on a custom contract.</li>
<li><strong>No stock-level sync.</strong> Xero's product catalog isn't designed to track inventory; merchants who need stock sync use Sage Accounting instead.</li>
<li><strong>No projects / timeslips.</strong> Out-of-scope for an e-commerce connector.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_gijT" id="whats-next-v11">What's next (v1.1+)<a href="https://magento-xero.byte8.dev/blog/v1-0-0-release#whats-next-v11" class="hash-link" aria-label="Direct link to What's next (v1.1+)" title="Direct link to What's next (v1.1+)" translate="no">​</a></h2>
<p>If you have specific asks, email <code>helo@byte8.io</code>. We'll prioritise based on the design-partner cohort feedback. Likely first hits:</p>
<ul>
<li><code>provider_reference</code> end-to-end (the human-readable Xero invoice numbers)</li>
<li>Customer detail-page block (per-binding Xero contact URL)</li>
<li>Order detail-page rollup block (per-invoice statuses on the order)</li>
<li>Backfill CLI for pre-PR7 invoices</li>
<li>Per-customer payment terms map (currently binding-level only)</li>
</ul>]]></content:encoded>
            <category>release</category>
        </item>
    </channel>
</rss>