Torna alla documentazione dell'API

Il registro delle modifiche dell'API

Ogni modifica al contratto pubblico dell'API (/v1) e degli eventi che manda, giorno per giorno, con la fonte nella storia della piattaforma. Le regole su che cosa è compatibile e sulla deprecazione sono nella guida, alla voce «Versioni e deprecazione».

Il registro è in inglese, come il contratto OpenAPI: è il testo che Core verifica contro la storia della specifica.

Il registro in Markdown

Every change to the public contract of the API (/v1) and of the events it sends, day by day since 7 September 2026. The rules on what is compatible and on deprecation are in the guide, section 10 («Versions and deprecation»).

  • Compatible: an integration written against the previous contract keeps working without changes (a new operation, a new optional field, a new response field, a new error code, a new event type). Ignore what you do not know.
  • Breaking: an integration written correctly against the previous contract may stop working, or behave differently.
  • Documentation: the document describes better what the API already did; no behaviour changed.

Before 1 November 2026 there was no versioning policy, and some breaking changes were made inside /v1 while the API had no integrator in production: they are listed below as Breaking, so that nothing is hidden. In the platform's own register (core.api_audit, read on 1 November 2026) the only live calls ever made are 17 calls of 7 September 2026, from three keys of a test account revoked the same day; no live key is active and no webhook endpoint is registered. From 1 November 2026 a breaking change no longer happens inside /v1: it comes with a new path version or through a deprecation with at least 12 months of notice (Deprecation and Sunset headers on every response).

The date is the day the change was written into the published specification (docs/openapi.json) or, for a change of behaviour, into the code; the release that answers you is in the x-core-version header, and «live from» names the first release that carried it where the platform's records say so. Each entry cites its source in the history of the platform (commit). This file is checked against the history of the specification by tests/api/registro-contro-storia.mjs: every operation and event type that ever appeared in the specification has its entry on the day it appeared.

2026-11-01

  • Compatible · new test route GET /v1/_deprecation_probe (gai_test_… keys only; 404 ROTTA_SCONOSCIUTA with a live key): it carries the Deprecation (RFC 9745), Sunset (RFC 8594) and Link: rel="deprecation" headers of a deprecated operation, so you can test the code that reads them. It is deprecated by construction and is never retired. From today a deprecated operation carries deprecated: true and x-deprecation in the specification and the three headers on every response once the route is known (not on a 401). No real operation is deprecated. Source: corsia VER-1, e7238d40.
  • Compatible · GET /v1/products: next_cursor is present only when another page really exists (on a last page that happens to be full it is now null; before, it was set on every full page and the next call came back empty). Following next_cursor until null returns the same products. Live from core-api v23. Source: 96118f03, c4fcfa0d (SANDBOX-2).

2026-10-31

  • Breaking · webhooks follow Standard Webhooks 1.0.0: the headers webhook-id (the event id, the same on every retry), webhook-timestamp (Unix seconds of the attempt) and webhook-signature: v1,<base64> over <id>.<timestamp>.<body> (two signatures during a secret rotation) replace the five x-gai-* headers; the event type and the attempt stay in the body (type, attempt). Verify with the official standardwebhooks library. No endpoint was registered when the format changed. Live from core-events v20. Source: 525691396, 7cc675668, merged in 4b0a71225 (HOOK-STD-1).
  • Breaking · the signing secret is whsec_<base64 of 32 bytes> and the HMAC key is the decoded bytes (before: whsec_ and 64 hexadecimal characters, used whole). Source: 525691396 (HOOK-STD-1).
  • Breaking · how your receiver's answer is read: 410 Gone disables the endpoint (no more deliveries until it is created again); redirects are not followed; Retry-After lengthens the wait (at most 24 hours); every other 4xx/5xx is retried. Source: 525691396 (HOOK-STD-1).
  • Compatible · longer retries and more time to answer: ten attempts over about three days (immediately, then 1 min, 5 min, 30 min, 2 h, 5 h, 10 h, 14 h, 20 h, 24 h, with ±10 % jitter) instead of six in about 8.5 hours; 15 seconds to answer instead of 10. Source: 525691396 (HOOK-STD-1).
  • Compatible · every event body carries the new field timestamp (equal to occurred_at). Source: 7cc675668 (HOOK-STD-1).
  • Compatible · secret rotation from the portal, with two valid signatures for an overlap of up to 72 hours (a portal route, not /v1). Source: b40a428eb (HOOK-STD-1).
  • Compatible · new operations GET /v1/errors and GET /v1/errors/{code}: the catalog of error codes, readable without a key; every error response carries the new field error.doc_url, the page of its code. Live from core-api v21. Source: f85bb86f, merged in 2cfb89f3 (DOCS-AGENTI-1).
  • Compatible · GET /v1/openapi.json is readable without a key, with ETag, Cache-Control: public, max-age=300, 304 on If-None-Match and Access-Control-Allow-Origin: *. Live from core-api v21. Source: f85bb86f (DOCS-AGENTI-1).
  • Documentation · the specification is published in English, with a tested request and response example for every operation and event; the limit bounds (1 to 200) already enforced by the code are written in the schemas; AGENTS.md, the integration prompt and the quickstart. Source: f85bb86f (DOCS-AGENTI-1).
  • Compatible · PUT /v1/customers also accepts the field names of the customer model (customer_ref as an alternative to external_ref, full_name, street, house_number, city, postal_code, floor, intercom, delivery_notes, language, exemption); a field of neither list is not written and the response says so in warnings (CAMPO_SCONOSCIUTO). Live from core-api v19. Source: 81f58e6d, merged in db852976 (VALID-1).
  • Breaking · PUT /v1/customers: the phone must be international E.164 (TELEFONO_NON_E164; before, any text was accepted) and is stored as + and digits; new rejections CAMPO_IN_DUE_POSTI, VALORE_NON_AMMESSO, TESTO_TROPPO_LUNGO. Live from core-api v19. Source: 81f58e6d (VALID-1).

2026-10-30

  • Breaking · PUT /v1/products became a merge: on a product that already exists only the fields the item names are updated, attributes are merged and a key set to null is removed (before, an item with only the price cleared the other fields). Live from core-api v16. Source: c3be5b5e2, 5f57be07 (DATA-C2).
  • Breaking · the catalog contract fields (min_order_qty, min_order_unit, sold_by_weight, avg_piece_weight_kg, items_per_pack, pack_only, stock_managed, unit_price, gross_weight_kg, tare_kg, list_price, subcategory, vat_rate, diet_tags, the offer_* fields) are typed fields of the product and are validated also when they arrive inside attributes, where before they entered unchecked; new item codes NUMERO_NON_VALIDO, UNITA_NON_AMMESSA, DATA_NON_VALIDA, BOOLEANO_NON_VALIDO, VALORE_NON_AMMESSO, DATE_INVERTITE, CAMPO_IN_DUE_POSTI. Source: c3be5b5e2 (DATA-C2).
  • Compatible · the batch responses of products, inventory and customers carry the new field warnings (the item is written, but something in it will not be used, for example OFFERTA_NON_SCONTATA). Source: 5f57be07 (DATA-C2).
  • Breaking · PUT /v1/inventory: an item with store_code is rejected (PUNTO_VENDITA_SCONOSCIUTO) unless the shop has that point of sale; before, store_code was ignored and the price applied to the whole shop. Source: c3be5b5e2 (DATA-C2).
  • Compatible · PUT /v1/inventory also accepts the strike-through list_price, the offer fields (offer_price, offer_start, offer_end, offer_min_qty, offer_label; null removes) and is_online. Source: 5f57be07 (DATA-C2).
  • Compatible · new operations for the catalog lifecycle: DELETE /v1/products/{sku} (withdraw a product: it is switched off, not deleted; sending it again puts it back on sale), POST /v1/products/snapshots and POST /v1/products/snapshots/{snapshot_id}/commit (a full snapshot that switches off what it does not contain, with a 90 % gate; optional snapshot_id in PUT /v1/products), GET /v1/catalog/freshness, GET /v1/catalog/feed, PUT /v1/catalog/feed and POST /v1/catalog/feed/run (a scheduled catalog feed). Live from core-api v16; the freshness read answered 500 on v16 and works from v17. Source: 5f57be07, 359226607 (DATA-C2, API-TX1).
  • Compatible · new operation PUT /v1/order_history with the new scope history:write (shops that live on GroceryAI only). Source: 201de93f, merged in 50b4b304 (DATA-C3).
  • Compatible · new operation POST /v1/chat_identity_tokens (scope chat:write, secret key): opens the site chat to a customer signed in on your site. Source: a1d2e892, merged in e36ff354 (WEB-ID-1).
  • Compatible · new operations GET /v1/rules, PUT /v1/rules, POST /v1/rules/preview, GET /v1/store_texts and PUT /v1/store_texts with the new scopes rules:read, rules:write, texts:read, texts:write; their error envelope may carry a list errors next to error. Live from core-api v17. Source: cf3546b0, merged in 853b5293 (DATA-C4).
  • Compatible · new operations GET /v1/stores and PUT /v1/stores (points of sale; the PUT is the whole list); PUT /v1/inventory accepts a declared store_code; optional store_code parameter in GET /v1/products. Live from core-api v18. Source: 8db0588e, merged in 3eaac8ed (DATA-C6).

2026-10-27

  • Compatible · new field order.currency (ISO 4217) in the orders of shops that live on GroceryAI. Live from core-chat v66 and core-events v16. Source: b28ae23a (COMM-4B).

2026-10-26

  • Compatible · in the order event, order.customer.phone and email are filled when the customer gave them in the chat (fields that already existed and could be null). Source: e1c7a56d7 (ORD-6).

2026-10-23

  • Breaking · Idempotency-Key is scoped to the shop and the environment (before, the same key used first with a test key and then with a live one replayed the test response in live without writing) and expires after 24 hours (before, never). Live from core-api v14. Source: 8327216b (SEC-2).
  • Compatible · new scope chat:write (opening chat sessions from your server with the secret key). Source: 8327216b (SEC-2).

2026-10-22

  • Breaking · the meaning of delivered_amount in POST /v1/orders/{order_id}/status changed: from «the value of the goods, without delivery or extras» to «the total the customer paid for what was delivered, delivery and extras included». The route accepts the same body; what the shop must send changed. Source: 05f4c844 (BILL-2).

2026-10-21

  • Compatible · new operation POST /v1/orders/{order_id}/status: the shop reports what happened to an order (delivered, substituted, not delivered, returned). Live from core-api v13. Source: aaf3773d, merged in 098d60ef (BILL-1).

2026-10-13

  • Documentation · the specification describes the events sent to your endpoint, order.confirmed, support.requested and webhook.ping (section webhooks), the shapes of every response, the error codes per status and the headers; info.version stays 1.0.0. The guides for integrators are published. Source: 6d4643a5, 0e3b08c69 (PORTAL-D10).
  • Compatible · a failure between the reservation of an Idempotency-Key and the handler no longer leaves the key stuck (before: 500, then 409 RICHIESTA_IN_CORSO forever; now the retry replays the 500). Live from core-api v8. Source: d6c9e326b (PORTAL-D10).

2026-10-12

  • Compatible · new operations GET /v1/support_requests and POST /v1/support_requests/{support_id}/ack: customer support requests in pull, with acknowledgement; new event type support.requested. Live from core-api v7. Source: 6d34ddcf (P232).

2026-10-11

  • Compatible · the order event order.confirmed reaches version 2 (schema_version: 2): order.customer carries channel, fullName, address, city, zip, phone, email, notes, missing_fields; no field removed. Source: cafb061b0 (ORD-1), 51547f1a9 (ORD-3).

2026-10-07

  • Compatible · a second kind of key, the publishable gai_pk_<environment>_…, without scopes: on /v1 it opens nothing (403 AMBITO_MANCANTE); a key whose name and record disagree on its kind gets 401 CHIAVE_INCOERENTE. Source: c0cb23b9a (W1).

2026-09-14

  • Breaking · PUT /v1/products: a price in a currency other than the shop's is a rejected item (before, any ISO 4217 code was accepted). Source: 32173ff30 (D4).
  • Compatible · new header x-core-version on every response (the release that answered). Source: 9d1d53bff (P29).

2026-09-07

  • Compatible · first published contract: GET /v1/openapi.json, PUT /v1/products, GET /v1/products, PUT /v1/inventory, PUT /v1/customers, GET /v1/customers/{external_ref}, GET /v1/orders and POST /v1/orders/{order_id}/ack; API keys per account with environment (test, live) and scopes, rate limit with Retry-After, batches of up to 500 items validated one by one, Idempotency-Key on writes, request_id on every response, one error format. Source: 18453327 (D1).
  • Compatible · signed webhooks (x-gai-signature: sha256=<hex>, HMAC-SHA256 of timestamp and body) with retries. Source: 78ce7e5fd (D2).
  • Breaking, reverted the same day · GET /v1/orders and POST /v1/orders/{order_id}/ack answered 409 to test keys; the same day the 409 became a filter: a test key sees the test orders, a live key the real ones, and every event carries environment. Source: c78c8e11, def35b43 (D1, D3).