Changelog

Track breaking changes, new features, and improvements to the Pixee PIM API.

v6.42.0 — app API

  • No public route was added, removed or changed: the public reference stays at 635 paths and 751 operations, and the public contract v1 (/ext, /windev) is unchanged.
  • This release adds, in the app, Settings › Supervision › Service status (GET /settings/etat-service: service state, last successful backup, instance version and whether it is up to date — opened instance by instance) and the control-plane exchange behind it. Those routes carry the Settings tag or are internal to the Pixee control plane and are not part of the public reference; their response schemas appear in components.schemas without being referenced by any public operation.

v6.41.0 — app API

  • Added (authentication) GET /auth/session-policy — public, like /auth/password-policy: inactivite_max_minutes, the maximum session inactivity in force (Settings › Security, 120 minutes by default). See Authentication → Session policy.
  • Removed (exports) the six /exports/schedules* operations now answer 410 EXPORT_SCHEDULES_RETIRED (nothing read or written) and are marked deprecated; the ExportSchedule* schemas are gone. Export schedules were never run — use the schedules of a sync profile. The routes will disappear after 30 days without calls. See Exports → Export schedules (retired).
  • Added (connections) sync profiles — contenus accepts medias (image gallery) and marques (brand): an export profile carrying only those updates existing products on PrestaShop, WooCommerce or Magento (never creates one; texts, prices and stocks untouched). Elsewhere and on import the profile is saved but not executable: 409 SYNC_PROFIL_NON_EXECUTABLE with details.raison: "contenu_partiel_non_pris_en_charge" and, new, details.contenus_non_pris_en_charge. Two more profile types: “Médias”, “Fiche + médias”. The import “Par défaut” no longer lists medias / marques. See Connectors → Sync profiles.
  • Changed (connections) POST /sync-profils/types creates only the types executable in that direction on that platform (no SEO or “Médias” type on import; none to Dolibarr, Sage or Odoo; no SEO type to Magento) — they used to be created, then refused at launch. On PrestaShop a texts / SEO-only profile no longer sets product features or GPSR records.
  • Changed (products) POST /products/{product_id}/media/upload reads title, alt_text, position and is_primary from the multipart form (they were read from the query string, so form values were lost); is_primary: true replaces the product's previous primary image.
  • Added (errors) VALIDATION_HOST_UNRESOLVED (400, a host that does not resolve, details.champ) — previously reported as VALIDATION_URL_REJECTED_SSRF — and EXPORT_SCHEDULES_RETIRED (see Errors).
  • The public reference grows from 634 to 635 paths and from 750 to 751 operations. The instance alert state (etat on /settings/alertes) and the Pixee fleet supervision routes are not part of the public reference. The public contract v1 is unchanged.

v6.40.0 — app API

  • No public route was added, removed or changed: the public reference stays at 634 paths and 750 operations, and the public contract v1 (/ext, /windev) is unchanged.
  • Changed (products) POST /products/corbeille/restaurer — a product whose internal reference (SKU) has since been taken by another product stays in the trash with statut: "ignore" and motif: "sku_deja_utilise", instead of a generic failure; the other products of the request are restored.
  • The instance alert settings and the supervision screens added in this release are not part of the public reference.

v6.39.0 — app API

  • Added (imports) POST /mapping-templates/{template_id}/dupliquer — duplicates a column (mapping) template: optional body { "name" }, otherwise “X (copie)”, suffixed if needed; the copy is never the default. See Imports → Duplicate a mapping template.
  • Added (imports) GET /mapping-templates and GET /mapping-templates/supplier/{supplier_id} accept ?import_type= and return import_type for each template; the supplier's default template comes first.
  • Changed (imports) template names are unique per supplier and import type (case ignored) on creation, rename and duplication: 409 MAPPING_TEMPLATE_NOM_PRIS with details.modele_existant_id; existing duplicates stay readable. Only one default per supplier and import type, and imports started without a template (email, FTP, scheduled) apply that default first. POST /mapping-templates/code2asin saves the per-field modes (global_mode, field_options: skip, fill, overwrite) and takes remplacer: true to rewrite the template of the same name. See Imports → Mapping templates.
  • Added (connections) sync profiles — an import profile may carry mapping_id, a named import mapping of the same connection (or null for “Par défaut”); it is applied at launch and on schedules, and the import guards are judged with it. Refusals: 422 SYNC_PROFIL_INVALIDE with details.raison mapping_envoi_interdit, mapping_inconnu or mapping_incompatible. POST /sync-profils/{profil_id}/lancer accepts {"apercu": true} on an import profile to launch only its import preview (apercu_import_seulement otherwise). See Connectors → Sync profiles.
  • Added (errors) MAPPING_TEMPLATE_NOM_PRIS (see Errors).
  • The public reference grows from 633 to 634 paths and from 749 to 750 operations. Named import mappings of the shops (/{platform}/import/mappings, /import/modeles-mapping, their /copier actions) are managed in the app and are not part of the public reference. The public contract v1 is unchanged.

v6.38.0 — app API

  • Changed (connections) sync profiles now run what they announce: their surcharges are applied by the synchronization, and an export profile with textes / seo without fiche sends only those texts on PrestaShop and WooCommerce (existing products only: no creation, images, variations or combinations). raison_non_executable and 409 SYNC_PROFIL_NON_EXECUTABLE details.raison take new values: inactif, surcharge_non_appliquee (with details.surcharges_non_appliquees) and contenu_partiel_non_pris_en_charge; the v6.37 values surcharges_au_lot_suivant, contenu_partiel_au_lot_suivant and mapping_au_lot_suivant are gone — update any code that matched them. POST /sync-profils/types creates the export “SEO” and “SEO + contenus” types with the override textes_envoyes (their text groups, toujours) where the platform has that option. See Connectors → Sync profiles.
  • Added (imports) GET /imports/ returns peut_relancer for each job: it can be retried — status allows it and the file is still stored.
  • No public route was added or removed: 633 paths, 749 operations; the public contract v1 is unchanged.

v6.37.0 — app API

  • Added (connections) sync profiles — /sync-profils, 9 operations under the Connectors tag: list a connection's profiles (with the two computed “Par défaut”), create, read, update, delete, list and create the profile types (Stock, Stock + prix, SEO, SEO + contenus), attach a profile to a sync schedule, and launch a profile. They cover the PrestaShop, WooCommerce, Magento, Dolibarr, Sage and Odoo connections. Launching an export profile creates only previews to validate — nothing is sent before; a profile that is not neutral (overrides, partial product record) or inactive cannot be launched yet: 409 SYNC_PROFIL_NON_EXECUTABLE. See Connectors → Sync profiles.
  • Added (errors) SYNC_PROFIL_INTROUVABLE, SYNC_PROFIL_INVALIDE, SYNC_PROFIL_NOM_PRIS, SYNC_PROFIL_UTILISE, SYNC_PROFIL_NON_EXECUTABLE, SYNC_PROFIL_INCOMPATIBLE (see Errors).
  • Schedules without a profile run “Par défaut”, exactly as before. No other public route changed: the public reference grows from 628 to 633 paths and from 740 to 749 operations; the public contract v1 (/ext, /windev) is unchanged.

v6.35.0 and v6.36.0 — app API

  • No public route was added, removed or changed: the public reference stays at 628 paths and 740 operations, and the public contract v1 (/ext, /windev) is unchanged.
  • Changed (connections) field correspondences saved for a PrestaShop, WooCommerce or Magento connection are now applied on export, on top of the default mapping (never instead of it), as they already were for Dolibarr and Sage. Saving a correspondence outside the allowed fields is refused with 422 — new code SYNC_FIELD_MAPPING_TARGET_UNKNOWN, alongside SYNC_FIELD_MAPPING_TARGET_PROTECTED, SYNC_FIELD_MAPPING_SOURCE_INVALID, SYNC_FIELD_MAPPING_STRATEGY_UNSUPPORTED and VALIDATION_INVALID_PATTERN (see Errors). The per-platform correspondence routes are not part of the public reference.
  • Changed (connections) outbound calls to shops and ERPs now follow instance-wide caps (calls per second, simultaneous synchronizations) set by an administrator; a synchronization over the cap waits instead of failing. The rate limits of this API are unchanged.

v6.34.0 — app API

  • Removed (export destination) Google Drive is no longer offered as an export destination. platform_type: "gdrive" stays in the PlatformType enum so existing Drive platforms can still be read, but creating, testing, previewing, sending to or scheduling one answers 422 EXPORT_INTEGRATION_ABSENT (POST /exports/platforms, POST /exports/platforms/test, POST /exports/platforms/{platform_id}/test…). Use ftp, sftp, s3 or minio. Google Drive remains an import source (import_type: "google_drive"). See Exports → Export platforms.
  • No public route was added or removed; the public contract v1 (/ext, /windev) is unchanged.

Public contract v1 — October 2026

Since October 7, 2026, /api/v1/ext/* and /api/v1/windev/* — the families called with an API key — form the public contract, major version 1, with its own frozen specification (openapi-public-v1.json, 20 operations), its own version header and a deprecation policy (see API versioning). Entries below are listed most recent first.

October 30, 2026

  • Breaking (announced in v1 by exception) POST /ext/products, POST /ext/products/batch, PUT /ext/products/{ean}, PATCH /ext/products/{ean} — category_id is no longer written (the former category tree has been removed): the key is ignored and cited in champs_ignores (champs_ignores_par_fiche in a batch). Read back, category_id stays in the contract and is always null. File products with the Category Manager.
  • Deprecated GET /windev/categories — it served the former category tree and now returns an empty list (same shape), with the Deprecation / Sunset headers; removal on April 28, 2027 at the earliest. The category sent by POST /windev/products/sync is filed in the Category Manager.

October 26, 2026

  • Breaking (announced in v1 by exception) WinDev ambiguous reference — GET/PATCH /windev/products/{ref}, POST /windev/products/{ref}/activate|deactivate, POST /windev/products/sync, POST /windev/stock/update, POST /windev/prices/update: when the EAN or manufacturer reference designates several live products, none is chosen and nothing is written — 409 WINDEV_REFERENCE_AMBIGUOUS on single routes (details: reference, champ, produits), status: "error" + error_code on the line of a batch. Previously 500.
  • Breaking (announced in v1 by exception) WinDev trash — a product in the trash is no longer returned by GET /windev/products, /products/since/{timestamp} (nor counted in total); GET /windev/products/{ref} of a product that exists only in the trash answers 409 WINDEV_PRODUCT_IN_TRASH. Writes to such a product are refused with the same code (previously it was modified and reactivated): restore it, then resend.
  • Breaking (announced in v1 by exception) WinDev price direction — POST /windev/products/sync, PATCH /windev/products/{ref}, POST /windev/prices/update: price_ht is now stored as the selling price excl. VAT (previously as purchase cost, and price_ttc as selling price). price_ttc is never stored: alone, the line is refused (WINDEV_PRICE_TTC_ONLY, 422 on PATCH); with price_ht, it is cited in champs_ignores. In reads, price_ttc is computed: price_ht × (1 + tax_rate / 100), null without tax_rate. See WinDev → Prices.
  • Breaking (announced in v1 by exception) POST /windev/products/sync — an update no longer reactivates a deactivated product; only a created product is activated.
  • Fixed POST /windev/products/sync — category is attached to the existing category with that name (or id); no category is created; unknown or ambiguous → category_unresolved on the line, the product's category untouched.
  • Added champs_ignores (and champs_ignores_par_fiche on batches) on every /ext and /windev write: unknown keys stay tolerated for the whole life of v1, but are now listed in the response instead of being dropped silently. Refusing them (422 REQUEST_UNKNOWN_FIELD) is reserved for a future v2.
  • Added GET /ext/products, /ext/products/{ean}, /ext/products/delta (and writes that return the product) — read-only fields sku, condition, net_content, net_content_unit, gross_weight, and product safety (EU GPSR): fabricant (resolved manufacturer, with provenance and personne_responsable) and avertissements_securite. See External API → Read-only fields.
  • Clarified min_order_quantity and lead_time_days sent by WinDev are the product's (minimum sale quantity, product lead time), not a supplier's. No behaviour changes.

October 23, 2026

  • Fixed /ext writes — brand_name is matched against your brand directory (exact name ignoring case and accents, alias, or name without legal suffix); unknown, ambiguous or disabled → name kept without an attached brand; no brand is created. Changing the name detaches the previous brand; PUT with brand_name absent or null, or PATCH with "", detaches it. See External API → Brands.
  • Added POST /ext/products/batch — data.brands_unresolved.
  • Fixed PATCH /windev/products/{ref} and POST /windev/products/sync — same brand matching for brand; brand: "" detaches the brand. Added brand_unresolved (inconnue, ambigue, inactive) on the sync line.

October 21, 2026

  • Clarified POST /ext/products/batch — a url_slug that looks like a full address (a : before the first /, such as javascript:, including encoded forms: :, :, full-width colon) in one product refuses the entire request on entry (422 VALIDATION_URL_SLUG_SCHEME); no product of the batch is saved. Send only the end of the address (my-product-42), then resend the batch. A slug that is only too long still refuses just its product. No behaviour changes.
  • Fixed POST /ext/products/batch and POST /windev/products/sync — an unexpected error on one product no longer returns the technical error text (database query, values) in error_details or error: the reason says the product was not saved, that the others are processed each on its own, and gives a reference to pass on to support. The reason for a deliberate refusal (name required to create, slug, product cap) is unchanged.
  • Fixed POST /windev/products/sync — the wait for the product-cap check is bounded to 5 seconds for the whole call (previously up to 5 seconds per creation). Beyond that, a creation whose cap cannot be checked right away is refused with a named error — resend it; updates are always made.

October 20, 2026

  • Breaking (announced in v1 by exception) POST /ext/products, PUT /ext/products/{ean}, PATCH /ext/products/{ean}, PATCH /windev/products/{ref} — url_slug is limited to 255 characters (maxLength: 255); beyond, 422 VALIDATION_URL_SLUG_TOO_LONG. Such a slug could never be saved (the database refused it with a 500): only the refusal code changes, no valid data is affected.
  • Fixed POST /ext/products/batch — a product whose url_slug exceeds 255 characters is refused alone (error_details, named reason); the other products of the batch are saved.
  • Fixed POST /ext/products, POST /ext/products/batch, POST /windev/products/sync — creating a product respects the product cap of your plan, like the app screens and imports. At the cap: 403 BILLING_LICENSE_QUOTA_EXCEEDED on the single route, or 409 BILLING_LICENSE_QUOTA_BUSY if another creation was checking the cap at the same moment (retry); in a batch, only that product is refused (named reason in error_details or error). An update is never refused by the cap. See External API → Product cap.

October 15, 2026

  • Breaking (announced in v1 by exception) POST /ext/products, PUT /ext/products/{ean}, PATCH /ext/products/{ean} — weight must be lower than 10 000 000 (kg), width, height and depth lower than 100 000 000 (cm); NaN and infinity are refused. Out of range: 422, field named. These values could never be saved (the database refused them with a 500): only the refusal code changes.
  • Fixed POST /ext/products/batch — an out-of-range product is refused alone (error_details, named reason); the others are saved, and a product in error no longer interrupts the following ones.

October 10, 2026

  • Fixed GET /windev/status no longer carries the session token (BearerAuth) in the contract. The route never required authentication; the contract now says so. No behaviour changes.
  • Fixed the 12 /windev/* operations describe the data payload of their response (status, product, page of products, sync, stock and price results, categories, suppliers) instead of a free value. Objects stay open (additionalProperties): a field added later is not a breaking change. No response changes.
  • Added GET /ext/status and GET /windev/status return api_version (major version of the contract, same value as the API-Version header). The version field ("1.0" / "1.1") is unchanged and frozen: read api_version.
  • Added error responses of /ext/* and /windev/* (missing or refused key, not found, validation, quota, server error) also carry API-Version: 1, and the deprecation headers when the operation is deprecated. No response body changes.

October 7, 2026

  • Added frozen public specification of v1: openapi-public-v1.json (20 operations, /api/v1/ext and /api/v1/windev), declaring the APIKeyHeader (X-API-Key) security scheme. Any breaking change against this file is refused before release unless announced here.
  • Added outgoing webhooks carry the X-PM-Webhook-Version: 1 header and a webhook_version: "1" field in the (signed) payload. Nothing else changes in the payload. See Webhooks → Payload version.
  • Added every response of /ext/* and /windev/* carries API-Version: 1 (major version of the contract, distinct from the application version). No route changed.
  • Added deprecation mechanism: a deprecated operation will carry Deprecation, Sunset and Link: <…>; rel="deprecation", with at least 180 days' notice. No operation is deprecated today.

Public reference (app API) since September 18, 2026

The public reference (/reference) follows the application (v6.40.0): 634 paths and 750 operations, against 449 paths and 548 operations on September 18. These routes are documented but carry no stability promise beyond this changelog — only /ext and /windev form the versioned contract.

  • Removed (27 operations):
    • Products: GET /products/categories, POST /products/{product_id}/entities/rewrite-all and POST /products/{product_id}/entities/{entity_id}/rewrite-description (replaced by POST /enrichment/products/{product_id}?types=descriptions&entity_id=…); category_id is now refused by POST /products/ and PUT /products/{product_id} (422).
    • AI Enrichment: POST /enrichment/web/batch/estimate, POST /enrichment/web/images/batch.
    • Exports: POST /exports/schedule (singular, without platform — the schedule it announced was never executed; persisted /exports/schedules are unchanged); POST /exports/products and POST /exports/suppliers (placeholders that answered “completed” without exporting anything).
    • Brands: the pending-brands queue (GET /brands/pending, GET /brands/pending/{pending_id}, POST /brands/pending/{pending_id}/validate, POST /brands/pending/bulk-validate) and POST /brands/suggest-matches.
    • Categories: the former generic category tree (GET /categories/web, GET /categories/{category_id}/tree|children|parents|translations, PUT /categories/{category_id}/translations), the legacy migrations (POST /categories-manager/categories/migrate-product-categories, POST /categories-manager/mappings/import-from-legacy), and the direct structure writes (POST|PUT|DELETE /categories-manager/taxonomies…, POST /categories-manager/taxonomies/{taxonomy_id}/categories, PUT|DELETE /categories-manager/categories/{category_id}) — replaced by POST /categories-manager/structure/apercu then /structure/appliquer, journaled and undoable. See Catalog → Categories.
  • Added (219 operations) — Products 60, Categories 50, Brands 42, AI Enrichment 35, Authentication 13, Connectors 10, Pricing 3, Exports 2, Search 2, Code2ASIN 1, Suppliers 1. Among them: brand correspondences per shop, brand proposals and GPSR manufacturer records (/brands/correspondances…, /brands/propositions…, /brands/fabricants…), category families, structure changes and AI proposals (/categories-manager/familles…, /structure…, /propositions-ia…). They are listed in /reference; the resource pages here summarise the main ones.
  • Changed: write bodies of the app API refuse unknown keys with 422 REQUEST_UNKNOWN_FIELD (the detail names the keys, nothing is written) — the public families /ext and /windev are not affected in v1. POST /suppliers/test-connection with a Google Drive source answers 422 SUPPLIER_INTEGRATION_ABSENT; gdrive is refused as an import-config type (use google_drive).

v6.19.x — September 18, 2026 (contract fixes)

A contract test suite now exercises every public operation against its own spec. It found the following, all fixed on September 18, 2026.

Breaking changes

  • 503 is no longer used for a missing configuration. Nine operations answered 503 Service Unavailable when a per-instance dependency was simply not set up (Odoo connection, connector webhook secret, AI provider, price-monitoring shared key, vector search engine). They now answer 409 Conflict with an error_code from the *_NOT_CONFIGURED family and a details.how_to_fix. 503 is reserved for a configured dependency that is momentarily unreachable, and always carries Retry-After. Affected: POST /brands/import-from-odoo, POST /connectors/{shopify,woocommerce,bigcommerce}/webhook, POST /enrichment/products/{product_id}, GET /prices/export-watchlist, POST /prices/observations, GET /search/products/{product_id}/similar. See Errors → Dependency not configured.
  • GET /prestashop/config behaves like the other connector config endpoints: 200 {"configured": false} when nothing is configured (was 404), and the configured boolean is always present. (Internal module; listed here because integrations built on the old 404 will see a change.)
  • template_id is an integer on DELETE /mapping-templates/code2asin/{template_id} and POST /mapping-templates/code2asin/{template_id}/set-default. A non-numeric value now yields 422 (was 500).

Fixed

  • File downloads declare their real content type in the public spec — text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/xml, image/png — instead of the FastAPI default application/json: GET /categories-manager/mappings/export-csv, GET /compliance/export, GET /compliance/gdsn/catalog, GET /compliance/dpp/{id}/qr, GET /imports/export, GET /prices/map/export, GET /products/export/csv, GET /products/export/excel. Regenerate any client you generated from the earlier spec.
  • Three categories-manager read endpoints (/attributes/{attribute_id}, /categories/{category_id}/attributes, /mappings/suggestions) declared an object and returned a list, which surfaced as 500 once the list was empty. The spec now declares the list; the payload did not change.
  • PATCH /prices/monitored/{product_id} returns 404 PRODUCT_NOT_FOUND for an unknown product (was 500).
  • POST /enrichment/web/price-bot/run and GET /enrichment/web/price-bot/status were broken in every environment by an internal import error and answered 503 / {"status": "unknown"}. Fixed.

v6.19.x — September 2026

This release covers what changed on the public API surface between June 19 and September 17, 2026.

Breaking changes

  • Public spec now reports the real version. GET /api/v1/openapi-public.json had been frozen at "6.2.1" since March; it now reports the actual running version (6.19.x). If you compared this field to detect API changes, re-check your assumptions.
  • Public reference is now an allowlist (fail-closed), effective since August 19, 2026. Only these families appear on /api/v1/openapi-public.json and this site: Authentication, Products (+ Brands, Categories, Suppliers, Product Tags, Search, Product Search), Imports, Exports, AI Enrichment, Connectors, Pricing, Compliance, EAN Lookup, Code2ASIN, External API, Webhooks. The WooCommerce and Magento 2 sync modules, Dolibarr, Sage X3, PrestaShop, and Odoo integrations are no longer part of the public reference — they are documented on docs.pixeepim.com. (Their inbound webhook/push endpoints under /api/v1/connectors/* remain public — see Connectors.)
  • Price entry update/delete moved off the per-product path. PATCH /products/{product_id}/prices/{price_id} no longer exists. Use PATCH /prices/{price_id} and the new DELETE /prices/{price_id} instead — see Price Monitor.
  • GET /connectors/ now returns a plain array, not the { items, meta } paginated envelope. It is not paginated.
  • /auth/register requires an invitation token. It completes a subscription created through an emailed, signed token — it is not an open self-signup endpoint. If you were probing this route for generic account creation, that never worked as a public signup flow and won't going forward.

New: Price Lists API

A full price-list system was added under /api/v1/price-lists/*: create channel-scoped price lists (with priority and validity window), add priced entries per product (with tiered min_quantity pricing), bulk-create up to 500 entries, and resolve the effective price for a product across all matching lists. See Price Monitor → Price lists.

New: Repricing

/api/v1/prices/repricing/* (10 endpoints): define rules that automatically adjust prices from conditions (competitor price, margin floor, category, supplier, product), simulate a rule (and its revenue impact) before it ever touches a live price, run repricing manually or let it run on schedule, and revert any individual automated change from its history. See Price Monitor → Repricing.

New: WinDev in the public reference

/api/v1/windev/* (12 endpoints) is now included in the public OpenAPI spec, grouped under the External API tag. It was previously a real, working surface documented only internally — it now shows up in /reference and on this site's WinDev Integration page like any other public family.

New and expanded endpoints

  • Connectors — platform catalog (GET /connectors/platforms, /platforms/{id}, /platforms/{id}/field-map, /platforms/{id}/guide), an aggregated GET /connectors/sync-status dashboard feed, full connector CRUD (POST/PATCH/DELETE /connectors/{id}, previously read-only in this reference), sync job history (GET /connectors/{id}/jobs) and per-job status (GET /connectors/{id}/sync/jobs/{job_id}), and four inbound webhook endpoints (Shopify, WooCommerce, BigCommerce, Magento 2 push) — each HMAC/token-verified with a 24-hour Redis replay-protection window.
  • Price Monitor — GET /analytics/price-sources, GET /products/{id}/stock/history, GET/POST /prices/export-watchlist and /prices/observations (B2C scraper hub ingestion), a validation queue for low-confidence competitor matches (GET /prices/validation, POST /prices/validation/{item_id}), competitor blacklisting (POST/DELETE /prices/competitors/blacklist*), per-alert history (GET /prices/alerts/{id}/history), a MAP violations export, and bulk MAP price setting.
  • Webhooks — GET /webhooks/events (discover subscribable event types instead of hardcoding them), POST /webhooks/{id}/toggle, DELETE /webhooks/{id}, and page/per_page pagination on list and delivery-log endpoints (previously skip/limit on logs).
  • External API — API key management (GET/POST /api-keys, GET/PATCH/DELETE /api-keys/{id}, POST /api-keys/{id}/rotate) is now documented alongside /ext/* and /windev/* under the same public tag. See External API → API key management.
  • Authentication — GET /auth/me, POST /auth/logout, GET /auth/csrf-token, GET /auth/test, POST /auth/login/json, GET /auth/lockout/status/{email}, POST /auth/lockout/unlock/{email} are now documented. Refresh-token rotation includes reuse detection: presenting an already-rotated refresh token revokes the entire token family. Cookie-based session clients must now send a CSRF double-submit header (X-CSRF-Token, fetched from /auth/csrf-token) on mutating requests — API-key and bearer-token clients are exempt.
  • Errors — the error envelope itself (error.code, error_code, type, message, details, path, request_id, timestamp) is unchanged, but message is now genuinely localized via Accept-Language (French and English), and Content-Language in the response always announces the language actually served rather than the one requested. MODULE_DISABLED (403) and LICENSE_SUSPENDED (403, read-only mode) are documented as distinct, non-enveloped error shapes — see Errors.

Rate limiting rebalanced

All 26 tiers were reviewed; most read/write/bulk limits increased 5–10× to support large catalogs (100k+ products) — e.g. READ_STANDARD and READ_ADMIN to 1000/min, WRITE_STANDARD/WRITE_CONFIG/WRITE_UPLOAD/WRITE_USER_MGMT to 100/min, all BULK_* tiers to 500/min. AI_BATCH moved the other way, tightening from 5/min to 1/hour (cost control). Three tiers not previously documented here are now covered: AUTH_REGISTER, AUTH_LOGOUT, EXPORT_SCHEDULE. See Rate Limiting for the full table.

v6.19.x — Breaking changes for integrators (June 2026)

Authentication changes (SEC-01, SEC-02, SEC-03)

  • Refresh token mechanism changed — Refresh tokens are now server-side, DB-backed (rotation + family revocation on reuse detection). The POST /auth/refresh endpoint no longer accepts a Bearer token in the header — it reads the refresh_token HttpOnly cookie set at login. Clients that passed a JWT in Authorization to refresh must migrate to cookie-based refresh.

  • Access token TTL reduced: 120 min → 15 min — Review your token handling to ensure clients refresh before expiry.

  • API key header changed: Authorization: Bearer → X-API-Key — The API key authentication header is now X-API-Key: pm_live_.... The previous Authorization: Bearer pm_live_... format is no longer valid for API key authentication.

  • Code2ASIN exports: JWT query param → presigned URL — Export downloads now require a presigned URL obtained via POST /code2asin/exports/{job_id}/download-url (valid 5 min). The old ?token=<jwt> query parameter is removed.

API changes

  • External API (/api/v1/ext/*) — New M2M integration surface with 8 endpoints. Auth: X-API-Key. Scopes: ext:products:read, ext:products:write. See External API.

  • WinDev Integration (/api/v1/windev/*) — New WinDev-optimized sync surface with 12 endpoints and WinDev-friendly envelope. Auth: X-API-Key. See WinDev Integration.

  • Pagination standardized — All paginated endpoints now use page/per_page parameters (default: 20, max: 100). The skip/limit parameters are deprecated legacy aliases.

  • Workflow Engine (/api/v1/workflow/*) — Product publication workflow: draft → review → approved → published → archived. Completeness gate ≥ 70%. 10 endpoints.

Removals

  • GraphQL/Hasura proxy removed — The /api/v1/graphql proxy has been removed. Headless integrations should use the External API REST surface (/api/v1/ext/*) instead.

v4.5 — May 2026

Major platform update.

  • Rebranding: Products Manager → Pixee PIM. Base URL updated to https://api.pixeepim.com/api/v1/
  • Authentication: Added JWT Bearer Token support (120-minute TTL, refreshable). API keys now prefixed pm_live_ / pm_test_ with granular scopes
  • Products: New bulk endpoints (POST /products/bulk, PATCH /products/bulk). Products now identified by UUID; EAN remains unique index. Added cost_price, weight, is_active fields
  • Imports: Jobs moved to /imports/jobs. Added pause/resume/cancel controls. Added /preview endpoint for pre-flight validation. New automated recurring imports via /imports/automations
  • Exports: Format-specific endpoints (/exports/csv/products, /exports/json/products, /exports/excel/products, /exports/zip/products). New export platforms (Google Drive, S3, MinIO, SFTP). Scheduled exports via /exports/schedules
  • AI Enrichment: New multi-provider job system at /ai-enrichment/jobs. Support for OpenAI, Anthropic Claude, and configurable models. Cost tracking per job. Provider recommendation engine at /ai-services/recommendations/{use_case}
  • Price Monitor: New endpoint structure at /prices/products/{id}. Added competitor price management, price history, stats, and best-price endpoints. Margin tracking
  • EAN Lookup: Changed from GET /ean-lookup/{ean} to POST /ean-lookup/lookup with provider selection. Batch limit raised to 500 EANs. Added cache stats and pending queue management
  • Webhooks: New events: import.started, supplier.created, supplier.updated, ean.resolved. Added delivery logs with per-entry retry (POST /webhooks/{id}/logs/{log_id}/retry)
  • Code2ASIN: Full job lifecycle: create → start → pause/resume/cancel. Added results with confidence scoring, manual accept/reject, global statistics, and CSV/JSON export
  • Rate Limiting: Replaced plan-based limits with per-tier system (AUTH, READ_STANDARD, WRITE_STANDARD, EXPORT_STANDARD, etc.) backed by Redis
  • Pagination: Standardised to skip/limit parameters. Response wrapper changed from data to items. meta object enriched with has_next and has_previous
  • Errors: Response format updated — detail field replaces error/message. Added 202 Accepted for async operations, 423 Locked for account lockout

v1.0 — March 2024

Initial public release.

  • Products CRUD API (GET, POST, PATCH, DELETE)
  • Bulk import via CSV and JSON (/imports)
  • Export catalog to CSV/Excel (/exports)
  • AI enrichment for descriptions and attributes (/enrichment)
  • Connector sync for Shopify, WooCommerce, PrestaShop (/connectors)
  • EAN lookup and validation (/ean-lookup)
  • Price monitoring and alerts (/price-monitor)
  • Code2ASIN mapping (/code2asin)
  • Compliance & Digital Product Passport endpoints (/compliance)
  • Webhook support for real-time event notifications
  • API key authentication

API versioning

The version is part of the base URL (https://api.pixeepim.com/api/v1/). The public contract is the set of families called with an API key — /api/v1/ext/* and /api/v1/windev/*; its frozen specification is openapi-public-v1.json. The other /api/v1 routes are the API of the app screens: documented in /reference, without a stability promise beyond this changelog.

  • API-Version: 1 is set on every response of the public families, successes and errors. It is the major version of the contract, independent of the application version (info.version of the public reference).
  • One major version = one prefix. A breaking change opens /api/v2/ext next to /api/v1/ext; both live together for the whole deprecation notice of v1.
  • Not breaking (no version change): adding a route, a response field, an optional parameter, an enum value in a response, or a more precise error code under the same status. Your client must ignore fields it does not know.
  • Breaking: removing or renaming a route, a field or a parameter; making an optional parameter required; changing a field's type or meaning; changing a success HTTP status; tightening validation on an input that was accepted so far; changing a unit or a format (dates, decimals).

Deprecation

  • A deprecated operation carries Deprecation (RFC 9745), Sunset (RFC 8594) and Link: <https://apidoc.pixeepim.com/changelog>; rel="deprecation" on its responses.
  • Minimum notice: 180 days, for every client, between the announcement and the removal. When an Enterprise contract provides for it, the notice is 12 months; the Sunset date is then set to honour the longest contractual notice among the clients using the operation.
  • Every deprecation is announced on this page the day it is decided. No operation is deprecated today.

Outgoing webhooks follow the same rules, with their own version (X-PM-Webhook-Version) — see Webhooks → Payload version.

Was this page helpful?