Skip to main content

API reference

The plugin registers three Admin API endpoints (route scope api) via PHP attributes in the controller vlp8n\Controller\Api\N8nAPI. They are called by the Administration service vlp8nService, but can also be addressed directly through the authenticated Shopware Admin API.

Endpoints

MethodPathDescription
GET / POST/api/_action/vlp8n/send_productsSend products
GET / POST/api/_action/vlp8n/send_customersSend customers
GET / POST/api/_action/vlp8n/send_ordersSend orders

Parameters

ParameterTypeEndpointsDescription
sales_channel_idstringallID of the sales channel; determines the webhook URL used and the data context
category_idsstring[]send_productsOptional filter on one or more category IDs
sync_countintallCounter passed by the admin service
note

These endpoints belong to the Admin API scope and require valid authentication (an OAuth token of the Shopware Administration). They are not publicly reachable.

Responses

send_products:

{
"success": true,
"total_sync": 128,
"total_products": 128
}

send_customers / send_orders:

{
"success": true,
"total_sync": 42
}

Possible error messages (success: false):

msgMeaning
no_webhook_urlNo webhook URL is configured for the action
no_products_foundNo products found for the selection

Webhook call

The plugin sends the payload via HTTP POST to the configured URL:

POST <webhook-url>
Content-Type: application/json

Sending is considered successful if n8n responds with an HTTP status 2xx and no cURL error occurs. The body is an array of objects in each case.

Payload: products

[
{
"id": "0190a1...",
"number": "SW10001",
"name": "Example product",
"description": "Product description …",
"stock": 25,
"priceNet": 41.18,
"priceGross": 49.0,
"purchasePrice": 30.0,
"prices": { "eur": 49.0, "usd": 53.9 },
"coverUrl": "https://shop.example.com/media/…/cover.jpg",
"url": "https://shop.example.com/example-product",
"categories": ["Category A", "Category B"],
"options": ["Size: L", "Color: Blue"],
"customFields": { "my_field": "value" }
}
]
  • prices contains the gross price per currency of the sales channel (key = lowercase ISO code).
  • customFields keys are sanitized (see below).

Payload: customers

[
{
"salesChannel": "Storefront",
"salesChannelId": "0190a1...",
"language": "German",
"languageLocale": "de-DE",
"orderCount": 3,
"orderTotalAmount": 247.5,
"affiliateCode": "",
"campaignCode": "",
"customFields": { "my_field": "value" }
}
]

(additionally includes, among other things, master data and the customer's default billing address.)

Payload: orders

[
{
"id": "0190a1...",
"orderNumber": "10025",
"amountTotal": 119.9,
"currency": "EUR",
"salesChannel": "Storefront",
"closedate": "2026-05-31T10:15:00+00:00",
"lineItems": [
{ "label": "Example product", "quantity": 2, "unitPrice": 49.0 }
],
"customFields": { "my_field": "value" }
}
]

For each order the customer including the default billing address (street, city, zip, country) is also included.

Sanitizing custom field keys

To make custom field keys valid JSON/object keys, they are normalized by sanitizeCustomFieldKey():

  • German umlauts are replaced: ä→ae, ö→oe, ü→ue, ß→ss (including uppercase).
  • Other accented characters are transliterated to ASCII.
  • Any character other than A–Z, a–z, 0–9 and _ becomes _.
  • Multiple _ are collapsed, leading/trailing _ removed.
  • If the result is empty, custom_field is used.

➡️ If you run into problems, see Troubleshooting.