Blog

Create short links in GitHub Actions

, updated

Install the flared CLI in the job, give it an API token in FLARED_TOKEN, and run flared link create URL --json. The workflow below makes a short link for each GitHub release, tags it with UTM parameters, and adds it to the release notes.

What you need

  • A Flared account. Free works and includes the API and the CLI.
  • An API token. In the dashboard, open Connections, API tokens, and create one with the links:write scope. Add domains:read if links go on your own domain.
  • The token as a repository secret named FLARED_TOKEN, under Settings, Secrets and variables, Actions.

The workflow

Save this as .github/workflows/release-link.yml:

name: Release short link
on:
  release:
    types: [published]
permissions:
  contents: write
jobs:
  link:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm install -g @flaredlink/cli
      - name: Create the short link
        id: link
        env:
          FLARED_TOKEN: ${{ secrets.FLARED_TOKEN }}
          TAG: ${{ github.event.release.tag_name }}
          URL: ${{ github.event.release.html_url }}
        run: |
          slug="release-$(echo "$TAG" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9\n' '-')"
          short=$(flared link create "$URL" --slug "$slug" \
            --idempotency-key "release-${{ github.event.release.id }}" \
            --utm-source github --utm-medium release --utm-campaign "$slug" \
            --json | jq -r '.link.shortUrl')
          echo "url=$short" >> "$GITHUB_OUTPUT"
          echo "Short link: $short" >> "$GITHUB_STEP_SUMMARY"
      - name: Add it to the release notes
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ github.event.release.tag_name }}
        run: |
          notes=$(gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json body -q .body)
          gh release edit "$TAG" --repo "$GITHUB_REPOSITORY" \
            --notes "$notes"$'\n\n'"Share this release: ${{ steps.link.outputs.url }}"

When you publish a release such as v2.4.0, the job:

  1. Installs the CLI (npm install -g @flaredlink/cli), which needs Node.js 20 or later.
  2. Makes a slug from the tag, release-v2-4-0: Flared slugs use lowercase letters, digits, and hyphens.
  3. Creates the link to the release page, with utm_source=github, utm_medium=release, and the slug as utm_campaign on the destination.
  4. Reads the short address from the JSON output, writes it to the job summary, and appends it to the release notes with the GitHub CLI.

Re-runs do not make a second link

A job that fails after the create step will run again, and a create that runs twice must not fail on its own slug. The --idempotency-key option handles this: for 24 hours, a create with the same key and the same input returns the link from the first run instead of a new one. The key here is the release ID, which stays the same across re-runs.

After 24 hours, a second create with the same slug fails with SLUG_TAKEN and exit code 6. Flared keeps every slug reserved, even after you turn a link off, so an old short address never points somewhere new.

Exit codes for your scripts

The CLI returns stable exit codes, so a step can react to the reason for a failure: 0 success, 3 not signed in, 4 not allowed, 6 rejected input such as a taken slug, 7 plan limit, 8 rate limited, and 9 service unavailable. With --json, the error goes to standard error as {"error": {"code", "message", "requestId"}}.

Use your own domain

Add --domain with a subdomain that you set up in Flared, such as go.example.com. The CLI checks that the domain is active before it creates the link, which needs the domains:read scope on the token.

flared link create "$URL" --slug "$slug" --domain go.example.com --json

See custom domains for the CNAME record. Free includes 5 custom domains.

Other ways to call Flared

  • Without Node.js, call the REST API with curl. Send an Idempotency-Key header; the API requires one on every create.
  • Read clicks from the same job with flared analytics release-v2-4-0 --json.
  • For a self-hosted Flared, set FLARED_API_URL to its API address, such as https://links.example.com/v1.
  • To ask for links in a chat instead, connect an AI assistant to the MCP server.