Webhooks
Receive real-time HTTP notifications whenever events occur in your workspace — tours published, leads submitted, assets processed, and more.
How It Works
When an event occurs in your workspace, 3Syxty sends an HTTP POST request to each registered webhook URL that subscribes to that event type. The request body contains a JSON payload describing the event.
Webhooks are configured per-workspace via the Studio UI (Settings → Webhooks) or programmatically via the Webhooks API.
Event Types
| Event | Description |
|---|---|
project.created |
A new project was created |
project.updated |
Project settings were modified |
project.deleted |
A project was deleted |
project.published |
A tour was published or republished |
project.unpublished |
A tour was unpublished |
scene.created |
A scene was added to a project |
scene.updated |
Scene properties were modified |
scene.deleted |
A scene was removed |
asset.uploaded |
A new asset was uploaded |
asset.processed |
Asset processing (transcode, tile) completed |
asset.deleted |
An asset was deleted |
lead.submitted |
A lead form was submitted by a viewer |
member.invited |
A new member was invited to the workspace |
member.removed |
A member was removed from the workspace |
quiz.completed |
A learner completed a quiz attempt |
comment.created |
A new review comment was added |
ai.job.completed |
An AI processing job finished |
export.ready |
A self-hosted export package is ready for download |
Payload Format
Every webhook delivery sends a JSON POST request with the following structure:
// POST to your webhook URL // Content-Type: application/json { "id": "evt_a1b2c3d4e5f6", "type": "project.published", "created_at": "2026-03-03T20:30:00Z", "workspace_id": "ws_x9y8z7", "data": { "project_id": "proj_8kF2x9mN", "name": "Luxury Villa Tour", "published_url": "https://tours.3syxty.com/t/luxury-villa", "scenes_count": 24 } }
Request Headers
| Header | Description |
|---|---|
Content-Type |
Always application/json |
X-3Syxty-Signature |
HMAC-SHA256 signature of the request body |
X-3Syxty-Event |
The event type (e.g. project.published) |
X-3Syxty-Delivery |
Unique delivery ID for idempotency tracking |
User-Agent |
3Syxty-Webhook/1.0 |
Signature Verification
Every webhook delivery is signed with your webhook secret using HMAC-SHA256. Always verify the signature to ensure the request originates from 3Syxty.
// Your webhook secret (from Settings → Webhooks) $secret = 'whsec_your_webhook_secret'; // Get the raw request body and signature header $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_3SYXTY_SIGNATURE'] ?? ''; // Compute the expected signature $expected = hash_hmac('sha256', $payload, $secret); // Timing-safe comparison if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Invalid signature'); } // Signature valid — process the event $event = json_decode($payload, true);
Retry Policy
If your endpoint returns a non-2xx status code or fails to respond within 10 seconds, 3Syxty will retry the delivery with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry (final) | 24 hours |
After 5 failed attempts, the delivery is marked as failed. You can view failed deliveries and manually retry them via the Webhooks API or the Studio UI. Webhooks that consistently fail are automatically disabled after 100 consecutive failures.
Best Practices
Respond quickly
Return a 2xx response within 10 seconds. Process the event asynchronously if needed.
Always verify signatures
Never skip signature verification. It protects you from spoofed requests.
Handle duplicates
Use the X-3Syxty-Delivery header for idempotency. The same event may be delivered more than once during retries.
Use HTTPS endpoints
Webhook URLs must use HTTPS. HTTP endpoints are rejected.