Webhooks & Automation
Automate your build workflow with webhooks. Receive notifications when builds complete, or trigger builds automatically on code changes.
Incoming Webhooks (Trigger Builds)
GitHub Push Trigger
Automatically build when you push to a branch.
Configuration
- Go to Creator Portal → Project → Settings → Webhooks
- Enable Auto-build on push
- Configure filters:
{
"trigger": "push",
"enabled": true,
"branches": ["main", "release/*"],
"paths": {
"include": ["Source/**", "CMakeLists.txt"],
"exclude": ["docs/**", "*.md"]
},
"build_config": {
"platforms": ["macos", "windows"],
"formats": ["vst3", "au"],
"release_type": "dev"
}
}Trigger Rules
| Field | Description |
|---|---|
branches | Only trigger for these branches |
paths.include | Only trigger when these files change |
paths.exclude | Never trigger for these files |
Example: Production Releases
{
"trigger": "push",
"branches": ["main"],
"build_config": {
"release_type": "patch",
"flags": {
"enableActivationKeys": true
}
}
}GitHub Release Trigger
Build when you create a GitHub release.
{
"trigger": "release",
"enabled": true,
"release_types": ["published"],
"build_config": {
"release_type": "release",
"platforms": ["macos", "windows"],
"formats": ["vst3", "au"]
}
}Manual Webhook Trigger
Trigger builds from your own CI/CD.
Endpoint:
POST https://api.beatconnect.com/functions/v1/external-builds/{project_id}/trigger
Authentication:
X-Webhook-Secret: your-webhook-secret
Or HMAC signature:
X-Signature: sha256=abc123...
Request Body:
{
"ref": "refs/heads/main",
"commit_sha": "abc1234...",
"platforms": ["macos", "windows"],
"formats": ["vst3", "au"],
"release_type": "patch"
}Response:
{
"build_id": "build-uuid",
"status": "queued"
}Outgoing Webhooks (Notifications)
Receive notifications when build status changes.
Configuration
- Go to Creator Portal → Project → Settings → Webhooks
- Add Notification webhook URL
- Select events to receive
Events
| Event | Description |
|---|---|
build.queued | Build created and waiting |
build.started | Build execution started |
build.success | Build completed successfully |
build.failed | Build failed |
build.cancelled | Build was cancelled |
Payload Format
{
"event": "build.success",
"timestamp": "2025-01-15T10:35:00Z",
"build": {
"id": "build-uuid",
"project_id": "project-uuid",
"version": "1.0.1",
"build_number": 5,
"status": "success",
"platforms": ["macos", "windows"],
"formats": ["vst3", "au"],
"duration_seconds": 245,
"artifacts": [
{
"platform": "macos",
"format": "vst3",
"file_name": "MyPlugin.vst3",
"file_size": 5242880,
"download_url": "https://..."
}
]
}
}Failure Payload
{
"event": "build.failed",
"timestamp": "2025-01-15T10:35:00Z",
"build": {
"id": "build-uuid",
"status": "failed",
"error_message": "CMake configuration failed",
"error_logs": "CMake Error at CMakeLists.txt:15...",
"failed_at_step": "configure"
}
}Signature Verification
All outgoing webhooks include a signature:
X-BeatConnect-Signature: sha256=abc123...
X-BeatConnect-Timestamp: 1642320000
Verify in Node.js:
const crypto = require('crypto');
function verifyWebhook(payload, signature, timestamp, secret) {
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}Verify in Python:
import hmac
import hashlib
def verify_webhook(payload, signature, timestamp, secret):
signed_payload = f"{timestamp}.{payload}"
expected = 'sha256=' + hmac.new(
secret.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)Integration Examples
Slack Notifications
// Webhook receiver
app.post('/webhook/beatconnect', async (req, res) => {
const { event, build } = req.body;
let message;
let color;
switch (event) {
case 'build.success':
message = `✅ Build ${build.version} succeeded!`;
color = 'good';
break;
case 'build.failed':
message = `❌ Build ${build.version} failed: ${build.error_message}`;
color = 'danger';
break;
default:
message = `Build ${build.version}: ${event}`;
color = 'warning';
}
await fetch(process.env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
attachments: [{
color,
text: message,
fields: [
{ title: 'Version', value: build.version, short: true },
{ title: 'Build #', value: build.build_number, short: true }
]
}]
})
});
res.status(200).send('OK');
});Discord Notifications
app.post('/webhook/beatconnect', async (req, res) => {
const { event, build } = req.body;
const embed = {
title: event === 'build.success'
? '✅ Build Succeeded'
: '❌ Build Failed',
color: event === 'build.success' ? 0x00ff00 : 0xff0000,
fields: [
{ name: 'Version', value: build.version, inline: true },
{ name: 'Platforms', value: build.platforms.join(', '), inline: true }
],
timestamp: new Date().toISOString()
};
if (event === 'build.failed') {
embed.fields.push({
name: 'Error',
value: build.error_message.slice(0, 1000)
});
}
await fetch(process.env.DISCORD_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ embeds: [embed] })
});
res.status(200).send('OK');
});GitHub Actions Integration
Trigger BeatConnect build from GitHub Actions:
# .github/workflows/build.yml
name: Build Plugin
on:
push:
branches: [main]
paths:
- 'Source/**'
- 'CMakeLists.txt'
jobs:
trigger-build:
runs-on: ubuntu-latest
steps:
- name: Trigger BeatConnect Build
run: |
curl -X POST \
"https://api.beatconnect.com/functions/v1/external-builds/${{ secrets.BEATCONNECT_PROJECT_ID }}/trigger" \
-H "X-Webhook-Secret: ${{ secrets.BEATCONNECT_WEBHOOK_SECRET }}" \
-H "Content-Type: application/json" \
-d '{
"ref": "${{ github.ref }}",
"commit_sha": "${{ github.sha }}",
"platforms": ["macos", "windows"],
"formats": ["vst3", "au"]
}'
- name: Wait for Build
run: |
# Poll for build completion (simplified)
sleep 300 # Wait 5 minutes
- name: Download Artifacts
run: |
# Download signed binaries for further processing
curl -o artifacts.zip \
"https://api.beatconnect.com/functions/v1/builds/$BUILD_ID/download/all" \
-H "Authorization: Bearer ${{ secrets.BEATCONNECT_TOKEN }}"Auto-Deploy to Website
// After build success, deploy to your download page
app.post('/webhook/beatconnect', async (req, res) => {
const { event, build } = req.body;
if (event !== 'build.success') {
return res.status(200).send('OK');
}
// Update your website's download links
await updateDownloadPage({
version: build.version,
artifacts: build.artifacts.map(a => ({
platform: a.platform,
format: a.format,
url: a.download_url
}))
});
// Notify via email
await sendEmail({
to: 'team@yourcompany.com',
subject: `New Release: v${build.version}`,
body: `Version ${build.version} is ready for download.`
});
res.status(200).send('OK');
});Webhook Security
Best Practices
- Always verify signatures — Never trust unverified payloads
- Check timestamps — Reject old webhooks (replay protection)
- Use HTTPS — Never use HTTP for webhook endpoints
- Rotate secrets — Change webhook secrets periodically
Timestamp Validation
function isTimestampValid(timestamp, toleranceSeconds = 300) {
const now = Math.floor(Date.now() / 1000);
return Math.abs(now - parseInt(timestamp)) <= toleranceSeconds;
}IP Allowlisting
BeatConnect webhooks come from these IPs:
- Contact support for current IP ranges
- Use signature verification as primary security
Troubleshooting
Webhook Not Received
- Check endpoint URL is correct
- Verify endpoint returns 2xx status
- Check firewall allows incoming connections
- Review webhook logs in Creator Portal
Signature Mismatch
- Ensure you’re using the raw request body
- Check secret matches exactly
- Verify timestamp is included in signature
Duplicate Webhooks
Implement idempotency:
const processedBuilds = new Set();
app.post('/webhook', (req, res) => {
const buildId = req.body.build.id;
if (processedBuilds.has(buildId)) {
return res.status(200).send('Already processed');
}
processedBuilds.add(buildId);
// Process webhook...
});Rate Limits
| Direction | Limit |
|---|---|
| Incoming (triggers) | 10/minute per project |
| Outgoing (notifications) | Unlimited |