Appearance
HTTP endpoints & webhooks
For developers
The plugin's own routes. Everything else — the shipping method, orders, tracking codes — uses Shopware's standard APIs.
POST /kmh-shipbubble/webhook/{salesChannelId}
Receives Shipbubble's webhooks. Storefront scope, no login. {salesChannelId} is a sales channel ID (32 hex characters) or default for the All Sales Channels settings. The configuration page shows the exact URL to paste into the Shipbubble dashboard (Settings → API keys & webhooks, test and live URL).
Authentication: header x-ship-signature must be the HMAC-SHA512 (hex) of the raw request body, keyed with the scope's sandbox or live API key. There is no separate webhook secret.
| Response | Body | Meaning |
|---|---|---|
200 | {"status":"accepted"} | Stored and queued for processing |
200 | {"status":"duplicate"} | The same body was received before; acknowledged, not processed again |
400 | {"status":"invalid_payload"} | Not a Shipbubble event body |
401 | {"status":"invalid_signature"} | Signature missing or wrong; nothing stored |
Processing happens in the message queue (ShipbubbleWebhookMessage), so the response doesn't wait for it. The new status is taken from the last entry of the body's package_status list. See Webhook processing.
The domain in the URL must be configured on a Shopware sales channel; otherwise Shopware answers 400 before the plugin sees the request.
Admin API
All under /api/_action/kmh-shipbubble/, authenticated like any Admin API call. The routes return 200 with "success": false, a reason and Shipbubble's message when Shipbubble refuses a request.
Shipments
| Route | ACL | Does |
|---|---|---|
POST shipment/{shipmentId}/create | kmh_shipbubble_shipment:update | Books the shipment. Body {"confirmed": true} books a re-quote the merchant was just shown. |
POST shipment/{shipmentId}/refresh | kmh_shipbubble_shipment:update | Reads the label from Shipbubble and applies its status. |
POST shipment/{shipmentId}/cancel | kmh_shipbubble_shipment:update | Asks Shipbubble to cancel. |
{shipmentId} is the ID of a kmh_shipbubble_shipment row. create returns:
json
{
"success": true,
"booked": false,
"oldCarrierPrice": 8467.0,
"newCarrierPrice": 8600.0,
"courierName": "Bubble Express",
"currency": "NGN"
}booked: false with both prices means a new price must be confirmed: call create again with {"confirmed": true} within 15 minutes.
Read shipments with the standard entity API, e.g. POST /api/search/kmh-shipbubble-shipment filtered by orderId (requires kmh_shipbubble_shipment:read), or load order.deliveries.kmhShipbubbleShipment.
Settings page
| Route | ACL | Returns |
|---|---|---|
POST test-connection | system_config:update | balance, currency of the Shipbubble wallet |
POST validate-sender | system_config:update | formattedAddress; stores the sender address code for the active mode |
GET couriers | system_config:read | options for Couriers offered at checkout |
GET package-categories | system_config:read | options for Package category |
GET products-without-weight | product:read | count of active products without a weight |
GET webhook-status | system_config:read | lastReceivedAt of the last webhook |
The first four take an optional salesChannelId to use that sales channel's settings.