Skip to main content

Webhooks

Webhooks allow your application to receive real-time HTTP callbacks when events occur in The One Stack. Instead of polling APIs for changes, register a webhook URL and the platform will POST event payloads to you.

Configuring Webhooks

  1. Navigate to Hub > Settings > Webhooks.
  2. Click Add Webhook.
  3. Enter your endpoint URL (must be HTTPS).
  4. Select the events you want to subscribe to.
  5. Copy the webhook secret -- you will need it to verify signatures.

Events

Each product emits events for its core entities. Subscribe to only the events you need.

PSA Events

EventDescription
ticket.createdA new ticket was created
ticket.updatedA ticket was modified (status, priority, assignment, etc.)
ticket.deletedA ticket was deleted
ticket.note_addedA note was added to a ticket
time_entry.createdA time entry was logged
time_entry.updatedA time entry was modified
project.createdA new project was created
project.status_changedA project status changed
sla.breachedAn SLA target was missed

CRM Events

EventDescription
contact.createdA new contact was added
contact.updatedA contact was modified
company.createdA new company was added
company.updatedA company was modified
deal.createdA new deal was created
deal.stage_changedA deal moved to a different pipeline stage
deal.wonA deal was marked as won
deal.lostA deal was marked as lost
activity.completedAn activity (call, meeting, task) was completed

Books Events

EventDescription
invoice.createdA new invoice was generated
invoice.sentAn invoice was sent to the client
invoice.paidAn invoice was fully paid
invoice.overdueAn invoice passed its due date without payment
payment.receivedA payment was recorded
journal_entry.createdA journal entry was posted

RMM Events

EventDescription
device.addedA new device was enrolled
device.removedA device was removed
alert.triggeredA monitoring alert fired
alert.resolvedA monitoring alert was resolved
script.completedA remote script execution finished
patch.installedA patch was successfully installed
patch.failedA patch installation failed

Security Events

EventDescription
alert.triggeredA security alert was raised
alert.escalatedAn alert was escalated to a higher severity
incident.createdA new security incident was opened
incident.resolvedA security incident was resolved
scan.completedA vulnerability scan finished
vulnerability.foundA new vulnerability was discovered

Payload Format

All webhook payloads follow a consistent JSON structure:

{
"id": "evt_abc123def456",
"event": "ticket.created",
"timestamp": "2026-03-09T14:30:00.000Z",
"tenantId": "tenant_xyz789",
"product": "psa",
"data": {
"id": "tkt_001",
"title": "Printer not responding",
"status": "open",
"priority": "medium",
"companyId": "comp_456",
"assignedTo": "[email protected]",
"createdAt": "2026-03-09T14:30:00.000Z"
}
}
FieldTypeDescription
idstringUnique event ID for idempotency checks
eventstringEvent type (e.g., ticket.created)
timestampstringISO 8601 timestamp of when the event occurred
tenantIdstringThe tenant that generated the event
productstringThe product that emitted the event
dataobjectThe full entity payload at the time of the event

Signature Verification

Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature of the request body, signed with your webhook secret. Always verify this signature to confirm the payload was sent by The One Stack.

Verification Examples

Node.js

const crypto = require('crypto');

function verifyWebhookSignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body, 'utf8')
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

// In your webhook handler:
app.post('/webhooks/theonestack', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);

if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}

// Process the event
const { event, data } = req.body;
console.log(`Received ${event}:`, data);

res.status(200).json({ received: true });
});

Python

import hmac
import hashlib

def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(signature, expected)

# In your webhook handler (Flask example):
@app.route("/webhooks/theonestack", methods=["POST"])
def handle_webhook():
signature = request.headers.get("X-Webhook-Signature")
if not verify_webhook_signature(request.data, signature, WEBHOOK_SECRET):
return jsonify({"error": "Invalid signature"}), 401

event = request.json
print(f"Received {event['event']}: {event['data']}")
return jsonify({"received": True}), 200

Retry Policy

If your endpoint does not return a 2xx status code, The One Stack retries delivery with exponential backoff:

AttemptDelay
1st retry1 minute
2nd retry10 minutes
3rd retry1 hour

After 3 failed retries, the event is marked as failed. Failed events can be viewed and manually retried from Hub > Settings > Webhooks > Delivery Log.

Best Practices

  • Respond quickly. Return a 200 response as soon as you receive the payload. Process the event asynchronously if your handling logic is slow.
  • Use the event ID for idempotency. The same event may be delivered more than once (e.g., during retries). Use id to deduplicate.
  • Always verify signatures. Never trust webhook payloads without verifying the X-Webhook-Signature header.
  • Use HTTPS. Webhook URLs must use HTTPS to ensure payloads are encrypted in transit.
  • Monitor your delivery log. Check for failed deliveries regularly in Hub > Settings > Webhooks.