Skip to main content

Webhook Streaming

Stream Muse data to web services and APIs via HTTP webhooks.

What are Webhooks?

Webhooks send data to a URL endpoint via HTTP POST requests. This enables integration with:

  • Cloud services and databases
  • Custom web applications
  • Data processing pipelines
  • IoT platforms
  • Real-time dashboards

Enabling Webhook Streaming

  1. Open SettingsOutput
  2. Find the Webhook Streaming section
  3. Toggle Enable Webhook
  4. Enter your webhook URL
  5. Configure advanced settings as needed
Settings Persistence

Your webhook configuration (including custom headers) is automatically saved and will be restored the next time you launch the app.

Configuration Options

Basic Settings

SettingDescriptionDefault
URLHTTPS endpoint to receive dataRequired
EnableToggle streaming on/offOff

Advanced Settings

SettingDescriptionDefaultRange
Batch SizeNumber of samples per request101-256
TimeoutRequest timeout in milliseconds2000100-5000
Max RetriesRetry attempts on failure31-5
Rate LimitRequests per second (0 = unlimited)00+
Custom HeadersAdditional HTTP headersNone-

Data Format

Webhook requests are sent as JSON with the following structure:

{
"timestamp": "2026-01-27T15:30:45.123Z",
"device_id": "HW-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX",
"batch": [
{
"type": "eeg",
"timestamp": 1706365845123,
"data": {
"tp9": -12.5,
"af7": 8.3,
"af8": -5.1,
"tp10": 15.2
}
},
{
"type": "acc",
"timestamp": 1706365845125,
"data": {
"x": 0.02,
"y": -0.98,
"z": 0.15
}
}
]
}

Example: Receiving in Node.js

const express = require('express');
const app = express();

app.use(express.json());

app.post('/muse-data', (req, res) => {
const { timestamp, device_id, batch } = req.body;

for (const sample of batch) {
console.log(`[${sample.type}] ${JSON.stringify(sample.data)}`);
}

res.status(200).send('OK');
});

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

Example: Receiving in Python (Flask)

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/muse-data', methods=['POST'])
def receive_data():
data = request.get_json()

for sample in data['batch']:
print(f"[{sample['type']}] {sample['data']}")

return jsonify({'status': 'ok'}), 200

if __name__ == '__main__':
app.run(port=3000)

Custom Headers

Add authentication or custom headers:

  1. Click Custom Headers in advanced settings
  2. Add headers in Key: Value format:
    Authorization: Bearer your-api-token
    X-Custom-Header: custom-value

Retry Behavior

When a request fails, Petal Metrics uses exponential backoff:

  1. First retry: Wait 100ms
  2. Second retry: Wait 1 second
  3. Third retry: Wait 5 seconds
  4. After max retries: Drop the batch and continue

Failed requests don't block new data from being sent.

Rate Limiting

The Rate Limit setting prevents overwhelming your endpoint:

  • Minimum time between requests (in milliseconds)
  • Data is batched and sent when the rate limit allows
  • Higher values = fewer requests, larger batches

Security Considerations

Use HTTPS

Always use HTTPS endpoints in production to encrypt data in transit.

Authentication

  • Use the Custom Headers feature to add authentication tokens
  • Implement IP allowlisting on your server if possible
  • Validate the device_id matches expected values

Data Validation

  • Your endpoint should validate incoming data structure
  • Implement rate limiting on your server as backup
  • Log and monitor for unusual patterns

Test Connection

Click Test Connection to send a test request to your endpoint. This helps verify:

  • URL is correct and reachable
  • Authentication headers are working
  • Your server responds with 200 OK

Troubleshooting

"Connection failed"

  • Verify the URL is correct and accessible
  • Check that HTTPS certificate is valid
  • Ensure your server is running

Requests timing out

  • Increase the timeout setting
  • Check your server's response time
  • Verify network connectivity

Data not arriving

  • Check server logs for errors
  • Verify authentication headers are correct
  • Test with a simple endpoint first (e.g., webhook.site)

Availability

Webhook streaming is available on all subscription plans (Basic, Standard, Advanced).