Remote HTTP Provider
Detailed reference for the primary integration pattern.
The Plugin HTTP Contract
Three HTTP communication paths:
Path A: External Service → ThreeU (Inbound Webhook)
Your service sends events to ThreeU when something happens.
Path B: Dashboard/POS → ThreeU → Plugin (Gateway)
A user triggers an action that ThreeU forwards to your service.
Path C: ThreeU → Remote Plugin (Outbound Action)
ThreeU calls your service directly for automated actions.
Path A: Inbound Webhook
POST /api/plugins/{id}/webhook
- Public route — no auth:sanctum required
- Protected by signature verification
- Protected by throttle:webhook
- Plugin resolved by path
id - Brand resolved by
brand_idbody orX-Brand-IDheader - Signature in
X-Plugin-Signatureheader - Secret is per-install
brand_plugins.webhook_secret
Inbound Webhook — Node.js
TypeScript
const crypto = require('crypto');
const payload = JSON.stringify({
event: "shipment.delivered",
brand_id: 123,
data: { shipment_id: "shp_abc123" }
});
const timestamp = Math.floor(Date.now() / 1000);
const signature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(timestamp + '.' + payload)
.digest('hex');
await fetch('https://api.threeu.app/api/plugins/42/webhook', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Plugin-Signature': `sha256=${signature}`,
'X-Plugin-Timestamp': String(timestamp),
'X-Brand-ID': '123'
},
body: payload
});Path B: Gateway Action
{GET|POST|PUT|DELETE} /api/plugins/{idOrSlug}/gateway/{action}
- Authenticated (requires auth:sanctum)
- Uses
plugin.accessmiddleware - Checks brand permissions and enabled actions
- Used for manual/on-demand actions
Path C: Outbound Action
Handled by RemoteHttpProvider::onAction() internally:
- Uses
manifest.provider.base_url+ actionpath - Signs requests with HMAC-SHA256
- Configurable timeouts per action
- Logs delivery status
- Parses and returns response
Handling Outbound Actions
TypeScript
// Your service receives:
app.post('/actions/shipping/get-rates', (req, res) => {
verifyThreeUSignature(req);
const { order, destination } = req.body;
const rates = calculateShippingRates(order, destination);
res.json({ success: true, rates });
});