MindPeeker Logo
Developers

Webhooks

Real-time event notifications and webhook integration for MindPeeker platform

Overview

Webhooks enable real-time notifications from MindPeeker to your application when specific events occur. Instead of continuously polling the API for status updates, you can receive instant notifications when sessions complete, analyses finish, or other important events happen.

Supported Events

Session Events

  • session.created - New session initiated
  • session.started - Session processing began
  • session.completed - Session finished successfully
  • session.failed - Session failed or was cancelled
  • session.progress_updated - Session progress updated (every 10%)

Analysis Events

  • analysis.created - New analysis queued
  • analysis.started - Analysis processing began
  • analysis.completed - Analysis completed successfully
  • analysis.failed - Analysis failed

Dowsing Events

  • dowsing.query_created - New dowsing query submitted
  • dowsing.query_completed - Dowsing query completed
  • dowsing.query_failed - Dowsing query failed

Account Events

  • account.subscription_updated - Subscription plan changed
  • account.usage_threshold_reached - Usage limit approaching
  • account.payment_succeeded - Payment processed successfully
  • account.payment_failed - Payment failed

System Events

  • system.maintenance_scheduled - Scheduled maintenance announced
  • system.service_disruption - Service disruption detected
  • system.security_alert - Security-related notification

Setting Up Webhooks

1. Create Webhook Endpoint

Create an HTTPS endpoint in your application that can receive POST requests:

// Express.js example
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-mindpeeker-signature'];
  const payload = req.body;
  
  // Verify webhook signature (recommended)
  const expectedSignature = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');
    
  if (signature !== `sha256=${expectedSignature}`) {
    return res.status(401).send('Invalid signature');
  }
  
  try {
    const event = JSON.parse(payload);
    
    // Handle different event types
    switch (event.type) {
      case 'session.completed':
        handleSessionCompleted(event.data);
        break;
      case 'analysis.completed':
        handleAnalysisCompleted(event.data);
        break;
      // ... other event types
    }
    
    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).send('Internal server error');
  }
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

2. Register Webhook

Register your webhook endpoint through the API or dashboard:

curl -X POST https://api.mindpeeker.com/v1/webhooks \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhook",
    "events": [
      "session.completed",
      "analysis.completed",
      "dowsing.query_completed"
    ],
    "secret": "your_webhook_secret_here",
    "active": true
  }'

3. Test Webhook

Test your webhook configuration:

curl -X POST https://api.mindpeeker.com/v1/webhooks/{webhook_id}/test \
  -H "Authorization: Bearer your_api_key"

Webhook Event Format

All webhook events follow this structure:

{
  "id": "evt_1234567890abcdef",
  "type": "session.completed",
  "created_at": "2025-01-15T10:30:00Z",
  "data": {
    "session_id": "sess_123456789",
    "status": "completed",
    "confidence_score": 0.87,
    "completed_at": "2025-01-15T10:30:00Z"
  },
  "livemode": true,
  "pending_webhooks": 0
}

Event-Specific Data

session.completed

{
  "type": "session.completed",
  "data": {
    "session_id": "sess_123456789",
    "type": "remote_viewing",
    "target": "Missing person investigation",
    "status": "completed",
    "confidence_score": 0.87,
    "duration_minutes": 28,
    "results": {
      "coordinates": {
        "latitude": 40.7128,
        "longitude": -74.0060
      },
      "descriptors": ["urban environment", "water body nearby"],
      "sketches": ["https://cdn.mindpeeker.com/sketches/sess_123456789_1.png"]
    },
    "completed_at": "2025-01-15T10:30:00Z"
  }
}

analysis.completed

{
  "type": "analysis.completed",
  "data": {
    "analysis_id": "anal_123456789",
    "target_type": "location",
    "status": "completed",
    "confidence_score": 0.91,
    "results": {
      "summary": "Analysis reveals structural anomalies...",
      "key_findings": [
        "Structural anomalies detected",
        "Temporal inconsistencies present"
      ],
      "risk_assessment": {
        "level": "medium",
        "factors": ["temporal_instability"]
      }
    },
    "processing_time": "45 minutes",
    "completed_at": "2025-01-15T11:15:00Z"
  }
}

dowsing.query_completed

{
  "type": "dowsing.query_completed",
  "data": {
    "query_id": "dowse_123456789",
    "query_type": "location",
    "question": "Find optimal location for water well",
    "answer": "positive",
    "confidence": 0.89,
    "coordinates": {
      "latitude": 40.7132,
      "longitude": -74.0058,
      "accuracy_meters": 15
    },
    "chart_data": {
      "chart_type": "radar",
      "readings": [0.8, 0.6, 0.9, 0.7],
      "interpretation": "Strong positive response"
    },
    "completed_at": "2025-01-15T09:45:00Z"
  }
}

Security

Signature Verification

All webhook requests are signed with HMAC-SHA256 using your webhook secret:

import hmac
import hashlib

def verify_webhook_signature(payload, signature, secret):
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(
        f'sha256={expected_signature}',
        signature
    )

signature = request.headers.get('X-MindPeeker-Signature')
payload = request.body

if verify_webhook_signature(payload, signature, 'your_webhook_secret'):
    # Process webhook
    pass
else:
    # Reject webhook
    pass

IP Whitelisting

For additional security, you can whitelist MindPeeker's webhook IP addresses:

52.52.52.52
52.53.53.53

TLS Requirements

  • Webhook endpoints must use HTTPS
  • TLS 1.2 or higher required
  • Valid SSL certificates required

Best Practices

1. Fast Response Times

Respond to webhook requests quickly (within 5 seconds):

// Acknowledge immediately, process asynchronously
app.post('/webhook', (req, res) => {
  // Quick validation
  if (!verifySignature(req.body, req.headers['x-mindpeeker-signature'])) {
    return res.status(401).send('Invalid signature');
  }
  
  // Acknowledge immediately
  res.status(200).send('OK');
  
  // Process asynchronously
  setImmediate(() => {
    processWebhook(req.body);
  });
});

2. Idempotency

Handle duplicate webhook deliveries:

const processedEvents = new Set();

function processWebhook(event) {
  if (processedEvents.has(event.id)) {
    console.log('Duplicate event, skipping');
    return;
  }
  
  processedEvents.add(event.id);
  
  // Process event
  handleEvent(event);
}

3. Error Handling

Implement robust error handling:

async function handleSessionCompleted(data) {
  try {
    const session = await updateSessionInDatabase(data.session_id, data);
    
    if (data.confidence_score > 0.8) {
      await notifyHighConfidenceResult(session);
    }
    
  } catch (error) {
    console.error('Error handling session completion:', error);
    
    // Retry logic or alert monitoring
    await alertMonitoringSystem(error);
  }
}

4. Monitoring and Logging

Monitor webhook delivery and processing:

// Log all incoming webhooks
app.post('/webhook', (req, res) => {
  console.log('Webhook received:', {
    type: req.body.type,
    id: req.body.id,
    timestamp: new Date().toISOString()
  });
  
  // ... processing logic
});

// Monitor webhook health
setInterval(async () => {
  const stats = await getWebhookStats();
  console.log('Webhook stats:', stats);
}, 60000); // Every minute

Retry Policy

MindPeeker automatically retries failed webhook deliveries:

AttemptDelayMax Duration
1Immediate-
25 seconds5 seconds
330 seconds35 seconds
42 minutes2 minutes 35 seconds
510 minutes12 minutes 35 seconds
630 minutes42 minutes 35 seconds
71 hour1 hour 42 minutes 35 seconds

If all retries fail, the webhook is marked as failed and you'll receive a webhook.failed event.

Managing Webhooks

List Webhooks

curl -X GET https://api.mindpeeker.com/v1/webhooks \
  -H "Authorization: Bearer your_api_key"

Update Webhook

curl -X PATCH https://api.mindpeeker.com/v1/webhooks/{webhook_id} \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["session.completed", "analysis.completed"],
    "active": true
  }'

Delete Webhook

curl -X DELETE https://api.mindpeeker.com/v1/webhooks/{webhook_id} \
  -H "Authorization: Bearer your_api_key"

Testing

Local Development

Use tools like ngrok to test webhooks locally:

ngrok http 3000

curl -X POST https://api.mindpeeker.com/v1/webhooks \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://abc123.ngrok.io/webhook",
    "events": ["session.completed"],
    "secret": "test_secret"
  }'

Test Events

Send test events to your webhook:

curl -X POST https://api.mindpeeker.com/v1/webhooks/{webhook_id}/test \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "session.completed",
    "test_data": {
      "session_id": "test_session_123",
      "confidence_score": 0.85
    }
  }'

SDK Support

All official SDKs provide webhook utilities:

Python

from mindpeeker.webhooks import WebhookHandler

handler = WebhookHandler('your_webhook_secret')

@handler.on('session.completed')
def handle_session_completed(event):
    print(f"Session {event.data.session_id} completed")

@app.route('/webhook', methods=['POST'])
def webhook():
    event = handler.construct_event(request.data, request.headers['X-MindPeeker-Signature'])
    handler.process_event(event)
    return 'OK'

JavaScript

import { WebhookHandler } from '@mindpeeker/javascript';

const handler = new WebhookHandler('your_webhook_secret');

handler.on('session.completed', (event) => {
  console.log(`Session ${event.data.session_id} completed`);
});

// In Express
app.post('/webhook', (req, res) => {
  const event = handler.constructEvent(req.body, req.headers['x-mindpeeker-signature']);
  handler.processEvent(event);
  res.status(200).send('OK');
});

Troubleshooting

Common Issues

  1. Invalid Signature
    • Check webhook secret matches
    • Ensure raw payload is used for verification
    • Verify encoding (UTF-8)
  2. Timeout Errors
    • Ensure webhook responds within 5 seconds
    • Process heavy operations asynchronously
    • Check network connectivity
  3. Duplicate Events
    • Implement idempotency handling
    • Track processed event IDs
    • Use database transactions
  4. SSL Certificate Issues
    • Ensure valid SSL certificate
    • Check certificate chain
    • Verify TLS version compatibility

Debug Mode

Enable debug mode for detailed logging:

const handler = new WebhookHandler('your_webhook_secret', {
  debug: true,
  logLevel: 'verbose'
});

Monitoring Dashboard

Monitor webhook delivery in your MindPeeker dashboard:

  • Delivery success rate
  • Average response time
  • Error breakdown
  • Retry attempts

Support

For webhook support: