# Sending Trading Signals

## How To Obtain An API Key

To link your trading strategy with Compendium, head back to the admin page of your Verified Trading Bot. Scroll down until you see the "View This Bot's Alert API Key" section, then click the "View My Bot API Key" button. This will reveal your private API key, which you can then input into the Compendium WebHook.

{% hint style="warning" %}
It's crucial to keep your API key confidential as it's used to identify calls. Sharing your API key can result in unauthorized signals being sent and potentially compromise the security of your group. If you suspect that your API key has been compromised, we recommend clicking the "Reroll API Key" button. Don't forget to update the API key in your webhooks to ensure that your strategy continues to post trades successfully.
{% endhint %}

## Formatting WebHook Signals

Now that you have your API key it is time to learn how signals can be sent!

All signals should be sent to the following webhook URL as POST. If you are using TradingView it will automatically format webhook + JSON in the correct method.

### Understanding JSON Formatting

You can learn more about specific JSON formatting at the link below.

{% embed url="<https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON>" %}

### Posting Webhooks From TradingView

Please follow TradingView's internal documentation for educational resources on posting Webhook orders from their system.

{% embed url="<https://www.tradingview.com/support/solutions/43000529348-about-webhooks/>" %}
Official documentation provided by TradingView on interacting with their webhooks system.
{% endembed %}

### **Webhook URL**

The webhook URL for our verified trading bots router is different from our regular Signal Provider webhook. The webhook information is available on request through your designated representative channel in our official discord server.

{% hint style="warning" %}
A "success" return from the provided Webhook means that the URL was successfully pinged in your workflow. It does not mean that the `signal` or `orderchain` was formatted correctly and still may result in a trade post error.&#x20;
{% endhint %}

### **Webhook JSON Format**

```json
{
  "apiKey": "insertGroupAPIKeyHere",  
  "orderchain" : [
        {
          "signal" : "place",
          "orderType" : "limit",
          "symbol" : "BTC-USDT-SWAP",
          "marketType" : "linear",
          "side" : "buy",
          "risk" : "100",
          "mode" : "cross",
          "reduceOnly" : "false",
          "postOnly" : "false",
          "ioc" : "false",
          "fok" : "false",
          "price" : "20000",
          "tpTrigger" : "21000",
          "tpPrice" : "21500",
          "tpType" : "last",
          "tpOrderType" : "limit",
          "slTrigger" : "19900",
          "slPrice" : "19500",
          "slType" : "last",
          "slOrderType" : "limit"
        }
    ]
}
```

The above JSON example shows a single signal in the `orderchain` array. Please read the next section to understand how to fully utilize this new integration.

## Understanding the `orderchain` Array

Our new signal system requires signal commands to be sent in the `orderchain` array, even if you are only sending a single command. We can now offer supremely advanced capabilities by offering the capability to chain orders together. We have provided some simple examples below.

{% hint style="info" %}
The `orderchain` array has a capacity of accommodating a **maximum of 5 signal types in a stacked manner** and mandates the presence of **at least one signal type** to effectively transmit a trade notification signal. It is imperative to acknowledge that the execution of Orderchain commands is dependent on the sequence of WebHook post in which they are transmitted, thus dictating their placement order.
{% endhint %}

### Single Signal Post Example

The following example shows the user sending a single signal in the `orderchain` array to close all open positions.

```json
{
  "apiKey": "insertGroupAPIKeyHere",  
  "orderchain" : [
        {
            "signal" : "closeall"
        }
    ]
}
```

### Sending Multiple Signals At Once

The following example shows the user sending multiple signals in the `orderchain` array. This specific example shows the user closing all open positions and then opening a new trade. This code snippet should be helpful if your trading strategy is always in a trade and needs to flip sides from "short" to "long" or vice-versa.

```json
{
  "apiKey": "insertGroupAPIKeyHere",  
  "orderchain" : [
        {
            "signal" : "closeall"
        },
        {
            "signal" : "place",
            "orderType" : "limit",
            "symbol" : "BTC-USDT-SWAP",
            "marketType" : "linear",
            "side" : "buy",
            "risk" : "100",
            "mode" : "cross",
            "reduceOnly" : "false",
            "postOnly" : "false",
            "ioc" : "false",
            "fok" : "false",
            "price" : "20000",
            "tpTrigger" : "21000",
            "tpPrice" : "21500",
            "tpType" : "last",
            "tpOrderType" : "limit",
            "slTrigger" : "19900",
            "slPrice" : "19500",
            "slType" : "last",
            "slOrderType" : "limit"
        }
    ]
}
```

## All Available Signal Parameters

{% hint style="info" %}
All parameters should be sent as a "string" from your POST API call. This is to simplify connections from platforms like TradingView while normalizing our structure. It is also important to note that if you are passing a number, it should be treated as an `integer` within the "string".
{% endhint %}

<table><thead><tr><th width="178">Parameter</th><th width="98.33333333333331">Type</th><th>Requirements &#x26; Description</th></tr></thead><tbody><tr><td>signal</td><td><em>String</em></td><td><strong>ALWAYS</strong> <em><strong>REQUIRED</strong></em> - See valid values below</td></tr><tr><td>orderId</td><td><em>String</em></td><td>Required if <code>signal</code> = cancel</td></tr><tr><td>orderType</td><td><em>String</em></td><td>Required if <code>signal</code> = place. See valid values below</td></tr><tr><td>symbol</td><td><em>String</em></td><td>Required if <code>signal</code> parameter requires.</td></tr><tr><td>marketType</td><td><em>String</em></td><td>Optional - if <code>signal</code> is <code>cancel</code> type, the orders canceled will be of <code>marketType</code>.</td></tr><tr><td>side</td><td><em>String</em></td><td>Required if <code>signal</code> = place</td></tr><tr><td>risk</td><td><em>String</em></td><td>Required if <code>signal</code> = place</td></tr><tr><td>price</td><td><em>String</em></td><td>Required if <code>orderType</code> requires it (eg limit)</td></tr><tr><td>mode</td><td><em>String</em></td><td>Optional - default value = <code>cross</code></td></tr><tr><td>reduceOnly</td><td><em>String</em></td><td>Optional - default is <code>false</code></td></tr><tr><td>postOnly</td><td><em>String</em></td><td>Optional - default value is <code>false</code></td></tr><tr><td>ioc</td><td><em>String</em></td><td>Optional - default = <code>false</code></td></tr><tr><td>fok</td><td><em>String</em></td><td>Optional - default = <code>false</code></td></tr><tr><td>tpTrigger</td><td><em>String</em></td><td>Optional</td></tr><tr><td>tpPrice</td><td><em>String</em></td><td>Required if <code>tpTrigger</code> submitted and <code>tpOrderType</code> = <code>limit</code></td></tr><tr><td>tpType</td><td><em>String</em></td><td>Optional - default = <code>last</code></td></tr><tr><td>tpOrderType</td><td><em>String</em></td><td>Required if <code>tpTrigger</code> submitted</td></tr><tr><td>slTrigger</td><td><em>String</em></td><td>Optional</td></tr><tr><td>slPrice</td><td><em>String</em></td><td>Required if <code>slTrigger</code> submitted and <code>slOrderType</code> = <code>limit</code></td></tr><tr><td>slType</td><td><em>String</em></td><td>Optional - default = <code>last</code></td></tr><tr><td>slOrderType</td><td><em>String</em></td><td>Required if <code>slTrigger</code> submitted</td></tr></tbody></table>

## Understanding Each Parameter

The following breakdown includes **JSON Type**, **Required Conditions**, & **Valid Values** for all available `signal` parameters.

<details>

<summary>signal</summary>

**JSON type:** "String"

**Required:** Always

**Valid Values:**

* `place` : used to place orders
* `cancel` : cancels ONE specific order, must provide `orderid`&#x20;
* `cancelall` : cancels ALL open orders without regard to market or complexity
* `cancelbuys` : cancels all open buy orders
* `cancelsells` : cancels all open sell orders
* `canceltps` : cancel all take profit orders (including embedded TP orders)
* `cancelsls` : cancels all stop loss orders (including embedded SL orders)
* `canceltriggers` : cancels all orders having TP or SL orders embedded but not both
* `close` : if submitted with a symbol (e.g. symbol: `BTC-USDT-SWAP`), then closes all current positions on that symbol. Otherwise closes all positions on all tokens (same behavior as `closeall`)
* `closeall` : closes all positions on all token markets
* `closelongs` : closes all long positions on any token market
* `closeshorts` : closes all short positions on any token

</details>

<details>

<summary>orderID</summary>

**JSON type:** "String"

**Required:** required if `signal` = cancel (specifies order to cancel)

**Valid Values:** insert `orderid` from exchange to cancel.

</details>

<details>

<summary>orderType</summary>

**JSON type:** "String"

**Required:** required if `signal` = place.

**Valid Values:** `limit` or `market`

</details>

<details>

<summary>symbol</summary>

**JSON type:** "String"

**Required:** Required if `signal` parameter requires.

**Valid Values:** must be a VALID symbol on native exchange. (e.g. symbol: `BTC-USDT-SWAP`)

</details>

<details>

<summary>marketType</summary>

**JSON type:** "String"

**Required:** Optional - if `signal` is cancel type, the orders canceled will be of `marketType`. if omitted and `signal` is cancel type then spot and perpetual orders will be canceled.

**Valid Values:** `linear, inverse,` or `spot`

**Deprecated Values:** `perpetual`

</details>

<details>

<summary>side</summary>

**JSON Type:** "String"

**Required:** Required if `signal` = place

**Valid Values:** `buy` or `sell`

</details>

<details>

<summary>risk</summary>

**JSON Type:** "String"

**Required:** Required if `signal` = place

**Valid Values:**

* Risk is limited from 1 - 100 for spot markets.&#x20;
* Risk can be above 100 for perpetual swap markets.

**Explanation:** Risk is our system's version of trade size.

**Examples of `risk` utilization:**

* 50 = 50% of the connected exchange account balance
* 100 = 100% of the connected exchange account balance
* 150 = 150% of the connected exchange account balance (1.5x Leverage)
* 200 = 200% of the connected exchange account balance (2x Leverage)

</details>

<details>

<summary>price</summary>

**JSON Type:** Integer within "String"

**Required:** Required if `orderType` requires it (eg limit)

**Valid Values:** Insert price to initiate order as a "string"

**Example:** `"21000"` (must be formatted as an integer within the string)

</details>

<details>

<summary>mode</summary>

**JSON Type:** "String"

**Required:** Optional, default value = `cross`

**Trade Mode Explanation:** Trade Mode, when placing an order, you need to specify the trade mode. (Notes taken specifically from OKX documentation)\
\
**Valid Values:**

* `cash` for spot markets
* `cross` for perpetual markets

</details>

<details>

<summary>reduceOnly</summary>

**JSON Type:** "String"

**Required:** Optional - default is `false`

**Valid Values:** `true` or `false` (passed in a "string"). The default value is `false`.\
Only applicable to `MARGIN` orders, and `FUTURES/SWAP` orders in `net` mode\
Only applicable to `Single-currency margin` and `Multi-currency margin`

</details>

<details>

<summary>postOnly</summary>

**JSON type:** "String"

**Required:** Optional - default value is `false`

**Valid Values:** `true` or `false` (passed as "string")&#x20;

</details>

<details>

<summary>ioc</summary>

**JSON Type:** "String"

**Required:** Optional - default = `false`

**Valid Values:** `true` or `false` (passed as "string")

</details>

<details>

<summary>fok</summary>

**JSON Type:** "String"

**Required:**  Optional - default = `false`

**Valid Values:** `true` or `false` (passed as a "string")

</details>

<details>

<summary>tpTrigger</summary>

**JSON Type:** Integer within a "String"

**Required:** Optional

**Valid Values:** Insert price to initiate order as a "string"

**Example:** `"21000"` (must be formatted as an integer within the string)

</details>

<details>

<summary>tpPrice</summary>

**JSON Type:** Integer within "String"

**Required:** Required if `tpTrigger` submitted and `tpOrderType` = `limit`

**Valid Values:** Insert price to initiate order as a "string"

**Example:** `"21000"` (must be formatted as an integer within the string)

</details>

<details>

<summary>tpType</summary>

**JSON Type:** "String"

**Required:** Optional - default = `last`

**Valid Values:**

* `last` : last price
* `index` : index price
* `mark` : mark price

</details>

<details>

<summary>tpOrderType</summary>

**JSON Type:** "String"

**Required:** Required if `tpTrigger` is submitted

**Valid Values:** `limit` or `market`

</details>

<details>

<summary>slTrigger</summary>

**JSON Type:** Integer within a "String"

**Required:** Optional

**Valid Values:** Insert price integer to initiate order as a "string"

**Example:** `"21000"` (must be formatted as an integer within the string)

</details>

<details>

<summary>slPrice</summary>

**JSON Type:** Integer within a "String"

**Required:** Required if `slTrigger` submitted and `slOrderType` = `limit`

**Valid Values:** Insert price integer to initiate order as a "string"

**Example:** `"21000"` (must be formatted as an integer within the string)

</details>

<details>

<summary>slType</summary>

**JSON Type:** "String"

**Required:** Optional - default = `last`

**Valid Values:**

* `last` : last price
* `index` : index price
* `mark` : mark price

</details>

<details>

<summary>slOrderType</summary>

**JSON Type:** "String"

**Required:** Required if `tpTrigger` is submitted

**Valid Values:** `limit` or `market`

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.compendium.finance/automation-terminal/verified-trading-bots/for-algo-and-strategy-authors/sending-trading-signals.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
