---
title: "A link was deleted"
method: POST
path: "link.delete"
tags: ["Webhooks"]
---

# A link was deleted

`POST link.delete` (webhook)

Sent to the acting user's webhooks when a link is deleted (API or dashboard). data is the link as it was before deletion.

Every delivery is an HTTP POST with a JSON body `{event, timestamp, data}`. `X-Flyn-Signature` is `t=<timestamp>,v1=<hex>`, where v1 is HMAC-SHA256 keyed with the full webhook secret (including the `whsec_` prefix) over `<t>.<raw request body>`. To verify: split the header on commas, recompute the HMAC over t, a dot and the raw body bytes (not a re-serialised body), compare in constant time, and reject a t (milliseconds) older than your tolerance. Flyn makes one delivery attempt per event with a 10 s timeout (redirects included). A 2xx answer counts as success; a non-2xx answer counts as a failure, and after 10 counted failures in a row the webhook is set inactive. A URL whose host resolves to a private address or fails DNS resolution is not sent to and counts as a failure. Timeouts, connection errors and redirects to a private host are not counted.

## Headers

- `X-Flyn-Signature` string, required
- `X-Flyn-Event` string, required
- `User-Agent` 'Flyn-Webhook/1.0', required

## Payload

- LinkDeleteEvent
  - `event` 'link.delete', required
  - `timestamp` integer, required: Unix time in milliseconds.
  - `data` Link, required: A short link, as returned by every /api/links endpoint and sent in link.create, link.update and link.delete webhook deliveries. Every field is always present.
    - `id` string, uuid, required: Link id.
    - `slug` string, required: Back-half of the short URL.
    - `url` string, required: Destination URL.
    - `shortUrl` string, uri, required: Full short URL, `https://<domain>/<slug>`.
    - `domain` string, required: Short domain the link lives on. New links default to the current Flyn short domain.
    - `title` string, nullable, required: Display title.
    - `clicks` integer, required: Human clicks (bots and scanners excluded). This is the headline number.
    - `botClicks` integer, required: Clicks filtered out as bots or scanners.
    - `qrScans` integer, required: Clicks that arrived from a Flyn QR code; a subset of `clicks`.
    - `totalClicks` integer, required: `clicks` + `botClicks`.
    - `status` 'active' | 'expired' | 'archived', required: Stored status. A link past `expiresAt` keeps `active` here; the redirect checks the expiry itself.
    - `tags` string[], required
    - `createdAt` string, date-time, required
    - `expiresAt` string, nullable, required: Expiry as stored (ISO 8601), or null.
    - `folderId` string, uuid, nullable, required
    - `password` boolean, required: True when the link is password protected. The password itself is never returned.
    - `ogTitle` string, nullable, required
    - `ogDescription` string, nullable, required
    - `ogImage` string, nullable, required
    - `targeting` Targeting, required: Smart-routing rules as stored. `device` takes four keys, `ios`, `android`, `windows` and `macos`, each applying only to visitors on that operating system, and a device rule takes priority. There is no `desktop` key: Linux, ChromeOS and any other or unrecognised system match no device rule and fall through to the link's other rules. `windows` and `macos` must be http or https URLs, and the aliases `mac`, `osx`, `win`, `desktop` and `linux` are rejected with 400 `INVALID_TARGETING`. `geo` maps ISO 3166-1 alpha-2 country codes (upper case) to a destination and applies to every visitor whose country is known, desktop included. A visitor matching no rule falls through to the rotation, or the legacy A/B split, when one is set, else goes to the link url. A PATCH replaces the whole targeting object; nothing is merged into the stored rules. Safari on an iPad usually sends the same user agent as Safari on a Mac, so on a link with a `macos` destination, Safari on a Mac or an iPad (or any browser sending that same user agent) first loads a blank check page that tells a Mac from an iPad, then continues at once. A browser with JavaScript off continues as a Mac. The check page records no click; the click is recorded once, when the browser continues to the short link with the reserved query parameters `flyn_os` and `flyn_ref` (the original referrer), which are never passed to a destination. Chrome, Edge and Firefox on a Mac skip the check page, and a link without a `macos` rule never shows it. Device and country rules, including the Safari check page, do not apply to password-protected links, to a link that has reached its click limit, or to mailto, tel and sms links.
      - `device` object
        - `ios` string: Destination for iOS visitors, such as an iPhone. Safari on an iPad usually sends the same user agent as Safari on a Mac (see Targeting).
        - `android` string: Destination for Android visitors.
        - `windows` string: Destination for Windows visitors. Must be an http or https URL, for example a Microsoft Store or download page.
        - `macos` string: Destination for Mac visitors. Must be an http or https URL, for example a Mac App Store or download page. Setting it turns on the Safari check page described on Targeting.
      - `geo` object: Country code to destination, for example {"US": "https://example.com/us"}.
    - `cloaking` boolean, required
    - `noIndex` boolean, required: Stored value of the legacy per-link no-index flag. It has no effect on how the link is served: every short link is already served with a noindex robots header on every plan, whether or not this is set.
    - `notes` string, nullable, required: Private notes.
    - `abUrlB` string, nullable, required: Legacy two-way A/B view of `rotation`, kept for older integrations.
    - `abSplit` number, nullable, required: Legacy A/B split: percent kept on the primary url.
    - `rotation` RotationEntry[], nullable, required: Weighted destinations, or null when the link does not rotate.
      - `id` string, required: Stable destination id (8 characters when minted by Flyn). Reported as `variant` on link.click deliveries.
      - `url` string, uri, required: Destination URL.
      - `weight` number, required: Relative weight, not a percentage. Weights are normalised when a visitor is routed.
      - `label` string, nullable, required: Optional display label.
    - `deepLink` boolean, required: Native-app handoff mode on mobile.
    - `pixelIds` string[], required: Retargeting pixels fired on click.
    - `forwardParams` boolean, required: Query-string passthrough to the destination.
    - `clickLimit` integer, nullable, required: Maximum human clicks. Once reached, visitors go to `fallbackUrl`, or to the expired-link page when no http(s) `fallbackUrl` is set.
    - `fallbackUrl` string, nullable, required: Destination after the click limit is reached.
    - `conversionTracking` boolean, required: When true, each human click gets a `flyn_id` click id for conversion pings.
    - `conversions` integer, required: Recorded conversions, net of refunds (never below 0).
    - `conversionValueCents` integer, required: Summed conversion value in minor units.
    - `conversionCurrency` string, nullable, required: Currency of the summed value.

## Acknowledgement `200`

Return any 2xx to acknowledge the delivery.

---

[API](https://skmtc.dev/flyn/apis/flyn-api.md) · [All operations](https://skmtc.dev/flyn/apis/flyn-api/llms.txt) · [OpenAPI document](https://skmtc.dev/flyn/apis/flyn-api/revisions/977962a98ccb?raw)
