is_percentage_processing_fee flag (default: false / fixed amount). The processing_fee_amount is automatically computed server-side on every save using the order/quote base (subtotal + tax + shipping − discounts, clamped to $0). Applies across the v2 API, CSV import, and quote-to-order conversion.quote_number is now automatically generated from the record ID on creation. The field is no longer required on POST or CSV import.Quotes
items[] flattened to canonical shape; id added to all nested objectsquote_status defaults to Draft when not supplied; enum and reference integrity validation added; quote_contact_id correctly derived; geo_json cascade fixedquote_number now enforceditems[] flattened; id added to nested objectsOrders
items[] flattened to canonical shape; doc examples correcteditems[] flattened in response; *_contact_id fields removed (not in schema); geo_json cascade fixeditems[] flattened in response; order_company correctly marked as not requiredOrder Items
order.uuid now rejectedpage/size required flags corrected; 400 example fixed; nested id fields addedOrder Discounts
id added to nested order and discount objects across GET list, GET single, DELETEOrder Shipping Packages
Payments
id added; stale enum values removed; 404 shape correctedid fixedQuote Discounts
id added to nested quote and discount objectsQuote Items
id added to nested objects in DELETE 200 doc exampleQuote Shipping Packages
page/size correctly marked Optionalid added to nested objectsSystem Fields
Custom Fields
id validation addedConfiguration
livemode rejectedmeasurement_unit and weight_unitFreight Suppliers
page/size correctly marked Optional in GET list docProducts
effective_price is now always computed server-side on create/update and cannot be overridden via the API or CSV importeffective_price on all existing products and variants using paginated queries (500 per page) to avoid table locksid sub-field added to all nested relation objects (order, quote, contact, company, discount, product, product variant) across orders and quotes v2 API responses and doc examplesIs Percentage Processing Fee columnitems[] on orders and quotes has been flattened from { id, properties: { uuid, ... } } to a flat object { id, uuid, ... } across all endpoints (GET list, GET single, POST, PATCH, DELETE). Any client reading item.properties.* will break.quote_number is now required on quotes PATCH.*_contact_id fields removed from Orders POST — these were not in the order schema and are no longer accepted.processing_fee_amount is now server-computed on every save. Any client-supplied value is ignored and overwritten. Clients should stop sending this field and read it back from the response.effective_price — effective_price on products and product variants now always stores the ex-tax active list price. Previously it stored the raw sale_price or regular_price regardless of tax-inclusive flags.
is_tax_included, is_sale_price_tax_included, or is_variant_sale_price_tax_included set to true will see effective_price change after the backfill migration runs.effective_price will reorder. Re-test any storefront listing, sort, or price-range filter that reads this field.effective_price is read-only. It is computed server-side on every create/update; values sent in POST/PATCH bodies or CSV imports are ignored and overwritten — read it back from the response.total_price is unchanged. It stays tax-inclusive.POST /crm/api/v2/custom-fields/contacts endpoint.POST /crm/api/v2/custom-fields/companies endpoint.created_by (set once at creation, immutable on edit) alongside last_updated_by, so the original creator stays visible after the activity has been edited.{"error":"unauthorized"}) on the original URL across all HTTP methods. Previously the response was a 302 redirect to the login page; clients that followed the redirect must update to handle the 401 directly.errors (array) to singular error (string). Clients that parse the errors array on this endpoint must switch to error.PlaceAutocompleteElement), keeping the feature working as Google retires the legacy widget.old_url contained a leading slash (was producing double-slash URLs)./v2/contacts/{uuid} now preserves every untouched property — previously, sending only the field you wanted to change could either return a 400 error or null out the rest of the contact./v2/tasks/{uuid} and /v2/tasks/comments/{uuid} no longer returns 400 when the request body omits a field; untouched properties are preserved, matching the contacts behaviour.Faster related_records: Reduced object allocations in related_records, improving performance up to 4x.
Asset cache invalidation now per-instance: Changed the internal implementation of cache invalidation for assets. The updated=... query parameter appended by the asset_url (and asset_path) filter is now derived from a per-instance assets_updated_at timestamp that is bumped whenever assets change, instead of being derived per asset. This means all asset URLs are invalidated together when any asset is updated, ensuring CDN caches stay consistent.
Batched page loading on deploy: Pages are now loaded in batches during deploy, providing better support for very large deploys - particularly those containing pages generated by Static Site Generators (SSG).
Faster Instance Clone asset dump: The asset manifest step of pos-cli clone is significantly faster, reducing the time spent in the export phase of cloning instances with large numbers of assets.
InstanceClone clone-record status on export failure: Previously, InstanceClone could leave the target instance's clone record in pending indefinitely when export failed (for example due to an oversized file). Failures are now surfaced cleanly as a terminal failed status with a sanitized error message, so pos-cli polling resolves instead of hanging.
cache_control argument for admin_assets_create and admin_asset_update mutations: When provided, the value (for example max-age=31536000, public) is stored in the asset's metadata and applied as the Cache-Control header on the underlying object in the file storage provider (S3, R2, etc.), allowing CDNs and browsers to cache assets according to your policy.
authorization_policies argument for admin_page_create and admin_page_update mutations: Authorization policies can now be associated with a page by name (the same identifier used in Liquid frontmatter, e.g. page_policy or modules/my_module/page_policy), in addition to the existing authorization_policy_ids. Names and ids can be combined; all provided names must resolve to existing AuthorizationPolicy records.
url argument in admin_assets_create: Asset URLs are now derived from the asset name and the per-instance CDN, so the argument is ignored. Upload bytes via admin_assets_presign_urls first, then call admin_assets_create without the url argument. The argument will be removed in a future release.search_by / keyword / exact interact, and how search combines with pagination and sort./admin/api/<module>/<resource>#<endpoint>. Older URLs redirect there automatically so existing bookmarks and shared links keep working.event_uuid on event sponsors, cart_uuid on cart items) now show a description instead of rendering blank..file_name, .extension, .url) under upload fields. The information is still available in the resource's response Object reference where it belongs.axios HTTP client from 0.27.x (end-of-life) to 1.16.0, picking up two years of security patches and bug fixes.