# Webhooks and signals

> Start a workflow from another system's request or from a market signal. Set up an incoming webhook or a signal monitor under Automations, with its checks, duplicate handling and limits.

Source: https://orbitalaip.com/docs/workflows/webhooks-and-signals

## Where webhooks and signals live

Incoming webhooks and signal monitors start from **Automations** (the lightning button): click **Add automation**, then **Configure** on **Incoming webhook** or **Monitor a signal**; see [Where schedules live](https://orbitalaip.com/docs/workflows/schedules#where-schedules-live).

Automated runs use the workflow's [main](https://orbitalaip.com/docs/glossary#main) version once it has one; a workflow with no main runs the canvas. See [Main](https://orbitalaip.com/docs/workflows/runs-and-versions#main).

## Set up an incoming webhook

1. **Open the webhook setup**
   
   In **Automations**, click **Configure** on **Incoming webhook**.

2. **Name it and pick a sender preset**
   
   Give it a **Name**, then pick a **Sender preset**.

3. **Set the checks**
   
   Choose **Authenticate requests** and **Duplicate deliveries**, described below.

4. **Map the payload**
   
   Under **Payload fields**, click **Add field** for each value the workflow should read from the request. This is optional unless the workflow needs an asset.

5. **Create it and copy the URL**
   
   Check the **Run policy**, then click **Create webhook**. Click **Copy**, paste the URL into the sending system, then click **Done**.

Editing the webhook shows the URL again under **Active endpoint**, and a **Trigger** node shows it under **Webhook URL**.

### Authentication

With **Private URL token**, the long token at the end of the URL is the credential, so share the URL only with the sending system. You can also tick **Also require secret text in the request body** and set a **Body secret** that must appear in the raw body. This suits TradingView alerts, which cannot be signed.

With **Signed request (HMAC)**, set the **Signature header** the sender uses, such as `x-signature`, and paste the **Shared secret** you gave the sender. Orbital compares the header with an HMAC-SHA256 hex digest of the exact request body, with or without a `sha256=` prefix. Without a secret the webhook cannot be activated.

### Presets

| Preset | Authentication | Duplicates | Payload fields |
| --- | --- | --- | --- |
| Generic webhook | Private URL token | Provider delivery ID, header x-orbital-delivery-id | none |
| TradingView | Private URL token | Same-body window | symbol, action and price (a Number), added when the list is empty |
| GitHub | Signed request (HMAC), header x-hub-signature-256 | Provider delivery ID, header x-github-delivery | none |

For **GitHub**, set the repository webhook's content type to `application/json`, because a form-encoded body is not split into fields.

### Duplicate deliveries

- **Provider delivery ID** reads the header named in **Delivery ID header** and does not run a delivery whose ID was seen before. A request without the header counts as new.

- **Same-body window** treats identical bodies within one block of **Duplicate window (seconds)**, default 300, as one delivery. Blocks follow the clock, so a retry just after a block ends runs again.

- **Allow repeated deliveries** runs every request, so repeated requests can start repeated billable runs.

### Payload fields

Each mapping reads an **Incoming JSON path**, such as `data.symbol`, into a **Workflow input**, such as `asset`, as a **Value type** such as **Number** or **Ticker → asset**. The mapped values fill the run inputs that **Run** asks for. With no mapping, a **Trigger** node exposes the parsed body on its **Payload** port.

**Ticker → asset** turns a ticker into the asset the workflow works on. A workflow that needs an asset cannot be activated until a mapping fills that input, usually with **Ticker → asset**. Until then the form shows **Required asset mapping missing**; **Add required mapping** adds one that reads `symbol`.

### What the endpoint accepts

Send a POST request with a JSON body of up to 1 MB. A plain-text body is also read: `key: value` pairs, one per line or separated by pipes, or `symbol, action, price` separated by commas. Other text arrives whole under `raw`.

For the replies to a refused request, see [A webhook is refused](https://orbitalaip.com/docs/workflows/troubleshooting#a-webhook-is-refused).

## Set up a signal monitor

1. **Open the signal setup**
   
   In **Automations**, click **Configure** on **Monitor a signal**.

2. **Choose what to watch**
   
   Under **1. Choose what to watch**, pick a source card.

3. **Define the condition**
   
   Under **2. Define the condition**, select an active listed stock in **Asset** and pick a **Condition**. A threshold condition shows a field named after the measure, such as **Session change**.

4. **Review source freshness**
   
   Under **3. Review source freshness**, **Expected freshness** says how often the source is checked. Orbital picks the cadence.

5. **Activate it**
   
   Check the **Run policy**. The **Review** box reads your condition in words, such as **Run when AAPL crosses above 3%**. Click **Activate monitor**.

### Sources

Each source watches a single listed stock and is checked about every 5 minutes. **Price move (% today)** takes readings only while the regular US session is open.

| Source | Fires when | Conditions |
| --- | --- | --- |
| News | a news article is published about the asset | Any new event |
| Price move (% today) | the asset's session change meets your condition | the value conditions on Session change (%) |
| Analyst ratings | an analyst publishes or revises a rating or price target | Any new event, or the value conditions on Price target (USD) |
| SEC 8-K disclosures | the company files an 8-K | Any new event |
| Corporate guidance | the company issues or revises financial guidance | Any new event |

### Conditions

- **Any new event** starts a run for every new item.

- **Value is above** and **Value is below** compare each reading with your value.

- **Crosses above**, **Crosses below** and **Crosses in either direction** fire when the value moves through yours from one reading to the next. On **Analyst ratings**, each new price target is a reading.

- **Enters a range** fires when the value moves from outside to inside the range from one reading to the next.

On **Price move (% today)**, each condition fires at most once per trading session in each direction. The first check after you save sets the baseline, whatever the condition, so nothing that happened before starts a run. The run's payload carries the event, with the reading and the direction of the move.

If too many monitors already watch a source and asset, setup is refused with a message that the platform monitor limit has been reached.

## The run policy

Both setups include **Run policy**, the same one a schedule has, with **Skip the new run** and 120 runs an hour as defaults. Runs held by **Confirmation before every run** wait in the drawer under **Needs your decision**. See [Run policy](https://orbitalaip.com/docs/workflows/schedules#run-policy).

## Manage webhooks and monitors

**Automations** lists a webhook by its **Name**, or as **Incoming webhook** without one, and a monitor as **Signal monitor**. Each row shows its policy line, such as **Skip overlap · 120/hr**, its **Last outcome**, and **Edit**, pause or resume, and remove. A paused webhook answers **Not found** to its sender, and a paused monitor starts no runs.
