WinDev Integration
Synchronise your WinDev applications with Pixee PIM — push products in batch, update stock and prices, and pull the full catalog with a response format designed for WinDev's HTTP calls.
The WinDev API (/api/v1/windev/*) uses a simplified JSON envelope that maps cleanly to WinDev variables. Products are identified by reference (internal WinDev key) or EAN, and all batch endpoints accept up to 5 000 items per call.
As of v6.19, /api/v1/windev/* is included in the public OpenAPI reference (grouped under the External API tag alongside /api/v1/ext/*). The two surfaces remain functionally distinct — separate response envelopes, separate scopes (windev:read / windev:write / windev:sync) — this only means the machine-readable spec at /reference now covers WinDev too.
Overview
| Base URL | https://api.pixeepim.com/api/v1/windev |
|---|---|
| Auth | X-API-Key header |
| Read scope | windev:read |
| Write scope | windev:write |
| Sync scope | windev:sync |
| Stock / price batch | 5 000 items max |
| Product sync batch | 1 000 items max |
| Contract version | API-Version: 1 on every response |
Create WinDev API keys in Settings → API Keys and select the appropriate scopes. A single key can carry multiple scopes.
Authentication
All endpoints except GET /status require an API key in the X-API-Key header. GET /status declares no security requirement in the contract (since October 10, 2026 it is no longer marked with the session token BearerAuth); it never required authentication.
Authenticated request
curl https://api.pixeepim.com/api/v1/windev/products \
-H "X-API-Key: pm_live_abc123..."
Scopes
| Scope | Grants access to |
|---|---|
windev:read | GET /products, GET /products/since/{ts}, GET /products/{ref}, GET /categories, GET /suppliers |
windev:write | PATCH /products/{ref}, POST /products/{ref}/activate, POST /products/{ref}/deactivate, POST /stock/update, POST /prices/update |
windev:sync | POST /products/sync |
Response format
Every response uses the same WinDev-friendly envelope:
Success
{
"success": true,
"code": 200,
"message": "125 produits trouvés",
"data": [...],
"count": 125,
"page": 1,
"pages": 10,
"total": 125
}
success and code map directly to WinDev boolean and integer variables. count reflects the number of items in data for that page; total is the full dataset size across all pages.
Since October 10, 2026 the contract describes the data payload of each of the 12 operations (status, product, page of products, sync, stock and price results, categories, suppliers) instead of a free value. The objects stay open (additionalProperties): a field added later is not a breaking change. No response changed — same keys, same values; a field that was absent (error, warning…) stays absent.
Errors (401, 403, 404, 409, 422, 500) use the platform's standard error envelope, not the WinDev envelope:
Error
{
"error": {
"code": 404,
"error_code": "PRODUCT_NOT_FOUND",
"type": "not_found",
"message": "…",
"details": { "reference": "REF-001" },
"path": "/api/v1/windev/products/REF-001",
"request_id": "abc-123",
"timestamp": "2026-10-21T10:00:00Z"
}
}
In batch endpoints (/products/sync, /stock/update, /prices/update) a failure on one line does not fail the call: it is reported on that line of data (status: "error" or "not_found", with error, and error_code for a named refusal — see Named refusals).
Unknown fields
Writes tolerate keys they do not know (nothing is refused, nothing is written for them) and list them, sorted, in the envelope's champs_ignores (empty list when there are none). On a batch (/products/sync, /stock/update, /prices/update), champs_ignores is the union for all lines and champs_ignores_par_fiche gives the detail: [{ "index": 0, "ean": "…", "reference": "…", "champs": ["…"] }] (index from 0; reference on /products/sync only). Reads carry both keys as null. Unknown keys stay tolerated for the whole life of contract v1.
Named refusals
These refuse the request on single-product routes (409 / 422, standard error envelope) and refuse only the line in a batch (status: "error" + error_code, the other lines go on). Nothing is written for a refused line.
error_code | Status (single routes) | When |
|---|---|---|
WINDEV_PRODUCT_IN_TRASH | 409 | The product is in the trash (and no live product carries this reference). Restore it, then resend. A product in the trash is no longer returned by the lists, the delta or total; GET /products/{ref} of a product that exists only in the trash answers this 409 |
WINDEV_REFERENCE_AMBIGUOUS | 409 | The EAN or manufacturer reference designates several live products: none is chosen. details: reference, champ (ean or manufacturer_reference), produits (up to 10 conflicting ids). Fix the duplicate in Pixee PIM, then resend |
WINDEV_PRICE_TTC_ONLY | 422 (PATCH) | price_ttc sent without price_ht — see Prices |
Prices (HT and TTC)
Since October 26, 2026, price_ht is the selling price excl. VAT of the product (before: it was stored as the purchase cost, and price_ttc as the selling price). price_ttc is never stored: sent alone, the line is refused (WINDEV_PRICE_TTC_ONLY); sent with price_ht, it is cited in champs_ignores. WinDev no longer writes the purchase cost. In reads, price_ht is the selling price excl. VAT and price_ttc is computed: price_ht × (1 + tax_rate / 100), rounded to the cent, null without tax_rate.
Versioning and product cap
API-Version: 1is set on every/windevresponse, errors included.GET /statusreturns the same value indata.api_version;data.version("1.1") is a frozen historical value — readapi_version. Deprecation headers and notice: see External API → Versioning. The frozen specification of both families isopenapi-public-v1.json.- Product cap. Since October 20, 2026, a product created by
POST /products/syncrespects the product cap of your plan (see External API → Product cap). At the cap, only that product is refused, with a named reason in itserror; the other products of the call are processed, and updates are always made. - The wait for the cap check is bounded to 5 seconds for the whole call (since October 21, 2026; previously up to 5 seconds per creation). Beyond that, a creation whose cap cannot be checked right away is refused with a named
error(another creation was checking the cap at the same time) — resend it.
Status
Public health check — no authentication required. Returns api_version (major version of the public contract, same value as the API-Version header), the frozen historical version, and the list of available endpoints. Use this to verify connectivity from WinDev before running a sync.
Request
curl https://api.pixeepim.com/api/v1/windev/status
Response
{
"success": true,
"code": 200,
"message": "WinDev API opérationnelle",
"data": {
"api": "ProductsManager WinDev API",
"version": "1.1",
"api_version": "1",
"timestamp": "2026-06-19T10:00:00Z",
"endpoints": [
"GET /api/v1/windev/status",
"GET /api/v1/windev/products",
"POST /api/v1/windev/products/sync",
"GET /api/v1/windev/products/since/{timestamp}",
"PATCH /api/v1/windev/products/{ref}",
"GET /api/v1/windev/products/{ref}",
"POST /api/v1/windev/stock/update",
"POST /api/v1/windev/prices/update",
"GET /api/v1/windev/categories",
"GET /api/v1/windev/suppliers"
]
},
"count": 1
}
List products
Returns a paginated product list. Use for the initial full sync when no reference timestamp exists yet.
Requires windev:read.
Query parameters
- Name
page- Type
- integer
- Description
Page number, starting at
1(default:1).
- Name
limit- Type
- integer
- Description
Items per page, max
500(default:100).
- Name
search- Type
- string
- Description
Free-text search across product name and reference.
- Name
ean- Type
- string
- Description
Exact EAN filter.
- Name
active_only- Type
- boolean
- Description
Return only active products (default:
true).
Request
curl "https://api.pixeepim.com/api/v1/windev/products?page=1&limit=100&active_only=true" \
-H "X-API-Key: pm_live_abc123..."
Response
{
"success": true,
"code": 200,
"message": "1250 produits trouvés",
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"ean": "3760000000001",
"manufacturer_reference": "012-1146",
"name": "Support TV mural fixe",
"brand": "KIMEX",
"price_ht": null,
"price_ttc": null,
"stock": 0,
"is_active": true,
"updated_at": "2026-06-19T09:30:00Z"
}
],
"count": 100,
"page": 1,
"pages": 13,
"total": 1250
}
Sync products
Push up to 1 000 products from WinDev to Pixee PIM in a single call. Each product is matched first by EAN (if provided), then by reference. On match: update; no match: create — a creation counts against your plan's product cap. Only a created product is activated automatically: an update no longer reactivates a deactivated product.
Each line of data reports ref, ean, id (null on error) and status (created, updated or error), plus error (and error_code for a named refusal) when status is error, warning when the supplier code is unknown, brand_unresolved (inconnue, ambigue or inactive) when brand matched no brand of your directory, and category_unresolved (inconnue or ambigue) when category matched no existing category. An unexpected error on one product refuses only that product: its error says it was not saved, that the others are processed each on its own, and gives a reference to pass on to support — never the technical error text.
Requires windev:sync.
Body parameters
Pass a JSON array directly (not wrapped in an object key):
- Name
reference- Type
- string
- Description
WinDev internal reference — used as fallback key when no EAN is provided.
- Name
ean- Type
- string
- Description
EAN/GTIN. Preferred matching key.
- Name
name- Type
- string
- Description
Product name.
- Name
brand- Type
- string
- Description
Brand name, matched against your brand directory (exact name ignoring case and accents, alias, or name without legal suffix). Unmatched: the name is kept without an attached brand — no brand is created.
""detaches the brand.
- Name
price_ht- Type
- number
- Description
Selling price excl. VAT (EUR).
- Name
price_ttc- Type
- number
- Description
Never stored — alone, the line is refused (
WINDEV_PRICE_TTC_ONLY); withprice_ht, cited inchamps_ignores.
- Name
stock- Type
- integer
- Description
Stock quantity.
- Name
weight- Type
- number
- Description
Weight in kg.
- Name
supplier_code- Type
- string
- Description
Supplier code for stock tracking.
See the full schema in Sync product fields below.
Request
curl -X POST https://api.pixeepim.com/api/v1/windev/products/sync \
-H "X-API-Key: pm_live_abc123..." \
-H "Content-Type: application/json" \
-d '[
{
"reference": "ART-001",
"ean": "3760000000001",
"name": "Support TV mural fixe",
"brand": "KIMEX",
"price_ht": 18.50,
"tax_rate": 20,
"stock": 42,
"weight": 1.5
},
{
"reference": "ART-002",
"name": "Câble HDMI 2m",
"price_ht": 5.00,
"stock": 150
}
]'
Response
{
"success": true,
"code": 200,
"message": "Sync terminé : 1 créés, 1 mis à jour, 0 erreurs",
"data": [
{ "ref": "ART-001", "ean": "3760000000001", "status": "updated", "id": "550e8400-..." },
{ "ref": "ART-002", "ean": null, "status": "created", "id": "661f9511-..." }
],
"count": 2,
"champs_ignores": [],
"champs_ignores_par_fiche": []
}
Sync product fields
| Field | Type | Notes |
|---|---|---|
reference | string | Required — WinDev internal key |
ean | string | EAN/GTIN (preferred match key) |
name | string | Required — product name |
brand | string | Brand name, matched against the brand directory, never created (brand_unresolved otherwise) |
short_description | string | |
description | string | |
price_ht | number | Selling price excl. VAT in EUR |
price_ttc | number | Never stored — see Prices |
stock | integer | ≥ 0 |
supplier_code | string | |
weight | number | kg |
width / height / depth | number | cm |
unit_of_measure | string | |
package_weight | integer | grams |
package_quantity | integer | ≥ 1 |
upc / gtin / external_id | string | |
min_order_quantity | integer | ≥ 1 — the product's minimum sale quantity (not a supplier's minimum purchase) |
lead_time_days | integer | ≥ 0 — the product's lead time (not a supplier's) |
hs_code | string | Customs tariff code |
country_of_origin | string | ISO 3166-1 alpha-2 (e.g. FR) |
dangerous_goods | boolean | |
color / size / material | string | |
tax_rate | number | 0–100 |
warranty_duration | integer | months |
category | string | Category name (or id): attached to the existing category with that name (case, accents and punctuation ignored), filed in the Category Manager. No category is created; unknown or ambiguous → the product's category is untouched and the line carries category_unresolved |
Products since timestamp
Returns products created or updated since the given Unix timestamp. Designed for incremental sync — store the timestamp after each sync and pass it as since on the next call.
Requires windev:read.
Path parameters
- Name
timestamp- Type
- integer
- Description
Unix timestamp in seconds (e.g.
1750291200for 2026-06-19 00:00:00 UTC).
Query parameters
- Name
page- Type
- integer
- Description
Page number (default:
1).
- Name
limit- Type
- integer
- Description
Items per page, max
500(default:100).
Request
curl "https://api.pixeepim.com/api/v1/windev/products/since/1750291200?limit=200" \
-H "X-API-Key: pm_live_abc123..."
WinDev pseudo-code
// Store last sync timestamp in a global variable or DB
nLastSync est un entier = GlbLastSyncTimestamp
sURL est une chaîne = ...
"https://api.pixeepim.com/api/v1/windev/products/since/" + nLastSync
HTTPRequête(sURL, httpGET, sRéponse, "", "X-API-Key: " + sAPIKey)
// Parse JSON response
// GlbLastSyncTimestamp = DateSystèmeVersTimestamp(DateSystème())
Get a product
Retrieves a single product by its WinDev reference or EAN. The ref path parameter is tried first as a manufacturer_reference, then as an EAN.
Requires windev:read.
Path parameters
- Name
ref- Type
- string
- Description
WinDev reference or EAN of the product to retrieve.
Request
curl https://api.pixeepim.com/api/v1/windev/products/ART-001 \
-H "X-API-Key: pm_live_abc123..."
Response
{
"success": true,
"code": 200,
"message": "Produit trouvé",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"ean": "3760000000001",
"manufacturer_reference": "ART-001",
"name": "Support TV mural fixe",
"brand": "KIMEX",
"is_active": true,
"updated_at": "2026-06-19T09:30:00Z"
},
"count": 1
}
Update a product
Partially updates a product identified by WinDev reference or EAN. Only fields included in the payload are modified — omitted fields are left unchanged.
Requires windev:write.
Fires a product.updated webhook event on success.
url_slug is limited to 255 characters (since October 20, 2026): beyond, the request is refused with 422 VALIDATION_URL_SLUG_TOO_LONG. An update is never refused by the product cap. price_ht is the selling price excl. VAT; price_ttc alone → 422 WINDEV_PRICE_TTC_ONLY (see Prices). A product in the trash → 409 WINDEV_PRODUCT_IN_TRASH; an ambiguous reference → 409 WINDEV_REFERENCE_AMBIGUOUS.
Path parameters
- Name
ref- Type
- string
- Description
WinDev reference or EAN of the product to update.
The body accepts any writable product field. Fields include everything from POST /products/sync plus extended attributes:
- Identifiers:
name,ean,asin,upc,gtin,external_id,reference,url_slug - Content:
brand,description,short_description,promotional_text - Status:
is_active,lifecycle_status,discontinued,end_of_life_date - Dimensions:
weight,width,height,depth,unit_of_measure - Packaging:
package_length,package_width,package_height,package_weight,package_quantity - B2B:
min_order_quantity,max_order_quantity,order_increment,lead_time_days,backorder_allowed,preorder_available,requires_quote,is_b2b_only - Compliance:
hs_code,country_of_origin,dangerous_goods,dangerous_goods_class,reach_compliant,rohs_compliant,ce_marked,weee_category - Energy:
energy_class,recyclable,eco_friendly,carbon_footprint_kg - Warranty:
warranty_duration,warranty_type,return_policy_days,return_allowed - Physical:
color,color_secondary,size,material,finish,style,pattern - JSON:
technical_specs,compatibility - Inline:
price_ht(selling price excl. VAT),stock,supplier_code,tax_rate
Request
curl -X PATCH https://api.pixeepim.com/api/v1/windev/products/ART-001 \
-H "X-API-Key: pm_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"price_ht": 19.99,
"stock": 38,
"is_active": true,
"warranty_duration": 24,
"ce_marked": true
}'
Response
{
"success": true,
"code": 200,
"message": "Produit mis à jour",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"ean": "3760000000001",
"name": "Support TV mural fixe",
"is_active": true,
"updated_at": "2026-06-19T10:05:00Z"
},
"count": 1
}
Activate / Deactivate
Convenience endpoints to toggle product visibility without a full PATCH body.
POST /products/{ref}/activate→ setsis_active = true,status = activePOST /products/{ref}/deactivate→ setsis_active = false,status = inactive
Both require windev:write and fire a product.updated webhook event.
Path parameters
- Name
ref- Type
- string
- Description
WinDev reference or EAN of the product.
Activate
curl -X POST https://api.pixeepim.com/api/v1/windev/products/ART-001/activate \
-H "X-API-Key: pm_live_abc123..."
Response
{
"success": true,
"code": 200,
"message": "Produit activé",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"is_active": true,
"status": "active"
},
"count": 1
}
Update stock
Updates stock quantities in batch — up to 5 000 items per call. Products are matched by EAN.
If supplier_code is provided, the stock is updated on the supplier_products record for that supplier. Otherwise, the generic product_stocks entry is updated.
Fires a stock.updated webhook event (first 50 EANs included in payload).
Each line of data reports ean, updated (boolean) and status — updated, not_found or error — with error when the status is not_found or error, and error_code for a named refusal.
Requires windev:write.
Body parameters
Pass a JSON array directly:
- Name
ean- Type
- string
- Description
EAN of the product.
- Name
stock- Type
- integer
- Description
New stock quantity (≥ 0).
- Name
supplier_code- Type
- string
- Description
Supplier code — routes the update to the supplier-level stock record.
Request
curl -X POST https://api.pixeepim.com/api/v1/windev/stock/update \
-H "X-API-Key: pm_live_abc123..." \
-H "Content-Type: application/json" \
-d '[
{ "ean": "3760000000001", "stock": 42, "supplier_code": "KIMEX" },
{ "ean": "3760000000002", "stock": 0 },
{ "ean": "3760000000003", "stock": 15, "supplier_code": "KIMEX" }
]'
Response
{
"success": true,
"code": 200,
"message": "Stocks : 2 mis à jour, 1 introuvables, 0 erreurs",
"data": [
{ "ean": "3760000000001", "updated": true, "status": "updated" },
{ "ean": "3760000000002", "updated": false, "status": "not_found", "error": "…" },
{ "ean": "3760000000003", "updated": true, "status": "updated" }
],
"count": 3
}
Update prices
Updates product prices in batch — up to 5 000 items per call. Products are matched by EAN.
price_ht is stored as the selling price excl. VAT (since October 26, 2026; before, it was stored as cost). price_ttc is never stored: a line with price_ttc only is refused (status: "error", error_code: "WINDEV_PRICE_TTC_ONLY"); with price_ht, it is cited in champs_ignores.
Fires a price.updated webhook event (first 50 EANs included in payload).
Each line of data reports ean, updated and status (updated, not_found or error), the recorded price_ht when updated, and error (plus error_code for a named refusal) otherwise.
Requires windev:write.
Body parameters
- Name
ean- Type
- string
- Description
EAN of the product.
- Name
price_ht- Type
- number
- Description
Selling price excl. VAT in EUR (≥ 0) — the only price stored.
- Name
price_ttc- Type
- number
- Description
Never stored — alone, the line is refused (
WINDEV_PRICE_TTC_ONLY).
Request
curl -X POST https://api.pixeepim.com/api/v1/windev/prices/update \
-H "X-API-Key: pm_live_abc123..." \
-H "Content-Type: application/json" \
-d '[
{ "ean": "3760000000001", "price_ht": 18.50 },
{ "ean": "3760000000002", "price_ttc": 9.99 }
]'
Response
{
"success": true,
"code": 200,
"message": "Prix : 1 mis à jour, 0 introuvables, 1 erreurs",
"data": [
{ "ean": "3760000000001", "updated": true, "status": "updated", "price_ht": 18.5 },
{ "ean": "3760000000002", "updated": false, "status": "error", "error_code": "WINDEV_PRICE_TTC_ONLY", "error": "…" }
],
"count": 2,
"champs_ignores": [],
"champs_ignores_par_fiche": []
}
Categories
Deprecated since October 30, 2026 (v6.33.0). This route served the former category tree, which has been removed: it now returns an empty list (same envelope and item shape) and carries the Deprecation / Sunset headers. Removal on April 28, 2027 at the earliest. The category sent by POST /products/sync is filed in the Category Manager.
Item shape kept in contract v1: id, name, slug, parent_id, level, path, is_active, product_count.
Requires windev:read.
Request
curl https://api.pixeepim.com/api/v1/windev/categories \
-H "X-API-Key: pm_live_abc123..."
Response
{
"success": true,
"code": 200,
"message": "0 catégories",
"data": [],
"count": 0
}
Suppliers
Returns the list of active suppliers sorted by name. Use supplier_code values when pushing products via POST /products/sync or POST /stock/update.
Requires windev:read.
Request
curl https://api.pixeepim.com/api/v1/windev/suppliers \
-H "X-API-Key: pm_live_abc123..."
Response
{
"success": true,
"code": 200,
"message": "8 fournisseurs",
"data": [
{
"id": "c3d4e5f6-...",
"name": "KIMEX International",
"code": "KIMEX",
"is_active": true,
"contact_email": null,
"contact_phone": null,
"country": "FR"
}
],
"count": 8
}