Errors

The Pixee PIM API uses standard HTTP status codes and returns structured JSON error responses when something goes wrong.

Error response format

Most error responses follow this unified envelope:

Error response

{
  "error": {
    "code": 404,
    "error_code": "PRODUCT_NOT_FOUND",
    "type": "not_found",
    "message": "The EAN field is required.",
    "details": null,
    "path": "/api/v1/products/550e8400-e29b-41d4-a716-446655440000",
    "request_id": "abc-123",
    "timestamp": "2026-09-17T10:30:00Z"
  }
}
FieldDescription
error.codeHTTP status code, repeated in the body
error.error_codeStandardized machine-readable code (e.g. PRODUCT_NOT_FOUND)
error.typeError category: validation_error, not_found, conflict, authentication_error, authorization_error, database_error, rate_limit_exceeded, internal_server_error, http_error
error.messageHuman-readable, localized description (see Localization below)
error.detailsOptional structured detail — e.g. a list of field errors on 422
error.pathThe request path that produced the error
error.request_idCorrelates with server-side logs — include it when reporting an issue
error.timestampISO 8601 timestamp of when the error occurred

Divergent shapes — endpoints that don't use the envelope above

A handful of error sources predate the unified envelope and were deliberately not rewritten to avoid silently changing an already-integrated contract. Match on the field names below, not on error.code:

SituationStatusShape
Rate limit exceeded429{ "error": "rate_limit_exceeded", "message", "detail", "retry_after" } — error is a string here. See Rate Limiting.
CSRF token missing/invalid403{ "detail", "error_type": "csrf_validation_error", "debug": {...} }
Module disabled on this instance403{ "detail", "code": "MODULE_DISABLED", "module_id": "..." }
Instance license suspended (read-only mode)403{ "detail", "code": "LICENSE_SUSPENDED" }

HTTP status codes

StatusMeaning
200 OKRequest succeeded
201 CreatedResource created successfully
202 AcceptedRequest accepted — async processing started
204 No ContentRequest succeeded, no body returned
400 Bad RequestInvalid request parameters
401 UnauthorizedMissing, invalid, or expired credential
403 ForbiddenInsufficient scope or permissions — or MODULE_DISABLED / LICENSE_SUSPENDED (see above)
404 Not FoundResource not found
409 ConflictResource already exists (e.g. duplicate EAN) — or a dependency this operation needs is not configured on the instance (see Dependency not configured) — or the plan's product cap could not be checked right now (BILLING_LICENSE_QUOTA_BUSY, retry)
422 Unprocessable EntityValidation error on request body
423 LockedAccount locked after repeated failed login attempts
429 Too Many RequestsRate limit exceeded — see Rate Limiting
500 Internal Server ErrorUnexpected server error
503 Service UnavailableA configured dependency is momentarily unreachable, or maintenance. Always carries a Retry-After header and error_code: SYSTEM_SERVICE_UNAVAILABLE — retry after the delay. Since September 18, 2026 a missing configuration is never a 503

Dependency not configured (409)

Some operations depend on something an administrator sets up per instance: an Odoo connection, a connector's webhook secret, an AI provider assigned to a usage, the shared key of the price monitoring service, the optional vector search engine. When that setup is missing, the API answers 409 Conflict with an error_code from the *_NOT_CONFIGURED family. This is a permanent state of the instance, not an outage: retrying will not help, fixing the configuration will. error.details names the dependency and the fix.

409 — dependency not configured

{
  "error": {
    "code": 409,
    "error_code": "ODOO_NOT_CONFIGURED",
    "type": "conflict",
    "message": "No Odoo connection is configured on this instance. Enter the Odoo URL, database and credentials in the Odoo Sync screen before running this import.",
    "details": { "dependency": "odoo", "how_to_fix": "Renseignez l'URL, la base et les identifiants Odoo dans l'écran Odoo Sync (/odoo-sync)" },
    "path": "/api/v1/brands/import-from-odoo",
    "request_id": "abc-123",
    "timestamp": "2026-09-18T10:30:00Z"
  }
}
Error codeRaised byWhat to do
ODOO_NOT_CONFIGUREDPOST /brands/import-from-odooAn administrator enters the Odoo URL, database and credentials in the Odoo Sync screen
CONNECTOR_WEBHOOK_NOT_CONFIGUREDPOST /connectors/{shopify,woocommerce,bigcommerce}/webhook (409), POST /connectors/magento/push (401)The connector or its webhook secret is missing on the PixeePIM side — the sender's credentials are not at fault
AI_PROVIDER_NOT_CONFIGUREDPOST /enrichment/products/{product_id}Add a provider key in Settings → AI Services, or assign a provider to the “enrichment” usage
SCRAPER_SYNC_KEY_NOT_CONFIGUREDGET /prices/export-watchlist, POST /prices/observationsThe shared key with the price monitoring service is not set on this instance — ask an administrator
SEARCH_VECTOR_NOT_CONFIGUREDGET /search/products/{product_id}/similarSimilarity search is an optional add-on; ask an administrator to enable it on the instance

Validation errors (422)

Field-level validation failures populate error.details as an array:

422 Response

{
  "error": {
    "code": 422,
    "error_code": "VALIDATION_FAILED",
    "type": "validation_error",
    "message": "Request validation failed",
    "details": [
      { "field": "body.name", "message": "Field required", "type": "missing" }
    ],
    "path": "/api/v1/products",
    "request_id": "abc-123",
    "timestamp": "2026-09-17T10:30:00Z"
  }
}

Common error codes

Error codeDescription
AUTHENTICATION_REQUIREDNo credential provided
INVALID_API_KEYAPI key is invalid or revoked
PERMISSION_DENIEDCredential does not have access to this resource
NOT_FOUND / PRODUCT_NOT_FOUND / IMPORT_JOB_NOT_FOUNDThe requested resource does not exist
VALIDATION_FAILEDOne or more fields failed validation
DUPLICATE_EANA product with this EAN already exists
RATE_LIMIT_EXCEEDEDToo many requests — retry after the indicated delay
IMPORT_PARSE_FAILED / IMPORT_PERSISTENCE_FAILEDImport job encountered errors — check the error report
ACCOUNT_LOCKEDToo many failed login attempts — try again later
MODULE_DISABLEDThe module owning this route is switched off on this instance
LICENSE_SUSPENDEDThe instance's license is suspended — write operations are blocked (read-only mode)
*_NOT_CONFIGUREDA per-instance dependency is missing — 409, see Dependency not configured
SYSTEM_SERVICE_UNAVAILABLEA configured dependency is momentarily unreachable — 503 with Retry-After
BILLING_LICENSE_QUOTA_EXCEEDED403 — product creation refused: the plan's product cap is reached (updates are never refused). See External API → Product cap
BILLING_LICENSE_QUOTA_BUSY409 — another creation was checking the product cap at the same moment; nothing was written — retry
VALIDATION_URL_SLUG_TOO_LONG422 — url_slug longer than 255 characters (/ext and WinDev writes)
VALIDATION_URL_SLUG_SCHEME422 — url_slug looks like a full address (javascript:…); send only the end of the address. In POST /ext/products/batch it refuses the whole request
REQUEST_UNKNOWN_FIELD422 — the JSON body carries keys the operation does not declare; error.details names them and nothing is written. The public families /ext and /windev never answer it in contract v1: they tolerate unknown keys and list them in champs_ignores
WINDEV_PRODUCT_IN_TRASH / WINDEV_REFERENCE_AMBIGUOUS / WINDEV_PRICE_TTC_ONLYWinDev named refusals (409 / 409 / 422 on single routes, error_code on the line of a batch) — see WinDev → Named refusals
EXPORT_INTEGRATION_ABSENT422 — the export destination has no integration on this instance: Google Drive (platform_type: gdrive) can no longer be created, tested, previewed, sent to or scheduled — see Exports
SUPPLIER_INTEGRATION_ABSENT422 — POST /suppliers/test-connection with a Google Drive source (google_drive / gdrive): not offered as a supplier source
SYNC_FIELD_MAPPING_TARGET_UNKNOWN / SYNC_FIELD_MAPPING_TARGET_PROTECTED / SYNC_FIELD_MAPPING_SOURCE_INVALID / SYNC_FIELD_MAPPING_STRATEGY_UNSUPPORTED422 — a field correspondence of a shop or ERP connection is refused when saved: unknown target field, target held by the catalogue (identity, EAN, price, weight, categories…), source outside the allowed list, or strategy not supported by the platform. Nothing is written
SYNC_PROFIL_INTROUVABLE404 — the sync profile does not exist (deleted, or another platform); reload the connection's profiles. See Connectors → Sync profiles
SYNC_PROFIL_INVALIDE422 — a sync profile setting is unreadable or not allowed (name, direction, contents outside the closed list, override outside the allow-list, preview mode, unknown key, scope given at launch when the profile fixes one; since v6.39 mapping_id on an export profile — mapping_envoi_interdit —, unknown or of another connection — mapping_inconnu —, or making the connection's options unreadable — mapping_incompatible —, and {"apercu": true} on a profile that is not an import of products — apercu_import_seulement); details.raison and details.champ name it. Nothing is saved
SYNC_PROFIL_NOM_PRIS409 — a profile with this name already exists on this connection (case ignored). Nothing is created
SYNC_PROFIL_UTILISE409 — the profile is used by schedules (details.plannings): it cannot be deleted, nor change direction or contents, until they are attached to another profile. Nothing is changed
SYNC_PROFIL_NON_EXECUTABLE409 — the profile cannot be launched or attached to a schedule: it would not run as it announces. details.raison: inactif, surcharge_non_appliquee (an override the synchronization does not apply or no unit of the profile reads — listed in details.surcharges_non_appliquees), contenu_partiel_non_pris_en_charge (partial product record the platform or direction does not support — texts / SEO outside PrestaShop / WooCommerce export, media / brand outside PrestaShop / WooCommerce / Magento export; listed since v6.41 in details.contenus_non_pris_en_charge). Since v6.38 overrides and partial records run where supported, and since v6.39 a named import mapping runs. Nothing is launched
SYNC_PROFIL_INCOMPATIBLE422 — profile and schedule do not match: another connection, another direction, a schedule running both directions, or other units; details.raison. Nothing is changed
MAPPING_TEMPLATE_NOM_PRIS409 — since v6.39, a column (mapping) template of the same supplier and import type already has this name (case ignored): creation, rename, duplication, Code2ASIN template without remplacer. details.modele_existant_id names it — replace it or choose another name. Nothing is changed. See Imports → Mapping templates
VALIDATION_HOST_UNRESOLVED400 — a server address you sent (FTP / SFTP host, URL of a source, webhook or platform…) does not resolve: its name matches no address. Check the spelling of the host (no ftp:// scheme or path); details.champ names the field. Distinct, since v6.41, from VALIDATION_URL_REJECTED_SSRF (an address that points to an internal network). Nothing is changed
EXPORT_SCHEDULES_RETIRED410 — the export schedules (/exports/schedules*) are retired: nothing is read or written; use the schedules of a sync profile (see Exports)
VALIDATION_INVALID_PATTERN422 — a value does not match its expected format (for instance an unreadable Magento attribute code in a field correspondence)
EXPORTS_INSTANCE_INTERDITS409 — sending to shops and ERPs is disabled for this instance by the Pixee PIM team (imports stay allowed)
SYSTEM_INTERNAL_ERRORUnexpected server error (5xx)

Public API families (/ext, /windev)

Error responses of /api/v1/ext/* and /api/v1/windev/* (missing or refused key, not found, validation, quota, server error) carry the API-Version: 1 header — and the deprecation headers when the operation is deprecated — like their successful responses. The body is the envelope above; nothing else changes. A refusal returned directly by a middleware (module gate, license, CSRF) may come without these headers: the HTTP status is enough. See External API → Versioning.

Localization

error.message is translated based on the Accept-Language header. Only French (fr) and English (en) have translated message catalogs today, even though the underlying locale middleware accepts a broader set of locales for other purposes.

Request a localized error

curl https://api.pixeepim.com/api/v1/products/00000000-0000-0000-0000-000000000000 \
  -H "Authorization: Bearer {api_key}" \
  -H "Accept-Language: fr"

Async operations

Endpoints that start long-running jobs (imports, exports, enrichment) return 202 Accepted immediately. Poll the job's status endpoint until the status is completed or failed:

202 Accepted

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing"
}

Was this page helpful?