Subscribing
Create a subscription with a POST to /webhooks. You provide a target URL (must be HTTPS), an array of event types, and an optional description. We return a subscription ID and a signing secret. The signing secret is shown once — store it before the response window closes.
curl -X POST https://api.suiteprofit.org/v1/webhooks \
-H "Authorization: Bearer rp_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://ops.hotel-marszalkowska.pl/webhooks/suiteprofit",
"events": ["rate.suggested", "invoice.issued"],
"description": "Ops pipeline v2"
}' Event types
| Event | Description |
|---|---|
rate.suggested | Autopricer has a new rate suggestion pending approval. |
rate.approved | A rate suggestion was approved and pushed to Profitroom Booking Engine. |
rate.rejected | A rate suggestion was rejected. |
review.drafted | Reviews Aggregator has drafted a reply to a new review. |
review.published | A review reply was published to the source platform. |
whatsapp.received | A guest replied to a WhatsApp Concierge message. |
whatsapp.sent | A WhatsApp Concierge template was successfully delivered. |
invoice.issued | A KSeF invoice was issued for a completed reservation. |
invoice.corrected | A correcting invoice (faktura korygująca) was issued. |
connection.d_edge.failed | A Profitroom API call failed authentication or hit an unexpected error. |
Payload shape
Every payload is JSON. The top-level envelope is stable across event types:
{
"id": "evt_2b7d1c8a19f4",
"type": "rate.suggested",
"created_at": "2026-07-28T09:12:44Z",
"delivery_id": "del_a92c81",
"property_id": "prop_1489",
"data": {
"suggestion_id": "rsg_87542",
"room_type_code": "STDD",
"date": "2026-08-14",
"current_rate": { "currency": "EUR", "minor_units": 12000 },
"proposed_rate": { "currency": "EUR", "minor_units": 13400 },
"trigger": "pace_ahead_15pct"
}
} HMAC signature
We sign every delivery with HMAC-SHA256 over the raw request body, using the subscription's signing secret. The signature is sent in X-Suiteprofit-Signature as a hex string. Verify by recomputing HMAC on the raw body — not the parsed JSON — and comparing constant-time.
// Node example
const crypto = require('crypto');
const expected = crypto
.createHmac('sha256', process.env.RP_WEBHOOK_SECRET)
.update(rawBody)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sigHeader))) {
return res.status(401).end();
} Delivery guarantees
At-least-once. We consider a delivery successful when your endpoint returns HTTP 2xx within 15 seconds. Anything else — timeout, non-2xx, connection refused — is a failure and we retry.
Retry policy
Failed deliveries retry with exponential backoff over 72 hours: at 1 min, 5 min, 15 min, 1h, 4h, 12h, 24h, 48h, 72h. After 72 hours we mark the event dead-lettered. You can inspect and manually retry dead-lettered events in the Suite Profit dashboard, or via POST /webhooks/deliveries/{id}/retry up to 30 days after the original event.
Rate limits on your endpoint
We will not deliver more than 20 events per second per subscription; excess is queued. If you need higher throughput, split events across multiple subscriptions with different filter sets.
Testing
Every subscription supports a POST /webhooks/{id}/ping that sends a synthetic webhook.ping event. Use this to verify signing before wiring up production events.