Contrat API V1
Nous recommandons l’API server-to-server. JavaScript est uniquement une solution analytique de secours facultative et ne fonctionne qu’après l’obtention du consentement analytique.
Contrat API V1 Lien vers la section Contrat API V1
Nous recommandons l’API server-to-server. JavaScript est uniquement une solution analytique de secours facultative et ne fonctionne qu’après l’obtention du consentement analytique.
Les commandes, le chiffre d’affaires et les indicateurs dérivés ne sont affichés que lorsque le suivi des conversions est actif. Ils servent uniquement à l’analyse et ne modifient pas la facturation CPC.
schema_version
1.0
payload_contract
order_v1
Content-Type
application/json
request_limit
64 KiB
Comment connecter la mesure Lien vers la section Comment connecter la mesure
Nous recommandons l’API server-to-server. JavaScript est uniquement une solution analytique de secours facultative et ne fonctionne qu’après l’obtention du consentement analytique.
- 1 Enregistrez le paramètre zclid de l’URL de destination avec le panier ou la commande pendant 30 jours.
- 2 Sur le serveur, créez une empreinte HMAC-SHA-256 stable de l’ID interne de la commande à l’aide d’une clé distincte. N’envoyez ni l’ID brut ni de données personnelles.
- 3 Après la création de la commande, envoyez le JSON à l’API et signez le corps exact de la requête avec la clé secrète d’intégration.
- 4 Pour le paiement, l’annulation et les remboursements cumulés, réutilisez les mêmes zclid et order_id_hash. Conservez les totaux et lignes finaux.
La clé secrète d’intégration ne s’affiche qu’une seule fois. Enregistrez-la dans le gestionnaire de secrets du serveur du marchand.
Recommandé : API server-to-server Lien vers la section Recommandé : API server-to-server
Le serveur du marchand envoie les commandes validées, les changements de statut et les remboursements directement à Zoneo. N’insérez jamais la clé secrète dans le navigateur.
https://izoneo.fr/api/v1/conversions
https://izoneo.fr/api/v1/conversions/sandbox
Sur le serveur, créez une empreinte HMAC-SHA-256 stable de l’ID interne de la commande à l’aide d’une clé distincte. N’envoyez ni l’ID brut ni de données personnelles.
order_id_hash · PHP
$orderIdHash = hash_hmac(
'sha256',
"zoneo-order-v1\n".$internalOrderId,
$_ENV['ZONEO_ORDER_HASH_KEY'],
);
Exemple de requête Lien vers la section Exemple de requête
Après la création de la commande, envoyez le JSON à l’API et signez le corps exact de la requête avec la clé secrète d’intégration.
order_v1 · JSON
{
"schema_version": "1.0",
"zclid": "018fb72a-7d8e-7c3c-a4da-f37ce07ad739",
"order_id_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"currency": "EUR",
"occurred_at": "2026-08-31T12:34:56Z",
"status": "placed",
"refund_amount_minor": 0,
"totals": {
"items_gross_minor": 14000,
"discount_minor": 1500,
"shipping_gross_minor": 390,
"fees_gross_minor": 100,
"tax_minor": 2165,
"order_total_gross_minor": 12990
},
"items": [
{
"merchant_item_id": "ITEM_ID_FROM_FEED",
"item_group_id": "MODEL-10",
"variant_id": "size:42",
"name": "PRODUCT_NAME",
"gtin": "8581234567890",
"quantity": 2,
"unit_price_gross_minor": 7000,
"line_total_gross_minor": 14000
}
],
"order_locale": "fr",
"expected_delivery_date": "2026-09-03"
}
| JSON | Champs obligatoires | V1 |
|---|---|---|
schema_version |
✓ | = "1.0" |
zclid |
✓ | UUID |
order_id_hash |
✓ | HMAC-SHA-256 · [a-f0-9]{64} |
currency |
✓ | ISO 4217 · EUR |
occurred_at |
✓ | ISO 8601 · UTC |
status |
✓ | placed | paid | cancelled | partially_refunded | refunded |
refund_amount_minor |
✓ | integer ≥ 0 · Σ · monotonic |
totals |
✓ | object · integer · gross |
items |
✓ | array[1..100] |
order_locale |
— | BCP 47 |
expected_delivery_date |
— | YYYY-MM-DD |
| items[] | Champs obligatoires | V1 |
|---|---|---|
merchant_item_id |
✓ | feed.ITEM_ID · stable |
quantity |
✓ | integer · 1..1000 |
unit_price_gross_minor |
✓ | integer ≥ 0 |
line_total_gross_minor |
✓ | unit_price_gross_minor × quantity |
item_group_id |
— | string |
variant_id |
— | string |
name |
— | string · PRODUCT_NAME · PII = 0 |
gtin |
— | [0-9]{8,14} |
totals · EUR · integer
totals.items_gross_minor = sum(items[].line_total_gross_minor)
totals.order_total_gross_minor = totals.items_gross_minor - totals.discount_minor + totals.shipping_gross_minor + totals.fees_gross_minor
line_total_gross_minor = unit_price_gross_minor × quantity
Signature canonique Lien vers la section Signature canonique
Si vous n’avez pas enregistré la clé secrète d’origine, utilisez Restaurer la clé secrète et enregistrez immédiatement la nouvelle clé en lieu sûr.
| HTTP | V1 |
|---|---|
Content-Type |
application/json |
X-Zoneo-Integration-ID |
zci_... |
X-Zoneo-Timestamp |
Unix · UTC |
X-Zoneo-Nonce |
CSPRNG · unique · len ≥ 16 |
Idempotency-Key |
order:{hash}:{status} |
X-Zoneo-Signature |
v1=HMAC_SHA256_HEX |
HMAC-SHA-256 · canonical request
UPPERCASE_HTTP_METHOD
/exact/request/path
unix_timestamp
nonce
idempotency_key
sha256_hex_of_exact_raw_body
body_hash = SHA256(raw_body)
signature = HMAC_SHA256(api_secret, canonical_request)
X-Zoneo-Signature = "v1=" + lowercase_hex(signature)
S2S · PHP
<?php
$path = '/api/v1/conversions';
$body = json_encode($payload, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES);
$timestamp = time();
$nonce = bin2hex(random_bytes(16));
$idempotencyKey = 'order:'.$orderIdHash.':'.$payload['status'];
$canonical = implode("\n", [
'POST',
$path,
(string) $timestamp,
$nonce,
$idempotencyKey,
hash('sha256', $body),
]);
$signature = hash_hmac('sha256', $canonical, $_ENV['ZONEO_API_SECRET']);
$headers = [
'Content-Type: application/json',
'X-Zoneo-Integration-ID: '.$_ENV['ZONEO_INTEGRATION_ID'],
'X-Zoneo-Timestamp: '.$timestamp,
'X-Zoneo-Nonce: '.$nonce,
'Idempotency-Key: '.$idempotencyKey,
'X-Zoneo-Signature: v1='.$signature,
];
$curl = curl_init('https://izoneo.fr/api/v1/conversions');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $body,
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
Créée → Remboursée Lien vers la section Créée → Remboursée
Pour le paiement, l’annulation et les remboursements cumulés, réutilisez les mêmes zclid et order_id_hash. Conservez les totaux et lignes finaux.
order_v1 · lifecycle
placed -> paid | cancelled | partially_refunded | refunded
paid -> partially_refunded | refunded
partially_refunded -> refunded
cancelled, refunded -> terminal
0 <= refund_amount_minor <= totals.order_total_gross_minor
new_refund_amount_minor >= previous_refund_amount_minor
Idempotency-Key · retry
nonce₁ != nonce₂
retry = nonce₂ + Idempotency-Key₁ + SHA256(JSON₁)
Idempotency-Key₁ + SHA256(JSON₁) -> HTTP 200
Idempotency-Key₁ + SHA256(JSON₂) -> HTTP 409 idempotency_conflict
Sandbox V1 Lien vers la section Sandbox V1
Collez un JSON V1 pour vérifier les champs, les totaux et l’association au flux sans créer de commande ni modifier la facturation.
https://izoneo.fr/api/v1/conversions/sandbox
Mesure facultative via JavaScript Lien vers la section Mesure facultative via JavaScript
La bibliothèque conserve zclid après consentement et envoie uniquement l’événement placed initial depuis la page de remerciement. Envoyez les états suivants par S2S sécurisé.
Le consentement est désactivé par défaut. La fonction consent ne doit renvoyer true qu’après l’obtention d’un consentement analytique valide de l’utilisateur.
Chargement et initialisation
<script src="https://izoneo.fr/integrations/zoneo-conversion-v1.js"></script>
<script>
const zoneo = window.ZoneoConversions.init({
integrationId: 'zci_...',
apiBase: 'https://izoneo.fr/api/v1/conversions',
consent: () => analyticsConsent === true
})
zoneo.track({
order_id_hash: 'SERVER_HMAC_SHA256',
currency: 'EUR',
occurred_at: new Date().toISOString(),
status: 'placed',
totals: {
items_gross_minor: 12990,
discount_minor: 0,
shipping_gross_minor: 0,
fees_gross_minor: 0,
tax_minor: 2165,
order_total_gross_minor: 12990
},
items: [{
merchant_item_id: 'ITEM_ID_FROM_FEED',
quantity: 1,
unit_price_gross_minor: 12990,
line_total_gross_minor: 12990
}]
})
</script>
État de l’intégration Lien vers la section État de l’intégration
Événements acceptés et rejetés au cours des 7 derniers jours.
HTTP 201 · JSON
{
"data": {
"conversion_reference": "6bfca33e-3ac7-48dc-a733-c1f313853269",
"status": "placed",
"source": "s2s",
"verification": "hmac_current",
"schema_version": "1.0",
"payload_contract": "order_v1",
"totals": {
"items_gross_minor": 14000,
"discount_minor": 1500,
"shipping_gross_minor": 390,
"fees_gross_minor": 100,
"tax_minor": 2165,
"order_total_gross_minor": 12990
},
"refund_amount_minor": 0,
"net_revenue_minor": 12990,
"items": {
"count": 1,
"quantity_total": 2,
"matched_count": 1,
"match_status": "complete"
},
"totals_reconciled": true,
"warnings": [],
"currency": "EUR",
"created": true,
"idempotent": false,
"deduplicated": false,
"provisional": false,
"billing_impact": false
}
}
HTTP 4xx · JSON
{
"error": {
"code": "order_total_mismatch",
"field": "totals.order_total_gross_minor",
"details": {
"expected_minor": 12990,
"received_minor": 13000
}
}
}
invalid_signature
stale_timestamp
replayed_nonce
pii_not_allowed
items_total_mismatch
order_total_mismatch
currency_mismatch
click_not_eligible
store_or_market_mismatch
not_last_zoneo_click
attribution_window_expired
invalid_state_transition
order_definition_conflict
refund_amount_decreased
order_attribution_conflict
Protection des données personnelles Lien vers la section Protection des données personnelles
Dernières commandes reçues par Zoneo à des fins analytiques uniquement. Aucun identifiant brut ni donnée personnelle ne sont affichés.
Sur le serveur, créez une empreinte HMAC-SHA-256 stable de l’ID interne de la commande à l’aide d’une clé distincte. N’envoyez ni l’ID brut ni de données personnelles.
Les commandes, le chiffre d’affaires et les indicateurs dérivés ne sont affichés que lorsque le suivi des conversions est actif. Ils servent uniquement à l’analyse et ne modifient pas la facturation CPC.
Comment connecter la mesure
Nous recommandons l’API server-to-server. JavaScript est uniquement une solution analytique de secours facultative et ne fonctionne qu’après l’obtention du consentement analytique.