Magento-REST-API-Adapter
Drop-in-kompatibel zu Magento 2
Zuletzt aktualisiert: 5. September 2026
Eine Drop-in-kompatible REST API für STOAR, die das Wire-Format von Magento 2 nachbildet — gleiche URL-Pfade, gleiche searchCriteria[…]-Abfragesyntax, gleiche Feldnamen in der Antwort, gleicher Auth-Ablauf. Bestehende Magento-Client-Bibliotheken sprechen ohne Änderung mit STOAR.
Der Adapter ist die erste Implementierung eines erweiterbaren API-Adapter-Frameworks: Dieselben Daten werden in unterschiedlichen Hersteller-Ausprägungen bereitgestellt (Magento jetzt, Shopify / WooCommerce / eigene Adapter später), ohne die Bestell-Geschäftslogik zu duplizieren.
Inhaltsverzeichnis #
- Schnellstart
- Authentifizierung
- Endpunkte
- Syntax der Search-Criteria-Abfragen
- Feld-Mapping (Magento ↔ STOAR)
- Antwortstruktur
- Praxisbeispiel
- Fehlerstruktur
Schnellstart #
# 1. Get an admin token
TOKEN=$(curl -s -X POST https://app.stoar.ai/rest/V1/integration/admin/token \
-H 'Content-Type: application/json' \
-d '{"username":"[email protected]","password":"your-password"}' \
| tr -d '"')
# 2. List the most recent 5 orders
curl -s "https://app.stoar.ai/rest/V1/orders?searchCriteria[pageSize]=5" \
-H "Authorization: Bearer $TOKEN" \
| jq '.items[] | {entity_id, increment_id, status, grand_total}'
# 3. Fetch a single order
curl -s "https://app.stoar.ai/rest/V1/orders/123" \
-H "Authorization: Bearer $TOKEN" \
| jq
Authentifizierung #
Intern nutzt der Adapter persönliche Zugriffstokens von Laravel Sanctum, nach außen folgt der Ablauf jedoch exakt dem Magento-Kontrakt: Zugangsdaten per POST senden, eine Token-Zeichenkette erhalten, diese als Authorization: Bearer … mitschicken.
| Token-Typ | Endpunkt | TTL | Ability | Einsatzzweck |
|---|---|---|---|---|
| Admin | POST /rest/V1/integration/admin/token |
4 h | magento:admin |
Backend-Operationen (Bestellungen auflisten, erstatten, stornieren) |
| Kunde | POST /rest/V1/integration/customer/token |
1 h | magento:customer |
Storefront-Integrationen |
Alle /rest/V1/orders/*-Endpunkte erfordern magento:admin. Ein Kunden-Token liefert an diesen Endpunkten 403.
Token-Format
Ein erfolgreicher Token-Endpunkt gibt das rohe Token als JSON-quotierten Skalar zurück — exakt der Magento-Kontrakt:
HTTP/1.1 200 OK
Content-Type: application/json
"abc123def456…"
Verwende es in nachfolgenden Anfragen:
Authorization: Bearer abc123def456…
Tokens liegen in personal_access_tokens (Sanctums Standardtabelle) und lassen sich jederzeit widerrufen, indem du die entsprechende Zeile löschst oder im Code $user->tokens()->delete() aufrufst.
Endpunkte #
Alle Pfade sind relativ zu /rest/V1 (wortgleiches Magento-Präfix).
POST /rest/V1/integration/admin/token
Stellt ein Admin-Token aus admin_users-Zugangsdaten aus. Der Benutzername wird gegen die Spalte email oder name geprüft.
Anfrage
POST /rest/V1/integration/admin/token
Content-Type: application/json
{ "username": "[email protected]", "password": "secret" }
Antwort (200)
"3|EsTmpYnjA…"
Fehler
400— ungültige Zugangsdaten, inaktiver Benutzer oder fehlende Felder
POST /rest/V1/integration/customer/token
Stellt ein Kunden-Token aus stoar_shop_customers-Zugangsdaten aus. Der Benutzername ist die E-Mail-Adresse.
Anfrage
POST /rest/V1/integration/customer/token
Content-Type: application/json
{ "username": "[email protected]", "password": "secret" }
Antwort (200) — gleiche Struktur wie beim Admin-Token.
Fehler
400— ungültige E-Mail/Passwort, inaktiver Kunde, fehlende Felder
GET /rest/V1/orders
Listet Bestellungen mit voller Unterstützung für Magentos searchCriteria[…]-Abfragen — siehe Syntax der Search-Criteria-Abfragen weiter unten.
Authorization: Bearer-Admin-Token.
Antwort (200)
{
"items": [
{ /* full order object — see Response shape */ }
],
"search_criteria": {
"filter_groups": [...],
"sort_orders": [...],
"page_size": 20,
"current_page": 1
},
"total_count": 150
}
Standardwerte
pageSizesteht standardmäßig auf 20, begrenzt auf 500currentPagesteht standardmäßig auf 1- Keine Filter → alle Bestellungen, neueste zuerst (sortiert nach
id DESC)
GET /rest/V1/orders/{id}
Ruft eine einzelne Bestellung mit allen Relationen ab: Positionen, Zahlungen, Statusverläufe, Rechnungs- und Lieferadresse.
Authorization: Bearer-Admin-Token.
Antwort (200) — siehe Antwortstruktur.
Fehler
404—{ "message": "No such entity with %fieldName = %fieldValue", "parameters": ["entity_id", "99999"] }
POST /rest/V1/orders/{id}/cancel
Storniert eine offene oder bezahlte Bestellung. Löst denselben Ablauf aus wie die Admin-Oberfläche: setzt den Status auf cancelled, schreibt eine Statusverlaufs-Zeile und gibt Bestandsreservierungen frei (sofern die Bestellung eine session_id besitzt).
Authorization: Bearer-Admin-Token.
Anfrage: leerer Body.
Antwort (200) — true
Fehler
404— unbekannte Bestell-ID422— Bestellung befindet sich in einem Status, der keine Stornierung erlaubt (z. B.delivered,refunded)
GET /rest/V1/orders/{id}/comments
Listet den Statusverlauf der Bestellung auf (Magento nennt diese Einträge „Comments“).
Authorization: Bearer-Admin-Token.
Antwort (200)
{
"items": [
{
"entity_id": 42,
"parent_id": 123,
"comment": "Payment confirmed",
"status": "paid",
"created_at": "2026-04-10T12:00:00+00:00",
"is_customer_notified": false,
"is_visible_on_front": false,
"extension_attributes": { "old_status": "pending", "changed_by": "system" }
}
],
"search_criteria": { "filter_groups": [], "sort_orders": [], "page_size": 1, "current_page": 1 },
"total_count": 1
}
POST /rest/V1/orders/{id}/comments
Hängt einen Statusverlaufs-Kommentar an, ohne den Bestellstatus zu ändern.
Authorization: Bearer-Admin-Token.
Anfrage
{
"statusHistory": {
"comment": "Customer phoned to confirm delivery slot",
"is_customer_notified": false,
"is_visible_on_front": false
}
}
statusHistory.status ist optional — fehlt es, bleibt der bestehende Bestellstatus erhalten.
Antwort (200) — true
Fehler
400—statusHistory.commentfehlt404— unbekannte Bestell-ID
POST /rest/V1/order/{id}/refund
Hinweis — Magento verwendet die Singularform
/order/, NICHT/orders/. Der Adapter bildet das exakt nach.
Erstellt eine Rückerstattung. STOAR delegiert an das bestehende Order::processRefund(), das Stripe über StripeService::processRefund() aufruft. Die Bestellung wird auf refunded gesetzt (Vollerstattung) oder bleibt im aktuellen bezahlten Status, wobei refunded_amount aufsummiert wird (Teilerstattung).
Authorization: Bearer-Admin-Token.
Anfrage — Vollerstattung (Body oder arguments weglassen):
{}
Anfrage — expliziter Betrag:
{ "arguments": { "amount": 50.00 } }
Anfrage — positionsweise (Magento-Stil):
{
"items": [
{ "order_item_id": 456, "qty": 1 },
{ "order_item_id": 457, "qty": 2 }
]
}
Wird items[] übergeben, berechnet sich der Erstattungsbetrag aus dem gespeicherten price * qty jeder Position. Ein angegebenes arguments.amount überschreibt diese Berechnung.
Antwort (200) — Credit-Memo-ID (Integer). STOAR kennt keine eigene Credit-Memo-Entität, daher wird ersatzweise die Bestell-ID zurückgegeben.
Fehler
404— unbekannte Bestell-ID422— Bestellung ist nicht erstattungsfähig (kein Stripe Payment Intent, Status nicht paid/processing/shipped/delivered)
Syntax der Search-Criteria-Abfragen #
Der Endpunkt GET /rest/V1/orders akzeptiert die vollständige Magento-Search-Criteria-Grammatik.
Aufbau
searchCriteria[filter_groups][N][filters][M][field|value|condition_type]
searchCriteria[sortOrders][N][field|direction]
searchCriteria[pageSize]
searchCriteria[currentPage]
Filterlogik
- Filter innerhalb derselben
filter_groups[N]werden mit OR verknüpft - Verschiedene
filter_groups[N]werden mit AND verknüpft
Beispiel — Bestellungen mit status paid ODER shipped UND einer customer_email, die @example.com enthält:
GET /rest/V1/orders
?searchCriteria[filter_groups][0][filters][0][field]=status
&searchCriteria[filter_groups][0][filters][0][value]=paid
&searchCriteria[filter_groups][0][filters][0][condition_type]=eq
&searchCriteria[filter_groups][0][filters][1][field]=status
&searchCriteria[filter_groups][0][filters][1][value]=shipped
&searchCriteria[filter_groups][0][filters][1][condition_type]=eq
&searchCriteria[filter_groups][1][filters][0][field]=customer_email
&searchCriteria[filter_groups][1][filters][0][value]=%[email protected]
&searchCriteria[filter_groups][1][filters][0][condition_type]=like
Unterstützte Operatoren
condition_type |
Bedeutung | Beispiel |
|---|---|---|
eq |
gleich | value=paid&condition_type=eq |
neq |
ungleich | value=cancelled&condition_type=neq |
gt |
größer als | value=100&condition_type=gt |
gteq |
≥ | value=2026-01-01&condition_type=gteq |
lt |
kleiner als | |
lteq |
≤ | |
from |
Bereichsanfang (Alias für gteq) |
|
to |
Bereichsende (Alias für lteq) |
|
like |
SQL LIKE; die %-Platzhalter lieferst du selbst |
value=%25%40example.com&condition_type=like |
in |
kommagetrennte Liste | value=paid,shipped,delivered&condition_type=in |
nin |
NOT IN | |
null |
IS NULL | (kein value nötig) |
notnull |
IS NOT NULL | |
finset |
Teilstring-Abgleich nach bestem Bemühen |
Nicht unterstützte Operatoren oder unbekannte Felder → 400 mit erläuternder message.
Sortierung
searchCriteria[sortOrders][0][field]=created_at
searchCriteria[sortOrders][0][direction]=DESC
searchCriteria[sortOrders][1][field]=grand_total
searchCriteria[sortOrders][1][direction]=ASC
direction akzeptiert ASC oder DESC (Standard ASC). Mehrere Sortierungen wirken von links nach rechts.
Pagination
searchCriteria[pageSize]=25 # max 500
searchCriteria[currentPage]=2 # 1-indexed
Die Antwort spiegelt die tatsächlich angewendeten Werte zurück:
"search_criteria": { "page_size": 25, "current_page": 2 }
Feld-Mapping (Magento ↔ STOAR) #
Der Adapter stellt ausschließlich Magento-Feldnamen bereit. Intern verweist jeder Name auf eine STOAR-Spalte oder einen berechneten Wert. Felder, die nicht in dieser Liste stehen, lassen sich weder in filter_groups noch in sortOrders verwenden — der Versuch führt zu 400.
Filter- und sortierbar
| Magento-Feld | STOAR-Quelle | Hinweise |
|---|---|---|
entity_id |
id |
|
increment_id |
id |
beim Filtern numerisch behandelt (das Präfix ORD- dient nur der Darstellung) |
status |
status |
|
state |
status |
STOAR führt Magentos state in status zusammen |
customer_id |
customer_id |
|
customer_email |
customer_email |
|
customer_firstname |
customer_info->first_name |
über MariaDB JSON_EXTRACT aufgelöst |
customer_lastname |
customer_info->last_name |
ebenso |
grand_total |
total_amount |
|
subtotal |
subtotal |
|
tax_amount |
tax_amount |
|
shipping_amount |
shipping_amount |
|
discount_amount |
discount_amount |
|
coupon_code |
coupon_code |
|
currency_code |
currency |
|
order_currency_code |
currency |
|
created_at |
created_at |
|
updated_at |
updated_at |
Nur in der Antwort (Lesefelder)
Diese Felder erscheinen in der JSON-Antwort, taugen aber nicht als Filter- oder Sortierfelder:
total_paid,total_refunded— abgeleitet ausOrderPayment-Zeilen +refunded_amountcustomer_is_guest—customer_id === nullitems[],billing_address,shipping_address,payment,status_histories[]- Alle
base_*-Summen — STOAR ist einwährungsfähig, daher giltbase_grand_total === grand_total
Ableitung des state
STOAR status |
Magento state |
|---|---|
pending |
new |
paid, processing, shipped, delivered |
processing |
cancelled |
canceled |
refunded |
closed |
Antwortstruktur #
Eine vollständige Bestellantwort (der Kürze halber gekürzt):
{
"entity_id": 123,
"increment_id": "ORD-000123",
"state": "processing",
"status": "paid",
"customer_id": 45,
"customer_email": "[email protected]",
"customer_firstname": "Jane",
"customer_lastname": "Doe",
"customer_group_id": 0,
"customer_is_guest": false,
"base_currency_code": "EUR",
"currency_code": "EUR",
"order_currency_code": "EUR",
"grand_total": 115.0,
"base_grand_total": 115.0,
"subtotal": 100.0,
"base_subtotal": 100.0,
"tax_amount": 10.0,
"base_tax_amount": 10.0,
"shipping_amount": 5.0,
"base_shipping_amount": 5.0,
"discount_amount": 0.0,
"base_discount_amount": 0.0,
"total_paid": 115.0,
"total_refunded": 0.0,
"base_total_paid": 115.0,
"base_total_refunded": 0.0,
"shipping_description": "Standard",
"shipping_incl_tax": 5.0,
"base_shipping_incl_tax":5.0,
"created_at": "2026-04-10T09:00:00+00:00",
"updated_at": "2026-04-10T09:30:00+00:00",
"is_virtual": false,
"weight": 0,
"store_id": 1,
"coupon_code": null,
"items": [
{
"item_id": 456,
"order_id": 123,
"product_id": 789,
"product_type": "simple",
"sku": "WID-1-A",
"name": "Widget",
"qty_ordered": 2.0,
"qty_invoiced": 0.0,
"qty_shipped": 0.0,
"qty_refunded": 0.0,
"qty_canceled": 0.0,
"price": 50.0,
"base_price": 50.0,
"price_incl_tax": 55.0,
"row_total": 100.0,
"row_total_incl_tax":110.0,
"tax_amount": 10.0,
"tax_percent": 10.0,
"discount_amount": 0,
"extension_attributes": { "variant_id": 12 }
}
],
"billing_address": {
"entity_id": null,
"parent_id": 123,
"address_type": "billing",
"email": "[email protected]",
"firstname": "Jane",
"lastname": "Doe",
"street": "1 Test St",
"city": "Berlin",
"country_id": "DE",
"postcode": "10115",
"region": null,
"telephone": "+49…"
},
"shipping_address": { /* same shape, address_type="shipping" */ },
"payment": {
"entity_id": null,
"parent_id": 123,
"method": "stripe",
"base_amount_paid": 115.0,
"base_amount_refunded": 0.0,
"cc_trans_id": "pi_test_…",
"extension_attributes": {
"payments": [
{ "id": 1, "gateway": "stripe", "amount": 115.0, "currency": "eur",
"status": "succeeded", "reference": "pi_test_…", "archived_at": null,
"created_at": "2026-04-10T09:05:00+00:00" }
]
}
},
"status_histories": [
{
"entity_id": 1,
"parent_id": 123,
"comment": null,
"status": "pending",
"created_at": "2026-04-10T09:00:00+00:00",
"extension_attributes": { "old_status": null, "changed_by": "System" }
},
{
"entity_id": 2,
"parent_id": 123,
"comment": "Payment confirmed via webhook",
"status": "paid",
"created_at": "2026-04-10T09:05:00+00:00",
"extension_attributes": { "old_status": "pending", "changed_by": "System" }
}
],
"extension_attributes": {
"lookup_token": "abc…",
"tracking_number": null,
"tracking_url": null,
"tracking_carrier": null,
"shipment_status": null,
"admin_notes": null,
"customer_notes": null
}
}
Praxisbeispiel #
Nachfolgend eine echte Antwort aus der Produktion für GET /rest/V1/orders/10126 — eine bezahlte Bestellung über USD $936.98 mit zwei einfachen Produktpositionen. Personenbezogene Daten (E-Mail, Telefon, Lookup-Token, exakte Straßenadresse) wurden anonymisiert; alles andere ist wortgetreu.
Anfrage
GET /rest/V1/orders/10126
Authorization: Bearer 1|vYuVLH4wvkSFfhwAVHGhzVMkOVbKkw8S5gKjVU5o9212c81b
Antwort (200)
{
"entity_id": 10126,
"increment_id": "ORD-010126",
"state": "processing",
"status": "paid",
"customer_id": 5794,
"customer_email": "[email protected]",
"customer_firstname": "Jane",
"customer_lastname": "Doe",
"customer_group_id": 0,
"customer_is_guest": false,
"base_currency_code": "USD",
"currency_code": "USD",
"order_currency_code": "USD",
"grand_total": 936.98,
"base_grand_total": 936.98,
"subtotal": 936.98,
"base_subtotal": 936.98,
"tax_amount": 0,
"base_tax_amount": 0,
"shipping_amount": 0,
"base_shipping_amount": 0,
"discount_amount": 0,
"base_discount_amount": 0,
"total_paid": 0,
"total_refunded": 0,
"base_total_paid": 0,
"base_total_refunded": 0,
"shipping_description": "Free Shipping",
"shipping_incl_tax": 0,
"base_shipping_incl_tax":0,
"created_at": "2025-06-03T04:56:43+00:00",
"updated_at": "2025-06-03T04:56:43+00:00",
"is_virtual": false,
"weight": 0,
"store_id": 1,
"coupon_code": null,
"items": [
{
"item_id": 30219,
"order_id": 10126,
"product_id": 112238,
"product_type": "simple",
"sku": "RELOOP_TERMINALMIX8_025-DEF",
"name": "Reloop Terminal Mix 8",
"qty_ordered": 3,
"qty_invoiced": 0,
"qty_shipped": 0,
"qty_refunded": 0,
"qty_canceled": 0,
"price": 299,
"base_price": 299,
"price_incl_tax": 299,
"base_price_incl_tax": 299,
"original_price": 299,
"base_original_price": 299,
"row_total": 897,
"base_row_total": 897,
"row_total_incl_tax": 897,
"base_row_total_incl_tax":897,
"discount_amount": 0,
"base_discount_amount": 0,
"discount_percent": 0,
"tax_amount": 0,
"base_tax_amount": 0,
"tax_percent": 0,
"amount_refunded": 0,
"base_amount_refunded": 0,
"row_weight": 0,
"created_at": "2025-06-03T04:56:43+00:00",
"updated_at": "2025-06-03T04:56:43+00:00",
"is_qty_decimal": false,
"no_discount": false,
"parent_item_id": null,
"extension_attributes": { "variant_id": 95589 }
},
{
"item_id": 30220,
"order_id": 10126,
"product_id": 51706,
"product_type": "simple",
"sku": "SK8-SOCK-027-DEF",
"name": "Premium Skateboard Socks",
"qty_ordered": 2,
"qty_invoiced": 0,
"qty_shipped": 0,
"qty_refunded": 0,
"qty_canceled": 0,
"price": 19.99,
"base_price": 19.99,
"price_incl_tax": 19.99,
"base_price_incl_tax": 19.99,
"original_price": 19.99,
"base_original_price": 19.99,
"row_total": 39.98,
"base_row_total": 39.98,
"row_total_incl_tax": 39.98,
"base_row_total_incl_tax":39.98,
"discount_amount": 0,
"base_discount_amount": 0,
"discount_percent": 0,
"tax_amount": 0,
"base_tax_amount": 0,
"tax_percent": 0,
"amount_refunded": 0,
"base_amount_refunded": 0,
"row_weight": 0,
"created_at": "2025-06-03T04:56:43+00:00",
"updated_at": "2025-06-03T04:56:43+00:00",
"is_qty_decimal": false,
"no_discount": false,
"parent_item_id": null,
"extension_attributes": { "variant_id": 33857 }
}
],
"billing_address": {
"entity_id": null,
"parent_id": 10126,
"address_type": "billing",
"email": null,
"firstname": "Jane",
"lastname": "Doe",
"middlename": null,
"prefix": null,
"suffix": null,
"street": "1 Example Street",
"city": "Phoenix",
"country_id": "US",
"postcode": "85001",
"region": "AZ",
"region_code": "AZ",
"region_id": null,
"telephone": "+1-555-0100",
"fax": null,
"company": null,
"customer_address_id": null
},
"shipping_address": {
"entity_id": null,
"parent_id": 10126,
"address_type": "shipping",
"email": null,
"firstname": "Jane",
"lastname": "Doe",
"middlename": null,
"prefix": null,
"suffix": null,
"street": "1 Example Street",
"city": "Phoenix",
"country_id": "US",
"postcode": "85001",
"region": "AZ",
"region_code": "AZ",
"region_id": null,
"telephone": "+1-555-0100",
"fax": null,
"company": null,
"customer_address_id": null
},
"payment": {
"entity_id": null,
"parent_id": 10126,
"base_amount_authorized": 936.98,
"base_amount_paid": 0,
"base_amount_refunded": 0,
"base_shipping_amount": 0,
"base_shipping_captured": 0,
"base_shipping_refunded": 0,
"billing_address_id": null,
"cc_avs_status": null,
"cc_cid_status": null,
"cc_exp_month": null,
"cc_exp_year": null,
"cc_last4": null,
"cc_number_enc": null,
"cc_owner": null,
"cc_status": null,
"cc_status_description": null,
"cc_trans_id": null,
"created_at": null,
"updated_at": null,
"method": "payid",
"po_number": null,
"protection_eligibility": null,
"quote_payment_id": null,
"extension_attributes": { "payments": [] }
},
"status_histories": [],
"extension_attributes": {
"lookup_token": "REDACTED-FOR-DOCS",
"tracking_number": null,
"tracking_url": null,
"tracking_carrier": null,
"shipment_status": null,
"admin_notes": null,
"customer_notes": null
}
}
Was dieses Beispiel über den Kontrakt aussagt
Einige Punkte dieser echten Antwort verdienen Beachtung, weil sie Integratoren überraschen können:
| Feld | Beobachtet | Warum es „falsch“ wirken kann |
|---|---|---|
total_paid, payment.base_amount_paid |
0 |
Der status der Bestellung lautet paid, ihr OrderPayment-Audit-Log ist jedoch leer. Der Adapter berechnet total_paid als Summe der nicht archivierten, erfolgreichen OrderPayment-Zeilen — er leitet den Zahlbetrag nicht allein aus dem Bestellstatus ab. Bestellungen aus der Zeit vor dem Zahlungs-Audit liefern hier 0, obwohl sie bezahlt sind. |
payment.method |
"payid" |
Das ist der STOAR-Gateway-Key, kein Magento-kanonischer Methodenname. Mögliche Werte sind unter anderem stripe, bank_transfer, cash_on_delivery, payid, invoice sowie jedes über GatewayRegistry registrierte eigene Gateway. |
status_histories |
[] |
Statuslogs kamen erst nach der Anlage einiger Altbestellungen hinzu, ältere Bestellungen liefern daher ein leeres Array. Neu angelegte Bestellungen haben immer mindestens einen Eintrag (den initialen Status pending). |
qty_invoiced, qty_shipped, qty_refunded, qty_canceled |
0 für alle Positionen |
STOAR kennt keine eigenen Invoice-/Shipment-Entitäten, daher werden positionsbezogene Fulfilment-Zähler stets als 0 gemeldet. Verwende stattdessen die Felder total_refunded und status auf Bestellebene. |
coupon_code |
null |
Nur gefüllt, wenn die Bestellung mit einem Rabattcode aufgegeben wurde. Ohne Bezug zu Rabatten aus Warenkorbregeln. |
customer_id + customer_is_guest: false |
beide gefüllt | Wenn die Bestellung von einem angemeldeten Kunden aufgegeben wurde. Gastbestellungen liefern customer_id: null und customer_is_guest: true. |
weight |
0 |
STOAR erfasst kein Gewicht je Bestellung; das Feld existiert nur zur Kompatibilität mit Magento-Clients. |
store_id |
1 |
STOAR ist Single-Store; dieses Feld ist immer 1. |
extension_attributes.lookup_token |
geschwärzt | Das ist STOARs „Magic-Link“-Token je Bestellung für die Bestellstatus-Seiten von Gästen. Gib es niemals in Client-Code oder öffentlichen Logs preis — der Besitz des Tokens genügt, um die Bestellung ohne Authentifizierung einzusehen. |
Fehlerstruktur #
Jeder /rest/V1/*-Fehler folgt dem Magento-Envelope:
{
"message": "Human message with %fieldName placeholders",
"parameters": ["fieldName", "fieldValue"],
"trace": "…stack trace…"
}
parameters korrespondiert mit den Platzhaltern %1, %2 oder %fieldName in message, sodass lokalisierte Clients Werte einsetzen können.
trace ist nur enthalten, wenn APP_DEBUG=true gesetzt ist.
| HTTP | Auslöser | Beispiel |
|---|---|---|
| 400 | fehlerhafte Eingabe — unbekanntes Filterfeld, nicht unterstützter condition_type, Validierungsfehler |
{ "message": "Unsupported condition_type: zorp" } |
| 401 | fehlendes oder ungültiges Token | { "message": "Consumer is not authorized to access %resources", "parameters": ["Magento_Sales::sales"] } |
| 403 | Token mit falscher Ability (z. B. Kunden-Token an einem Admin-Endpunkt) | { "message": "The consumer does not have access to the requested resource." } |
| 404 | unbekannte Bestell-ID | { "message": "No such entity with %fieldName = %fieldValue", "parameters": ["entity_id", "99999"] } |
| 422 | Vorbedingung verletzt (nicht stornierbare Stornierung, nicht erstattungsfähige Erstattung) | { "message": "Order 5 cannot be cancelled in status 'delivered'." } |
| 500 | unerwarteter Serverfehler | { "message": "Internal server error." } (im Debug-Modus erscheint die echte Meldung) |
Siehe auch #
- Adobe-Commerce-REST-Referenz — die Upstream-Spezifikation, die dieser Adapter nachbildet