Skip to content

Webhooks

Receive real-time notifications when events occur in your Trakkr account. Integrate with Zapier, Make, Slack, Discord, and more.

Code example

Create Webhook
curl -X POST 'https://api.trakkr.ai/webhooks' \
  -H "Authorization: Bearer $TRAKKR_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://hooks.zapier.com/hooks/catch/123456/abcdef","events":["report_completed","rank_changed"],"brand_id":"00000000-0000-4000-8000-81f286d10c3c","auth_type":"none"}'
Response · 200 OK
{
  "id": "whk_abc123xyz",
  "object": "webhook",
  "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef",
  "events": ["report_completed", "rank_changed"],
  "brand_id": "00000000-0000-4000-8000-81f286d10c3c",
  "provider": "zapier",
  "active": true,
  "signing_secret": "redacted-example",
  "created_at": "2026-01-09T10:00:00Z"
}

Synthetic example. Values are made up.

API key required

10 to 60 req/min

Overview

Webhooks allow you to receive real-time HTTP notifications when events occur in your Trakkr account. Instead of polling for changes, webhooks push data to your endpoint the moment something happens.

Supported Integrations

  • • Generic webhooks (any HTTPS endpoint)
  • • Zapier and Make (Integromat)
  • • Slack (with rich block formatting)
  • • Discord (with embed formatting)
  • • Microsoft Teams (with adaptive cards)

Event Types

Subscribe to one or more event types when creating a webhook. Every type listed here has a live producer behind it.

EventDescription
Visibility and competitive position
visibility_changedYour visibility score moved beyond the alert threshold
rank_changedA tracked competitor crossed your brand. Carries competitors_crossed
competitor_changedA competitor's visibility moved beyond the alert threshold
competitor_addedA new competitor was detected or added
report_completedA report finished. report_type is daily for the daily visibility scan, or the document type when you call POST /get-reports
Citations
citation_gainedBrand gained a new citation source
citation_lostA page that was being cited stopped appearing
page_citedOne of your pages was cited by an AI model
Perception
perception_changedA perception score moved
narrative_shiftAI changed how it positions or talks about the brand
descriptor_changeThe words AI uses to describe the brand turned over
goal_achievedA perception goal reached its target
goal_regressionA perception goal slipped off track
Opportunities and content
opportunity_foundA citation opportunity was found
prompt_gapAI answers a prompt with competitors and not you
article_generatedAn article finished generating
article_publishedAn article was marked published
campaign_completedEvery article in a campaign finished
research_completedA research scan finished
Site health and crawlers
audit_score_droppedSite AI readiness score dropped
crawler_spikeAI crawler traffic spiked above its normal daily average
crawler_first_seenAn AI bot crawled one of your pages for the first time
crawler_silentA previously active AI bot stopped visiting
crawler_error_surgeAI crawlers started hitting broken pages
Actions
action_createdA new action landed in the queue
action_completedAn action was marked complete
Client portal
client_invite_acceptedA client accepted their invite to your white-label portal
client_access_revokedA client's portal access was revoked
If you are polling for fresh data, subscribe to report_completed instead. It fires when the daily visibility scan completes and carries that day's visibility along with the change since the previous report, so you can act on the event without a follow-up read.
Cadence differs by family. Crawler events are near real time and crawler_first_seen is the highest volume of all, one per new bot and page pair. Visibility, ranking, citation and competitor events follow the completed daily visibility scan. Content, action and client portal events fire as the work happens.

Create Webhook

POST/webhooks

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

JSON request body (required)

urlstringRequired

HTTPS endpoint URL

eventsstring[]Required

Event types to subscribe to

Fields in events

Array of string.

string.

brand_idstringRequired

Brand UUID

Format: uuid

auth_typestring | nullOptional

Authentication: "none", "bearer", "basic", or "api_key"

Default: "none" · Options: "none", "bearer", "basic", "api_key"

auth_tokenstring | nullOptional

Bearer token (if auth_type is bearer)

auth_usernamestring | nullOptional

auth_passwordstring | nullOptional

api_key_headerstring | nullOptional

api_key_valuestring | nullOptional

signing_secretstring | nullOptional

Custom signing secret (auto-generated if omitted)

headersobject | nullOptional

payload_templateobject | nullOptional

Responses and errors
200Successful Response

application/json

idstringRequired

objectstringOptional

Default: "webhook"

urlstringRequired

eventsstring[]Required

Fields in events

Array of string.

string.

brand_idstringRequired

providerstringRequired

activebooleanRequired

signing_secretstring | nullOptional

created_atstringRequired

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source

Register a new webhook endpoint to receive event notifications.

The provider is automatically detected from the URL. Trakkr will format payloads appropriately for Slack blocks, Discord embeds, and Teams cards.

Payload Format

Webhook payloads follow a consistent structure across all event types:

Webhook Payload · 200 Delivered
{
  "event": {
    "id": "evt_xyz789abc",
    "type": "visibility_changed",
    "triggered_at": "2026-01-09T14:30:00Z",
    "data": {
      "brand_id": "00000000-0000-4000-8000-81f286d10c3c",
      "previous_score": 42.5,
      "current_score": 38.2,
      "change_percent": -10.1,
      "direction": "down"
    }
  },
  "brand": {
    "id": "00000000-0000-4000-8000-81f286d10c3c",
    "name": "Notion",
    "website": "https://notion.so"
  },
  "workflow": {
    "id": "wf_123abc",
    "name": "Visibility Drop Alert"
  },
  "summary": "Visibility dropped 10.1% from 42.5 to 38.2",
  "meta": {
    "source": "trakkr",
    "version": "2.0",
    "event_id": "evt_xyz789abc",
    "timestamp": "2026-01-09T14:30:00Z"
  }
}

Synthetic example. Values are made up.

Use the meta.event_id field for idempotency. Store processed event IDs to prevent duplicate handling if a webhook is retried.

Payload Templating

Customize webhook payloads using variable substitution with double curly braces:

{
  "text": "Alert: {{brand.name}} visibility changed!",
  "score": "{{event.data.current_score}}",
  "change": "{{event.data.change_percent}}%"
}

Available Variables

{{brand.id}}{{brand.name}}{{brand.website}}{{event.type}}{{event.data.*}}{{summary}}{{workflow.name}}{{timestamp}}

Authentication

Secure your webhook endpoints with one of the supported authentication methods:

Bearer Token

Set auth_type: "bearer" and provide auth_token. The token is sent in the Authorization: Bearer header.

Basic Auth

Set auth_type: "basic" with auth_username and auth_password.

API Key Header

Set auth_type: "api_key" with api_key_header and api_key_value.

Signature Verification

Verify webhook authenticity using HMAC-SHA256 signatures. When you provide asigning_secret, every request includes an X-Trakkr-Signature header.

X-Trakkr-Signature: sha256=abc123def456...

Verification Example (Python)

import hmac
import hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

Retry Logic

Webhooks are retried automatically on failure with exponential backoff:

3 retries with delays of 1s, 2s, 4s (exponential backoff)

5xx errors and timeouts trigger retries

429 rate limits respect the Retry-After header

4xx client errors (except 429) are not retried. Ensure your endpoint returns 2xx status codes to acknowledge receipt.

Provider-Specific Formatting

Trakkr automatically formats payloads for popular platforms:

Discord

Rich embeds with title, description, fields, and Trakkr green accent color.

Slack

Block Kit formatting with headers, sections, and context elements.

Zapier & Make

Standard JSON payload with all fields available for mapping.

Manage webhooks

List webhooks with an optional brand filter, inspect one endpoint, remove it or send a test event. Each operation checks your API key and access.

GET /webhooks
GET/webhooks

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Request parameters

brand_idstring | nullqueryOptional

Filter by brand UUID

Format: uuid

Responses and errors
200Successful Response

application/json

webhooksobject[]Required

Fields in webhooks

Array of object.

idstringRequired

objectstringOptional

Default: "webhook"

urlstringRequired

eventsstring[]Required

Fields in events

Array of string.

string.

brand_idstringRequired

providerstringRequired

activebooleanRequired

signing_secretstring | nullOptional

created_atstringRequired

totalintegerRequired

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source
GET /webhooks/{webhook_id}
GET/webhooks/{webhook_id}

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Request parameters

webhook_idstringpathRequired

Responses and errors
200Successful Response

application/json

idstringRequired

objectstringOptional

Default: "webhook"

urlstringRequired

eventsstring[]Required

Fields in events

Array of string.

string.

brand_idstringRequired

providerstringRequired

activebooleanRequired

signing_secretstring | nullOptional

created_atstringRequired

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source
DELETE /webhooks/{webhook_id}
DELETE/webhooks/{webhook_id}

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Request parameters

webhook_idstringpathRequired

Responses and errors
200Successful Response

application/json

successbooleanRequired

deleted_idstringRequired

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source
POST /webhooks/{webhook_id}/test
POST/webhooks/{webhook_id}/test

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Request parameters

webhook_idstringpathRequired

Responses and errors
200Successful Response

application/json

successbooleanRequired

status_codeinteger | nullOptional

response_time_msinteger | nullOptional

errorstring | nullOptional

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source