# Changelog

> What changed in the API, the MCP server and the CLI.

Source: /docs/reference/changelog

### 13 October 2026 (Brand-neutral identifiers)

**New identifiers.** New API keys start with `sk_test_` or `sk_live_`. Webhook deliveries carry `X-Webhook-Signature`, `X-Webhook-Event`, `X-Webhook-Event-Id`, `X-Webhook-Delivery` and `X-Webhook-Attempt`, with the user agent `Webhook-Delivery/1.0`. Create results and ERP message replies name the invoice `invoiceId`. MCP resources use `einvoicing://` URIs and tool results carry `_meta: { "einvoicing/environment": … }`. OAuth access tokens, refresh tokens, authorization codes and client ids start with `oat_`, `ort_`, `oac_` and `ocl_`.

**CLI** is published as `@alyabooks/cli` and runs as `alyabooks`; settings live in `~/.alyabooks/config.json` and the `ALYABOOKS_API_KEY`, `ALYABOOKS_API_URL` and `ALYABOOKS_ORGANIZATION_ID` environment variables.

**Nothing to migrate.** Keys, tokens, webhook subscriptions and integrations created earlier keep working on deployments that accept the previous identifiers. Verify signatures with the new header names when you next touch your webhook handler.

### September 2026 (v1.0)

**Public API v1.** Invoices (batch create, list, JSON/PDF/XML download, status with ASP and FTA timeline, validation, submit, send, payments, housekeeping), invoice numbers and series settings, incoming imports with content sub-resources, customers, products, custom fields, webhooks, account endpoints. API keys with scopes and test/live environments, `X-Organization-Id` for CA firms, rate limiting, request log.

**Webhooks.** 24 events, HMAC-SHA256 signatures, retries with back-off, delivery log, test deliveries, automatic pause after repeated failures.

**Custom fields.** Field definitions and per-kind templates; values on documents and lines, validated, printed on PDFs and included in webhook payloads.

**MCP server** at `POST /api/v1/mcp` with about 70 tools and 7 resources.

**CLI** `@alyabooks/cli` 1.0.

**Docs.** This site, the OpenAPI document at `/openapi.json`, `llms.txt`, `AGENTS.md` and `CLAUDE.md` for coding agents.

### October 2026 (v1.1)

**Catalogue depth.** Customers gain company/person, legal form, category, `defaultPriceListId`, contact persons (`/customers/{id}/contact-persons`) and delivery/billing addresses (`/customers/{id}/addresses`); Peppol lookup (`GET /customers/peppol-lookup`, `POST /customers/{id}/verify-peppol`). Products gain item number, GLN, cost price with margin, inventory tracking and category. New resources: `/bundles` (with `GET /bundles/{id}/lines`), `/price-lists` and `GET /products/{id}/price`.

**Projects** (`/projects`) with totals, `projectId` on invoice inputs, `?projectId=` list filter, `GET /projects/{id}/documents`. Webhook `project.created`.

**Recurring invoices** (`/recurring-invoices`) with schedules, automation, runs, preview, `POST /invoices/{id}/make-recurring`; daily runner. Webhooks `recurring_invoice.generated` and `recurring_invoice.failed`.

**MCP** grows to about 115 tools and adds the `recurring_schedules` resource. **CLI** adds `project`, `recurring`, `bundle`, `price-list`, `customer persons|addresses|peppol` commands.

### October 2026 (v1.2)

**VAT.** Tax rates per organization (`/settings/tax-rates`) with exemption reasons written into the XML (`taxExemptionReasonCode` / `taxExemptionReason` on lines); `supplyEmirate` on invoices; VAT 201 worksheet (`GET /vat/worksheet`, JSON or CSV), tax periods (`GET /vat/periods`) and saved returns (`/vat/returns`). Rounding is half away from zero everywhere (see [Rounding rules](/docs/reference/rounding)).

**Accounting exports.** `GET /exports/accounting` produces Zoho Books, Xero and QuickBooks Online CSV and Tally XML for issued invoices or accepted incoming invoices.

**MCP** adds eight VAT tools; **CLI** adds `tax-rate`, `vat` and `export accounting`.

### November 2026 (v1.3)

**Accounting connectors.** QuickBooks Online and Xero (OAuth) and Odoo (JSON-RPC) on the connector framework, each with a sandbox mode: `GET /connectors`, `POST /connectors/{id}/sync` (pull contacts and invoices, push issued invoices once), `GET /connectors/{id}/links`. Webhook `connector.synced`. See [Accounting connectors](/docs/guides/connectors).

**Pay-by-link.** Payment gateways (Stripe, Telr, PayTabs, Tap, mock) under Settings → Payments; `POST /invoices/{id}/payment-link`, `GET /payment-links`, `POST /payment-links/{id}/cancel`; public pay page at `/pay/{token}`; gateway confirmations settle the link and record the payment. Webhook `payment_link.paid`.

**Bank feeds.** Lean Technologies, Tarabut and mock connections, statement import (`POST /bank/import`), transactions with match suggestions (`GET /bank/transactions`), confirm/unmatch/ignore, optional automatic confirmation. Webhook `bank.transaction_matched`. See [Pay-by-link and bank feeds](/docs/guides/payments-and-bank-feeds).

**MCP** adds ten integration, payment and bank tools; **CLI** 1.2 adds `connector`, `pay-link` and `bank`.

### November 2026 (v1.4)

**Simulated receiving.** `POST /incoming/simulate` (Test mode only) generates supplier invoices for a scenario — `standard`, `mixed_vat`, `reverse_charge`, `credit_note`, `foreign_currency`, `wrong_buyer`, `totals_mismatch`, `duplicate` — from a sample supplier or one of your contacts, and receives them through the real Peppol pipeline (validation, duplicate check, notifications, webhooks). `GET /incoming/simulate` lists scenarios and suppliers.

**Email templates.** `GET /settings/email-templates`, `PUT` and `DELETE /settings/email-templates/{kind}/{locale}`: subject and body per document kind in English and Arabic with `{{placeholders}}`. `POST /invoices/{id}/send` without `subject` or `message` now uses the organization's template.

**Options.** `GET` / `PATCH /settings/options`: hidden modules, draft number reservation (drafts may carry a temporary `DRAFT-…` number that becomes the real number on validation), inventory on issue and negative-stock policy (`allow`, `warn`, `block`), duplicate customer numbers, default CC/BCC applied to sends that set none.

**MCP** adds `simulate_incoming_invoice`, `list_email_templates`, `save_email_template`, `get_options`; **CLI** 1.3 adds `import simulate`, `email-template` and `options`.

### November 2026 (v1.5)

**Options.** `GET` / `PATCH /settings/options` adds three fields:

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `allowManualNumbers` | boolean | `false` | Whether people may type document numbers in the app editor. Off: the number field is read-only and new documents take the next number of the series. The API and imports can always supply `invoiceNumber`. |
| `showTextBlocks` | boolean | `false` | Whether new invoices in the app editor show salutation, introduction, closing and signature. The subject line always shows. Quotes and letters are not affected. |
| `terminology` | object | `{}` | `{ "buyer": { "singular", "plural" }, "seller": { "singular", "plural" } }`: the words the app uses for contact types (defaults customer/customers and supplier/suppliers). Lower case, up to 30 characters; `null` resets. Stored `type` values stay `buyer`, `seller`, `both`. |

**Number series.** The app's Document Numbering settings now also list the `customer` (default `C-{n}`) and `item` (default `IT-{n}`) series.

### November 2026 (v1.6)

**Terminology for received documents.** `terminology.incoming` on `GET` / `PATCH /settings/options` sets what the app calls incoming invoices: `{ "incoming": { "singular": "bill" } }`, one of `incoming invoice` (default), `bill`, `receipt`, `purchase invoice`; the plural follows. Only app labels change; the `/incoming` resources and `incoming.*` webhook events keep their names.

**Behaviour change.** A `PATCH` with `terminology` now keeps the roles you leave out at their current words (before, they were reset to the defaults). Send `"terminology": null` to reset everything.

**E-invoice status.** Submissions still in flight are now checked in the background, so `invoice.delivered`, `invoice.reported` and `invoice.rejected` fire without anyone polling the status endpoint.

**Incoming invoice content.** `PATCH /import/incoming/{importId}` edits the content of drafts: header, `seller` / `buyer` / `delivery` parties, `lineItems` (with `itemDescription` and `taxCategory`), `vatBreakdown`, `paymentTerms`, `earlyPaymentDiscounts` and `paymentMeans` (several, with account owner, BIC, bank name and reference). `GET …/content` now returns parties in camelCase with the same keys, `paymentMeans` as an array (was one object with `meansCode` / `accountId`), `paymentTerms.earlyPaymentDiscounts`, and the delivery address under `delivery`. Received XML fills the delivery address, every payment means, BIC, item descriptions and GLN. `projectId` can be set on incoming invoices at any time and is returned in the summary. MCP `update_incoming_invoice` and CLI `import update` cover the same edits.

**Simulation.** New scenario `with_pdf` for `POST /incoming/simulate`: a valid invoice with the supplier's PDF embedded in the XML.

### October 2026 (v1.3)

**Paid in advance and rounding.** Invoice inputs accept `prepaidAmount`, `roundingAmount`, `prepaymentInvoice` and `items[].billingPeriod`; responses add `payableAmount`, and `outstanding` follows it.

**Locked periods.** Filing a VAT return locks its period; lock dates `lockDateAll` and `lockDateNonAdmin` and `fiscalYearStartMonth` in `/settings/options`. Writes into a locked period return `409 period_locked`. New `POST /vat/returns/{id}/reopen`, `GET /vat/check-date`, scope `periods:manage`, webhooks `vat_return.filed`, `vat_return.reopened` and `lock_date.changed`, MCP tools `reopen_vat_return` and `check_period_date`. The `reopen: true` flag on `POST /vat/returns` now needs `periods:manage`.

**Errors.** Permission errors from the database return `403` (were `500`).

**Account.** Webhook `organization.ownership_transferred`. Two-factor login and section access apply to people signing in to the app; API keys are not affected.

### Planned (Next)

CRM lead sync, idempotency keys, OAuth for third-party apps.

### October 2026 (v1.6)

**Deemed supplies have nothing due.** An invoice whose `transactionTypes` include `deemed_supply` is stored and returned with no `dueDate`, no `paymentTerms` and an empty `paymentMeans`, whatever the input carried, and its `paymentStatus` is the new value `nothing_due`: `outstanding` is `0`, project `outstandingTotal` leaves it out, it is never overdue, `invoice.paid` is never emitted for it and `POST /invoices/{id}/payment-link` refuses it. The value is additive; code that switches on `paid` / `unpaid` should treat it like `paid`. `paymentStatus` filters accept it.

**Rules applied up front.** Transaction types a document kind forbids (`summary_invoice`, `deemed_supply`, `profit_margin` on 480 and 81, IBR-157-AE), line VAT categories a kind or type fixes (IBR-122-AE, IBR-116-AE) and document-level allowances on a margin scheme invoice (IBR-114-AE) are still reported by validation through the API; the web editor now prevents them before validation.

### October 2026 (v1.7)

**ERP intake.** `POST /erp/{connector}/messages` takes what an ERP pushes, a CargoWise UniversalTransaction (bare, in a UniversalInterchange or a SOAP envelope, credit notes with their `CreditNoteReason`) or one InvoiceInput as JSON, stores it, maps it through the organisation's charge map (`GET/PUT /erp/connectors/{type}`) and creates and submits the invoice. A resend answers `duplicate`; failures are kept and can be replayed (`GET /erp/messages`, `GET /erp/messages/{id}`, `POST /erp/messages/{id}/replay`). HTTP Basic authentication with the key as password is accepted. See [ERP intake](/docs/guides/erp-intake).

**Dry run.** `POST /invoices/validate` maps and validates an InvoiceInput, or an ERP message with `?connector=cargowise`, without storing anything: the report, mapping notes and a preview.

**Explained errors.** Every validation issue carries `path` (the field as you sent it), `scope` (`document` or `organization`), Alya Books's `explanation` and `fix` in English and Arabic, and a public `docsUrl`; input-check errors carry `path` and `scope` too. Invoice webhook payloads add `validation` and, on `invoice.rejected`, `rejection` with the stage and the provider's error. See [Errors](/docs/reference/errors).

**MCP** adds eight ERP tools (`dry_run_invoice`, `dry_run_erp_message`, `send_erp_message`, `list_erp_messages`, `get_erp_message`, `replay_erp_message`, `list_erp_connectors`, `update_erp_connector`), marks submitting, sending, replaying and reopening a VAT return as destructive, and names the environment (`test` or `live`) in every result's `_meta`.

**Docs.** Every page has Copy as Markdown, View as Markdown, Open in Claude and Open in ChatGPT; each page is plain Markdown at its address plus `.md`, and the whole site is `/docs/llms-full.txt`.

### October 2026 (v1.8)

**MCP over OAuth.** claude.ai, ChatGPT and other MCP clients can connect as custom connectors with a sign-in instead of an API key: protected resource and authorization server metadata under the API base, dynamic client registration, authorization code with PKCE, rotating refresh tokens, revocation. The user approves the organisation, test or live and the scopes in the Alya Books app; connections are listed and revoked under API access → API keys → Connected apps. Access tokens work on `/mcp` only. See [MCP server](/docs/guides/mcp-server).

**Charge maps merge.** `PUT /erp/connectors/{type}` takes `mode: "merge"` with `removeChargeCodes` / `removeVatCodes`; `update_erp_connector` always merges; the audit log keeps the previous maps.

### October 2026 (v1.9)

**Invoice PDFs without a PDF service.** `GET /invoices/{id}?format=pdf`, `download_invoice` and email attachments return the PDF of invoices, credit and debit notes and proformas on every environment; Alya Books draws them with the same generator as the app.

**Download links.** `GET /invoices/{id}/download-link?format=pdf|xml|html` stores the file privately and returns a signed `url` that works for 15 minutes without an API key. `download_invoice` returns a PDF this way by default (`delivery: "inline"` for base64).

**Draft buyer details.** A customer's TRN or name change now reaches its draft and validated invoices.

### October 2026 (v1.10)

**Document designs.** `GET /design-templates` lists the organisation's PDF designs with their layout: `standard`, or `logistics` with a shipment panel (job number, house bill, references, custom fields shown on PDF). Invoices take `designTemplateId` on create and through `PATCH /invoices/{id}`; ERP connectors take `designTemplateId` so their invoices use it. MCP: `list_design_templates`, and `designTemplateId` on `update_invoice_housekeeping` and `update_erp_connector`.

**Invoice PDF.** Prints the buyer's address and trade licence under Bill To, the design's accent colour and the company logo (PNG or JPEG), and custom fields flagged "show on PDF".

### October 2026 (v1.11)

**CargoWise envelopes.** `POST /erp/cargowise/messages` accepts any Content-Type and unwraps the Universal XML from SOAP (elements, escaped text or base64 gzip stream), JSON fields, base64, gzip and form posts. Messages store and return the sender's `messageId` and the `envelope` they arrived in; the dry run (`POST /invoices/validate?connector=cargowise`) unwraps the same way.

**Security.** Bank matching and payment links refuse callers who are not signed in; connector credentials are no longer readable by organisation members; scheduled jobs refuse every call when their secret is not configured.

### October 2026 (Docs)

**CargoWise integration kit.** New pages for integrators: [CargoWise integration kit](/docs/guides/cargowise-integration), [Testing a CargoWise integration](/docs/guides/cargowise-testing), [CargoWise field mapping](/docs/reference/cargowise-field-mapping) (also as CSV), [Replies to the ERP](/docs/reference/erp-replies) and [Status updates back to the ERP](/docs/guides/erp-status-updates), with a charge-code template to download. Background jobs now run on a schedule: FTA status checks and webhook retries every 5 minutes, the Peppol fetch every 15 minutes, daily jobs at 02:00 and 18:45 UAE time.
