Webhooks

Webhooks

Receive real-time notifications when session statuses change, eliminating the need for continuous polling.

Quick Setup

  1. Navigate to your Dashboard Profile Settings
  2. In Developer Settings, enter your webhook URL
  3. Save settings

Your endpoint will receive notifications for all session status changes.

Webhook Event

session_status_changed

Triggered when a session transitions between statuses (e.g., incompletecomplete or incompletefailed).

Available for all session types: image_to_3d, multiview_to_3d, text_to_image, image_to_kit, retopology, animation.

Payload Structure

Webhook Payload Schema

FieldTypeDescription
typestringEvent type. Always "session_status_changed"
payloadobjectEvent payload containing session details
payload.session_idstringUnique session identifier
payload.user_idstringUser identifier who owns the session
payload.session_typestringType of session (image_to_3d, multiview_to_3d, etc.)
payload.old_statusstringPrevious session status
payload.new_statusstringNew session status
payload.timestampstringISO 8601 timestamp of the status change
payload.session_dataobjectComplete session object - see schema below

Session Data Schema

The session_data field contains the complete session object as defined in the API specification. The structure varies by session type. Here’s an example for Image to 3D sessions:

For other session types, refer to their specific documentation pages.

Note: Large embedding arrays (input_image_embedding fields) are automatically removed from the payload to optimize size and delivery speed.

Example Payload

{
  "type": "session_status_changed", 
  "payload": {
    "session_id": "SESSION_1756711515_3265503",
    "user_id": "681dcde5253883b154accfde", 
    "session_type": "image_to_3d",
    "old_status": "incomplete",
    "new_status": "complete",
    "timestamp": "2025-09-01T07:26:51.484Z",
    "session_data": {
      /* Complete session object as per API schema above */
    }
  }
}

Delivery Details

  • Method: HTTP POST with Content-Type: application/json
  • Timeout: 5 seconds
  • Retries: 3 attempts with exponential backoff (2s, 4s, 8s delays)
  • Expected Response: Return 2xx status code
  • Async Processing: Webhook failures don’t affect session processing

Implementation

Basic Handler

// Node.js/Express
app.post('/webhook', express.json(), (req, res) => {
  const { type, payload } = req.body;
  
  if (type === 'session_status_changed') {
    const { session_id, new_status, session_data } = payload;
    
    if (new_status === 'complete') {
      // Handle completed session
      processCompletedSession(session_data);
    } else if (new_status === 'failed') {
      // Handle failed session
      handleFailure(session_data);
    }
  }
  
  res.status(200).send('OK');
});
# Python/Flask
@app.route('/webhook', methods=['POST'])
def webhook():
    data = request.get_json()
    
    if data['type'] == 'session_status_changed':
        payload = data['payload']
        
        if payload['new_status'] == 'complete':
            process_completed_session(payload['session_data'])
        elif payload['new_status'] == 'failed':
            handle_failure(payload['session_data'])
    
    return '', 200

Best Practices

  • Use HTTPS for your webhook endpoint
  • Respond quickly (under 5 seconds) to avoid timeouts
  • Handle duplicates - implement idempotency using session_id + timestamp
  • Log webhook receipts for debugging
  • Queue heavy processing - respond immediately, process asynchronously

Testing

Use ngrok for local development:

ngrok http 3000
# Use the HTTPS URL: https://abc123.ngrok.io/webhook

Requirements

  • Publicly accessible HTTPS URL (HTTP allowed for testing)
  • Must accept POST requests
  • Should return 200-299 status codes
  • Must respond within 5 seconds

Advantages over Polling

  • Real-time notifications
  • Reduced API usage
  • Lower latency
  • More efficient resource usage