Integrations6 min read

API & Webhooks

Integrate MergeShield into your workflows with the REST API and outgoing webhooks. 65+ endpoints, HMAC-signed payloads.

How the API & webhooks work

Interactive walkthrough · 6 steps · 40 seconds

1Step 1 of 6

API Key Authentication

Create API keys with the msk_ prefix for programmatic access. Keys are SHA-256 hashed and never stored in plaintext.

msk_ prefix

SHA-256 hashed storage. Never stored in plaintext.

Authentication

The MergeShield API supports two authentication methods:

  • Session cookies — For browser-based dashboard access, managed by Better Auth with GitHub OAuth
  • API keys — For programmatic access from scripts, CI/CD pipelines, or external services

API keys are created from the Settings page. Each key has a name, optional expiration date, and scopes. The key format uses an msk_ prefix followed by 40 hexadecimal characters. The key is displayed once at creation time and cannot be retrieved again — only a SHA-256 hash is stored.

To authenticate, include the key in the Authorization header as a Bearer token. Keys can be revoked at any time from the Settings page, which immediately invalidates all requests using that key. See the full API docs for details.

Authenticating with an API key
curl -H "Authorization: Bearer msk_your_api_key_here" \
  -H "X-Org-Id: your-org-id" \
  https://api.mergeshield.dev/api/pulls

Making API Calls

The API base URL is https://api.mergeshield.dev. All protected endpoints require an X-Org-Id header specifying which organization context the request operates in. If your account belongs to a single organization, the API can auto-select it, but explicitly providing the header is recommended.

Response formats:

  • Success: JSON with a data key containing the response payload
  • Error: JSON with an error key containing a code string and human-readable message

Common error codes:

  • UNAUTHORIZED (401) — Missing or invalid authentication
  • FORBIDDEN (403) — Insufficient permissions for the requested action
  • NOT_FOUND (404) — Resource doesn't exist or isn't accessible
  • RATE_LIMITED (429) — Too many requests (see Rate Limits)
  • INTERNAL_ERROR (500) — Server-side error

The API provides over 65 endpoints across 16 resource groups: Pull Requests, Repositories, Analyses, Agents, Trust, Approvals, Risk Policies, Auto-Merge Decisions, Analytics, Notifications, Events (SSE), Organizations, API Keys, Webhooks, Billing, and Audit. Full endpoint documentation is available at mergeshield.dev/docs.

Fetch pull requests for your organization
curl -H "Authorization: Bearer msk_your_api_key_here" \
  -H "X-Org-Id: your-org-id" \
  "https://api.mergeshield.dev/api/pulls?page=1&limit=20"

Rate Limits

API requests are rate-limited using a fixed-window algorithm backed by Redis (with an in-memory fallback when Redis is unavailable):

  • API key auth: 120 requests per minute (keyed by API key prefix)
  • Session auth: 60 requests per minute (keyed by client IP)

When a rate limit is exceeded, the API returns a 429 Too Many Requests response with these headers:

  • Retry-After — Seconds to wait before making another request
  • X-RateLimit-Limit — Your rate limit ceiling
  • X-RateLimit-Remaining — Remaining requests in the current window
  • X-RateLimit-Reset — UTC epoch time when the window resets

For high-throughput integrations, API key authentication is recommended for both the higher rate limit and easier tracking. If you need to perform bulk operations, space requests with a small delay to stay within limits.

Webhook Setup

Outgoing webhooks let MergeShield push events to your own HTTP endpoints in real time. To set up a webhook:

  1. 1Navigate to the Settings page in the dashboard
  2. 2Scroll to the Webhooks section
  3. 3Click Create Webhook
  4. 4Provide an HTTPS URL and optionally select which event types to subscribe to

Webhook payloads are delivered as HTTP POST requests with a JSON body. Each delivery includes three custom headers:

  • X-MergeShield-Signature — HMAC-SHA256 signature for verification
  • X-MergeShield-Event — The event type string (e.g., analysis_completed)
  • X-MergeShield-Delivery — A unique delivery ID for deduplication

Webhooks include automatic health monitoring. After 10 consecutive delivery failures, the subscription is automatically deactivated. You can reactivate it from the Settings page once the endpoint issue is resolved. A test delivery button is available to verify your endpoint.

Webhook Configuration
URLhttps://example.com/webhook
Events
analysis_completedhigh_risk_pr
StatusActive
Last delivery2 min ago, 200 OK

HMAC Verification

Every webhook delivery is signed with HMAC-SHA256 using the secret key generated when you create the subscription. The signature is included in the X-MergeShield-Signature header.

To verify a webhook delivery:

  1. 1Compute the HMAC-SHA256 of the raw request body using your webhook secret as the key
  2. 2Compare the resulting hex digest with the X-MergeShield-Signature header value
  3. 3Use a timing-safe comparison function to prevent timing attacks

If the signature does not match, reject the request with a 401 or 403 status. This protects your endpoint from forged webhook deliveries.

Verify webhook signature in Node.js
const crypto = require("crypto");

function verifyWebhookSignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body, "utf8")
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your Express handler:
app.post("/webhook", (req, res) => {
  const signature = req.headers["x-mergeshield-signature"];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).send("Invalid signature");
  }

  // Process the event
  const event = req.headers["x-mergeshield-event"];
  console.log("Received event:", event, req.body);
  res.status(200).send("OK");
});

Event Types

MergeShield supports seven webhook event types covering the core governance lifecycle:

  • analysis_completed — Fires when a PR risk analysis finishes. Includes the full risk score breakdown and agent detection results.
  • high_risk_pr — Fires specifically for PRs scoring above 50, providing an immediate alert for changes that need attention.
  • auto_merge_approved — Fires when all auto-merge rules pass and a merge is scheduled or executed.
  • auto_merge_blocked — Fires when one or more rules prevent auto-merge, including the specific block reasons.
  • trust_updated — Fires when an agent's trust score changes by 5 or more points. Useful for monitoring agent behavior trends.
  • agent_detected — Fires when a PR is identified as being authored by a known AI agent.
  • approval_required — Fires when a PR triggers an approval workflow, including the risk score and configured escalation reviewers.

All event payloads include the organization ID, repository details, and PR metadata for context. See the webhook documentation for full payload schemas.