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
| Method | Path | Description |
|---|---|---|
GET / POST | /api/_action/vlp8n/send_products | Send products |
GET / POST | /api/_action/vlp8n/send_customers | Send customers |
GET / POST | /api/_action/vlp8n/send_orders | Send orders |
Parameters
| Parameter | Type | Endpoints | Description |
|---|---|---|---|
sales_channel_id | string | all | ID of the sales channel; determines the webhook URL used and the data context |
category_ids | string[] | send_products | Optional filter on one or more category IDs |
sync_count | int | all | Counter passed by the admin service |
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):
msg | Meaning |
|---|---|
no_webhook_url | No webhook URL is configured for the action |
no_products_found | No 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" }
}
]
pricescontains the gross price per currency of the sales channel (key = lowercase ISO code).customFieldskeys 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–9and_becomes_. - Multiple
_are collapsed, leading/trailing_removed. - If the result is empty,
custom_fieldis used.
➡️ If you run into problems, see Troubleshooting.