Événements : commandes, transactions et factures
Cette page détaille les cinq clés du parcours d’achat : la commande, la transaction de paiement et la facture. Un achat complet peut produire, dans cet ordre logique mais pas forcément dans cet ordre d’arrivée, un created_checkoutorder, un ou plusieurs created_checkouttransaction puis updated_checkouttransaction, et un created_checkoutinvoice. Pour la configuration générale, voir Comprendre un envoi de webhook.
Objet commande
Section intitulée « Objet commande »Chaque envoi lié à une commande porte l’objet complet. Lignes et coupon sont détaillés dans les deux sections suivantes.
| Champ | Type | Nullable | Description |
|---|---|---|---|
order_id, user_id | entier | non | Identifiants internes. |
user_uuid | chaîne | non | Identifiant public du client (cus_...). |
email, first_name, last_name, phone | chaîne | oui sauf email | Coordonnées, lues depuis l’adresse de la commande. |
status | chaîne | non | Voir le tableau des statuts ci-dessous. |
created, created_at | date ISO 8601 | non | Date de création, toujours en UTC. |
items | tableau | non | Lignes, voir Objet ligne de commande. |
coupon | objet ou tableau vide | non | Voir Objet coupon : le type change selon qu’un coupon est appliqué ou non. |
shipping | chaîne | non | Frais de port, point décimal ("4.90"). |
count | entier | non | Nombre de lignes. |
total_tax_paid, total_discount_inc, total_shipping_paid | chaîne | non | Totaux, virgule décimale ("31,81"). |
total_paid | chaîne | oui | Total payé, virgule décimale ; nul tant que non calculé. |
subscription_uuid | chaîne | oui | Abonnement d’origine, s’il y en a un. |
revenue, refunded | chaîne | oui | CA et remboursé liés à l’abonnement, point décimal ; nuls sans abonnement. |
customerRevenue, customerRefund | chaîne | non | CA et remboursé côté client, point décimal ; "0.00" sans abonnement, jamais nuls. |
subTransactionsSuccess | entier | oui | Nombre de transactions réussies de l’abonnement lié, toutes commandes confondues ; nul sans abonnement. |
totalTransactionsSuccess | entier | non | Nombre de transactions réussies du client, tous abonnements confondus ; jamais nul. |
countTransactions | entier | non | Nombre de transactions de cette commande ; jamais nul. |
next_billing | date ISO 8601 | oui | Prochaine échéance de l’abonnement d’origine. |
choices | (toujours nul) | oui | Toujours nul, champ réservé. |
retry_link | chaîne | oui | Lien de reprise de paiement ; nul sans secret client. |
paid_transaction_id, paid_class_key | chaîne | oui | Identifiant et moyen de paiement de la transaction payée. |
prestashop_order_id | entier | oui | Identifiant côté PrestaShop. |
status prend l’une de huit valeurs :
| Statut | Sens |
|---|---|
pending | En attente de paiement. |
in_creation | En cours de création : adresse ou transporteur pas encore figés. |
in_process | En cours de traitement. |
completed | Payée. |
failed | Échouée. |
canceled | Annulée. |
need_action | Une action du client est nécessaire pour finaliser le paiement. |
withdrawal_requested | Une demande de rétractation est en cours. |
Objet ligne de commande
Section intitulée « Objet ligne de commande »Chaque élément de items correspond à un produit ou une formule commandés.
| Champ | Type | Nullable | Description |
|---|---|---|---|
id | entier | non | Identifiant de la ligne. |
price | nombre | non | Prix unitaire hors taxe. |
tax | chaîne | non | Taux de TVA, décimal en chaîne ("0.200"). |
quantity | entier | non | Quantité commandée. |
name | chaîne | non | Nom du produit ou de la formule au moment de la commande. |
type | chaîne | non | Type de produit vendu : formule ou produit (valeur technique). |
orderable | objet ou nul | oui | Voir l’encadré ci-dessous ; nul si le produit a été supprimé depuis. |
affilae, external_id, ref | chaîne | oui | Suivi d’affiliation, identifiant externe, référence produit. |
Objet coupon
Section intitulée « Objet coupon »Premier coupon appliqué, s’il y en a un. Sans coupon, coupon vaut [] ; avec un coupon, c’est un objet. Le type change d’un envoi à l’autre : testez le tableau vide en premier.
| Champ | Type | Nullable | Description |
|---|---|---|---|
id, uuid | entier, chaîne | non | Identifiant interne et code saisi par le client. |
plans | (toujours nul) | oui | Colonne JSON qui n’est plus renseignée. |
price, percent_off | chaîne | oui | Remise fixe, ou en pourcentage sous forme de fraction ("0.10" pour 10 %). |
duration | chaîne | non | Portée de la remise (once, repeating, forever sur d’anciens coupons). |
redeem_by | entier | non | Date limite d’utilisation, horodatage Unix. |
display_amount, display_percent | chaîne | oui | Montant ou pourcentage formatés pour l’affichage. |
Objet transaction
Section intitulée « Objet transaction »Chaque tentative de paiement produit une transaction. L’objet envoyé porte la commande complète sous la clé order.
| Champ | Type | Nullable | Description |
|---|---|---|---|
order_id, tenant_id | entier | non | Commande et boutique associées. |
order | objet ou nul | oui | Commande complète, voir Objet commande ; nul si supprimée. |
gateway | chaîne | non | Moyen de paiement (stripe…). |
transaction_id, token, detail, source_id, payment_intent_id | libre | oui | Identifiants et détail bruts, selon le prestataire. |
paid | booléen | non | Vrai une fois le paiement confirmé. |
amount, amount_refunded | chaîne | non | Montants, deux décimales. |
refunded | booléen | non | Vrai si la transaction a été remboursée. |
failure_message, failure_code | chaîne | oui | Détail d’un échec de paiement. |
invoice_id | entier | oui | Facture liée ; n’apparaît jamais dans changed, voir plus bas. |
statement_descriptor | chaîne | oui | Libellé affiché sur le relevé bancaire du client. |
user_id | entier | oui | Client, quand renseigné. |
created_at, updated_at | date ISO 8601 | non | Horodatages. |
Objet facture
Section intitulée « Objet facture »L’envoi part après validation en base, avec la commande complète sous la clé order.
| Champ | Type | Nullable | Description |
|---|---|---|---|
order_id, tenant_id | entier | non | Commande d’origine et boutique concernée. |
customer, company | objet ou nul | oui | Voir l’encadré ci-dessous, structure non contractuelle. |
emitted_at | date | non | Date d’émission, à minuit UTC (T00:00:00.000000Z). |
number | entier | non | Numéro de facture, propre à votre boutique. |
total_tax, total_discount, total, total_shipping | chaîne | non | Montants à trois décimales, point décimal ("5.320"). |
more | chaîne | oui | Mention complémentaire. |
uuid | chaîne | non | Numéro complet : préfixe, année-mois et numéro (F2026-09-42). |
order | objet ou nul | oui | Commande complète, voir Objet commande. |
gateway | chaîne | oui | Moyen de paiement de la transaction payée ; nul sans transaction payée. |
created_checkoutorder
Section intitulée « created_checkoutorder »Objet envoyé : commande complète. Délai avant envoi : 10 secondes, changed vide. Exemple complet : dans le contrat OpenAPI (/openapi/ciklik-webhooks.yaml), webhook created_checkoutorder.
Quand il part
Section intitulée « Quand il part »À chaque création réelle d’une commande : passage en caisse, prélèvement d’un abonnement, commande composable ou PrestaShop.
Quand il ne part pas
Section intitulée « Quand il ne part pas »Aucune écriture silencieuse identifiée à la création.
Ce que contient changed
Section intitulée « Ce que contient changed »Toujours un tableau vide.
Effets en cascade
Section intitulée « Effets en cascade »Aucun propre à la création. Voir les cascades entrantes sous updated_checkoutorder.
{ "order_id": 1, "user_id": 1, "user_uuid": "cus_Qx7hR3eaEowcv1DX", "first_name": "Claire", "last_name": "Martin", "phone": "+33612345678", "email": "claire.martin@example.com", "status": "pending", "created": "2026-09-10T08:15:42.000000Z", "items": [ { "id": 1, "price": 29.9, "tax": "0.200", "quantity": 1, "name": "Box découverte", "type": "App\\Product", "orderable": { "id": 1, "name": "Box découverte", "tenant_id": 1, "id_category": null, "quantity": 250, "active": true, "description_short": "Trois thés à découvrir", "description": "Trois thés à découvrir chaque mois.", "slug": "box-decouverte", "meta_description": "Box découverte de thés", "meta_title": "Box découverte", "details": "Sachets de 50 g.", "virtual_product": false, "salable": true, "default_variation": null, "created_at": "2026-09-10T08:15:42.000000Z", "updated_at": "2026-09-10T08:15:42.000000Z", "deleted_at": null, "order": 1, "rating_cache": 0, "rating_count": 0, "affilae": null, "tax": 0.2, "price": "29.900", "gift_card": false, "gift_plan": null, "featured": false, "disable_seo": false, "old_price": null, "exodus_id": "1042", "details_json": null, "ref": "BOX-DEC-001", "features": { "kcal": 0 }, "force_shipment": false, "composable": false, "selectable_quantities": null, "metadata": [], "customizations": [] }, "affilae": null, "external_id": "1042", "ref": "BOX-DEC-001" } ], "shipping": "4.90", "count": 1, "total_tax_paid": "5,32", "total_discount_inc": "2,99", "total_paid": "31,81", "total_shipping_paid": "4,90", "created_at": "2026-09-10T08:15:42.000000Z", "coupon": { "id": 1, "uuid": "BIENVENUE10", "plans": null, "price": null, "percent_off": "0.10", "duration": "once", "redeem_by": 1798757999, "display_amount": null, "display_percent": "10%" }, "subscription_uuid": "sub_N8PxGUEdS2U7DP", "revenue": "0.00", "refunded": "0.00", "customerRevenue": "0.00", "customerRefund": "0.00", "totalTransactionsSuccess": 0, "subTransactionsSuccess": 0, "next_billing": "2026-10-10T08:15:42.000000Z", "countTransactions": 1, "choices": null, "retry_link": "https://boutique.example.com/orders/1/users/1?token=tok_iDXOKjsWGKGwc94K0WptRORT", "paid_transaction_id": null, "paid_class_key": null, "prestashop_order_id": 1587, "changed": []}updated_checkoutorder
Section intitulée « updated_checkoutorder »Objet envoyé : commande complète, dans son état au moment de l’envoi. Délai avant envoi : aucun. Exemple complet : dans le contrat OpenAPI (/openapi/ciklik-webhooks.yaml), webhook updated_checkoutorder (le reste du contenu de l’envoi est identique à celui de created_checkoutorder).
Quand il part
Section intitulée « Quand il part »Changement de statut (confirmation du paiement, échec…), de transporteur, de frais de port ou de point relais, ou tout autre champ réellement modifié sur la commande.
Quand il ne part pas
Section intitulée « Quand il ne part pas »Cinq écritures silencieuses à connaître : passage en withdrawal_requested (demande de rétractation), retour à completed après validation d’un retrait par l’équipe Ciklik, liaison de la facture (invoice_id), marquage d’une relance (source = retry) et pose de la source à la création. Il n’existe pas non plus de deleted_checkoutorder : une commande n’est jamais notifiée comme supprimée.
Ce que contient changed
Section intitulée « Ce que contient changed »Les champs réellement modifiés, le plus souvent status, next_try, total_paid, transporter_id, shipping, shipping_tax et relay, avec updated_at. invoice_id n’y apparaît jamais dans le flux normal : sa liaison est, comme ci-dessus, silencieuse.
Effets en cascade
Section intitulée « Effets en cascade »- Les commandes en cours de création (
in_creation) sont réenregistrées une à deux fois à chaque changement d’adresse ou de transporteur sur l’abonnement lié, ou sur toute adresse liée à un abonnement :changedcontient alorstransporter_id,shipping,shipping_taxetrelay. Détail sur Événements : abonnements. - Les commandes en attente (
pending) passent en échec à l’annulation d’un abonnement, si l’option de fermeture est active pour votre boutique, et à sa suppression. - Les commandes en attente et en cours de création passent en échec à la mise en pause par l’équipe Ciklik avec fermeture des commandes, un périmètre plus large que l’annulation.
{ "status": "completed"}created_checkouttransaction
Section intitulée « created_checkouttransaction »Objet envoyé : transaction complète, avec la commande entière sous la clé order. Délai avant envoi : 10 secondes. Exemple complet : dans le contrat OpenAPI (/openapi/ciklik-webhooks.yaml), webhook created_checkouttransaction. Cet envoi part une fois la transaction enregistrée définitivement, d’où le délai.
Quand il part
Section intitulée « Quand il part »À la création d’une tentative de paiement : passage en caisse, prélèvement d’un abonnement.
Quand il ne part pas
Section intitulée « Quand il ne part pas »Aucune écriture silencieuse identifiée à la création.
Ce que contient changed
Section intitulée « Ce que contient changed »Toujours un tableau vide.
Effets en cascade
Section intitulée « Effets en cascade »Aucun propre à cet envoi.
{ "order_id": 1, "order": { "order_id": 1, "user_id": 1, "user_uuid": "cus_Qx7hR3eaEowcv1DX", "first_name": "Claire", "last_name": "Martin", "phone": "+33612345678", "email": "claire.martin@example.com", "status": "pending", "created": "2026-09-10T08:15:42.000000Z", "items": [ { "id": 1, "price": 29.9, "tax": "0.200", "quantity": 1, "name": "Box découverte", "type": "App\\Product", "orderable": { "id": 1, "name": "Box découverte", "tenant_id": 1, "id_category": null, "quantity": 250, "active": true, "description_short": "Trois thés à découvrir", "description": "Trois thés à découvrir chaque mois.", "slug": "box-decouverte", "meta_description": "Box découverte de thés", "meta_title": "Box découverte", "details": "Sachets de 50 g.", "virtual_product": false, "salable": true, "default_variation": null, "created_at": "2026-09-10T08:15:42.000000Z", "updated_at": "2026-09-10T08:15:42.000000Z", "deleted_at": null, "order": 1, "rating_cache": 0, "rating_count": 0, "affilae": null, "tax": 0.2, "price": "29.900", "gift_card": false, "gift_plan": null, "featured": false, "disable_seo": false, "old_price": null, "exodus_id": "1042", "details_json": null, "ref": "BOX-DEC-001", "features": { "kcal": 0 }, "force_shipment": false, "composable": false, "selectable_quantities": null, "metadata": [], "customizations": [] }, "affilae": null, "external_id": "1042", "ref": "BOX-DEC-001" } ], "shipping": "4.90", "count": 1, "total_tax_paid": "5,32", "total_discount_inc": "2,99", "total_paid": "31,81", "total_shipping_paid": "4,90", "created_at": "2026-09-10T08:15:42.000000Z", "coupon": { "id": 1, "uuid": "BIENVENUE10", "plans": null, "price": null, "percent_off": "0.10", "duration": "once", "redeem_by": 1798757999, "display_amount": null, "display_percent": "10%" }, "subscription_uuid": "sub_N8PxGUEdS2U7DP", "revenue": "0.00", "refunded": "0.00", "customerRevenue": "0.00", "customerRefund": "0.00", "totalTransactionsSuccess": 0, "subTransactionsSuccess": 0, "next_billing": "2026-10-10T08:15:42.000000Z", "countTransactions": 1, "choices": null, "retry_link": "https://boutique.example.com/orders/1/users/1?token=tok_iDXOKjsWGKGwc94K0WptRORT", "paid_transaction_id": null, "paid_class_key": null, "prestashop_order_id": 1587 }, "gateway": "stripe", "transaction_id": "ch_3QxK2mL9aBcDeFgH1a2b3c4d", "detail": null, "token": null, "tenant_id": 1, "paid": false, "amount": "31.81", "refunded": false, "source_id": "pm_1QxK2mL9aBcDeFgH", "failure_message": null, "failure_code": null, "invoice_id": null, "amount_refunded": "0.00", "statement_descriptor": "BOUTIQUE EXEMPLE", "user_id": 1, "created_at": "2026-09-10T08:15:42.000000Z", "updated_at": "2026-09-10T08:15:42.000000Z", "payment_intent_id": "pi_3QxK2mL9aBcDeFgH1a2b3c4d", "changed": []}updated_checkouttransaction
Section intitulée « updated_checkouttransaction »Objet envoyé : transaction complète, avec la commande entière sous la clé order, dans son état au moment de l’envoi. Délai avant envoi : 10 secondes. Exemple complet : dans le contrat OpenAPI (/openapi/ciklik-webhooks.yaml), webhook updated_checkouttransaction (le reste du contenu de l’envoi est identique à celui de created_checkouttransaction).
Quand il part
Section intitulée « Quand il part »Le cas le plus fréquent : le passage à payé, qui se lit dans changed.paid. Toute autre modification de la transaction (remboursement, échec de paiement) déclenche aussi cet envoi.
Quand il ne part pas
Section intitulée « Quand il ne part pas »La liaison de la facture à la transaction, c’est-à-dire la pose d’invoice_id, est une écriture silencieuse : ne comptez pas sur changed.invoice_id pour savoir qu’une facture a été émise, fiez-vous à created_checkoutinvoice.
Ce que contient changed
Section intitulée « Ce que contient changed »Le passage à payé se lit dans changed.paid (true). Les autres champs suivent le même principe : valeur brute telle que stockée en base.
Effets en cascade
Section intitulée « Effets en cascade »Aucun propre à cet envoi.
{ "paid": true}created_checkoutinvoice
Section intitulée « created_checkoutinvoice »Objet envoyé : facture complète, avec la commande entière sous la clé order. Délai avant envoi : 15 secondes. Exemple complet : dans le contrat OpenAPI (/openapi/ciklik-webhooks.yaml), webhook created_checkoutinvoice.
Quand il part
Section intitulée « Quand il part »Uniquement à l’émission d’une facture. Il n’existe ni updated_checkoutinvoice ni deleted_checkoutinvoice : une fois émise, une facture n’est jamais modifiée dans le contenu que vous recevez.
Quand il ne part pas
Section intitulée « Quand il ne part pas »Sans objet : cette clé ne connaît qu’un seul déclencheur, l’émission.
Ce que contient changed
Section intitulée « Ce que contient changed »Toujours un tableau vide : par construction, il n’y a jamais de second envoi à comparer.
Effets en cascade
Section intitulée « Effets en cascade »Aucun.
{ "order_id": 1, "customer": { "first_name": "Claire", "last_name": "Martin", "email": "claire.martin-dupont@example.com", "address": "27 avenue Jean Jaurès", "postcode": "69007", "city": "Lyon", "country": "France" }, "tenant_id": 1, "emitted_at": "2026-09-10T00:00:00.000000Z", "company": { "name": "Boutique Exemple SAS", "address": "5 place Bellecour", "postcode": "69002", "city": "Lyon", "siret": "12345678900012", "vat": "FR12345678900" }, "number": 42, "total_tax": "5.320", "total_discount": "2.990", "total": "31.810", "total_shipping": "4.900", "more": null, "uuid": "F2026-09-42", "order": { "order_id": 1, "user_id": 1, "user_uuid": "cus_Qx7hR3eaEowcv1DX", "first_name": "Claire", "last_name": "Martin", "phone": "+33612345678", "email": "claire.martin-dupont@example.com", "status": "completed", "created": "2026-09-10T08:15:42.000000Z", "items": [ { "id": 1, "price": 29.9, "tax": "0.200", "quantity": 1, "name": "Box découverte", "type": "App\\Product", "orderable": { "id": 1, "name": "Box découverte", "tenant_id": 1, "id_category": null, "quantity": 250, "active": true, "description_short": "Trois thés à découvrir", "description": "Trois thés à découvrir chaque mois.", "slug": "box-decouverte", "meta_description": "Box découverte de thés", "meta_title": "Box découverte", "details": "Sachets de 50 g.", "virtual_product": false, "salable": true, "default_variation": null, "created_at": "2026-09-10T08:15:42.000000Z", "updated_at": "2026-09-10T08:15:42.000000Z", "deleted_at": null, "order": 1, "rating_cache": 0, "rating_count": 0, "affilae": null, "tax": 0.2, "price": "29.900", "gift_card": false, "gift_plan": null, "featured": false, "disable_seo": false, "old_price": null, "exodus_id": "1042", "details_json": null, "ref": "BOX-DEC-001", "features": { "kcal": 0 }, "force_shipment": false, "composable": false, "selectable_quantities": null, "metadata": [], "customizations": [] }, "affilae": null, "external_id": "1042", "ref": "BOX-DEC-001" } ], "shipping": "4.90", "count": 1, "total_tax_paid": "5,32", "total_discount_inc": "2,99", "total_paid": "31,81", "total_shipping_paid": "4,90", "created_at": "2026-09-10T08:15:42.000000Z", "coupon": { "id": 1, "uuid": "BIENVENUE10", "plans": null, "price": null, "percent_off": "0.10", "duration": "once", "redeem_by": 1798757999, "display_amount": null, "display_percent": "10%" }, "subscription_uuid": "sub_N8PxGUEdS2U7DP", "revenue": "31.81", "refunded": "0.00", "customerRevenue": "31.81", "customerRefund": "0.00", "totalTransactionsSuccess": 1, "subTransactionsSuccess": 1, "next_billing": "2026-10-10T08:15:42.000000Z", "countTransactions": 1, "choices": null, "retry_link": "https://boutique.example.com/orders/1/users/1?token=tok_iDXOKjsWGKGwc94K0WptRORT", "paid_transaction_id": "ch_3QxK2mL9aBcDeFgH1a2b3c4d", "paid_class_key": "stripe", "prestashop_order_id": 1587 }, "gateway": "stripe", "changed": []}