Skip to main content

Setup

1

Open your application settings

Navigate to your application’s Issues settings in the Nightwatch dashboard.
2

Add a webhook

In the Webhooks section, configure your webhook:
  • Name: A descriptive label for your reference (e.g., “Slack notifications”, “Internal API”)
  • URL: An HTTPS endpoint that accepts POST requests
Only one webhook per application is allowed. To change the URL or name, edit the existing webhook configuration.

Request format

Every webhook request is an HTTP POST with a JSON body of this shape:
FieldTypeDescription
eventstringEvent type (e.g. issue.opened, issue.resolved)
timestampstringISO 8601 datetime when the event was sent (e.g. 2026-02-18T12:00:00.000000Z)
payloadobjectEvent data (see below) plus metadata
The payload object always includes:
FieldTypeDescription
webhook_idstringUUID of the webhook
application_idstringUUID of the application
organization_idstringUUID of the organization
Plus the event-specific fields described for each event below.

Events

issue.opened

Sent when a new issue is created (first time the exception or performance problem is detected). When it fires: A new issue is created for the application (e.g. new exception group or new slow route/job). Payload (in addition to metadata):
FieldTypeDescription
issueobjectThe issue (see Issue object)
environmentobjectEnvironment where the issue was detected (see Environment object)

issue.reopened

Sent when an issue that was previously resolved is seen again and reopened. When it fires: The same exception or performance issue is detected again after the issue was closed. Payload (in addition to metadata):
FieldTypeDescription
issueobjectThe issue (see Issue object)
environmentobjectEnvironment where the issue was detected (see Environment object)

issue.ignored

Sent when an issue’s status is set to Ignored. When it fires: A user (or automation) marks the issue as ignored. Payload (in addition to metadata):
FieldTypeDescription
issueobjectThe issue (see Issue object)
actorobjectUser who performed the action, if any (see Actor object)

issue.resolved

Sent when an issue’s status is set to Resolved. When it fires: A user (or automation) marks the issue as resolved. Payload (in addition to metadata):
FieldTypeDescription
issueobjectThe issue (see Issue object)
actorobjectUser who performed the action, if any (see Actor object)

Shared payload objects

Issue object

FieldTypeDescription
idstringIssue UUID
refintDisplay number (e.g. issue #123)
typestring"exception" or "alert"
titlestringIssue title
statusstring"open", "resolved", or "ignored"
prioritystring"none", "low", "medium", or "high"
urlstringLink to the issue in the dashboard

Environment object

FieldTypeDescription
idstringEnvironment UUID
namestringEnvironment name

Actor object

Present when the action was performed by a user.
FieldTypeDescription
idstringUser UUID
namestringUser display name
emailstringUser email
typestringAlways "user"

Example request

{
  "event": "issue.resolved",
  "timestamp": "2026-02-18T12:00:00.000000Z",
  "payload": {
    "issue": {
      "id": "9d4e2c1a-1234-5678-abcd-ef0123456789",
      "ref": 42,
      "type": "exception",
      "title": "Illuminate\\Database\\QueryException: SQLSTATE[23502]...",
      "status": "resolved",
      "priority": "high",
      "url": "https://nightwatch.laravel.com/us/applications/cf592d1a-5f91-4f3c-9c10-8c67013c4469/issues/42"
    },
    "actor": {
      "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
      "name": "Jane Doe",
      "email": "jane@example.com",
      "type": "user"
    },
    "webhook_id": "fa2d5c2d-3b8c-41ad-8cf6-52f80d446818",
    "application_id": "cf592d1a-5f91-4f3c-9c10-8c67013c4469",
    "organization_id": "9cfeeac6-d449-4924-852b-c3a3294db9c2"
  }
}

Verifying signatures

Each webhook request includes a Nightwatch-Signature header that allows you to verify the request came from Nightwatch and has not been tampered with.
1

Get your signing secret

You can find and copy the signing secret at any time in your application’s Issues settings > Webhooks > Edit.
2

Compute the expected signature

Using the raw request body (the exact JSON string received) and your signing secret, compute an HMAC-SHA256 signature:
  • Algorithm: HMAC-SHA256
  • Message: Raw request body
  • Key: Your webhook signing secret
3

Compare signatures

Compare the computed signature with the Nightwatch-Signature header using a constant-time comparison to prevent timing attacks. If they match, the request is authentic.
Store your webhook signing secret in your application’s configuration file or environment variables for security.
Laravel example:
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class NightwatchWebhookController extends Controller
{
    public function handle(Request $request): Response
    {
        $payload = $request->getContent();
        $signature = $request->header('Nightwatch-Signature');
        $secret = config('services.nightwatch.webhook_secret');
        
        $expectedSignature = hash_hmac('sha256', $payload, $secret);
        
        if (! hash_equals($expectedSignature, $signature)) {
            abort(401, 'Invalid signature');
        }
        
        // Process the verified webhook payload
        $data = json_decode($payload, true);
        
        // Handle the webhook event based on $data['event']
        match ($data['event']) {
            'issue.opened' => $this->handleIssueOpened($data['payload']),
            'issue.resolved' => $this->handleIssueResolved($data['payload']),
            'issue.reopened' => $this->handleIssueReopened($data['payload']),
            'issue.ignored' => $this->handleIssueIgnored($data['payload']),
            default => logger()->info('Unknown webhook event', ['event' => $data['event']]),
        };
        
        return response()->json(['status' => 'success']);
    }
    
    private function handleIssueOpened(array $payload): void
    {
        // Handle new issue notification
    }
    
    private function handleIssueResolved(array $payload): void
    {
        // Handle issue resolution notification
    }
    
    private function handleIssueReopened(array $payload): void
    {
        // Handle issue reopening notification
    }
    
    private function handleIssueIgnored(array $payload): void
    {
        // Handle issue ignored notification
    }
}
Configuration example (config/services.php):
return [
    // Other service configurations...
    
    'nightwatch' => [
        'webhook_secret' => env('NIGHTWATCH_WEBHOOK_SECRET'),
    ],
];