Webhooks
Webhooks send an HTTP POST with a JSON body to a URL you choose whenever a bug is created, updated, or commented on — whether the report came from a player’s game or from your team.
Setup
- Go to Integrate > Webhooks in your project dashboard
- Add the URL that should receive events (use HTTPS in production)
- Select the events you want to receive
- Optionally enter a signing secret (a long random string) so you can verify that deliveries come from Bugnet
- Use Test to send a sample payload and check your endpoint answers
Event Types
bug_created— A new bug report was filed (from an SDK, the web form, or a team member). A report stacked onto an existing one by grouping does not fire this event.bug_updated— A bug’s title, description, status, priority, category, assignee or visibility changedcomment_added— A comment was added to a bug
Payload Format
Every delivery is a JSON object with the event name, an RFC 3339 UTC timestamp, and event-specific data. The project is identified by data.project_slug.
{
"event": "bug_created",
"timestamp": "2026-03-13T12:00:00Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"report_number": 42,
"title": "Game crashes on level 5",
"description": "Crash when opening the inventory during the boss fight.",
"priority": "critical",
"category": "crash",
"project_slug": "a1b2c3-my-game"
}
}comment_added deliveries carry comment_id, report_number, title, body, is_internal and project_slug in data.
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
X-Bugnet-Event | The event name, e.g. bug_created (test for the Test button) |
X-Bugnet-Delivery | The delivery ID. It stays the same across retries of one event, so use it to ignore duplicates. |
X-Bugnet-Signature | sha256=<hex> — only sent when the webhook has a signing secret |
User-Agent | Bugnet-Webhooks/1.0 |
Verifying Signatures
When a webhook has a signing secret, every delivery carries X-Bugnet-Signature: sha256=<hex>, the HMAC-SHA256 of the raw request body keyed with your secret, hex-encoded. Compute the same value over the bytes you received (before parsing the JSON) and compare it in constant time. Reject the request if the header is missing or does not match.
const crypto = require('crypto');
// rawBody must be the exact bytes received, e.g. express.raw({ type: 'application/json' })
function verifyBugnet(rawBody, header, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected), b = Buffer.from(header || '');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}import hashlib, hmac
def verify_bugnet(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header or "")Webhooks saved without a secret are sent unsigned. The dashboard marks each webhook as signed or unsigned; to add a secret to an existing webhook, delete it and add it again with one.
Delivery Behavior
- Deliveries are sent in the background and do not slow down the request that triggered them. Each attempt has a 10-second timeout.
- Any response with a status below 400 counts as delivered (redirects are followed). Anything else — a 4xx or 5xx status, a timeout, or a connection error — is retried after 1, 5, 25 and 125 minutes, for up to 5 attempts in total, then the delivery is marked
failed. - Because of retries an endpoint can occasionally receive the same event twice; deduplicate on
X-Bugnet-Delivery. - Every delivery is recorded. Click Deliveries next to a webhook on the Integrate page, or call the deliveries endpoint below, to see the last 50 with their status, attempt count and last error.
- A webhook that is deleted or deactivated stops receiving deliveries, including pending retries.
API
# List webhooks
GET /api/projects/:slug/webhooks/generic
# Create webhook (event_types is a comma-separated string)
POST /api/projects/:slug/webhooks/generic
{"url":"https://example.com/hook","name":"Triage bot","event_types":"bug_created,bug_updated","secret":"a-long-random-string"}
# Delete webhook
DELETE /api/projects/:slug/webhooks/generic/:webhookId
# Send a signed test payload (returns the endpoint's status code)
POST /api/projects/:slug/webhooks/generic/:webhookId/test
# Recent deliveries (last 50)
GET /api/projects/:slug/webhooks/generic/:webhookId/deliveriesSlack
Post new bug reports, status changes, comments and a daily digest to Slack channels. Each connection is one channel with its own events and priority filter, so you can send every report to #qa and only critical ones to #live-ops.
Setup
- Open api.slack.com/apps, choose Create New App → From scratch and pick your workspace
- Under Incoming Webhooks, switch them on and choose Add New Webhook to Workspace, then pick the channel
- Copy the webhook URL (
https://hooks.slack.com/services/…) - In Bugnet, go to Integrate > Integrations > Slack, paste the URL, choose what to send and the minimum priority, and select Connect — Bugnet sends a test message straight away
Microsoft Teams
The same notifications as Slack, posted to a Teams channel as Adaptive Cards with an Open in Bugnet button.
Setup
- In Teams, open the channel, choose ••• next to its name, then Workflows
- Pick Post to a channel when a webhook request is received, name it “Bugnet”, confirm the team and channel and choose Add workflow
- Copy the URL Teams shows (on
logic.azure.comorpowerplatform.com) - In Bugnet, go to Integrate > Integrations > Microsoft Teams, paste it and select Connect
What gets posted
bug_created— every new report, from the dashboard or a player through the SDK. A report stacked onto an existing bug as a duplicate does not post again.bug_updated— status, priority, assignee, category and title changes, with who made them. Description edits are not posted.comment_added— comments. Internal notes are never posted.digest— a daily summary from 09:00: new, resolved and open bugs, open critical/high counts, crash-free sessions and the day’s most urgent new reports.
Priority filter: a connection only posts bugs at or above its minimum priority (all, medium+, high+ or critical only). A message the tool refuses is retried after 1, 5, 25 and 125 minutes; the connection shows its last error, and Deliveries lists every attempt. Pause stops a connection without removing it.
API
# List connections (secret_hint identifies the URL; it is never returned)
GET /api/projects/:slug/integrations
# Connect (provider is slack or teams)
POST /api/projects/:slug/integrations/:provider
{"secret":"https://hooks.slack.com/services/...","name":"#qa","event_types":["bug_created","bug_updated","digest"],"min_priority":"low"}
# Change events, priority filter, label, URL, or pause
PATCH /api/projects/:slug/integrations/:provider/:id
{"min_priority":"critical","is_active":true}
# Send a test message / recent deliveries / disconnect
POST /api/projects/:slug/integrations/:provider/:id/test
GET /api/projects/:slug/integrations/:provider/:id/deliveries
DELETE /api/projects/:slug/integrations/:provider/:idPagerDuty & Opsgenie
Page whoever is on call when a critical bug lands in a live game. Each bug is one incident (PagerDuty) or alert (Opsgenie), keyed by the bug, so repeat crashes never page twice; resolving, closing or won’t-fixing the bug resolves it, and reopening the bug triggers it again. Nothing else is sent.
- PagerDuty: on the service, add an Events API V2 integration and paste its integration key. Severity follows priority (critical → critical, high → error, medium → warning, low → info).
- Opsgenie: add an API integration with create and update access and paste its API key. Priority maps critical → P1 through low → P4.
- Both support US and EU regions. The dashboard suggests critical only; change the priority filter per connection. Send test raises a test event and resolves it straight away.
Sentry
When a report names an exception (its error type, such as NullReferenceException), Bugnet finds the most frequent unresolved Sentry issue with that error type in your project, links the two and leaves a note on the Sentry issue pointing to the player report. Resolving the bug resolves the Sentry issue; reopening it unresolves it; won’t fix ignores it.
- In Sentry, create an Internal Integration (Settings > Developer Settings > Custom Integrations) with Project: Read and Issue & Event: Read & Write, and copy its token
- In Bugnet, open Integrations > Sentry, choose your region (sentry.io or de.sentry.io), paste the token, load and pick the project
Reports without an error type are not linked. Send to Sentry on a bug links it on demand. Self-hosted Sentry is not supported yet.
Linear
File bugs as Linear issues in a team you choose — every new bug automatically, or only the ones you pick with Send to Linear on a bug’s page — and keep each issue moving as its bug is fixed.
Setup
- In Linear, open Settings > Security & access and create a personal API key (
lin_api_…) - In Bugnet, go to Integrate > Integrations > Linear, paste the key and choose Load teams
- Pick the team, choose whether to file every new bug (optionally only above a priority), and select Connect
The issue gets the report’s title and text, its details and a link back to Bugnet. Priority maps across (critical → Urgent, high → High, medium → Medium, low → Low). When the bug’s status changes, the issue moves to the team’s first workflow state of the matching kind: open → unstarted, in progress → started, resolved/closed → completed, won’t fix → canceled.
ClickUp
Turn bugs into ClickUp tasks in the list of your choice, automatically or with Send to ClickUp, and update the task’s status as the bug changes.
Setup
- In ClickUp, open your avatar > Settings > Apps and generate an API token (
pk_…) - In Bugnet, go to Integrate > Integrations > ClickUp, paste the token and choose Load lists
- Pick the list and select Connect
Priority maps onto ClickUp’s Urgent/High/Normal/Low. Lists name their statuses freely, so Bugnet goes by status type: open → the list’s open status, in progress → its first custom status, resolved → done (or closed), closed and won’t fix → closed.
For both trackers, a bug is only ever filed once per connection, failed attempts are retried like other deliveries, and the bug page lists every linked issue with its current state.
Jira Cloud
Studio Plus and up. Bugs are filed in the Jira project you choose as its Bug issue type (or its first standard type), labelled bugnet, with the report, its details and a link back. When the bug’s status changes, Bugnet takes the workflow transition into the matching status category — To Do, In Progress or Done — and leaves the issue alone if your workflow has no direct transition there.
- Create an API token at id.atlassian.com
- In Integrations > Jira, enter your site (
your-team.atlassian.net), the account’s email and the token, load and pick the project
Only Atlassian Cloud sites are accepted. Jira Data Center (Enterprise) is not available yet.
Asana
Creates a task in the project you choose for each bug (or on demand), and completes it when the bug is resolved, closed or won’t-fixed; reopening the bug reopens the task. Connect with a personal access token from the developer console.
Trello
Adds a card to the top of the list you choose. When the bug is resolved the card moves to the board’s first list named like Done, Complete, Fixed, Resolved or Shipped; in progress moves it to a Doing/In progress list; reopening moves it back to the list it was filed in. Connect with a Power-Up API key and token from trello.com/power-ups/admin.
Airtable, monday.com & Notion
These tools have columns you define, so Bugnet fills the ones whose names match its fields — Status, Priority (or Severity), Category, Platform, Version, Report #, Reporter, Description and a Bugnet/Link column — and skips anything missing or computed. The Status column follows the bug.
- Airtable: a record per bug in the table you choose; the title goes in the primary field and new select options are added as needed. Needs a personal access token with
data.records:read/writeandschema.bases:read. - monday.com: an item per bug on the board you choose, with the report as its first update; the Status column moves through Working on it, Done, Won’t fix and Reopened, and a status column titled Priority gets the priority. Needs your API token (avatar > Developers > My access tokens).
- Notion: a page per bug in the database you choose, with the report as the page body. Select properties get the value; a Notion status property moves between its To-do, In progress and Complete groups. Create an internal integration and add it to the database under ••• > Connections.
Google Play & App Store
Import your mobile game’s reviews every hour, see them under the connection with device, OS and app version, reply publicly from Bugnet, and — with File 1–2★ reviews that describe a bug on — turn low-star reviews that mention crashes, freezes, broken saves, black screens and the like into bug reports (platform Android or iOS, linked back to the review). Filed reports count toward your plan’s bug report limit and notify your team like any new report.
Google Play
- In Google Cloud, enable the Google Play Android Developer API, create a service account and download a JSON key
- In Play Console > Users and permissions, invite the service account’s email with access to the app and the Reply to reviews permission
- In Bugnet, paste the JSON key and the package name under Integrations > Google Play
Google only returns reviews with text from the last seven days, so the hourly import keeps the history. Replies are limited to 350 characters.
App Store
- In App Store Connect > Users and Access > Integrations, generate a Team API key with the Customer Support role or higher and download its
.p8file - In Bugnet, enter the Issuer ID and Key ID, paste the
.p8contents, load and pick the app under Integrations > App Store
Discord Integration
Send bug report notifications directly to your Discord server channels. Keep your team informed in real time without leaving Discord.
Setup
- Create a webhook URL in your Discord server (Server Settings > Integrations > Webhooks)
- Go to Integrate > Discord in Bugnet
- Add the Discord webhook URL
- Name the channel (e.g., "#bug-reports")
- Select which events trigger notifications
- Enable or disable the webhook at any time
Event Selection
- Each Discord webhook subscribes to its own set of events:
bug_created,bug_updated,comment_added - Add several Discord webhooks to route different events to different channels — for example new reports to
#bug-reportsand updates to#dev - Use Test to preview the Discord message format
API
# List Discord webhooks
GET /api/projects/:slug/webhooks/discord
# Create Discord webhook (event_types is a comma-separated string)
POST /api/projects/:slug/webhooks/discord
{"webhook_url":"https://discord.com/api/webhooks/...","channel_name":"bug-reports","event_types":"bug_created"}
# Update Discord webhook (any of webhook_url, channel_name, event_types, is_active)
PATCH /api/projects/:slug/webhooks/discord/:webhookId
{"is_active":false}
# Delete Discord webhook
DELETE /api/projects/:slug/webhooks/discord/:webhookId
# Test Discord webhook
POST /api/projects/:slug/webhooks/discord/:webhookId/testGitHub / GitLab Integration
Automatically create issues in your GitHub or GitLab repository from Bugnet bug reports. Keep your issue tracker in sync with player-reported bugs.
Setting Up GitHub
- Go to Integrate > GitHub/GitLab in your project dashboard
- Select GitHub as the provider
- Enter your repository URL (e.g.
https://github.com/your-org/your-game) - Add a Personal Access Token (see below)
- Click Connect
Creating a GitHub Personal Access Token
Bugnet needs a GitHub Personal Access Token (PAT) with permission to create issues in your repository. Here's how to create one:
- Go to GitHub > Settings > Developer settings > Personal access tokens > Fine-grained tokens
- Click Generate new token
- Give it a descriptive name, e.g.
Bugnet Issue Integration - Set Expiration to your preference (90 days, 1 year, or no expiration)
- Under Repository access, select Only select repositories and choose the repository you want to connect
- Under Permissions > Repository permissions, set:
- Issues — Read and write
- Metadata — Read-only (required, selected automatically)
- Click Generate token and copy the token
- Paste the token into the Access Token field in Bugnet's integration settings
Note: Fine-grained tokens are recommended over classic tokens because they limit access to only the repositories and permissions you specify. If your repository is in a GitHub organization, the organization owner may need to approve fine-grained token access under Organization settings > Personal access tokens > Settings.
If you prefer a classic token, go to Personal access tokens (classic) and create a token with the repo scope.
Setting Up GitLab
- Go to Integrate > GitHub/GitLab in your project dashboard
- Select GitLab as the provider
- Enter your GitLab project URL (e.g.
https://gitlab.com/your-org/your-game) - Create a Personal Access Token in GitLab: go to Preferences > Access Tokens, create a token with the
apiscope - Paste the token and click Connect
Auto-Creating Issues
When Auto-Create Issues is enabled, Bugnet automatically creates a GitHub or GitLab issue every time a new bug report is submitted. Each auto-created issue includes:
- Bug title and description from the report (for auto-captured crashes, the description includes the stack trace and recent logs)
- Priority and category, plus matching labels
- The Bugnet report number and project slug for cross-referencing
Enabling Auto-Create Issues
- Connect your repository with a valid access token (see setup above)
- Go to Integrate > GitHub/GitLab in your project dashboard
- Toggle Auto-create issues to on
An access token is required for auto-creation. Without a token, Bugnet cannot create issues on your behalf. If the token expires or is revoked, issue creation fails silently for new reports; update the token under Integrate > GitHub/GitLab to resume.
Issue Format
Auto-created issues are formatted as follows:
Title: Game crashes on level 5
{bug description}
---
**Priority:** critical
**Category:** crash
**Bugnet Report:** #42 (project: my-game)Labels are applied automatically: a category label (e.g. crash, visual; none for other) and, for critical and high bugs, a priority label (e.g. priority:critical). On GitHub the issue is also given the Bug issue type, where the repository supports issue types.
Auto-Create via API
You can also toggle auto-create issues via the API:
# Enable auto-create issues
PATCH /api/projects/:slug/git
{"auto_create_issues": true}
# Disable auto-create issues
PATCH /api/projects/:slug/git
{"auto_create_issues": false}Manual Issue Linking
You can also manually link a Bugnet bug to an existing GitHub or GitLab issue, or create a new issue from a specific bug report. This lets you track issue status from within Bugnet without requiring auto-creation.
API
# Get integration
GET /api/projects/:slug/git
# Connect repository (provider: "github" or "gitlab")
POST /api/projects/:slug/git
{"provider":"github","repo_url":"https://github.com/studio/my-game","access_token":"github_pat_..."}
# Update integration settings
PATCH /api/projects/:slug/git
{"auto_create_issues":true,"access_token":"github_pat_..."}
# Create an issue from bug #42
POST /api/projects/:slug/bugs/42/issue
# ...or link bug #42 to an existing issue
POST /api/projects/:slug/bugs/42/issue
{"issue_number":17,"issue_url":"https://github.com/studio/my-game/issues/17","issue_title":"Inventory crash"}
# Get linked issue
GET /api/projects/:slug/bugs/42/issue
# Search issues in the connected repo
GET /api/projects/:slug/git/issues?q=search+term
# Disconnect
DELETE /api/projects/:slug/gitSteam Integration
Connect your Steam app to sync player reviews and monitor sentiment. Bugnet pulls review data from the Steam API and provides analytics to help you understand player feedback.
Setup
- Go to Integrate > Steam
- Enter your Steam App ID (found in your Steamworks dashboard or store URL)
- Click Connect Steam App
- Bugnet starts syncing reviews and then re-syncs automatically about every 30 minutes while sync is enabled
Features
- Review Sync — Pulls player reviews and tracks positive/negative trends. Up to 1,000 reviews are kept on the free plan and 25,000 on Studio and Studio Plus
- Retention Radar — Flags churn risk as
low,mediumorcriticalfrom the share of negative reviews in the last 14 days (critical above 50%, medium from 25%) - Sentiment Trend — An average sentiment for the last 30 days, derived from each review’s thumbs up or down
- Playtime Correlation — See average playtime at review time to understand when players form opinions
- Refund Signals — Flags negative reviews written with under 2 hours of playtime, i.e. inside Steam’s refund window
- Manual Sync — Click "Sync Now" to fetch latest reviews on demand
Dashboard
The Steam dashboard shows a summary of your review data at a glance:
- Total reviews, positive %, negative %
- Sentiment trend over time
- Average playtime at review
- Churn risk level indicator
- Recent reviews list
API
# Connect Steam app
POST /api/projects/:slug/steam
{"app_id":"570"}
# Get integration status
GET /api/projects/:slug/steam
# Trigger manual sync
POST /api/projects/:slug/steam/sync
# Review dashboard, review list, history and refund signals
GET /api/projects/:slug/steam/dashboard
GET /api/projects/:slug/steam/reviews
GET /api/projects/:slug/steam/review-history
GET /api/projects/:slug/steam/refund-signals
# Pause or resume automatic sync
PATCH /api/projects/:slug/steam
{"sync_enabled":false}
# Disconnect
DELETE /api/projects/:slug/steamEmail Notifications
Bugnet emails your team when something happens on a project, so you don’t need to keep the dashboard open. Stay informed about bug activity without needing to check the dashboard constantly.
Notification Types
- New bug report submitted — sent to every project member except the person who filed it; a report stacked onto an existing bug sends nothing
- Bug status changed (e.g., resolved, closed)
- Bug assigned or reassigned
- New comment on a bug
- Weekly digest summary of project activity
Reply by Email
Team members can reply directly to notification emails to add comments. Reply content is parsed and added as a comment on the bug. Quote text from the original email is preserved for context.
Email reply tokens expire after 30 days for security.
Notification Preferences
Every notification email goes to the project’s members who have that type turned on, except the person who made the change. Each team member controls which emails they receive under Settings > Email Notifications. Every type is on until you turn it off.
| Setting | |
|---|---|
email_bug_created | A new bug report is filed |
email_bug_status | A bug’s status changes |
email_bug_assigned | A bug is assigned or reassigned |
email_bug_commented | Someone comments on a bug |
email_weekly_digest | The weekly summary |
To stop all Bugnet email, use the unsubscribe link at the bottom of any email; that opts you out of everything until you turn email back on.
API
# Get notification preferences
GET /api/notifications/preferences
# Update notification preferences
PUT /api/notifications/preferences
{"email_bug_created":true,"email_bug_status":true,"email_bug_assigned":true,"email_bug_commented":false,"email_weekly_digest":true}