Link
GitHub Get Started

Webhooks

Receive events from your tools via webhook endpoints.

Table of contents

  1. Overview
  2. Authentication
  3. Webhook Endpoints
    1. Perforce
    2. Jenkins
    3. Game Engine
    4. Deployment
    5. CI Systems
      1. Non-Jenkins CI must push its log
    6. Other Integrations
  4. Response Codes
  5. Testing Webhooks

Overview

Webhooks allow external tools to send events to ButterStack. Each integration has its own webhook endpoint with a unique token for authentication.

Authentication

All webhook endpoints use token-based authentication. The webhook_token is generated when you create an integration and is shown on the integration’s page (Project → Integrations → your integration).

The token can be delivered three ways; prefer a header, since a query string lands in proxy and access logs:

DeliveryAccepted by
X-ButterStack-Token: <token> headerThe platform endpoints (Perforce, Jira, Trello, Monday, Asana, Linear, GitHub, Diversion, Lore)
X-Webhook-Token: <token> header, or HTTP Basic with the token as the passwordThe CI intake (/webhooks/jenkins, /webhooks/ci)
?token=<token> query stringAll of the above
POST /webhooks/{platform}?token={webhook_token}

Webhook Endpoints

Perforce

Endpoint: POST /webhooks/perforce

ParameterTypeRequiredDescription
tokenstringYesIntegration webhook token
changelistintegerYesPerforce changelist number
timestampstringNoSubmission timestamp (ISO 8601)

Jenkins

Endpoint: POST /webhooks/jenkins

Body (JSON):

{
  "job_name": "MyGame-Build",
  "build_number": 456,
  "status": "SUCCESS",
  "build_url": "https://jenkins.example.com/job/MyGame-Build/456"
}

Game Engine

EndpointPurpose
POST /webhooks/game_engine/cooking_startedBuild cooking phase started
POST /webhooks/game_engine/asset_cookedIndividual asset cooked
POST /webhooks/game_engine/shaders_startedShader compilation started
POST /webhooks/game_engine/shaders_completedShader compilation finished
POST /webhooks/game_engine/packaging_startedPackaging phase started
POST /webhooks/game_engine/build_completedBuild finished successfully
POST /webhooks/game_engine/build_failedBuild failed

Deployment

Endpoint: POST /webhooks/deployment

Body:

{
  "platform": "steam",
  "event": "uploaded",
  "build_number": 456,
  "steam_app_id": "480"
}

Platform values: steam (alias steamworks), reddit_devvit (aliases reddit, devvit), youtube_playables (aliases youtube, playables), epic_games_store (aliases epic, epic_games), google_play (aliases google, android), apple_app_store (aliases apple, ios, app_store), unity_cloud (alias unity). Any other value is recorded as custom.

CI Systems

EndpointNotes
POST /webhooks/jenkinsJenkins and any other CI system that posts a flat JSON build payload
POST /webhooks/jenkins/build_notificationHMAC-signed build-status callback
POST /webhooks/jenkins/commit_triggerCommit-driven build trigger
POST /webhooks/ciNeutral alias for the three above. Same controller, same payloads - use it when the poster is GitHub Actions, TeamCity, or another non-Jenkins CI
POST /webhooks/buildkiteNative Buildkite intake. Verifies Buildkite’s X-Buildkite-Signature HMAC and rejects anything unsigned or stale

Non-Jenkins CI must push its log

ButterStack polls the Jenkins API for console output, artifacts, and build info. No other CI provider is polled - a CI server inside a studio’s own network is not reachable from ButterStack, and a build_url pointing at an internal host (http://teamcity-server:8111/...) or a private-tailnet address resolves to nothing from the outside.

So for GitHub Actions, TeamCity, or any other non-Jenkins poster, the log has to ride on the webhook payload itself:

{
  "job_name": "PilotLight_Verify",
  "build_number": "298",
  "status": "FAILURE",
  "build_url": "https://teamcity.example.com/buildConfiguration/PilotLight_Verify/298",
  "changelist": "207",
  "logs_tail": "<the last few hundred KB of the build log>"
}

logs_tail (also accepted as log or console) populates output_log, capped at 256,000 characters with the oldest content dropped first. A report that omits it leaves ButterStack with no log for that build.

This is not cosmetic: output_log is the only build output the AI failure investigator can read. Without logs_tail the investigator has no error text to work from and will return a low-confidence infrastructure finding saying so rather than a real diagnosis (#1940).

Other Integrations

IntegrationEndpoint
JiraPOST /webhooks/jira
LinearPOST /webhooks/linear
TrelloPOST /webhooks/trello
Monday.comPOST /webhooks/monday
AsanaPOST /webhooks/asana
GitHubPOST /webhooks/github (requires X-GitHub-Event; X-Hub-Signature-256 when a secret is configured)
DiversionPOST /webhooks/diversion
LorePOST /webhooks/lore - see the Lore integration guide

Each of these except the CI intake also answers GET /webhooks/{platform}/verify, which returns {"status":"verified","service":"..."} for provider handshakes.

Response Codes

CodeDescription
200Event processed, or recognized as a duplicate delivery and skipped
202Event accepted and queued for asynchronous processing (Perforce and Lore return this)
401Missing or invalid token, or a failed signature check
403The integration’s project is paused or archived and cannot receive webhooks
404No active integration matches the token
422Malformed or unparseable body
429Rate limit exceeded
500Internal server error

There is no {project_id} path segment on any webhook endpoint: the token identifies the integration, and therefore the project.

Testing Webhooks

curl -X POST \
  "https://www.butterstack.com/webhooks/perforce" \
  -H "X-ButterStack-Token: YOUR_TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "changelist=12345"

Copyright © 2026 ButterStack. All rights reserved.

Esc
Type to search the documentation