Zum Inhalt springen

BigCommerce-REST-API-Adapter

Kompatibel zu v2/v3

Zuletzt aktualisiert: 5. September 2026

Eine unmittelbar einsetzbare, kompatible REST-API für STOAR, die BigCommerce v2 (/api/v2/orders) und v3 (/api/v3/catalog/products) nachbildet — dieselben URL-Pfade, dieselben RFC-2822-Datumsangaben, dasselbe numerische status_id-Vokabular, dieselbe { data, meta.pagination }-Hülle in v3, dieselben X-Pagination-*-Header in v2, derselbe X-Auth-Token-Header. Bestehende BigCommerce-Client-Bibliotheken (bigcommerce/api Node SDK, bigcommerce-api-php, BigCommerce Python) sprechen ohne Änderung mit STOAR.

Dies ist die vierte Implementierung von STOARs erweiterbarem API-Adapter-Framework (nach Magento, WooCommerce und Shopify). Sie zeigt, dass die Architektur zwei Versionsvarianten unter einem Adapter (v2 + v3) trägt, ohne Geschäftslogik zu duplizieren.


Inhaltsverzeichnis #


Schnellstart #

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"

Bearer-Auth (-H "Authorization: Bearer $TOKEN") wird ebenfalls als Fallback akzeptiert.


Authentifizierung #

Der kanonische Auth-Header von BigCommerce lautet X-Auth-Token: <token>. STOARs Adapter akzeptiert ihn sowie einen Bearer-Fallback:

Methode Format Anwendungsfall
X-Auth-Token X-Auth-Token: <sanctum-token> Standard für alle BigCommerce-Client-Bibliotheken
Bearer (STOAR-Erweiterung) Authorization: Bearer <sanctum-token> Natives Sanctum — austauschbar mit den anderen Adaptern

Tokens werden auf STOARs Seite /manager/api-tokens ausgestellt oder programmatisch über AdminUser::createToken('label', ['bigcommerce:admin']). Ein einzelnes Token kann die Ability jedes Adapters gleichzeitig tragen (bigcommerce:admin + magento:admin + shopify:admin + woocommerce:admin).

Die AuthTokenMiddleware läuft vor auth:sanctum und überführt X-Auth-Token in einen Authorization: Bearer …-Header. Aus Sicht von STOAR ist jede BC-Anfrage eine normale, per Sanctum authentifizierte Anfrage.

Der OAuth-Client-Credential-Flow (echte BC-Apps gehen über /auth/load und /oauth2/token) wird nicht unterstützt.


Endpunkte #

Alle Pfade sind relativ zu /api. v2-Endpunkte liegen unter /api/v2, v3-Endpunkte unter /api/v3.

GET /api/v2/orders

Bestellungen auflisten — flaches Array im Body plus Pagination-Header.

Autorisierung: bigcommerce:admin. Query: siehe Query-Parameter.

Antwort:

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

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

Warum Header statt Hülle? Genau das ist die tatsächliche Konvention von BC v2. v3-Endpunkte nutzen die { data, meta }-Hülle (siehe Katalogprodukte weiter unten). Echte BC-Client-Bibliotheken beherrschen beides.


GET /api/v2/orders/{id}

Einzelne Bestellung — reines Objekt (in v2 KEINE Hülle).

Fehler:

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

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

Hinweis — Positionen liegen an einem SEPARATEN Endpunkt und sind nicht in die Bestellressource eingebettet. Das ist einer der größeren Unterschiede von BC gegenüber Magento, WooCommerce und Shopify (die Positionen jeweils inline führen).

Antwort: flaches Array von BC-v2-Positionsobjekten.

[
  {
    "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

Katalogprodukte auflisten — v3-Hülle mit data + meta.pagination.

Query: siehe Query-Parameter.

Antwort (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 ist ab Seite 2 enthalten, links.next auf allen Seiten außer der letzten.


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

Einzelnes Produkt — v3-Hülle mit data (einzelnes Objekt) und leerem meta.

Antwort:

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

Query-Parameter #

Gemeinsam (Bestellungen + Produkte)

Parameter Standard Zweck
limit 50 Einträge pro Seite (max. 250)
page 1 Seitenzahl, 1-basiert

Nur v2-Bestellungen

Parameter Beispiel Wirkung
status_id 11 Numerischer BC-Statuscode → in Stoar-Status übersetzt
customer_id 42 Nach Kunde filtern
min_id / max_id 100 id-Bereich
min_date_created / max_date_created 2025-01-01T00:00:00 created_at-Bereich
sort id:desc <field>:<asc\|desc>. Felder: id, date_created, date_modified, total_inc_tax

Nur v3-Katalogprodukte

V3 unterstützt die reichhaltigere Operator-Suffix-Syntax von BC: id:in, price:min usw.

Parameter Beispiel Wirkung
id 42 exakte id
id:in 1,2,3 id IN Liste
id:not_in 4,5 id NOT IN Liste
sku WID-1 exakte sku
name Widget exakter Name
keyword widget LIKE-Teilstring auf dem Namen
is_visible true / false wird zu active / inactive übersetzt
is_featured true / false Filter auf is_featured
categories 5 exakte Kategorie-id
price:min 10 price >=
price:max 100 price <=
sort name, -price, -date_created, id führendes - kehrt die Richtung um

Unbekannte Operatoren oder Felder werden stillschweigend ignoriert — genau wie bei BC.


Feld-Mapping (BigCommerce ↔ STOAR) #

Bestellung (v2)

BC-v2-Feld STOAR-Quelle Hinweise
id id numerisch
status_id status (übersetzt) numerischer BC-Code (1, 11, 7, 3, 10, 5, 4) — siehe Statusübersetzung
status status (übersetzt) String-Label („Pending“, „Awaiting Fulfillment“, „Shipped“, …)
customer_id customer_id ?? 0 Gastbestellungen erhalten 0
date_created, date_modified created_at, updated_at RFC-2822-Format (NICHT ISO 8601)
date_shipped updated_at, wenn status='shipped'/'delivered' sonst leerer String
currency_code, default_currency_code currency (in Großbuchstaben) z. B. EUR
currency_exchange_rate immer '1.0000000000' Stoar ist einwährungsfähig
total_inc_tax total_amount NUMERISCHER Float (KEIN String — das ist V3-/WC-Verhalten)
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 erstes nicht archiviertes OrderPayment.gateway
payment_status 'captured', wenn payment_status='succeeded' sonst leer
refunded_amount refunded_amount ?? 0
staff_notes admin_notes
customer_message customer_notes
billing_address billing_info-JSON verschachteltes Objekt — flache Struktur mit den Schlüsseln street_1/street_2
products Unterressource {url, resource}-Zeiger auf /orders/{id}/products
shipping_addresses Unterressource {url, resource}-Zeiger (nicht implementiert)
coupons Unterressource {url, resource}-Zeiger (nicht implementiert)
items_total sum(items.quantity)
items_shipped sum(items.quantity), wenn status='shipped'/'delivered', sonst 0
customer_locale immer 'en' nicht gespeichert
channel_id immer 1 nicht modelliert

Bestellposition line_item (v2 /products)

BC-v2-Feld Stoar-Quelle
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 zuerst die Varianten-SKU, ersatzweise die des Produkts
type immer '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[] ein Element mit dem Variantennamen (sofern nicht Default)
weight, width, height, depth immer 0
is_refunded, quantity_refunded, refund_amount immer false/0 (Stoar verfolgt Erstattungen nur auf Bestellebene)

Katalogprodukt (v3)

BC-v3-Feld STOAR-Quelle Hinweise
id id
name, description, sku direkt übernommen
type immer 'physical' BC kennt zusätzlich 'digital'; Stoar führt nur physische Ware
is_visible status === 'active' bool
availability 'available', wenn aktiv, sonst 'disabled' enum
is_featured is_featured bool
inventory_tracking 'product' für einfache, 'variant' für konfigurierbare Produkte
inventory_level stock (bei konfigurierbaren Produkten Summe der Varianten)
inventory_warning_level low_stock_threshold ?? 0
price price (roh) NUMERISCHER Float
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] Array mit einem einzelnen Int (KEINE verschachtelten Objekte)
base_variant_id id der ersten Variante
images[] image_path + gallery_paths Inline-Array
variants[] inline vollständige Variantenobjekte
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 (v3 nutzt ISO, v2 RFC 2822)
condition immer 'New' nicht modelliert
total_sold, view_count, reviews_rating_sum, reviews_count immer 0 nicht aggregiert
related_products immer [-1] BC-Konvention für „automatisch verwandt“
brand_id immer null Stoar hat kein Markenmodell

Katalogprodukt-Variante (v3)

BC-v3-Feld Stoar-Quelle
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[] immer [] (Stoar-Variantenattribute nutzen ein anderes Modell)

Statusübersetzung #

BigCommerce verwendet NUMERISCHE status_id-Codes plus ein paralleles String-Feld status. Der Übersetzer zerlegt Stoars Enum in beides.

Stoar → BigCommerce (Ausgabe)

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

BigCommerce-Filter → Stoar (Parsing)

?status_id=N wird über dieselbe Nachschlagetabelle übersetzt. Codes ohne Eintrag in der Tabelle (z. B. BC-Status 2 = „Manually Verified“ oder 6 = „Declined“) fallen stillschweigend durch — passend zu BCs Verhalten bei fehlender exakter Entsprechung. Die vollständige Codetabelle des echten BC hat rund 14 Einträge; STOAR stellt die sieben bereit, die sich sauber abbilden lassen.

Produktstatus

BigCommerce hat kein String-Feld status — es nutzt is_visible (bool) plus das availability-Enum. Filtere mit ?is_visible=true nach aktiven und mit ?is_visible=false nach inaktiven Produkten.


Antwortstruktur #

v2-Bestellung — kommentiert

{
  "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,
  "..."
}

v3-Katalogprodukt — gekürzt

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

Praxisbeispiel #

GET /api/v2/orders/10126 gegen die Produktion. Dieselbe Stoar-Bestellung wie in Magento, WooCommerce und Shopify — hier in BC-v2-Struktur gerendert. Personenbezogene Daten anonymisiert.

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

Fallstricke, die Integratoren kennen sollten

Feld Beobachtet Grund
date_created, date_modified RFC-2822-String v2 nutzt gezielt RFC 2822 (Tue, 03 Jun 2025 04:56:43 +0000). v3-Endpunkte nutzen ISO 8601 — die Inkonsistenz stammt von BC, wir bilden sie nach.
payment_method "payid" Stoars Gateway-Key — kein BC-kanonischer Methodenname.
payment_status "captured" bei bezahlten Bestellungen BC hat ein eigenes Statusvokabular; wir bilden succeeded auf captured ab.
total_inc_tax, total_ex_tax usw. Floats (z. B. 936.98) BC v2 gibt Beträge als Floats aus — anders als WooCommerce/Shopify, die Strings mit zwei Nachkommastellen verwenden.
country "United States" Langform, aus ISO-2 über eine kleine Nachschlagetabelle abgeleitet (DE/US/GB/AU/AT/CH). Andere Länder liefern "".
products, shipping_addresses, coupons {url, resource}-Zeiger auf Unterressourcen BC-Konvention für „folge dieser URL, um verwandte Daten zu laden“. /orders/{id}/products ist implementiert, die übrigen sind noch nicht verfügbar.
customer_locale immer "en" nicht am Stoar-Customer gespeichert.
channel_id immer 1 Stoar ist Single-Store; BC unterstützt mehrere Kanäle.
currency_exchange_rate immer "1.0000000000" Stoar ist einwährungsfähig.
staff_notes, customer_message admin_notes, customer_notes BC-Terminologie.
external_*, ebay_order_id, cart_id leer / null / „0“ Stoar hat keine Marktplatzanbindung.

Fehlerstruktur #

BigCommerce verwendet eine Hülle im Stil von 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 verweist immer auf BCs Dokumentationsseite zu den Statuscodes. errors erscheint nur bei Validierungsfehlern (400).

HTTP Auslöser title
400 fehlerhafte Query / Validierung Invalid query parameters. (mit errors-Map)
401 fehlendes oder ungültiges Token Not authenticated.
403 Token mit falscher Ability Insufficient OAuth scope.
404 unbekannte Ressource The {resource} requested could not be found.
422 Vorbedingung nicht erfüllt dynamische Meldung
429 Rate-Limit überschritten Too many requests. (mit den Headern X-Rate-Limit-Time-Reset-Ms und X-Rate-Limit-Requests-Left)
500 unerwarteter Serverfehler Internal Server Error

Rate-Limiting #

Dieselbe per Sanctum-Token gekennzeichnete api-rest-Drosselung, die alle anderen Adapter schützt, schützt auch die BC-Routen. Schwellwert und Hauptschalter konfigurierst du unter /manager/api-settings. Beim Auslösen nutzt die Antwort BCs RFC-7807-Hülle:

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"
}

Die X-Rate-Limit-*-Header entsprechen dem dokumentierten Verhalten von BC. Das echte BC liefert mehr Header und arbeitet mit sekundengenauen Fenstern; STOAR nutzt Laravels Minutenfenster — nah genug für die Kompatibilität mit Client-Bibliotheken.

Ein einzelnes Sanctum-Token, das über alle vier Adapter verwendet wird, teilt sich einen Bucket — die Oberfläche zur Konfiguration ist im Abschnitt Rate-Limiting der Magento-Dokumentation Schritt für Schritt beschrieben.


Siehe auch #

  • app/Api/Adapters/BigCommerce/Support/StatusTranslator.php — bidirektionales Vokabular-Mapping
  • BigCommerce-REST-API-Referenz — die Upstream-Spezifikation, die dieser Adapter nachbildet