Create webhook destinations where you want to receive webhook events.

Creating a webhook destination

You can create a destination by clicking the “New Destination” button in the Destinations view.

Understanding webhook destination fields

At least one webhook filter must be created before you can create a webhook destination.
The Name, URL, and Event Filters fields are required. All other fields are optional.
FieldDescription
Name *The name of the destination.
URL *The URL to send the event to.
ProjectsThe projects from which Findings will trigger events.
Event FiltersThe filters to use for the destination. You can select multiple filters.
EnabledWhether sending events to the destination is enabled.
HeadersAdditional HTTP headers to send with the event.
Auth HeadersAuthentication specific HTTP headers to send with the event.
Auth headers values must be created as secure Secrets in the Integrations —> Secrets view.

Webhook payloads

Webhook events are sent as JSON payloads to the destination URL. The Content-Type header is always application/json.
{
  "event_type": "finding_pinned",
  "timestamp": "2025-08-15T22:27:39.047356Z",
  "delivery_id": "ea2482c1-f928-4763-a9d0-245c456d03e2",
  "data": {
    "resource_type": "finding",
    "resource": {
      "agent_name": "race",
      "attack_feasibility": "easy",
      "attack_walkthrough": "1. The attacker authenticates as a valid user and identifies two accounts they control.\n2. The attacker crafts multiple concurrent POST requests to the /api/v3/transfer endpoint.",
      "class": "race",
      "confidence": "high",
      "created_at": "2025-08-15T22:27:39.047356Z",
      "description": "The MakeTransfer handler performs a read-modify-write sequence on account balances without any locking or database transaction, making it vulnerable to race conditions.",
      "endpoint_method": "POST",
      "endpoint_path": "/api/v3/transfer",
      "fixed_code_block": "tx := db.Begin()\nres := tx.Clauses(clause.Locking{Strength: \"UPDATE\"}).Where(&models.Account{\n\tToken:     input.AccountFrom,\n\tPartition: currentUser.Partition,\n}).First(&source)",
      "handler_class_name": "ApiController",
      "handler_method_name": "MakeTransfer",
      "id": "race-3f1174136e93fdf8d26511869343804fddcfeb0a948aa81aafa352f3612dd500",
      "location": {
        "file_path": "handlers/transfers.go",
        "hash": "70a9f266f7e90b1ea18bd82ed6700128c3da974e95d6d19cae7844b2de44038a",
        "line": 23,
        "url": "https://gitlab.com/ghostsecurity/ghostbank-go/-/blob/981be7365cc7b7da32d5ab28e635f6d35b0ff4f1/handlers/transfers.go#L23"
      },
      "name": "Race condition in account balance update allows overdrawing via concurrent transfers",
      "project_id": "5d41402abc4b2a76b9719d911017c592",
      "remediation": "Wrap the balance check and update logic in a database transaction and use row-level locking (e.g., SELECT ... FOR UPDATE) to prevent concurrent modifications.",
      "remediation_effort": "easy",
      "repo_commit_hash": "981be7365cc7b7da32d5ab28e635f6d35b0ff4f1",
      "repo_id": "1e7d8c9b-ce80-41ae-8645-5b2a89165615-gitlab-69265683",
      "repo_url": "https://gitlab.com/ghostsecurity/ghostbank-go",
      "severity": "high",
      "status": "open",
      "supporting_files": [
        {
          "file_path": "handlers/transfers.go",
          "hash": "70a9f266f7e90b1ea18bd82ed6700128c3da974e95d6d19cae7844b2de44038a",
          "line": 23,
          "url": "https://gitlab.com/ghostsecurity/ghostbank-go/-/blob/981be7365cc7b7da32d5ab28e635f6d35b0ff4f1/handlers/transfers.go#L23"
        }
      ],
      "updated_at": "2025-08-15T22:27:39.047356Z",
      "user_status": "active",
      "vulnerable_code_block": "// find source account\nres := db.Where(&models.Account{\n\tToken:     input.AccountFrom,\n\tPartition: currentUser.Partition,\n}).First(&source)"
    }
  }
}

Webhook event retries

Ghost webhook events are retried up to 5 times if the destination URL returns a status code of 400 or above within 10 seconds. The retry interval is as follows (after the initial attempt):
  • +5s
  • +10s
  • +20s
  • +40s
  • +60s

Webhook source IP

All Ghost webhook events are sent from a static source IP address. You may need to allowlist this IP address to ensure that webhook events are not blocked by a firewall.
34.56.55.29