LogoFreestyle

Triggers and Webhooks

Triggers let you automate actions when events occur in your git repositories, such as pushes to specific branches.

Creating a Trigger

Create a webhook trigger that fires on push events.

import { freestyle } from "freestyle-sandboxes";

const { repo } = await freestyle.git.repos.create();

await repo.createTrigger({
  trigger: {
    event: "push",
    branch: ["main"], // optional: filter by branch
    fileGlob: ["*.js"], // optional: filter by file patterns
  },
  action: {
    type: "webhook",
    url: "https://your-webhook-url.com",
  },
});

When your trigger is activated, a payload is sent to the specified URL in the following format.

interface GitTriggerPayload {
  repoId: string;
  branch: string; // The branch that was updated
  commit: string; // The SHA of the commit
}

Local Development

For local development, use a tool like Tailscale to create a secure tunnel to your localhost.

Install Tailscale following the quickstart guide, then expose your local server:

# Replace 3000 with your server's port
tailscale funnel 3000

The output provides a public URL you can use as the webhook URL in your trigger configuration.

Webhook Signing

Webhooks include a signature in the x-freestyle-signature header for verifying request authenticity. The signature is a JWT (EdDSA) containing a body_sha256 field with the SHA256 hash of the webhook payload.

The public key for verification is available at https://git.freestyle.sh/.well-known/jwks.json.

import crypto from 'crypto';
import { createRemoteJWKSet, jwtVerify } from 'jose';

const JWKS = createRemoteJWKSet(
  new URL('https://git.freestyle.sh/.well-known/jwks.json')
);

async function verifyWebhook(request) {
  const signature = request.headers['x-freestyle-signature'];
  const bodyText = await request.text(); // Get raw body text

  // Verify JWT signature
  const { payload } = await jwtVerify(signature, JWKS, {
    algorithms: ['EdDSA'],
  });

  // Verify payload hash
  const payloadHash = crypto
    .createHash('sha256')
    .update(bodyText)
    .digest('hex');

  if (payload.body_sha256 !== payloadHash) {
    throw new Error('Payload verification failed');
  }

  // Parse body after verification
  const body = JSON.parse(bodyText);
  return { payload, body };
}

Listing Triggers

List all triggers for a repository.

const triggers = await repo.listTriggers();
console.log(triggers);

Deleting Triggers

Remove a trigger by its ID.

await repo.deleteTrigger({
  triggerId: "trigger-id",
});

On this page

Freestyle AI

Documentation assistant

Experimental: AI responses may not always be accurate—please verify important details with the official documentation.

How can I help?

Ask me about Freestyle while you browse the docs.