Skip to content

Documentation

Deployments from Vercel

Every production deployment can become a record in Kicklace — named after the commit, with its branch and a link to the build — moving through a pipeline of its own. Once a deploy is a record entering a stage, “when production deploys, draft the changelog email” is an ordinary automation.

Written for the developer who ships on Vercel (#199). Every production deployment becomes a Release in Kicklace — named after the commit, with its branch, its commit message and a link to the build — and releases move through a pipeline of their own, Deployed → Announced. There is no code to write and nothing to deploy.

Why a record and not an event: a deployment is not a person, and the automation engine runs on records. Once a deploy is a record entering a stage, "when production deploys, draft the changelog email" is an ordinary automation over the engine that was already there.

The screen is Settings → Integrations → Vercel, and only an owner or an admin can change it.

There is a shorter way in (#200): pressing Add Integration in Vercel writes Kicklace's keys into your projects for you, allows their addresses, and — in the same click — makes the webhook this page otherwise asks you to register by hand. docs/vercel-integration.md is that door. Everything below is still how it works underneath, and is still the way to set it up when you would rather not install anything.


Setting it up

1. Make the address. Settings → Integrations → Vercel → Connect Vercel. Two things happen: you get an address of the form https://<your Kicklace>/api/webhooks/vercel/<token>, and the workspace gains the Releases object with the pipeline Deployed → Announced. The token is not a secret on its own — the signature is what proves a post came from Vercel — but it is not published either, so a stranger cannot guess your endpoint.

2. Register it in Vercel. Choose your team in the Vercel dashboard, then Settings → Webhooks → Create Webhook. Tick Deployment Succeeded, choose which projects it covers, and paste the address as the endpoint URL. (Account webhooks are a Pro and Enterprise feature, and a team may have up to twenty of them.)

Ticking more events is harmless: everything else is answered 200 and ignored, which is what stops Vercel retrying it.

3. Bring back the secret. The Webhook Created dialog shows a secret key once, and it is not shown again. Paste it into the second step in Kicklace. It is encrypted at rest and never shown back — the screen says "set on the 8th" and offers Replace. Until it is in, nothing is taken: Kicklace answers no_signing_secret and writes the refusal to your heartbeat. If the secret has gone, delete the webhook in Vercel and create it again.

Vercel signs with x-vercel-signature: an HMAC-SHA1 of the raw request body, hex, keyed with that secret. There is no timestamp in the scheme, so there is no skew window to keep. Kicklace compares it in constant time and refuses anything else.

What a deployment becomes

Only deployment.succeeded with target: "production" is a release. A preview is somebody's branch, and deployment.created, deployment.error and deployment.canceled are a build's own progress: a customer hears about what shipped, not about what was attempted.

One release lands in the stage Deployed, with:

Field From
Name the commit message's first line, or Deployment dpl_… when there is no commit
url the deployment's page in Vercel's dashboard, else the deployment's own host
commit the whole commit message
branch the branch it was built from
sha the commit's SHA
deploymentId Vercel's own id for the deployment
deployedAt the day Vercel says the event happened

The commit keys Vercel sends are prefixed with the git provider — githubCommitSha, gitlabCommitMessage, bitbucketCommitRef — and Kicklace reads all three. A deployment made from the CLI carries no commit at all, and that is a real deployment: it is named after its id and the commit fields are left blank.

A deployment lands once. Vercel retries, and a webhook may be delivered more than once; the release is looked up by deploymentId before anything is written, so a second post answers already_recorded, writes nothing, and fires no automation.

The automation to write

Under Automations, by hand or through Claude:

When a Release enters Deployed, draft an email to Product updates from Release notes, for a person to send.

The draft_broadcast action writes the email to that list from that template's words, leaves it in the composer, and tells the workspace's owners and admins that a draft is waiting. Nothing is sent and nothing is scheduled. You open the draft, read what shipped, edit it, and send it yourself — which is the only way a list of people ever hears from you in Kicklace.

Move the release to Announced when you have sent it, or add a move_stage to the automation that sends nothing and only marks it.

What never happens

  • Nothing is ever sent because you deployed. The action drafts; a person sends.
  • Kicklace never talks back to Vercel. It reads the webhook and nothing else: no token, no API call, no deployment of yours started, stopped or promoted from here.
  • Disconnecting keeps your releases. The address stops answering; the Releases object and every release in it stay exactly where they are. A webhook going away is not a reason to throw away what shipped.
  • No traffic. Vercel has no webhook for visitors, so this door carries deployments only. Visits and signups come from Kicklace's own script tag, under Settings → Your website.

What you will see

Every post is one row in your website's heartbeat (Settings → Your website), marked as coming from a server, so Vercel's posts sit beside the website's: On the timeline, That deployment is already a release here, Not something Kicklace records, The signature did not hold.

The answers

Answer HTTP What it means
{ ok: true, status: "recorded", id } 200 A new release, and the trigger fired
{ ok: true, status: "already_recorded", id } 200 This deployment is already here; nothing written
{ ok: true, status: "ignored" } 200 A preview, a failed build, or an event Kicklace has no use for
{ ok: false, error: "unknown_endpoint" } 404 No workspace has that address
{ ok: false, error: "no_signing_secret" } 400 The second step is not done
{ ok: false, error: "bad_signature" } 400 The signature did not match this body
{ ok: false, error: "too_large" } 413 Over 128 KB
{ ok: false, error: "server_error" } 500 Kicklace fell over; Vercel should retry

Checked against Vercel's own documentation on 2026-09-08: https://vercel.com/docs/webhooks, https://vercel.com/docs/webhooks/webhooks-api, and https://vercel.com/docs/headers/request-headers#x-vercel-signature.