Aller au contenu

Adaptateur REST API BigCommerce

Compatible v2/v3

Dernière mise à jour : 5 September 2026

Une API REST compatible et directement substituable pour STOAR, qui reproduit BigCommerce v2 (/api/v2/orders) et v3 (/api/v3/catalog/products) — mêmes chemins d'URL, mêmes dates RFC 2822, même vocabulaire numérique status_id, même enveloppe { data, meta.pagination } en v3, mêmes en-têtes X-Pagination-* en v2, même en-tête X-Auth-Token. Les bibliothèques clientes BigCommerce existantes (bigcommerce/api Node SDK, bigcommerce-api-php, BigCommerce Python) dialoguent avec STOAR sans aucune modification.

Il s'agit de la quatrième implémentation du framework d'adaptateurs d'API extensible de STOAR (après Magento, WooCommerce et Shopify). Elle démontre que l'architecture prend en charge deux variantes de version sous un même adaptateur (v2 + v3) sans dupliquer la moindre logique métier.


Sommaire #


Démarrage rapide #

TOKEN="5|abcdef…"     # Sanctum personal-access token with bigcommerce:admin ability

# v2 — orders
curl -H "X-Auth-Token: $TOKEN" \
     "https://app.stoar.ai/api/v2/orders?limit=5" | jq '.[] | {id, status_id, status, total_inc_tax}'

# v2 — line items for a specific order (separate sub-endpoint)
curl -H "X-Auth-Token: $TOKEN" \
     "https://app.stoar.ai/api/v2/orders/10126/products" | jq '.[].name'

# v3 — catalog products with pagination meta envelope
curl -H "X-Auth-Token: $TOKEN" \
     "https://app.stoar.ai/api/v3/catalog/products?limit=2&page=1" | jq '.meta.pagination'

# v3 — single product
curl -H "X-Auth-Token: $TOKEN" \
     "https://app.stoar.ai/api/v3/catalog/products/789"

L'authentification Bearer (-H "Authorization: Bearer $TOKEN") est également acceptée en repli.


Authentification #

L'en-tête d'authentification canonique de BigCommerce est X-Auth-Token: <token>. L'adaptateur STOAR l'accepte, ainsi qu'un repli Bearer :

Méthode Format Cas d'usage
X-Auth-Token X-Auth-Token: <sanctum-token> Valeur par défaut de toutes les bibliothèques clientes BigCommerce
Bearer (extension STOAR) Authorization: Bearer <sanctum-token> Sanctum natif — interchangeable avec les autres adaptateurs

Les tokens sont émis depuis la page /manager/api-tokens de STOAR, ou par programme via AdminUser::createToken('label', ['bigcommerce:admin']). Un même token peut porter simultanément les abilities de tous les adaptateurs (bigcommerce:admin + magento:admin + shopify:admin + woocommerce:admin).

Le middleware AuthTokenMiddleware s'exécute avant auth:sanctum et promeut X-Auth-Token en en-tête Authorization: Bearer …. Du point de vue de STOAR, toute requête BC est une requête Sanctum authentifiée ordinaire.

Le flux OAuth client credentials (les vraies applications BC passent par /auth/load et /oauth2/token) n'est pas pris en charge.


Points de terminaison #

Tous les chemins sont relatifs à /api. Les points de terminaison v2 se trouvent sous /api/v2, ceux de la v3 sous /api/v3.

GET /api/v2/orders

Liste les commandes — tableau plat dans le corps + en-têtes de pagination.

Autorisation : bigcommerce:admin. Requête : voir Paramètres de requête.

Réponse :

HTTP/1.1 200 OK
X-Pagination-Total-Count: 150
X-Pagination-Page-Total:  3
Content-Type: application/json

[
  { /* order object — see Response shape */ }
]

Pourquoi des en-têtes plutôt qu'une enveloppe ? C'est la convention réelle de BC v2. Les points de terminaison v3 utilisent l'enveloppe { data, meta } (voir les produits du catalogue ci-dessous). Les vraies bibliothèques clientes BC gèrent les deux.


GET /api/v2/orders/{id}

Commande unique — objet brut (AUCUNE enveloppe en v2).

Erreurs :

{ "status": 404, "title": "The order requested could not be found.", "type": "..." }

GET /api/v2/orders/{id}/products

Remarque — les lignes de commande résident sur un point de terminaison SÉPARÉ ; elles ne sont pas intégrées à la ressource commande. C'est l'une des différences majeures de BC par rapport à Magento, WooCommerce et Shopify (qui intègrent tous les lignes de commande).

Réponse : tableau plat d'objets de ligne BC v2.

[
  {
    "id":              30219,
    "order_id":        10126,
    "product_id":      112238,
    "variant_id":      95589,
    "name":            "Widget",
    "sku":             "WID-1-A",
    "type":            "physical",
    "base_price":      299,
    "price_ex_tax":    299,
    "price_inc_tax":   299,
    "base_total":      897,
    "total_ex_tax":    897,
    "total_inc_tax":   897,
    "quantity":        3,
    "is_refunded":     false,
    "product_options": [],
    "..."
  }
]

GET /api/v3/catalog/products

Liste les produits du catalogue — enveloppe v3 avec data + meta.pagination.

Requête : voir Paramètres de requête.

Réponse (200) :

{
  "data": [
    { /* product — see Response shape */ }
  ],
  "meta": {
    "pagination": {
      "total":         150,
      "count":         50,
      "per_page":      50,
      "current_page":  1,
      "total_pages":   3,
      "links": {
        "current": "https://.../api/v3/catalog/products?page=1&limit=50",
        "next":    "https://.../api/v3/catalog/products?page=2&limit=50"
      },
      "too_many":      false
    }
  }
}

links.previous est présent à partir de la page 2 ; links.next sur toutes les pages sauf la dernière.


GET /api/v3/catalog/products/{id}

Produit unique — enveloppe v3 avec data (objet unique) + meta vide.

Réponse :

{
  "data": { /* product — see Response shape */ },
  "meta": {}
}

Paramètres de requête #

Communs (commandes + produits)

Paramètre Défaut Objet
limit 50 éléments par page (max. 250)
page 1 numéro de page, indexé à partir de 1

Commandes v2 uniquement

Paramètre Exemple Effet
status_id 11 Code de statut numérique BC → traduit en statut Stoar
customer_id 42 Filtrer par client
min_id / max_id 100 plage d'id
min_date_created / max_date_created 2025-01-01T00:00:00 plage created_at
sort id:desc <field>:<asc\|desc>. Champs : id, date_created, date_modified, total_inc_tax

Produits du catalogue v3 uniquement

La v3 prend en charge la syntaxe plus riche des suffixes d'opérateur de BC : id:in, price:min, etc.

Paramètre Exemple Effet
id 42 id exact
id:in 1,2,3 id IN liste
id:not_in 4,5 id NOT IN liste
sku WID-1 sku exact
name Widget nom exact
keyword widget LIKE sur une sous-chaîne du nom
is_visible true / false traduit en active / inactive
is_featured true / false filtre sur is_featured
categories 5 id de catégorie exact
price:min 10 price >=
price:max 100 price <=
sort name, -price, -date_created, id un - en tête inverse le sens

Les opérateurs ou champs inconnus sont ignorés silencieusement — comme le fait BC.


Correspondance des champs (BigCommerce ↔ STOAR) #

Commande (v2)

Champ BC v2 Source STOAR Remarques
id id numérique
status_id status (traduit) code numérique BC (1, 11, 7, 3, 10, 5, 4) — voir Traduction des statuts
status status (traduit) libellé texte (« Pending », « Awaiting Fulfillment », « Shipped », …)
customer_id customer_id ?? 0 les commandes invité reçoivent 0
date_created, date_modified created_at, updated_at format RFC 2822 (PAS ISO 8601)
date_shipped updated_at si status='shipped'/'delivered' chaîne vide sinon
currency_code, default_currency_code currency (en majuscules) p. ex. EUR
currency_exchange_rate toujours '1.0000000000' Stoar est monodevise
total_inc_tax total_amount float NUMÉRIQUE (PAS une chaîne — c'est le comportement V3 / WC)
total_ex_tax total_amount - tax_amount
total_tax tax_amount
subtotal_ex_tax subtotal
subtotal_inc_tax subtotal + tax_amount
subtotal_tax tax_amount
shipping_cost_ex_tax, shipping_cost_inc_tax, base_shipping_cost shipping_amount
discount_amount, coupon_discount discount_amount
payment_method premier OrderPayment.gateway non archivé
payment_status 'captured' si payment_status='succeeded' vide sinon
refunded_amount refunded_amount ?? 0
staff_notes admin_notes
customer_message customer_notes
billing_address JSON billing_info objet imbriqué — structure plate avec les clés street_1/street_2
products sous-ressource pointeur {url, resource} vers /orders/{id}/products
shipping_addresses sous-ressource pointeur {url, resource} (non implémenté)
coupons sous-ressource pointeur {url, resource} (non implémenté)
items_total sum(items.quantity)
items_shipped sum(items.quantity) si status='shipped'/'delivered', sinon 0
customer_locale toujours 'en' non stocké
channel_id toujours 1 non modélisé

Ligne de commande line_item (v2 /products)

Champ BC v2 Source Stoar
id OrderItem.id
order_id OrderItem.order_id
product_id OrderItem.product_id
variant_id OrderItem.variant_id
name, name_customer, name_merchant OrderItem.name
sku SKU de la variante d'abord, à défaut celui du produit
type toujours 'physical'
base_price, price_ex_tax OrderItem.price
price_inc_tax price + (tax_amount / quantity)
base_total, total_ex_tax price * quantity
total_inc_tax (price * quantity) + tax_amount
total_tax OrderItem.tax_amount
quantity OrderItem.quantity
product_options[] un élément portant le nom de la variante (lorsqu'il n'est pas Default)
weight, width, height, depth toujours 0
is_refunded, quantity_refunded, refund_amount toujours false/0 (Stoar suit les remboursements au seul niveau commande)

Produit du catalogue (v3)

Champ BC v3 Source STOAR Remarques
id id
name, description, sku repris tel quel
type toujours 'physical' BC propose aussi 'digital' ; Stoar ne gère que le physique
is_visible status === 'active' booléen
availability 'available' si actif, sinon 'disabled' énumération
is_featured is_featured booléen
inventory_tracking 'product' pour un produit simple, 'variant' pour un configurable
inventory_level stock (somme des variantes pour un configurable)
inventory_warning_level low_stock_threshold ?? 0
price price (brut) float NUMÉRIQUE
sale_price special_price ?? 0 float
calculated_price min(price, special_price) float
weight weight ?? 0 float
tax_class_id tax_class_id ?? 0
categories [category_id] tableau d'un seul entier (PAS des objets imbriqués)
base_variant_id id de la première variante
images[] image_path + gallery_paths tableau en ligne
variants[] en ligne objets de variante complets
custom_url {url: "/{slug}", is_customized: false, create_redirect: false}
page_title, meta_description, meta_keywords meta_title, meta_description, []
date_created, date_modified created_at, updated_at ISO 8601 (la v3 utilise ISO, la v2 RFC 2822)
condition toujours 'New' non modélisé
total_sold, view_count, reviews_rating_sum, reviews_count toujours 0 non agrégés
related_products toujours [-1] convention BC pour « produits liés automatiquement »
brand_id toujours null Stoar n'a pas de modèle de marque

Variante de produit du catalogue (v3)

Champ BC v3 Source Stoar
id Variant.id
product_id Variant.product_id
sku Variant.sku
price, calculated_price Variant.price
inventory_level Variant.stock
weight, calculated_weight Variant.weight
purchasing_disabled !Variant.is_active
image_url Variant.image_path ?? ""
option_values[] toujours [] (les attributs de variante Stoar suivent un autre modèle)

Traduction des statuts #

BigCommerce utilise des codes status_id NUMÉRIQUES accompagnés d'un champ texte status parallèle. Le traducteur décompose l'énumération Stoar en ces deux valeurs.

Stoar → BigCommerce (rendu)

status Stoar status_id status (texte)
pending 1 Pending
paid 11 Awaiting Fulfillment
processing 7 Awaiting Pickup
shipped 3 Shipped
delivered 10 Completed
cancelled 5 Cancelled
refunded 4 Refunded

Filtre BigCommerce → Stoar (analyse)

?status_id=N est traduit via la même table de correspondance. Les codes absents de la table (p. ex. le statut BC 2 = « Manually Verified » ou 6 = « Declined ») passent silencieusement — conformément au comportement « pas d'équivalent exact » de BC. La table complète du vrai BC compte environ 14 entrées ; STOAR expose les sept qui se traduisent proprement.

Statut produit

BigCommerce n'a pas de champ texte status — il utilise is_visible (booléen) et l'énumération availability. Filtre avec ?is_visible=true pour les produits actifs et ?is_visible=false pour les inactifs.


Structure des réponses #

Commande v2 — annotée

{
  "id":             456,
  "customer_id":    45,
  "date_created":   "Tue, 03 Jun 2025 04:56:43 +0000",
  "date_modified":  "Tue, 03 Jun 2025 04:56:43 +0000",
  "date_shipped":   "",
  "status_id":      11,
  "status":         "Awaiting Fulfillment",
  "subtotal_ex_tax":   100,
  "subtotal_inc_tax":  110,
  "subtotal_tax":      10,
  "total_ex_tax":      105,
  "total_inc_tax":     115,
  "total_tax":         10,
  "items_total":       2,
  "items_shipped":     0,
  "payment_method":    "stripe",
  "payment_status":    "captured",
  "refunded_amount":   0,
  "currency_code":     "EUR",
  "currency_exchange_rate":   "1.0000000000",
  "default_currency_code":    "EUR",
  "billing_address": {
    "first_name":   "Jane",
    "last_name":    "Doe",
    "company":      "",
    "street_1":     "1 Test St",
    "street_2":     "",
    "city":         "Berlin",
    "state":        "",
    "zip":          "10115",
    "country":      "Germany",
    "country_iso2": "DE",
    "phone":        "+49…",
    "email":        "[email protected]",
    "form_fields":  []
  },
  "products": {
    "url":      "https://.../api/v2/orders/456/products",
    "resource": "/orders/456/products"
  },
  "shipping_addresses": {
    "url":      "https://.../api/v2/orders/456/shippingaddresses",
    "resource": "/orders/456/shippingaddresses"
  },
  "coupons": {
    "url":      "https://.../api/v2/orders/456/coupons",
    "resource": "/orders/456/coupons"
  },
  "store_default_currency_code": "EUR",
  "channel_id":     1,
  "..."
}

Produit du catalogue v3 — abrégé

{
  "data": {
    "id":                  789,
    "name":                "Widget",
    "type":                "physical",
    "sku":                 "WID-1",
    "description":         "<p>A great widget</p>",
    "weight":              0.5,
    "price":               99.99,
    "sale_price":          0,
    "retail_price":        0,
    "calculated_price":    99.99,
    "categories":          [5],
    "is_visible":          true,
    "is_featured":         true,
    "availability":        "available",
    "inventory_tracking":  "product",
    "inventory_level":     42,
    "page_title":          "Widget – buy now",
    "custom_url": {
      "url":             "/widget",
      "is_customized":   false,
      "create_redirect": false
    },
    "images": [
      { "id": 0, "image_file": "products/widget.webp", "is_thumbnail": true, "sort_order": 0, "url_thumbnail": "products/widget.webp", "url_zoom": "products/widget.webp", "..." }
    ],
    "variants": [
      { "id": 12, "product_id": 789, "sku": "WID-RED", "price": 99.99, "inventory_level": 22, "purchasing_disabled": false, "..." }
    ]
  },
  "meta": {}
}

Exemple réel #

GET /api/v2/orders/10126 en production. Il s'agit de la même commande Stoar que celle présentée pour Magento, WooCommerce et Shopify — rendue ici à la structure BC v2. Données personnelles anonymisées.

{
  "id":                 10126,
  "customer_id":        5794,
  "date_created":       "Tue, 03 Jun 2025 04:56:43 +0000",
  "date_modified":      "Tue, 03 Jun 2025 04:56:43 +0000",
  "date_shipped":       "",
  "status_id":          11,
  "status":             "Awaiting Fulfillment",
  "subtotal_ex_tax":    936.98,
  "subtotal_inc_tax":   936.98,
  "subtotal_tax":       0,
  "shipping_cost_ex_tax":  0,
  "shipping_cost_inc_tax": 0,
  "shipping_cost_tax":     0,
  "total_ex_tax":       936.98,
  "total_inc_tax":      936.98,
  "total_tax":          0,
  "items_total":        5,
  "items_shipped":      0,
  "payment_method":     "payid",
  "payment_provider_id":null,
  "payment_status":     "captured",
  "refunded_amount":    0,
  "order_is_digital":   false,
  "currency_id":        1,
  "currency_code":      "USD",
  "currency_exchange_rate":   "1.0000000000",
  "default_currency_id":      1,
  "default_currency_code":    "USD",
  "staff_notes":        "",
  "customer_message":   "",
  "discount_amount":    0,
  "coupon_discount":    0,
  "shipping_address_count": 1,
  "is_deleted":         false,
  "ebay_order_id":      "0",
  "cart_id":            null,
  "billing_address": {
    "first_name":   "Jane",
    "last_name":    "Doe",
    "company":      "",
    "street_1":     "1 Example Street",
    "street_2":     "",
    "city":         "Phoenix",
    "state":        "AZ",
    "zip":          "85001",
    "country":      "United States",
    "country_iso2": "US",
    "phone":        "+1-555-0100",
    "email":        "",
    "form_fields":  []
  },
  "products": {
    "url":      "https://app.stoar.ai/api/v2/orders/10126/products",
    "resource": "/orders/10126/products"
  },
  "shipping_addresses": {
    "url":      "https://app.stoar.ai/api/v2/orders/10126/shippingaddresses",
    "resource": "/orders/10126/shippingaddresses"
  },
  "coupons": {
    "url":      "https://app.stoar.ai/api/v2/orders/10126/coupons",
    "resource": "/orders/10126/coupons"
  },
  "store_default_currency_code": "USD",
  "store_default_to_transactional_exchange_rate": "1.0000000000",
  "custom_status":      "Awaiting Fulfillment",
  "channel_id":         1,
  "ip_address":         "",
  "ip_address_v6":      "",
  "geoip_country":      "",
  "geoip_country_iso2": "",
  "is_email_opt_in":    false,
  "credit_card_type":   null,
  "order_source":       "www",
  "external_source":    null,
  "external_id":        null,
  "external_merchant_id":null,
  "tax_provider_id":    "",
  "customer_locale":    "en",
  "external_order_id":  ""
}

Points de vigilance pour les intégrateurs

Champ Observé Pourquoi
date_created, date_modified chaîne RFC 2822 la v2 utilise spécifiquement RFC 2822 (Tue, 03 Jun 2025 04:56:43 +0000). Les points de terminaison v3 utilisent ISO 8601 — l'incohérence vient de BC, nous la reproduisons.
payment_method "payid" clé de passerelle Stoar — ce n'est pas un nom de méthode canonique BC.
payment_status "captured" pour les commandes payées BC dispose de son propre vocabulaire de statuts ; nous faisons correspondre succeededcaptured.
total_inc_tax, total_ex_tax, etc. des floats (p. ex. 936.98) BC v2 rend les montants sous forme de floats — contrairement à WooCommerce / Shopify qui utilisent des chaînes à 2 décimales.
country "United States" nom complet, déduit de l'ISO-2 via une petite table de correspondance (DE/US/GB/AU/AT/CH). Les autres pays renvoient "".
products, shipping_addresses, coupons pointeurs de sous-ressource {url, resource} convention BC signifiant « suis cette URL pour récupérer les données liées ». /orders/{id}/products est implémenté ; les autres ne sont pas encore disponibles.
customer_locale toujours "en" non stocké sur le Customer Stoar.
channel_id toujours 1 Stoar est mono-boutique ; BC gère le multicanal.
currency_exchange_rate toujours "1.0000000000" Stoar est monodevise.
staff_notes, customer_message admin_notes, customer_notes terminologie BC.
external_*, ebay_order_id, cart_id vide / null / « 0 » Stoar n'a aucune intégration marketplace.

Structure des erreurs #

BigCommerce utilise une enveloppe de style RFC 7807 :

{
  "status": 404,
  "title":  "The order requested could not be found.",
  "type":   "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes",
  "errors": { "<field>": "..." }
}

type pointe toujours vers la page de documentation des codes de statut de BC. errors n'est présent qu'en cas d'échec de validation (400).

HTTP Déclencheur title
400 requête incorrecte / validation Invalid query parameters. (avec la table errors)
401 token absent ou invalide Not authenticated.
403 token à l'ability incorrecte Insufficient OAuth scope.
404 ressource inconnue The {resource} requested could not be found.
422 précondition non remplie message dynamique
429 limite de débit dépassée Too many requests. (avec les en-têtes X-Rate-Limit-Time-Reset-Ms et X-Rate-Limit-Requests-Left)
500 erreur serveur inattendue Internal Server Error

Limitation de débit #

Le même throttle api-rest indexé sur le token Sanctum qui protège tous les autres adaptateurs protège les routes BC. Le seuil et l'interrupteur général se configurent sur /manager/api-settings. En cas de déclenchement, la réponse utilise l'enveloppe RFC 7807 de BC :

HTTP/1.1 429 Too Many Requests
X-Rate-Limit-Time-Reset-Ms: 60000
X-Rate-Limit-Requests-Left: 0
Content-Type: application/json

{
  "status": 429,
  "title":  "Too many requests.",
  "type":   "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes"
}

Les en-têtes X-Rate-Limit-* correspondent au comportement documenté par BC. Le vrai BC renvoie davantage d'en-têtes et utilise des fenêtres à la seconde ; STOAR utilise la fenêtre à la minute de Laravel — suffisamment proche pour la compatibilité avec les bibliothèques clientes.

Un même token Sanctum utilisé sur les quatre adaptateurs partage un seul compteur — voir la section Limitation de débit de Magento pour la visite guidée de l'interface de configuration.


Voir aussi #

  • app/Api/Adapters/BigCommerce/Support/StatusTranslator.php — correspondance bidirectionnelle des vocabulaires
  • Référence de la REST API BigCommerce — la spécification amont que cet adaptateur reproduit