Aller au contenu

É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.

Chaque envoi lié à une commande porte l’objet complet. Lignes et coupon sont détaillés dans les deux sections suivantes.

ChampTypeNullableDescription
order_id, user_identiernonIdentifiants internes.
user_uuidchaînenonIdentifiant public du client (cus_...).
email, first_name, last_name, phonechaîneoui sauf emailCoordonnées, lues depuis l’adresse de la commande.
statuschaînenonVoir le tableau des statuts ci-dessous.
created, created_atdate ISO 8601nonDate de création, toujours en UTC.
itemstableaunonLignes, voir Objet ligne de commande.
couponobjet ou tableau videnonVoir Objet coupon : le type change selon qu’un coupon est appliqué ou non.
shippingchaînenonFrais de port, point décimal ("4.90").
countentiernonNombre de lignes.
total_tax_paid, total_discount_inc, total_shipping_paidchaînenonTotaux, virgule décimale ("31,81").
total_paidchaîneouiTotal payé, virgule décimale ; nul tant que non calculé.
subscription_uuidchaîneouiAbonnement d’origine, s’il y en a un.
revenue, refundedchaîneouiCA et remboursé liés à l’abonnement, point décimal ; nuls sans abonnement.
customerRevenue, customerRefundchaînenonCA et remboursé côté client, point décimal ; "0.00" sans abonnement, jamais nuls.
subTransactionsSuccessentierouiNombre de transactions réussies de l’abonnement lié, toutes commandes confondues ; nul sans abonnement.
totalTransactionsSuccessentiernonNombre de transactions réussies du client, tous abonnements confondus ; jamais nul.
countTransactionsentiernonNombre de transactions de cette commande ; jamais nul.
next_billingdate ISO 8601ouiProchaine échéance de l’abonnement d’origine.
choices(toujours nul)ouiToujours nul, champ réservé.
retry_linkchaîneouiLien de reprise de paiement ; nul sans secret client.
paid_transaction_id, paid_class_keychaîneouiIdentifiant et moyen de paiement de la transaction payée.
prestashop_order_identierouiIdentifiant côté PrestaShop.

status prend l’une de huit valeurs :

StatutSens
pendingEn attente de paiement.
in_creationEn cours de création : adresse ou transporteur pas encore figés.
in_processEn cours de traitement.
completedPayée.
failedÉchouée.
canceledAnnulée.
need_actionUne action du client est nécessaire pour finaliser le paiement.
withdrawal_requestedUne demande de rétractation est en cours.

Chaque élément de items correspond à un produit ou une formule commandés.

ChampTypeNullableDescription
identiernonIdentifiant de la ligne.
pricenombrenonPrix unitaire hors taxe.
taxchaînenonTaux de TVA, décimal en chaîne ("0.200").
quantityentiernonQuantité commandée.
namechaînenonNom du produit ou de la formule au moment de la commande.
typechaînenonType de produit vendu : formule ou produit (valeur technique).
orderableobjet ou nulouiVoir l’encadré ci-dessous ; nul si le produit a été supprimé depuis.
affilae, external_id, refchaîneouiSuivi d’affiliation, identifiant externe, référence produit.

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.

ChampTypeNullableDescription
id, uuidentier, chaînenonIdentifiant interne et code saisi par le client.
plans(toujours nul)ouiColonne JSON qui n’est plus renseignée.
price, percent_offchaîneouiRemise fixe, ou en pourcentage sous forme de fraction ("0.10" pour 10 %).
durationchaînenonPortée de la remise (once, repeating, forever sur d’anciens coupons).
redeem_byentiernonDate limite d’utilisation, horodatage Unix.
display_amount, display_percentchaîneouiMontant ou pourcentage formatés pour l’affichage.

Chaque tentative de paiement produit une transaction. L’objet envoyé porte la commande complète sous la clé order.

ChampTypeNullableDescription
order_id, tenant_identiernonCommande et boutique associées.
orderobjet ou nulouiCommande complète, voir Objet commande ; nul si supprimée.
gatewaychaînenonMoyen de paiement (stripe…).
transaction_id, token, detail, source_id, payment_intent_idlibreouiIdentifiants et détail bruts, selon le prestataire.
paidbooléennonVrai une fois le paiement confirmé.
amount, amount_refundedchaînenonMontants, deux décimales.
refundedbooléennonVrai si la transaction a été remboursée.
failure_message, failure_codechaîneouiDétail d’un échec de paiement.
invoice_identierouiFacture liée ; n’apparaît jamais dans changed, voir plus bas.
statement_descriptorchaîneouiLibellé affiché sur le relevé bancaire du client.
user_identierouiClient, quand renseigné.
created_at, updated_atdate ISO 8601nonHorodatages.

L’envoi part après validation en base, avec la commande complète sous la clé order.

ChampTypeNullableDescription
order_id, tenant_identiernonCommande d’origine et boutique concernée.
customer, companyobjet ou nulouiVoir l’encadré ci-dessous, structure non contractuelle.
emitted_atdatenonDate d’émission, à minuit UTC (T00:00:00.000000Z).
numberentiernonNuméro de facture, propre à votre boutique.
total_tax, total_discount, total, total_shippingchaînenonMontants à trois décimales, point décimal ("5.320").
morechaîneouiMention complémentaire.
uuidchaînenonNuméro complet : préfixe, année-mois et numéro (F2026-09-42).
orderobjet ou nulouiCommande complète, voir Objet commande.
gatewaychaîneouiMoyen de paiement de la transaction payée ; nul sans transaction payée.

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.

À chaque création réelle d’une commande : passage en caisse, prélèvement d’un abonnement, commande composable ou PrestaShop.

Aucune écriture silencieuse identifiée à la création.

Toujours un tableau vide.

Aucun propre à la création. Voir les cascades entrantes sous updated_checkoutorder.

created_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": []
}

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).

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.

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.

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.

  • 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 : changed contient alors transporter_id, shipping, shipping_tax et relay. 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.
changed de updated_checkoutorder
{
"status": "completed"
}

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.

À la création d’une tentative de paiement : passage en caisse, prélèvement d’un abonnement.

Aucune écriture silencieuse identifiée à la création.

Toujours un tableau vide.

Aucun propre à cet envoi.

created_checkouttransaction
{
"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": []
}

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).

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.

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.

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.

Aucun propre à cet envoi.

changed de updated_checkouttransaction
{
"paid": true
}

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.

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.

Sans objet : cette clé ne connaît qu’un seul déclencheur, l’émission.

Toujours un tableau vide : par construction, il n’y a jamais de second envoi à comparer.

Aucun.

created_checkoutinvoice
{
"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": []
}