Back to docs

Events

Event types

Payload reference for link, campaign, post, and test events.

Call GET /v1/webhooks/event-types for the live catalog in your environment. Subscribe to specific types per endpoint, or pass an empty eventTypes array to receive all events.

webhook.test is only sent when you click Send test; it is not emitted by normal workspace activity.

Event envelope

Every delivery uses the same top-level shape. Event-specific fields live under data.object:

FieldTypeDescription
idstringUnique event id. Same value as the Styrar-Event-Id header.
typestringEvent name (for example link.clicked).
api_versionstringPayload schema version (2026-06-22).
created_atstringISO 8601 timestamp when the event was created.
workspace.typestringcompany or personal.
workspace.company_idstring | nullCompany id when workspace.type is company.
data.objectobjectEvent payload (documented per event below).

Full delivery example (envelope + link.created payload):

JSON
{
  "id": "evt_outbox_abc123",
  "type": "link.created",
  "api_version": "2026-06-22",
  "created_at": "2026-06-22T12:00:00.000Z",
  "workspace": {
    "type": "company",
    "company_id": "cmxyz_company"
  },
  "data": {
    "object": {
      "id": "clink_abc123",
      "short_code": "summer",
      "title": "Summer sale",
      "original_url": "https://example.com/sale",
      "is_active": true,
      "company_id": "cmxyz_company",
      "campaign_id": "ccamp_abc",
      "link_group_id": null,
      "created_at": "2026-06-22T12:00:00.000Z"
    }
  }
}

For personal workspaces, workspace.type is personal and workspace.company_id is null. The payload may include company_id: null on link objects.

Event summary

EventWhen it firesTypical volume
link.createdA short link is created (POST /v1/links, bulk create, or bulk upsert)Low
link.updatedA short link is updated (PATCH /v1/links/:id, bulk update, or bulk upsert)Low
link.deletedA short link is soft-deleted (DELETE /v1/links/:id or bulk delete)Low
link.clickedA tracked click is recorded (async, after redirect via click worker)High
link.experiment.completedAn A/B link experiment is completed and a winner is selectedLow
campaign.createdA campaign is created (POST /v1/campaigns)Low
post.publishedA social post publishes successfully to all platform targetsLow
webhook.testYou run Send test on an endpointOn demand

link.created

Fires when a new short link is saved in your workspace.

Common uses: Sync new links to a CRM, trigger welcome automations, or index links in an external search store.

data.object fields:

FieldTypeDescription
idstringLink id
short_codestringPublic short code
titlestring | nullLink title
original_urlstring | nullDestination URL
is_activebooleanWhether the link is active
company_idstring | nullOwning company (company workspace)
campaign_idstring | nullLinked campaign, if any
link_group_idstring | nullFolder/group id, if any
created_atstringISO 8601 creation time
JSON
{
  "id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale",
  "original_url": "https://example.com/sale",
  "is_active": true,
  "company_id": "cmxyz_company",
  "campaign_id": "ccamp_abc",
  "link_group_id": null,
  "created_at": "2026-06-22T12:00:00.000Z"
}

link.updated

Fires when an existing short link is modified (destination, title, tags, folder, UTM settings, etc.).

Common uses: Keep external systems in sync when a link changes without recreating it.

data.object fields: Same as link.created (see above).

JSON
{
  "id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale (updated)",
  "original_url": "https://example.com/sale-v2",
  "is_active": true,
  "company_id": "cmxyz_company",
  "campaign_id": "ccamp_abc",
  "link_group_id": "lgrp_promos",
  "created_at": "2026-06-22T12:00:00.000Z"
}

link.deleted

Fires when a short link is soft-deleted (isActive set to false). The link stops resolving publicly but remains in your workspace history.

Common uses: Remove links from external catalogs or pause automations tied to that short code.

data.object fields: Same shape as link.created, with is_active always false.

FieldTypeDescription
idstringLink id
short_codestringShort code at time of deletion
titlestring | nullLink title
original_urlstring | nullDestination URL
is_activebooleanfalse after soft delete
company_idstring | nullOwning company
campaign_idstring | nullLinked campaign, if any
link_group_idstring | nullFolder/group id, if any
created_atstringOriginal creation time
JSON
{
  "id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale",
  "original_url": "https://example.com/sale",
  "is_active": false,
  "company_id": "cmxyz_company",
  "campaign_id": "ccamp_abc",
  "link_group_id": null,
  "created_at": "2026-06-22T12:00:00.000Z"
}

link.clicked

Fires after a visitor click is persisted. Delivered asynchronously (not on the redirect path), so expect slight delay under load.

Common uses: Real-time click analytics, geo-based routing in your stack, CRM activity feeds, or warehouse ingestion.

Privacy: Payloads include geo and device dimensions, not raw IP addresses.

data.object fields:

FieldTypeDescription
idstringLink id
link_idstringSame as id
short_codestringShort code that was clicked
titlestring | nullLink title
countrystring | nullISO country code (geo lookup)
citystring | nullCity from geo lookup
devicestring | nullDevice class (for example mobile, desktop)
browserstring | nullBrowser name
osstring | nullOperating system
platformstring | nullPlatform hint from user agent parsing
referrerstring | nullReferrer URL when available
routing_rule_idstring | nullMatched geo/device routing rule, if any
experiment_variant_idstring | nullA/B variant id when click went through an experiment
clicked_atstringISO 8601 click time
JSON
{
  "id": "clink_abc123",
  "link_id": "clink_abc123",
  "short_code": "summer",
  "title": "Summer sale",
  "country": "NL",
  "city": "Amsterdam",
  "device": "mobile",
  "browser": "Chrome",
  "os": "iOS",
  "platform": null,
  "referrer": "https://instagram.com/",
  "routing_rule_id": null,
  "experiment_variant_id": null,
  "clicked_at": "2026-06-22T12:00:00.000Z"
}

link.experiment.completed

Fires when an A/B test on a short link is marked complete and a winning variant is selected.

Common uses: Log experiment outcomes, update dashboards, or trigger follow-up campaigns based on the winner.

data.object fields:

FieldTypeDescription
idstringExperiment id
link_idstringParent link id
short_codestring | nullParent link short code
statusstringcompleted
assignment_modestring | nullHow traffic was split (for example weighted)
winning_variant_idstring | nullId of the winning variant
ended_atstring | nullISO 8601 completion time
variantsarrayPer-variant results (see below)

Each item in variants:

FieldTypeDescription
idstringVariant id
labelstringHuman-readable label
weightnumberTraffic weight used in the test
destination_urlstringURL this variant sent traffic to
clicksnumberTotal clicks recorded for this variant
JSON
{
  "id": "lexp_abc123",
  "link_id": "clink_abc123",
  "short_code": "summer",
  "status": "completed",
  "assignment_mode": "weighted",
  "winning_variant_id": "lvar_b",
  "ended_at": "2026-06-22T14:00:00.000Z",
  "variants": [
    {
      "id": "lvar_a",
      "label": "Control",
      "weight": 50,
      "destination_url": "https://example.com/a",
      "clicks": 120
    },
    {
      "id": "lvar_b",
      "label": "Variant B",
      "weight": 50,
      "destination_url": "https://example.com/b",
      "clicks": 184
    }
  ]
}

campaign.created

Fires when a new campaign is created in your workspace.

Common uses: Provision campaign folders in external tools, start attribution workflows, or notify account managers.

data.object fields:

FieldTypeDescription
idstringCampaign id
namestringCampaign name
descriptionstring | nullCampaign description
company_idstring | nullOwning company
user_idstring | nullCreating user (personal campaigns)
brand_idstring | nullBrand scope when set
created_atstringISO 8601 creation time
JSON
{
  "id": "ccamp_abc123",
  "name": "Summer launch",
  "description": "Q2 product push",
  "company_id": "cmxyz_company",
  "user_id": null,
  "brand_id": "cbrand_abc",
  "created_at": "2026-06-22T12:00:00.000Z"
}

post.published

Fires when a scheduled or immediate post publishes successfully to all configured platform targets.

Common uses: Notify downstream systems that content is live, close the loop on campaign automations, or sync publish state to a data warehouse.

Note: Only emitted when every target succeeds. Partial failures do not emit this event today.

data.object fields:

FieldTypeDescription
idstringPost id
post_idstringSame as id
statusstringPUBLISHED
company_idstring | nullOwning company
user_idstring | nullOwning user (personal workspace)
brand_idstring | nullBrand scope when set
campaign_idstring | nullLinked campaign when set
published_atstringISO 8601 publish time
platform_countnumberNumber of platform targets on the post
JSON
{
  "id": "cpost_abc123",
  "post_id": "cpost_abc123",
  "status": "PUBLISHED",
  "company_id": "cmxyz_company",
  "user_id": null,
  "brand_id": "cbrand_abc",
  "campaign_id": "ccamp_abc123",
  "published_at": "2026-06-22T12:00:00.000Z",
  "platform_count": 3
}

webhook.test

Synthetic ping sent only when you click Send test in the dashboard or call POST /v1/webhooks/endpoints/:id/test.

Common uses: Validate your receiver URL, TLS, signature verification, and response handling before going live.

data.object fields:

FieldTypeDescription
endpoint_idstringEndpoint that received the test
messagestringFixed message: Styrar webhook test ping
JSON
{
  "endpoint_id": "wh_ep_abc123",
  "message": "Styrar webhook test ping"
}

Join the beta waitlist

By signing up you agree to receive marketing email. See our Privacy Policy.