# Pixels de suivi

Ces quatre endpoints gèrent les pixels de suivi d'une boutique, la même liste que le marchand modifie sur la page **Paramètres des pixels** du dashboard (`/dashboard/pixels`). Une boutique accepte sept types de pixel : Meta (Facebook), TikTok, Snapchat, Pinterest, Google Analytics, Google Tag Manager et Google Ads. Ce dont chaque plateforme a besoin, et comment vérifier que ses événements arrivent, se trouve dans le [guide des pixels](https://dzbuild.com/fr/fr/docs/marketing/pixels.md).

Les vérifications sont purement syntaxiques. Un `201` veut dire que les identifiants sont bien formés, pas que la plateforme publicitaire les a acceptés. Le token d'accès des événements serveur est en écriture seule : aucun endpoint ne le renvoie, et `has_token` indique si un token est enregistré.

## Avant de commencer[​](#avant-de-commencer "Lien direct vers Avant de commencer")

* `GET` demande `pixels:read`. `POST`, `PATCH` et `DELETE` demandent `pixels:write` et une `Idempotency-Key` (voir [Idempotence](https://dzbuild.com/fr/fr/api-docs/idempotency.md)). Les clés créées depuis le dashboard (**Paramètres → API**, `/dashboard/api`) ont les deux portées. Les portées sont figées à la création de la clé : une clé plus ancienne sans celle qu'il faut répond `403 forbidden`. Créez une nouvelle clé depuis le dashboard.
* Le plan fixe le nombre de pixels qu'une boutique peut avoir : aucun sur Free, un de chaque type sur Pro, sans limite sur Unlimited et Enterprise. Une clé personnelle ne fonctionne que sur une boutique avec un plan Enterprise actif. Une application installée peut aussi agir sur des boutiques en Free ou en Pro, où la limite s'applique.
* Le marchand peut affecter un pixel à des produits, des catégories ou des landing pages depuis le dashboard. L'API ne lit ni ne modifie ces affectations.

| Portée         | Description                                                                          |
| -------------- | ------------------------------------------------------------------------------------ |
| `pixels:read`  | Lire les pixels de suivi de la boutique. Les tokens d'accès ne sont jamais renvoyés. |
| `pixels:write` | Ajouter, modifier et supprimer des pixels de suivi.                                  |

## L'objet pixel[​](#lobjet-pixel "Lien direct vers L'objet pixel")

| Champ                      | Type           | Notes                                                                                                                            |
| -------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `id`                       | int            | L'id du pixel chez DZBuild, utilisé dans le chemin de `PATCH` et `DELETE`.                                                       |
| `pixel_type`               | string         | L'un des sept types ci-dessous. Fixé à la création.                                                                              |
| `pixel_id`                 | string         | L'identifiant de pixel, de balise ou de mesure fourni par la plateforme publicitaire. Fixé à la création.                        |
| `pixel_name`               | string ou null | Nom affiché.                                                                                                                     |
| `has_token`                | bool           | `true` quand un token d'accès pour les événements serveur est enregistré.                                                        |
| `test_event_code`          | string ou null | Le code de test des événements saisi dans le dashboard. L'API ne peut pas le définir, et un `PATCH` qui écrit un champ l'efface. |
| `ad_account_id`            | string ou null | L'identifiant du compte publicitaire Pinterest.                                                                                  |
| `conversion_label`         | string ou null | Le libellé de conversion Google Ads.                                                                                             |
| `is_active`                | bool           | `false` garde le pixel et coupe ses événements navigateur et serveur.                                                            |
| `is_default`               | bool           | Le passer à `true` le retire des autres pixels du même type de la boutique. L'endroit où un pixel se charge n'en dépend pas.     |
| `created_at`, `updated_at` | string         | `YYYY-MM-DD HH:MM:SS`, heure d'Alger.                                                                                            |

### Types de pixel[​](#types-de-pixel "Lien direct vers Types de pixel")

| `pixel_type`       | Plateforme         | Événements serveur                                            |
| ------------------ | ------------------ | ------------------------------------------------------------- |
| `facebook`         | Meta (Facebook)    | Oui, quand le pixel a un token d'accès.                       |
| `tiktok`           | TikTok             | Oui, quand le pixel a un token d'accès.                       |
| `snapchat`         | Snapchat           | Oui, quand le pixel a un token d'accès.                       |
| `pinterest`        | Pinterest          | Oui, quand le pixel a un token d'accès et un `ad_account_id`. |
| `google_analytics` | Google Analytics   | Non.                                                          |
| `gtm`              | Google Tag Manager | Non.                                                          |
| `google_ads`       | Google Ads         | Non. `conversion_label` n'est lu que pour ce type.            |

Un token envoyé pour un type sans événements serveur est enregistré mais jamais utilisé.

### Où un pixel se charge[​](#où-un-pixel-se-charge "Lien direct vers Où un pixel se charge")

Un pixel actif sans affectation se charge sur toutes les pages de la vitrine, landing pages incluses. Un pixel que le marchand a affecté à des produits, des catégories ou des landing pages ne se charge que sur les pages correspondantes, et ses événements serveur suivent la même règle. Un pixel créé par l'API démarre sans affectation.

## Le token d'accès[​](#le-token-daccès "Lien direct vers Le token d'accès")

`access_token` est le token des événements serveur copié depuis le gestionnaire d'événements de la plateforme publicitaire. L'API retire les caractères invisibles ainsi que les espaces et les guillemets qui l'entourent, puis le refuse avec `422 invalid_access_token` s'il contient encore `<`, une espace ou un saut de ligne, s'il est égal à `pixel_id`, ou si un token `facebook` fait moins de 40 caractères.

* Aucun endpoint ne renvoie le token. L'historique des changements de la boutique garde le masque `••••••••` à sa place.
* Sur `PATCH`, une chaîne vide, `null` ou une valeur contenant ce masque garde le token enregistré. Un token peut être remplacé mais pas retiré par l'API : pour l'enlever, supprimez le pixel et ajoutez-le de nouveau sans token, ce qui supprime aussi ses affectations.

## `GET /v1/pixels`[​](#get-v1pixels "Lien direct vers get-v1pixels")

Les pixels de la boutique, du plus récent au plus ancien, avec l'allocation du plan dans `limits`.

**Auth :** clé plateforme avec `pixels:read`.

### Paramètres de requête[​](#paramètres-de-requête "Lien direct vers Paramètres de requête")

| Param        | Type   | Défaut | Notes                                                                                                        |
| ------------ | ------ | ------ | ------------------------------------------------------------------------------------------------------------ |
| `pixel_type` | string | aucun  | Seulement les pixels de ce type. Un type inconnu renvoie une liste vide.                                     |
| `limit`      | int    | 50     | De 1 à 200.                                                                                                  |
| `cursor`     | string | aucun  | Le `next_cursor` de la page précédente. Voir [Pagination](https://dzbuild.com/fr/fr/api-docs/pagination.md). |

### Requête[​](#requête "Lien direct vers Requête")

```
curl 'https://api.dzbuild.app/v1/pixels?pixel_type=facebook' \

  -H "Authorization: Bearer $DZ_KEY"
```

### Réponse 200[​](#réponse-200 "Lien direct vers Réponse 200")

```
{

  "data": {

    "items": [

      {

        "id": 12,

        "pixel_type": "facebook",

        "pixel_id": "123456789012345",

        "pixel_name": "Main ad account",

        "has_token": true,

        "test_event_code": null,

        "ad_account_id": null,

        "conversion_label": null,

        "is_active": true,

        "is_default": false,

        "created_at": "2026-10-01 14:20:05",

        "updated_at": "2026-10-01 14:20:05"

      }

    ],

    "next_cursor": null,

    "has_more": false,

    "limits": {

      "plan": "enterprise",

      "can_add": true,

      "per_type_limit": null,

      "total_limit": null,

      "counts": {

        "facebook": 1,

        "tiktok": 1,

        "snapchat": 0,

        "pinterest": 0,

        "google_analytics": 1,

        "gtm": 0,

        "google_ads": 0

      },

      "total": 3

    }

  }

}
```

### `limits`[​](#limits "Lien direct vers limits")

`limits` accompagne chaque page et décrit toute la boutique, quel que soit le `pixel_type` filtré.

| Champ            | Signification                                                                                                                          |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `plan`           | Le plan de la boutique dont vient l'allocation.                                                                                        |
| `can_add`        | `false` quand le plan n'autorise aucun pixel. Il ignore les compteurs : comparez `counts` à `per_type_limit` avant d'ajouter un pixel. |
| `per_type_limit` | Pixels autorisés par type, `null` pour aucune limite.                                                                                  |
| `total_limit`    | Pixels autorisés au total, `null` pour aucune limite.                                                                                  |
| `counts`         | Pixels par type, avec une clé pour chacun des sept types.                                                                              |
| `total`          | Tous les pixels de la boutique, actifs ou non.                                                                                         |

## `POST /v1/pixels`[​](#post-v1pixels "Lien direct vers post-v1pixels")

Ajoute un pixel et répond `201` avec celui-ci.

**Auth :** clé plateforme avec `pixels:write`. **Nécessite `Idempotency-Key`.**

### Corps[​](#corps "Lien direct vers Corps")

| Champ              | Type   | Requis | Notes                                                                                                             |
| ------------------ | ------ | ------ | ----------------------------------------------------------------------------------------------------------------- |
| `pixel_type`       | string | oui    | L'un des sept types, en majuscules ou en minuscules. `type` est accepté aussi.                                    |
| `pixel_id`         | string | oui    | De 1 à 100 lettres, chiffres, `-` ou `_`. Un id `facebook` compte 15 à 17 chiffres, copiés depuis Events Manager. |
| `pixel_name`       | string | non    | Coupé à 100 caractères. `name` est accepté aussi.                                                                 |
| `access_token`     | string | non    | Suit les règles du token d'accès ci-dessus. Omettez-le ou envoyez `""` pour un pixel sans événements serveur.     |
| `ad_account_id`    | string | non    | Coupé à 64 caractères.                                                                                            |
| `conversion_label` | string | non    | Coupé à 64 caractères.                                                                                            |
| `is_active`        | bool   | non    | `true` par défaut.                                                                                                |
| `is_default`       | bool   | non    | `false` par défaut.                                                                                               |

### Ce que vérifie l'appel[​](#ce-que-vérifie-lappel "Lien direct vers Ce que vérifie l'appel")

Les vérifications se font dans cet ordre, et la première qui échoue donne l'erreur. Un refus est enregistré avec sa `Idempotency-Key` pendant 24 heures : une fois la cause corrigée, renvoyez l'appel avec une nouvelle `Idempotency-Key`.

1. `pixel_type` est l'un des sept types, sinon `422 invalid_pixel_type`.
2. `pixel_id` a le bon format, sinon `422 invalid_pixel_id`.
3. Le plan autorise un autre pixel de ce type, sinon `409 limit_reached`.
4. La boutique n'a pas de pixel du même type avec le même `pixel_id`, sinon `409 pixel_exists`.
5. `access_token`, s'il est envoyé, suit les règles du token d'accès, sinon `422 invalid_access_token`.

### Requête[​](#requête-1 "Lien direct vers Requête")

```
curl -X POST 'https://api.dzbuild.app/v1/pixels' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: pixel-meta-main-1" \

  -d '{"pixel_type": "facebook", "pixel_id": "123456789012345", "pixel_name": "Main ad account", "access_token": "EAAGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}'
```

### Réponse 201[​](#réponse-201 "Lien direct vers Réponse 201")

```
{

  "data": {

    "id": 12,

    "pixel_type": "facebook",

    "pixel_id": "123456789012345",

    "pixel_name": "Main ad account",

    "has_token": true,

    "test_event_code": null,

    "ad_account_id": null,

    "conversion_label": null,

    "is_active": true,

    "is_default": false,

    "created_at": "2026-10-01 14:20:05",

    "updated_at": "2026-10-01 14:20:05"

  }

}
```

## `PATCH /v1/pixels/{id}`[​](#patch-v1pixelsid "Lien direct vers patch-v1pixelsid")

Ne modifie que les champs envoyés et répond `200` avec le pixel. Un corps vide ne change rien.

**Auth :** clé plateforme avec `pixels:write`. **Nécessite `Idempotency-Key`.**

### Corps[​](#corps-1 "Lien direct vers Corps")

| Champ              | Type           | Notes                                                                                      |
| ------------------ | -------------- | ------------------------------------------------------------------------------------------ |
| `pixel_name`       | string ou null | Coupé à 100 caractères. `null` ou `""` l'efface.                                           |
| `access_token`     | string         | Un nouveau token remplace celui enregistré. Une chaîne vide, `null` ou le masque le garde. |
| `ad_account_id`    | string ou null | Coupé à 64 caractères. `null` ou `""` l'efface.                                            |
| `conversion_label` | string ou null | Coupé à 64 caractères. `null` ou `""` l'efface.                                            |
| `is_active`        | bool           | `false` met le pixel en pause et le garde.                                                 |
| `is_default`       | bool           | `true` le retire des autres pixels du même type de la boutique.                            |

`pixel_type`, `type` et `pixel_id` ne peuvent pas être envoyés, même avec leur valeur actuelle : l'appel répond `422 immutable_field`. Pour les changer, supprimez le pixel et ajoutez-en un nouveau.

### Requête[​](#requête-2 "Lien direct vers Requête")

```
curl -X PATCH 'https://api.dzbuild.app/v1/pixels/12' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Content-Type: application/json" \

  -H "Idempotency-Key: pixel-12-pause-1" \

  -d '{"is_active": false}'
```

### Réponse 200[​](#réponse-200-1 "Lien direct vers Réponse 200")

```
{

  "data": {

    "id": 12,

    "pixel_type": "facebook",

    "pixel_id": "123456789012345",

    "pixel_name": "Main ad account",

    "has_token": true,

    "test_event_code": null,

    "ad_account_id": null,

    "conversion_label": null,

    "is_active": false,

    "is_default": false,

    "created_at": "2026-10-01 14:20:05",

    "updated_at": "2026-10-02 09:05:41"

  }

}
```

## `DELETE /v1/pixels/{id}`[​](#delete-v1pixelsid "Lien direct vers delete-v1pixelsid")

Supprime le pixel et ses affectations aux produits, catégories et landing pages.

**Auth :** clé plateforme avec `pixels:write`. **Nécessite `Idempotency-Key`.**

### Requête[​](#requête-3 "Lien direct vers Requête")

```
curl -X DELETE 'https://api.dzbuild.app/v1/pixels/12' \

  -H "Authorization: Bearer $DZ_KEY" \

  -H "Idempotency-Key: pixel-12-delete-1"
```

### Réponse 200[​](#réponse-200-2 "Lien direct vers Réponse 200")

```
{

  "data": {

    "deleted": true,

    "id": 12

  }

}
```

## Annulation[​](#annulation "Lien direct vers Annulation")

Chaque écriture de pixel faite par l'API est enregistrée dans l'historique des changements de la boutique. La réponse d'écriture ne porte pas d'id de changement : retrouvez-le avec `GET /v1/changes?entity=pixels`, du plus récent au plus ancien, qui demande `store:read`. `POST /v1/changes/{id}/undo` annule un changement et demande `pixels:write` et une `Idempotency-Key`. Voir [Changements et annulation](https://dzbuild.com/fr/fr/api-docs/resources/changes.md).

* Annuler une modification rétablit `pixel_name`, `ad_account_id`, `conversion_label`, `is_active` et `is_default`. Le token n'est pas dans l'historique : il reste tel qu'il est maintenant.
* Annuler une suppression rajoute le pixel avec ses anciens champs, et avec son ancien `id` si cet id est encore libre, mais sans son token d'accès et sans ses affectations. La limite du plan et le contrôle des doublons s'appliquent toujours : cette annulation peut répondre `409 limit_reached` ou `409 pixel_exists`.
* Un ajout de pixel ne s'annule pas : l'annulation répond `422 nothing_to_restore`. Supprimez plutôt le pixel.
* Annuler la modification d'un pixel supprimé depuis répond `422 restore_target_missing`.
* Les changements de pixels faits dans le dashboard ne sont pas enregistrés, on ne peut donc pas les annuler par l'API.
* Le jeton d'une application installée ne peut ni lire ni annuler les changements : les deux répondent `403 forbidden`.

## Erreurs[​](#erreurs "Lien direct vers Erreurs")

| HTTP | Code                    | Cause                                                                                                                                                                                         |
| ---- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `bad_request`           | Le corps n'est pas un JSON valide, l'id du pixel dans le chemin n'est pas composé de chiffres, ou `Idempotency-Key` manque ou est mal formée sur `POST`, `PATCH` ou `DELETE`.                 |
| 401  | `unauthorized`          | Clé absente ou invalide.                                                                                                                                                                      |
| 402  | `quota_exceeded`        | Le quota mensuel de requêtes de la boutique est épuisé. Voir [Limites de taux](https://dzbuild.com/fr/fr/api-docs/rate-limits.md).                                                            |
| 403  | `forbidden`             | `Missing scope: pixels:read` ou `Missing scope: pixels:write`, ou `API access requires an active Enterprise plan` pour une clé personnelle dont la boutique n'a pas de plan Enterprise actif. |
| 404  | `not_found`             | Aucun pixel avec cet id dans la boutique. Un pixel d'une autre boutique répond de la même façon.                                                                                              |
| 409  | `limit_reached`         | Le plan n'autorise plus de pixel de ce type.                                                                                                                                                  |
| 409  | `pixel_exists`          | La boutique a déjà un pixel de ce type avec ce `pixel_id`.                                                                                                                                    |
| 413  | `payload_too_large`     | Le corps dépasse 1 Mo.                                                                                                                                                                        |
| 422  | `invalid_pixel_type`    | `pixel_type` manque ou n'est pas l'un des sept types.                                                                                                                                         |
| 422  | `invalid_pixel_id`      | `pixel_id` manque, dépasse 100 caractères, contient un caractère autre que lettres, chiffres, `-` et `_`, ou est un id `facebook` qui ne compte pas 15 à 17 chiffres.                         |
| 422  | `invalid_access_token`  | Le token enfreint l'une des règles du token d'accès.                                                                                                                                          |
| 422  | `immutable_field`       | Un `PATCH` a envoyé `pixel_type`, `type` ou `pixel_id`.                                                                                                                                       |
| 422  | `pixel_write_failed`    | L'écriture a été refusée alors que les vérifications ci-dessus étaient passées. Le message donne la raison et peut être en arabe.                                                             |
| 422  | `idempotency_key_reuse` | La même `Idempotency-Key` a servi avec une autre méthode, un autre chemin ou un autre corps.                                                                                                  |
| 429  | `rate_limited`          | Trop de requêtes. Attendez la durée de `Retry-After`.                                                                                                                                         |
| 500  | `server_error`          | La requête a échoué. Réessayez avec la même `Idempotency-Key`.                                                                                                                                |
