Skip to Content
DashboardWebhooks

Webhooks

Webhooks send HTTP POST notifications when your builds, submissions, or OTA updates complete or fail. Norrix supports three webhook types:

TypeDescription
GenericJSON payload to any HTTPS endpoint, signed with HMAC-SHA256
SlackRich Block Kit messages delivered to a Slack channel
TeamsAdaptive Card notifications via Power Automate (recommended) or legacy MessageCard

Events

EventDescription
build_completedBuild finished successfully
build_failedBuild failed
submit_completedStore submission succeeded
submit_failedStore submission failed
update_completedOTA update published
update_failedOTA update failed
allSubscribe to all events

Creating a Webhook

  1. Go to Dashboard → Settings → Webhooks
  2. Click + Add Webhook
  3. Enter a Name (e.g., “Build Notifications”)
  4. Select a Webhook Type (Generic, Slack, or Teams)
  5. Enter the URL for your chosen type (see setup guides below)
  6. Select Events to subscribe to
  7. Optionally configure Project Filtering
  8. Click Create

For Generic webhooks, a signing secret is displayed after creation. Copy it immediately — it won’t be shown again.

For Slack and Teams webhooks, no signing secret is generated. The webhook URL itself serves as authentication.


Slack Setup

Slack webhooks deliver rich, formatted messages using Block Kit with status indicators and metadata fields.

Creating a Slack Incoming Webhook

  1. Go to api.slack.com/apps 
  2. Click Create New AppFrom scratch
  3. Name the app (e.g., “Norrix Builds”) and select your workspace
  4. Go to Incoming Webhooks → Toggle Activate Incoming Webhooks on
  5. Click Add New Webhook to Workspace
  6. Select the channel to post to and click Allow
  7. Copy the webhook URL (starts with https://hooks.slack.com/services/...)

Adding to Norrix

  1. In Dashboard → Settings → Webhooks, click + Add Webhook
  2. Select Slack as the type
  3. Paste the Slack webhook URL
  4. Select events and click Create

What You’ll See in Slack

Notifications include:

  • Header with status (checkmark for success, X for failure)
  • Fields with project name, platform, version, build number, configuration, and distribution type
  • Optional message when a build, submit, or update includes a message
  • Context footer with organization name and operation ID

Microsoft Teams Setup

Teams webhooks deliver Adaptive Card notifications through Power Automate, or legacy MessageCard notifications if your tenant still allows Incoming Webhooks.

  1. Go to Power Automate  and create an Instant cloud flow
  2. Choose the When an HTTP request is received trigger
  3. Save the flow to generate the HTTP POST URL
  4. Add the Post adaptive card in a chat or channel action
  5. Pick the Team and Channel
  6. For Adaptive Card, use the dynamic content card from the trigger body
  7. Save the flow and copy the HTTP POST URL

Option B: Legacy Incoming Webhook (If Enabled)

  1. Open Microsoft Teams and navigate to the channel you want notifications in
  2. Click the menu on the channel → Connectors (or Manage channelConnectors)
  3. Find Incoming Webhook and click Configure
  4. Name the webhook (e.g., “Norrix Builds”) and optionally upload an icon
  5. Click Create
  6. Copy the webhook URL (from outlook.office.com or outlook.office365.com)

Adding to Norrix

  1. In Dashboard → Settings → Webhooks, click + Add Webhook
  2. Select Teams as the type
  3. Paste the Power Automate URL (recommended) or the legacy Incoming Webhook URL
  4. Select events and click Create

Payload for Power Automate

The Teams adapter sends a JSON body that includes the full Norrix payload plus an Adaptive Card:

{ "event": "build_completed", "timestamp": "2024-01-15T10:30:00.000Z", "organization": { "id": "org_abc123", "name": "My Team" }, "data": { "type": "build" }, "text": "Build Completed: my-app", "card": { "type": "AdaptiveCard", "version": "1.5", "body": [] } }

In your flow, pass card to the Post adaptive card in a chat or channel action.

What You’ll See in Teams

Notifications include:

  • Adaptive Card with status color (green for success, red for failure)
  • Title with status emoji and operation type
  • Facts section with build type, configuration, distribution, fingerprint, and organization
  • Optional message when a build, submit, or update includes a message

Generic Webhook Setup

Generic webhooks send the full JSON payload to any HTTPS endpoint. Payloads are signed with HMAC-SHA256 so your server can verify authenticity.

Adding to Norrix

  1. In Dashboard → Settings → Webhooks, click + Add Webhook
  2. Select Generic as the type
  3. Enter your HTTPS endpoint URL
  4. Select events and click Create
  5. Copy the signing secret — it’s only shown once

Payload Format

{ "event": "build_completed", "timestamp": "2024-01-15T10:30:00.000Z", "organization": { "id": "org_abc123", "name": "My Team" }, "data": { "type": "build", "buildId": "build-1234567890", "projectName": "my-app", "appId": "com.example.myapp", "platform": "ios", "version": "1.0.0", "buildNumber": "42", "buildType": "release", "configuration": "prod", "distributionType": "appstore", "status": "completed", "artifactUrl": "https://...", "fingerprintHash": "abc123..." } }

Headers

HeaderDescription
Content-Typeapplication/json
User-AgentNorrix-Webhook/1.0
X-Norrix-EventEvent name (e.g., build_completed)
X-Norrix-DeliveryUnique delivery ID
X-Norrix-TimestampISO 8601 timestamp
X-Norrix-Signaturesha256=<hex> HMAC-SHA256 signature

Payload Fields

Build Events

FieldTypeDescription
buildIdstringBuild ID
projectNamestringProject name
appIdstringApp bundle identifier
platformstringios, android, or visionos
versionstringApp version (e.g., 1.2.0)
buildNumberstringBuild number
buildTypestringdebug or release
configurationstringDeployment target (e.g., prod, stg)
distributionTypestringappstore, adhoc, or enterprise
statusstringcompleted or failed
artifactUrlstringDownload URL for IPA/APK
fingerprintHashstringNative dependency fingerprint
messagestringOptional status message

Submit Events

FieldTypeDescription
submitIdstringSubmission ID
appIdstringApp bundle identifier
platformstringios, android, or visionos
versionstringApp version
trackstringStore track (e.g., production, testflight)
buildIdstringAssociated build ID
statusstringcompleted or failed
messagestringOptional status message

Update Events (OTA)

FieldTypeDescription
updateIdstringUpdate ID
appIdstringApp bundle identifier
platformstringios, android, or visionos
versionstringApp version
buildNumberstringBuild number
configurationstringDeployment target
statusstringcompleted or failed
updateUrlstringURL to the update bundle
fingerprintHashstringNative dependency fingerprint
messagestringOptional status message

Signature Verification

Verify the X-Norrix-Signature header using HMAC-SHA256 with your signing secret:

const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(payload, 'utf8').digest('hex'); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); } // Express middleware app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-norrix-signature']; const payload = req.body.toString(); if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(payload); // Handle event... res.status(200).send('OK'); });

Project Filtering

Filter webhooks to specific projects:

Include Projects

Comma-separated list of project names to include:

my-app, other-app

Only events from these projects trigger the webhook.

Exclude Projects

Comma-separated list of project names to exclude:

test-app, experimental

Events from these projects are skipped.


Managing Webhooks

View Webhooks

Dashboard → Settings → Webhooks shows:

  • Name (with type badge for Slack/Teams)
  • URL
  • Events
  • Enabled status
  • Last triggered
  • Last status code

Edit Webhook

  1. Click on the webhook
  2. Update name, URL, events, or project filters
  3. Save changes

The webhook type cannot be changed after creation. To switch types, delete and recreate the webhook.

Regenerate Secret

Available for Generic webhooks only (Slack and Teams don’t use signing secrets):

  1. Edit the webhook
  2. Click Regenerate Secret
  3. Copy the new secret
  4. Update your server

Disable/Enable

Toggle the Enabled switch to temporarily disable a webhook without deleting it.

Delete Webhook

  1. Click Delete
  2. Confirm deletion

Delivery history is also deleted.


Delivery History

View recent deliveries for each webhook:

  • Timestamp
  • Event type
  • HTTP status code
  • Response time
  • Error message (if failed)

Retry Failed Deliveries

Currently, failed deliveries aren’t automatically retried. Configure your endpoint to be idempotent.


Best Practices

Respond Quickly

Return 200 OK within 10 seconds. Process events asynchronously:

app.post('/webhook', (req, res) => { // Acknowledge receipt immediately res.status(200).send('OK'); // Process asynchronously processEventAsync(req.body); });

Idempotency

Events may be delivered multiple times. Use the event ID for deduplication:

async function handleEvent(event) { if (await isProcessed(event.data.id)) { return; // Already handled } // Process event await markProcessed(event.data.id); }

Security

  • Generic: Always verify HMAC-SHA256 signatures. Rotate secrets if compromised.
  • Slack: Keep your webhook URL private. Regenerate in Slack if compromised.
  • Teams: Keep your webhook URL private. Regenerate the connector if compromised.
  • All types require HTTPS endpoints.