Pour les développeurs

API ouverte pour les développeurs

Notre API RESTful vous permet de créer des intégrations personnalisées et d'étendre les fonctionnalités de Tiktak PRO selon vos besoins spécifiques.

Documentation complète et facile à comprendre
Authentification sécurisée via Token
Endpoints bien structurés pour toutes les fonctionnalités
Gestion complète des produits avec variations
Support technique dédié pour les développeurs
// Example: Get all products
fetch('https://api.tiktakpro.com/api/v1/products', {
  method: 'GET',
  headers: {
    'Authorization': 'Token YOUR_API_KEY',
    'Content-Type': 'application/json'
  }
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

🚀 Pour commencer

Tout ce que vous devez savoir pour commencer à utiliser l'API TikTak PRO

URL de base

https://api.tiktakpro.com/api/v1

Authentification

Authorization: Token YOUR_API_TOKEN

💡 Note importante : Toutes les requêtes doivent inclure le header d'autorisation avec votre token d'API.

Documentation complète des APIs

Toutes les APIs disponibles avec exemples et paramètres détaillés

Récupérer les commandes

Récupère toutes les commandes disponibles avec options de filtrage.

Paramètres (Query)

step__slug - Filtrer par statut (ex: ?step__slug=confirmed,standby)

Exemple de requête

curl -X GET "https://api.tiktakpro.com/api/v1/orders/?step__slug=confirmed" \
  -H "Authorization: Token YOUR_API_TOKEN"

Détails d'une commande

Récupère tous les détails d'une commande spécifique (bon de sortie).

Exemple de requête

curl -X GET "https://api.tiktakpro.com/api/v1/orders/12345/" \
  -H "Authorization: Token YOUR_API_TOKEN"

Mettre à jour le statut

Met à jour le statut d'une commande.

Corps de la requête

{
  "order": 12345,
  "step": "expd"
}

Exemple de requête

curl -X POST "https://api.tiktakpro.com/api/v1/update-order-status/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"order": 12345, "step": "expd"}'

Modifier le statut (PATCH)

Alternative pour mettre à jour le statut d'une commande.

Corps de la requête

{
  "id": 12345,
  "step": 123002
}

⚠️ Important : L'URL doit toujours se terminer par un slash /

Exemple de requête

curl -X PATCH "https://api.tiktakpro.com/api/v1/orders/12345/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id": 12345, "step": 123002}'

Créer / modifier une commande

Crée une commande complète (client, adresse, transporteur, lignes produits). Le même endpoint sert à modifier une commande existante en ajoutant son id.

Authentification

Header Authorization: Token <token> — Base URL : https://api.tiktakpro.com/api/v1

Payload complet de création

{
  "order": {
    "total_amount": 99.9,
    "total_paid": 0,
    "total_after_discount": 99.9,
    "transport_price": 7.0,
    "intern_transport_price": 6.0,
    "payement_type": "CASH",
    "discount": 0,
    "country": "TN",
    "source": "Facebook",
    "exchange": false,
    "free_shipping": false,
    "comment": "",
    "name": "Nom du client",
    "phone": "20123456",
    "phone_extra": "",
    "gouvernorat": "Tunis",
    "delegation": "Tunis",
    "address": "Adresse complète",
    "code_postal": "1001",
    "meta_data": { "messenger": "" },
    "to_deliver_at": null,
    "page": null,
    "transport": 1,
    "step": 1,
    "customer": null,
    "invoice_number": null,
    "code_tva": null,
    "code": null,
    "payments": [],
    "_details": [
      {
        "quantity": 1,
        "product_id": 12345,
        "product_name": "T-shirt Blanc",
        "product_ref": "",
        "product_attrs": "Couleur: Blanc / Taille: M",
        "product_thumb": "https://...",
        "active_stock": true,
        "options": [],
        "category_id": null,
        "price_ttc": 89.9,
        "price_ttc_after_discount": 89.9,
        "final_price": 89.9,
        "discount": 0,
        "taxe_rate": 0,
        "price_ht": 89.9,
        "taxe_value": 0,
        "purchase_price": 0,
        "is_custom": false,
        "comment": ""
      }
    ]
  }
}

Champs principaux (obligatoires)

ChampTypeDescription
namestringNom du client
phonestringNuméro principal du client
addressstringAdresse de livraison
gouvernoratstringGouvernorat / Région
sourcestringSource de la commande (Facebook, WhatsApp…)
total_amountnumberTotal de la commande
total_after_discountnumberTotal après remise
transport_pricenumberFrais de livraison (0 si free_shipping)
payement_typestringCASH, CARD ou TRANSFER
transportnumberID du transporteur
_detailsarrayListe des produits de la commande
stepnumberID de l'état initial de la commande

Ligne produit — pack (avec options)

{
  "quantity": 1,
  "product_id": 12345,
  "product_parent_id": null,
  "product_name": "Pack Promo",
  "product_ref": "",
  "product_attrs": "",
  "product_thumb": "",
  "active_stock": true,
  "options": [
    {
      "product_id": 111,
      "product_name": "Produit A",
      "quantity": 1,
      "final_price": 30.0,
      "price_ttc": 30.0,
      "product_attrs": ""
    }
  ],
  "category_id": null,
  "price_ttc": 99.9,
  "price_ttc_after_discount": 99.9,
  "final_price": 99.9,
  "discount": 0,
  "taxe_rate": 0,
  "purchase_price": 0,
  "is_custom": false
}

Pour un pack, les champs price_ht et taxe_value ne sont pas envoyés.

Règles métier

  • Téléphone : valide pour le pays du compte (8 chiffres en Tunisie).
  • Produit minimum : au moins un produit dans _details.
  • Livraison gratuite : si free_shipping = true, transport_price et intern_transport_price doivent être à 0.
  • Échange : exchange = true marque la commande comme commande d'échange.
  • Transporteur : ID trouvé par nom via GET /transports/.
  • État : ID trouvé par nom via GET /steps/.

Réponse (200 / 201)

{
  "id": 987654,
  "order_number": "CMD-987654",
  "name": "Nom du client",
  "phone": "20123456",
  "total_amount": 99.9,
  "total_after_discount": 99.9,
  "step": { "id": 1, "name": "En attente" },
  "transport": { "id": 1, "name": "Transporteur X" },
  "_details": [ ... ]
}

Erreurs courantes

StatusCauseMessage
400Payload invalideDétails dans error.response.data.message
409Commande déjà synchronisée avec un transporteurorder_already_sent_to_transport
403Token invalide ou permissions insuffisantes—

Modification d'une commande

{
  "order": {
    "id": 987654,
    "total_amount": 99.9,
    "...": "..."
  }
}

⚠️ Une commande déjà synchronisée avec un transporteur ne peut plus être modifiée (erreur 409).

Endpoints liés

  • GET /orders/?serializer=export — liste des commandes
  • GET /orders/{id}/?serializer=export — détails d'une commande
  • POST /order-step-change/ — changement d'état
  • GET /transports/ — liste des transporteurs
  • GET /steps/ — liste des états

Exemple de requête

curl -X POST "https://api.tiktakpro.com/api/v1/back-order/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"order": {"name": "Nom du client", "phone": "20123456", "address": "Adresse complète", "gouvernorat": "Tunis", "source": "Facebook", "payement_type": "CASH", "transport": 1, "step": 1, "total_amount": 99.9, "total_after_discount": 99.9, "transport_price": 7.0, "_details": [{"quantity": 1, "product_id": 12345, "product_name": "T-shirt Blanc", "price_ttc": 89.9, "final_price": 89.9}]}}'

Lister les produits

Récupère la liste de tous vos produits.

Exemple de requête

curl -X GET "https://api.tiktakpro.com/api/v1/products/" \
  -H "Authorization: Token YOUR_API_TOKEN"

Détails d'un produit

Récupère les détails d'un produit spécifique.

Exemple de requête

curl -X GET "https://api.tiktakpro.com/api/v1/products/123/" \
  -H "Authorization: Token YOUR_API_TOKEN"

Lire un produit avec ses déclinaisons

Retourne le produit avec son tableau declinaisons[]. Chaque déclinaison contient attributs (tableau d'IDs) et _attributs (objets complets).

Exemple de requête

curl -X GET "https://api.tiktakpro.com/api/v1/product-variations/830022/" \
  -H "Authorization: Token YOUR_API_TOKEN"

Structure d'un attribut (_attributs)

{
  "id": 12345,
  "productoption_name": "Couleur",
  "name": "Couleur",
  "value": "Bleu",
  "is_color": true,
  "displaytype": "color",
  "position": 1,
  "productoption": 88
}

💡 Bonne pratique : toujours charger le produit complet via ce GET avant tout PUT, car la modification est un remplacement complet.

Créer un produit (payload complet)

Crée un produit et toutes ses déclinaisons en une seule requête. Le payload complet doit toujours être envoyé.

Corps de la requête

{
  "name": "T-shirt blanc",
  "description": "<p>Description HTML</p>",
  "reference": "REF-001",
  "bar_code": "123456789",
  "photo": "https://.../img.jpg",
  "photo_thumb": "https://.../img_thumb.jpg",
  "video_link": null,
  "price_ttc": 89.9,
  "price_ht": 75.5,
  "purchase_price": 40,
  "dealer_price": 60,
  "taxe_rate": 19,
  "discount": 0,
  "discount_type": "fixed_amount",
  "active_stock": true,
  "order_without_stock": false,
  "stock": 100,
  "delivery_price": 0,
  "custom_delivery_price": false,
  "declinaison": true,
  "default": false,
  "provider": "",
  "active": true,
  "display_on_website": true,
  "is_custom": false,
  "has_associtation": false,
  "sold": 0,
  "order": 1,
  "seo_title": null,
  "seo_description": null,
  "seo_slug": null,
  "seo_keywords": null,
  "seo_reviews": "27",
  "seo_stars": "4.9",
  "parent": null,
  "category": 12,
  "categories": [12, 34],
  "attributs": [{ "name": "Couleur", "value": "Bleu" }],
  "images": [{ "image": "url", "image_thumb": "url_thumb" }],
  "formula": [],
  "features": [],
  "packproducts": null,
  "subproducts_length": 0,
  "_category": null,
  "product_type": "physique",
  "declinaisons": []
}

Notes

price_ttc / price_ht sont attendus par l'API ; price n'est ajouté que s'il est fourni numériquement.

En création, attributs (niveau produit) est déduit de la 1re variante.

declinaison passe automatiquement à true si au moins une variante est présente.

product_type : physique, pack, landing… (jamais écrasé).

Pour une nouvelle déclinaison : parent = 0 et attributs sous forme de paires { name, value }.

{
  "id": 1367232,
  "name": "T-shirt blanc / M",
  "reference": "REF-001-M",
  "bar_code": "1234567890123",
  "photo": null,
  "photo_thumb": null,
  "price_ttc": 89.9,
  "price_ht": 75.5,
  "taxe_rate": 19,
  "discount": 0,
  "discount_type": "fixed_amount",
  "active_stock": true,
  "stock": 25,
  "delivery_price": 0,
  "custom_delivery_price": false,
  "declinaison": false,
  "default": false,
  "active": true,
  "is_custom": false,
  "sold": 0,
  "order": 1,
  "parent": 830022,
  "images": [],
  "formula": [],
  "product_type": "physique",
  "attributs": [12345, 12346]
}

Règles sur attributs

Déclinaison existante (PUT) : envoyer les IDs numériques des attributs. À défaut, les paires { name, value }. Si rien n'est exploitable, omettre le champ pour ne pas écraser le backend.

Nouvelle déclinaison : paires { "name": "Couleur", "value": "Bleu" } et parent = 0.

Modifier un produit et ses déclinaisons

Même structure que la création, avec en plus l'id du produit à la racine et l'id + parent de chaque déclinaison existante.

Corps de la requête

{
  "id": 830022,
  "name": "T-shirt blanc",
  "price_ttc": 89.9,
  "price_ht": 75.5,
  "stock": 100,
  "product_type": "physique",
  "has_associtation": false,
  "declinaisons": [
    {
      "name": "T-shirt blanc / XL",
      "reference": "REF-001-XL",
      "price_ttc": 89.9,
      "stock": 20,
      "parent": 0,
      "attributs": [
        { "name": "Couleur", "value": "Blanc" },
        { "name": "Taille", "value": "XL" }
      ]
    },
    {
      "id": 1367232,
      "name": "T-shirt blanc / M",
      "reference": "REF-001-M",
      "bar_code": "1234567890123",
      "stock": 25,
      "parent": 830022,
      "attributs": [12345, 12346]
    }
  ]
}

Gestion des déclinaisons

Ajouter : nouvelle déclinaison sans id, parent = 0, attributs en paires nom/valeur

Modifier : déclinaison avec son id et parent = {productId}

Supprimer : omettre la déclinaison du tableau

⚠️ PUT destructif : toute déclinaison absente du tableau declinaisons est supprimée côté backend. Ne jamais envoyer reference / bar_code vides sur une déclinaison existante.

Supprimer un produit
curl -X DELETE "https://api.tiktakpro.com/api/v1/product-variations/830022/" \
  -H "Authorization: Token YOUR_API_TOKEN"

Mise à jour rapide d'une déclinaison

Édition inline (prix, stock, photo) sans renvoyer tout le produit.

{
  "name": "T-shirt blanc / M",
  "price": 89.9,
  "stock": 25,
  "discount": 0,
  "discount_type": "fixed_amount",
  "photo": null,
  "photo_thumb": null
}

Log de changement de stock

POST /product-log/
{
  "product": 1367232,
  "action": "{User} a modifié le stock de {old} à {new}",
  "user": 32904
}

FonctionMéthodeURL
Contenu de la page produit (lecture)GET/product-content/{productId}/
Contenu (création)POST/product-content/
Contenu (mise à jour)PUT/product-content/{productId}/
Produits associés (lecture)GET/associated-products-search/{productId}
Produits associés (création)POST/associated-products/
Produits associés (mise à jour)PUT/associated-products/{groupId}/
Log de changement de stockPOST/product-log/
Liste / recherche produitsGET/products/?no_parent=true&search={term}
Catégories (sélecteur)GET/categories/?size=10&page=1&search={term}

Rappel métier : le flag d'association s'envoie avec la clé backend has_associtation (faute d'orthographe conservée côté API).

1. Le PUT est destructif : toujours partir des données complètes chargées via GET.

2. Ne jamais envoyer reference / bar_code vides sur une déclinaison existante.

3. has_associtation (typo) est la clé attendue par l'API.

4. Les prix passent par price_ttc / price_ht, pas uniquement price.

5. supplier_info, created_at, updated_at et autres champs read-only ne doivent pas être renvoyés.

Gestion complète des clients (lister, créer, modifier).

Créer un client (POST)

{
  "name": "Jean Dupont",
  "phone": "+33612345678",
  "email": "jean@example.com",
  "code_tva": "",
  "send_notification": true
}

Gestion des adresses de livraison des clients.

Créer une adresse (POST)

{
  "title": "Domicile",
  "address": "123 Rue de la Paix",
  "gouvernorat": "Tunis",
  "delegation": "La Marsa",
  "code_postal": "2070",
  "phone_extra": "",
  "default": true,
  "customer": 456
}
Pack développeur

Storefront TikTak — générez votre boutique avec Claude

Générez un site vitrine + checkout COD branché sur l'API TikTak, avec un design totalement libre. Le backoffice (produits, stock, commandes, upsells) ne change pas.

STOREFRONT_API.md

Documentation humaine : logique complète + les 17 endpoints du storefront.

llms.txt

Contrat Storefront complet en texte brut, à coller dans un Projet Claude.ai comme base de connaissance.

Ouvrir /storefront-llms.txt

tiktak-storefront/

Skill Cursor / Claude, à copier dans .cursor/skills/ du projet.

Démarrer avec Claude / Cursor

  1. Copier tiktak-storefront/ vers .cursor/skills/tiktak-storefront/ du projet client.
  2. (Claude.ai) coller llms.txt dans la connaissance du projet.
  3. Utiliser le prompt type ci-dessous.
  4. Fournir le slug boutique (sous-domaine *.tiktak.space) ou le domaine custom.
Génère une boutique (Next.js ou Nuxt) pour TikTak.
Slug {slug} ou domaine {domaine}. API https://api.tiktakpro.com/api/v1/
Suis le skill tiktak-storefront : bootstrap, catalogue, panier local,
checkout COD, upsell, confirmation. N'invente aucun endpoint.
La création de commande doit toujours être signée par la clé de
sécurité de la boutique, côté serveur uniquement.

🔐 Règle non négociable : la clé de sécurité

  • Toute réception de commande doit obligatoirement inclure la clé de sécurité de la boutique.
  • Une requête sans clé, ou avec une clé invalide, est rejetée — aucune commande n'est enregistrée.
  • La clé ne doit jamais apparaître dans le code front, le bundle JS ou une variable publique.
  • Le checkout appelle une route serveur de votre boutique, qui seule ajoute la clé avant d'appeler l'API TikTak.
  • En cas de fuite suspectée : régénérer immédiatement la clé depuis le backoffice.

Phase 1 (disponible)

Bootstrap boutique, catalogue, catégories, recherche, homepage builder (optionnelle), panier côté client, codes promo, checkout COD, upsell post-achat, confirmation.

Pas encore couvert

Paiement en ligne (Flouci, Konnect…), compte client / login / VIP, wishlist, panier abandonné, CAPI Facebook, zones de livraison dynamiques signées, MCP.

Contrat Storefront — Phase 1 (MVP)

Le backoffice TikTak reste la source de vérité (produits, stock, transporteurs, upsells, réglages). Le site généré ne fait que consommer ces endpoints. Base URL : https://api.tiktakpro.com/api/v1/ — lecture publique, toujours passer company (hashid boutique).

Identifiants

EntitéType d'idExemple
Boutique (company)Hashid string8GPmlML
Produit, variante, catégorie, transport, pageEntier4218
UpsellHashid stringXyZ1
Commande (order_code = order_ref)StringK7P2M

Ne jamais inventer d'id : toujours les lire dans les réponses.

Pagination (listes DRF)

Query : ?page=1&size=20 (size max 1000, défaut 10). Utiliser size, jamais page_size ni limit.

{
  "count": 84,
  "total_pages": 5,
  "current_page": 1,
  "next": "https://…?page=2",
  "previous": null,
  "results": []
}

website/menus-read/ et website/informations-read/ ne sont pas paginés (tableau / objet unique).

Filtres produits fréquents

Toujours : company={hashid} + active=true. Le queryset public force déjà active=True et display_on_website=True.

ParamètreRôle
no_parent=trueUniquement produits parents (pas les variantes)
show-children=falseN'embarque pas declinaisons[] (listes)
show-children=trueInclut les variantes (fiche produit) — défaut API
ids_in=1,2,3Produits ciblés
ids_not_in=1Exclusion
has_category=12Catégorie principale ou M2M (12,15)
search=Nom / référence / code-barres
ordering=created_at, updated_at, price, sold, name, reference, order (préfixe - = desc)
discount__gte=1Produits en promo
has_attributs=Filtre facette (ids d'attributs)

Logique globale

Domaine / slug
  ├─ GET get-store/                  → company.id, currency, works_with_transport
  └─ GET website/informations-read/  → store_settings (checkout, COD, formulaire)
  ├─ menus, homepage (optionnel), catalogue
  Panier = localStorage (aucun endpoint panier)
  ├─ GET transports-read/            si works_with_transport
  └─ POST website/get-auto-discount
  POST create-fast-order/          payement_type = CASH
  ├─ upsell_id → GET upsell + offre → POST update-order-upsell | refuser
  └─ sinon     → confirmation
  GET get-order-by-idref/{order_ref}/{company}

Le backend recalcule les totaux : total_amount envoyé est indicatif. Prix, remise, transport et stock sont repris côté serveur.

Bootstrap

Identifier la boutique par slug (boutique.tiktak.space → boutique) ou par domaine custom (?server=www.client.tn). GET get-store/ renvoie id (hashid), name, slug, logo, currency, works_with_transport, store_activated (403 si introuvable).

GET website/informations-read/ renvoie un objet : store_settings.cash_on_delivery, default_payement_type, formCheckout (champs dynamiques), checkout_message, seo_settings, css_settings, stock_settings.

slug formCheckoutChamp commande
name / phone / phone_extra / email / addressorder.name, order.phone, order.phone_extra, order.email, order.address
gouvorder.gouvernorat
cityorder.delegation
codeorder.code_postal
countryorder.country (défaut TN)
commentorder.comment
create_accountracine create_account (bool)
termsvalidation front uniquement
discount_coderacine promo_code

Si formCheckout est vide, afficher un formulaire par défaut : nom, téléphone, adresse, gouvernorat. Navigation : GET website/menus-read/?company={id}&position=header&active=true (prendre [0].menus).

Catalogue, prix et variantes

# Grille catégorie
products-read/?company={id}&page=1&size=20&active=true&no_parent=true&show-children=false&has_category={cat_id}&ordering=-created_at

# Recherche
products-read/?company={id}&no_parent=true&active=true&show-children=false&search={q}

# Fiche produit
products-read/{id}/?company={id}
product-by-slug?seo_slug={slug}&company={id}

Prix unitaire affiché :

discount_type == "fixed_amount"       → price - discount
discount_type == "percent"|"percentage" → price - (price * discount / 100)
formula et qty >= palier               → palier le plus haut dont quantity <= qty
  • Variantes : c'est declinaisons[i].id qui part dans product_id ; product_parent_id = parent de la variante (sinon id du produit).
  • Stock : si active_stock et pas order_without_stock, refuser qty > stock de la ligne commandée (variante, pas le parent).
  • Mise en page fiche : GET product-extra-read/?product={id}&company={id} (blocs data[]), fil d'Ariane : category-breadcrumb/{cat_id}/{company}.
  • Homepage optionnelle : GET website/page-read/?page_type=home&company={id} — un front custom peut ignorer main_content.

Panier (localStorage) — pas d'API

{
  "product_id": 4219,
  "product_parent_id": 4218,
  "product_name": "T-shirt",
  "product_ref": "TS-001",
  "category_id": 12,
  "quantity": 2,
  "active_stock": true,
  "price_ttc": 49.9,
  "price_ttc_after_discount": 39.9,
  "final_price": 79.8,
  "discount": 10,
  "product_attrs": "Rouge M",
  "product_thumb": "https://…"
}

Fusionner les lignes de même product_id (+ mêmes options). subtotal = somme des final_price ; total = subtotal - discount + transport_price.

Livraison et remises

  • Si company.works_with_transport : GET transports-read/?company={id} (use_for_web=true, active=true). Choisir le transporteur default, envoyer order.transport_id.
  • Prix custom produit : si tous les articles ont custom_delivery_price, port = max(delivery_price) ; sinon max(custom…, transporteur.price).
  • Phase 1 : ne pas implémenter delivery_quote_token / transport_key=delivery_zone_dynamic.
POST website/get-auto-discount
{
  "slug": "ma-boutique",
  "details": [
    { "product_id": 4218, "product_parent_id": 4218, "quantity": 1, "final_price": 39.9 }
  ],
  "code": "",
  "delivery_price": 7
}
// Réponse Phase 1 : un nombre = montant de remise (pas un %)

code vide → remise automatique boutique ; code renseigné → code promo. Au checkout, n'envoyer promo_code que pour un vrai code saisi (l'auto-remise envoie "").

Checkout COD — POST create-fast-order/

{
  "company": "8GPmlML",
  "source": "SITE CUSTOM",
  "promo_code": "",
  "create_account": false,
  "provider": null,
  "meta_data": {
    "client_ip": "41.x.x.x",
    "fingerprint": { "id": "fp_…" },
    "visit_source": null
  },
  "order": {
    "name": "Ahmed Ben Ali",
    "phone": "22123456",
    "phone_extra": "",
    "email": "",
    "address": "12 rue …",
    "gouvernorat": "Tunis",
    "delegation": "Tunis",
    "code_postal": "1000",
    "country": "TN",
    "comment": "",
    "payement_type": "CASH",
    "transport_id": 3,
    "total_amount": 86.8,
    "_details": []
  }
}

// Succès
{ "order_ref": "K7P2M", "payment": {}, "upsell_id": "XyZ1" }
  • payement_type : CASH (COD). Pas de ONLINE en Phase 1.
  • _details obligatoire et non vide ; phone nettoyé côté serveur.
  • 429 = trop de commandes IP/fingerprint → afficher une page succès factice (ne pas révéler le blocage) et ne pas vider le panier.
  • 400 : { "detail": "…" } (ex. _details is required, No step configured.).
  • Routage : upsell_id → /upsell/{upsell_id}/{order_ref} ; sinon /checkout-confirmation/{order_ref}.

Obligatoire — challenge checkout : aucune commande ne peut être créée sans un challenge checkout déjà en place. Tout front custom doit l'implémenter avant d'appeler create-fast-order/ :

  • Fingerprint navigateur obligatoire dans meta_data.fingerprint.id (stable par appareil).
  • Rate-limit actif : la commande est comptée par IP + fingerprint ; un dépassement renvoie 429.
  • L'IP réelle du client doit être transmise dans meta_data.client_ip via votre proxy serveur.
  • Sur 429 : afficher une page succès factice, ne pas vider le panier, ne pas révéler le blocage.
  • Une requête sans fingerprint ni challenge est considérée comme non conforme et peut être rejetée.

Rappel : la création de commande doit toujours passer par une route serveur de votre boutique (proxy), qui seule injecte la clé de sécurité et l'IP client. Jamais de clé dans le bundle JS.

Implémentation recommandée du fingerprint : FingerprintJS

Le champ meta_data.fingerprint.id doit être généré par une librairie de fingerprinting stable par appareil. La référence recommandée est l'open-source FingerprintJS (@fingerprintjs/fingerprintjs) — évitez les IDs maison (Math.random, localStorage seul, etc.) facilement contournables.

Installation

npm install @fingerprintjs/fingerprintjs

Exemple d'usage côté client

import FingerprintJS from '@fingerprintjs/fingerprintjs';

const fpPromise = FingerprintJS.load();

async function getFingerprint() {
  const fp = await fpPromise;
  const result = await fp.get();
  return result.visitorId; // stable par appareil
}

// Au moment du checkout :
const fingerprintId = await getFingerprint();
// → envoyé dans meta_data.fingerprint.id du payload create-fast-order/
  • L'appel à getFingerprint() doit se faire dans le composant checkout, avant l'envoi du payload.
  • visitorId reste stable pour un même appareil/navigateur, ce qui permet le rate-limit par IP + fingerprint exigé par create-fast-order/.
  • La version gratuite open-source suffit pour ce cas d'usage (pas besoin de l'API Pro payante de Fingerprint.com).
  • Le fingerprint seul ne suffit pas : il doit être combiné côté serveur avec l'IP réelle du client (meta_data.client_ip) dans la fonction proxy qui appelle l'API TikTak.
💡 Le calcul du fingerprint reste 100% côté client (React pur). Seul l'ajout de la clé de sécurité et de l'IP réelle nécessite une route serveur minimale (fonction serverless Vercel/Netlify/Cloudflare d'une trentaine de lignes) — le reste de la boutique peut être un SPA React classique.

Upsell (COD uniquement) et confirmation

  1. GET website/upsell/{company}/{upsell_id} — text_upsell, product_to_propose, discount (montant, pas %), free_shipping.
  2. GET get-order-by-idref/{order_ref}/{company} — commande déjà créée.
  3. GET products-read/?ids_in={product_to_propose}&company=… — prix barré = price, prix offre = price - discount.
  4. Accepter : POST update-order-upsell { "upsell", "order": "<order_ref>", "company" } → "Success".
  5. Refuser : aller à la confirmation sans POST.

Confirmation : GET get-order-by-idref/{order_ref}/{company} — afficher order_code, created_at, coordonnées, details[], transport_price, discount, total_after_discount et le checkout_message du store (404 si ref inconnue).

Catalogue des 17 endpoints Storefront

MéthodeCheminRôle
GETget-store/Boutique
GETwebsite/informations-read/Réglages store
GETwebsite/menus-read/Navigation
GETwebsite/page-read/Homepage / pages (page_type ou id)
GETproducts-read/Liste / recherche
GETproducts-read/{id}/Fiche par id
GETproduct-by-slugFiche par seo_slug
GETproduct-extra-read/Blocs fiche
GETcategories-read/{id}/Catégorie
GETcategory-breadcrumb/{id}/{company}Fil d'Ariane
GETtransports-read/Transporteurs web
POSTwebsite/get-auto-discountRemise
POSTcreate-fast-order/Créer commande
GETget-order-by-idref/{ref}/{company}Lire commande
GETwebsite/upsell/{company}/{id}Config upsell
POSTupdate-order-upsellAccepter upsell
GETwebsite/page-read/{id}/Page CMS par id

Ne pas appeler d'autres routes (products/, orders/, login-jwt/, stats, Shopify, MCP…).

Pièges à éviter

  1. company est un hashid, pas un entier.
  2. Pas d'endpoint panier — localStorage / Pinia / cookie.
  3. payement_type s'écrit avec un seul « e » (pas payment_type).
  4. order_ref = order_code, pas l'id numérique interne.
  5. Jamais d'upsell après un paiement ONLINE.
  6. discount upsell = montant, pas un pourcentage.
  7. Totaux recalculés côté serveur — ne pas faire confiance au front.
  8. Listes : no_parent=true + show-children=false ; fiche : show-children=true.
  9. Pagination : size, pas page_size / limit.
  10. Le challenge checkout est exigé pour tout front custom : meta_data.fingerprint + IP client + rate-limit. Le HMAC X-Checkout-Challenge reste spécifique au store officiel Nuxt.

Le MCP TikTak (mcp.tiktak.space) pilote le thème Nuxt officiel. Ce pack sert à construire un autre front. Implémentation officielle de référence : dépôt store-nuxt.

📋 Statuts de commande disponibles

Utilisez ces codes de statut (slug) pour filtrer ou mettre à jour vos commandes

standby→En attente
confirmed→Confirmée
preparing→En préparation
expd→Expédiée
delivered→Livrée
cancelled→Annulée
abandoned-cart→Panier abandonné

💡 Bonnes pratiques

🔐

Sécurité

Ne partagez jamais votre token d'API. Stockez-le dans des variables d'environnement sécurisées.

⚡

Performance

Utilisez la pagination pour les grandes listes. Mettez en cache les données fréquemment consultées.

🔄

Gestion d'erreurs

Implémentez une gestion robuste des erreurs et des mécanismes de retry pour les requêtes critiques.

📝

Logging

Loguez toutes vos requêtes API pour faciliter le débogage et le monitoring de vos intégrations.

Prêt à commencer ?

Créez votre compte et obtenez votre clé API pour commencer à intégrer TikTak PRO dès maintenant