Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.hellofriday.ai/llms.txt

Use this file to discover all available pages before exploring further.

HTTP signals receive JSON payloads over POST. The same endpoint serves two use cases:
  • Webhooks from external services (GitHub, Bitbucket, Jira, etc.) delivered through the bundled tunnel
  • Programmatic triggers from the CLI, Studio, or API calls directly against Friday
There’s no separate “manual” signal type — triggering by hand is just a POST to the HTTP signal’s API route.

Config

FieldTypeRequiredDefaultDescription
pathstringYesHTTP path for the webhook (method is always POST)
timeoutstringNoMax time before the signal handler gives up (e.g. 30s, 2m)

Example

workspace.yml
signals:
  new-pr:
    title: "New pull request"
    description: "Fires on GitHub PR events and manual triggers"
    provider: http
    config:
      path: "/pr"
    schema:
      type: object
      properties:
        pr_url: { type: string }
        repo:   { type: string }

Webhook URLs

External services deliver events to the bundled tunnel, which forwards them into Friday. The public URL shape is:
https://{tunnel-domain}/hook/{provider}/{workspaceId}/{signalId}
  • {tunnel-domain} — your Cloudflare tunnel host (ephemeral, shown in Studio → SettingsWebhook tunnel)
  • {provider} — determines how the incoming payload is transformed before reaching your job
  • {workspaceId} — the workspace owning the signal
  • {signalId} — the signal name from workspace.yml

Built-in providers

ProviderBehavior
githubExtracts pr_url from GitHub pull request events
bitbucketExtracts pr_url from Bitbucket pull request events
jiraExtracts issue_key, project_key from Jira issue events
rawForwards the payload as-is (no transformation)
Configure these URLs in the external service’s webhook settings (GitHub repo settings, Bitbucket repository webhooks, Jira automation) to wire them into Friday workflows.

Webhook mappings

The tunnel uses a webhook-mappings.yml file to decide which events to accept and how to extract signal payload fields from incoming webhook bodies. The image ships with sensible defaults for the starter spaces. Each provider entry defines:
  • event_header or event_field — where to find the event type (HTTP header for GitHub/Bitbucket, body field for Jira)
  • signature_header — header used for -SHA256 verification
  • events — map of event names to an optional actions filter and a mapping of output field to dot-path into the webhook body
providers:
  github:
    event_header: x-github-event
    signature_header: x-hub-signature-256

    events:
      pull_request:
        actions: [opened, reopened, synchronize]
        mapping:
          pr_url: "pull_request.html_url"

      issues:
        actions: [opened, labeled]
        mapping:
          issue_url: "issue.html_url"
          issue_key: "issue.number"
          title: "issue.title"
          action: "action"

      push:
        mapping:
          ref: "ref"
          repo: "repository.full_name"
          sha: "after"
          pusher: "pusher.name"

  bitbucket:
    event_header: x-event-key
    signature_header: x-hub-signature

    events:
      "pullrequest:created":
        mapping:
          pr_url: "pullrequest.links.html.href"

      "pullrequest:updated":
        mapping:
          pr_url: "pullrequest.links.html.href"

      "repo:push":
        mapping:
          repo: "repository.full_name"
          branch: "push.changes[0].new.name"
          sha: "push.changes[0].new.target.hash"

  jira:
    event_field: webhookEvent
    signature_header: x-hub-signature

    events:
      "jira:issue_created":
        mapping:
          issue_key: "issue.key"
          project_key: "issue.fields.project.key"
          summary: "issue.fields.summary"
          repo_url: "issue.fields.customfield_10000"

      "jira:issue_updated":
        mapping:
          issue_key: "issue.key"
          project_key: "issue.fields.project.key"
          summary: "issue.fields.summary"
          repo_url: "issue.fields.customfield_10000"

Customizing mappings

Place a custom webhook-mappings.yml in the config/ subdirectory of the Friday home directory (default ~/.atlas/config/webhook-mappings.yml). Friday loads it on startup, overriding the built-in defaults.

Triggering manually

The same signal can be fired directly against Friday — no tunnel, no provider prefix. This is how Studio’s Run button, friday signal trigger, and any API caller invoke HTTP signals.
curl -X POST http://localhost:18080/api/workspaces/<workspaceId>/signals/<signalId> \
  -H 'Content-Type: application/json' \
  -d '{ "payload": { "foo": "bar" } }'
The request body accepts two fields:
FieldTypeDescription
payloadobjectSignal payload — validated against schema if present
streamIdstringOptional stream ID for Server-Sent Events progress
The response is an execution handle that streaming clients can attach to.
friday signal trigger -n <signalId> -w <workspaceId> is the CLI wrapper for this call. See the CLI reference for the full command shape.

Payload validation

If a signal declares a schema block, the payload is validated before the job runs. Invalid requests get a 400 with the specific validation error; the job never starts.
workspace.yml
signals:
  deploy:
    title: "Deploy"
    description: "Trigger a deployment"
    provider: http
    config:
      path: "/deploy"
    schema:
      type: object
      required: [environment, version]
      properties:
        environment:
          type: string
          enum: [staging, production]
        version:
          type: string
          pattern: "^v[0-9]+\\.[0-9]+\\.[0-9]+$"

Signature verification

For external webhooks, the tunnel verifies HMAC-SHA256 signatures using the signature_header defined in the mapping. Set the shared secret on the external service’s side; Friday looks it up from workspace credentials. If signature verification fails, the tunnel returns 401 and the event never reaches Friday.

Troubleshooting

The default development tunnel is ephemeral — it gets a new random URL on every restart. For production, set TUNNEL_TOKEN to use a named Cloudflare tunnel with a stable hostname, or point the external service at a real reverse proxy.
Check that the event type is in the events: list for your provider in webhook-mappings.yml. Events not listed are dropped silently. Also check that actions (if present) includes the action on the incoming event — e.g. GitHub PR events with action: closed are filtered out by the default mapping.
Double-check the dot-paths in the mapping — a typo (e.g. pull_request.url instead of pull_request.html_url) silently resolves to undefined and the job sees an empty payload. Mapping errors don’t fail the webhook; they just produce empty fields.
The shared secret on the external service must match what Friday has stored. For GitHub, set the webhook secret in repo settings and rotate the corresponding Friday credential in the same push. Trailing whitespace in copied secrets is a common cause.