Webhooks
Send trading signals to UTM via webhooks from any source.
Overview
Webhooks allow external systems to send trading signals to UTM. This is useful for:
- Custom trading bots
- Third-party signal providers
- Automated scripts
- Any system that can make HTTP requests
Webhook URL
Send POST requests to:
https://api.universaltrademanager.com/api/v1/signals/ingest
Authentication
Include your API key in the request header:
X-API-Key: your-api-key-here
Or as a query parameter:
?apiKey=your-api-key-here
tip
Use the header method for better security. Query parameters may be logged.
Request Format
Basic Signal
POST /api/v1/signals/ingest
Content-Type: application/json
X-API-Key: your-api-key
{
"symbol": "AAPL",
"action": "openLong",
"accountId": "your-account-id",
"quantity": 100
}
Signal with Exit Rules
POST /api/v1/signals/ingest
Content-Type: application/json
X-API-Key: your-api-key
{
"symbol": "AAPL",
"action": "openLong",
"accountId": "your-account-id",
"quantity": 100,
"orderType": "LIMIT",
"limitPrice": 150.00,
"exitRules": {
"stopLoss": {
"type": "PERCENT",
"value": 2.0
},
"takeProfit": {
"type": "PERCENT",
"value": 5.0
}
}
}
Request Fields
Required Fields
| Field | Type | Description |
|---|---|---|
symbol | string | Stock symbol (e.g., "AAPL") |
action | string | Signal action (see below) |
accountId | string | Target account ID |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
quantity | number | - | Number of shares |
quantityType | string | FIXED | How to interpret quantity |
orderType | string | MARKET | Order type |
limitPrice | number | - | Limit price (for LIMIT orders) |
stopPrice | number | - | Stop price (for STOP orders) |
timeInForce | string | DAY | Order duration |
exitRules | object | - | Exit rule configuration |
strategyId | string | - | Associated strategy |
comment | string | - | Signal note |
Signal Actions
| Action | Description |
|---|---|
openLong | Open a long position (buy) |
openShort | Open a short position (sell short) |
closeLong | Close a long position (sell) |
closeShort | Close a short position (buy to cover) |
reverseToLong | Close short and open long |
reverseToShort | Close long and open short |
Quantity Types
| Type | Description | Example |
|---|---|---|
FIXED | Exact number of shares | 100 = 100 shares |
PERCENT_EQUITY | Percentage of account equity | 10 = 10% of equity |
DOLLAR_AMOUNT | Dollar value to invest | 5000 = $5,000 worth |
PERCENT_POSITION | Percentage of existing position | 50 = half of position |
Response Format
Success
{
"success": true,
"signalId": "uuid",
"status": "PENDING",
"message": "Signal received and queued for processing"
}
Error
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Invalid symbol format",
"details": [
{
"field": "symbol",
"message": "Symbol must be uppercase letters only"
}
]
}
Examples
Python
import requests
url = "https://api.universaltrademanager.com/api/v1/signals/ingest"
headers = {
"Content-Type": "application/json",
"X-API-Key": "your-api-key"
}
payload = {
"symbol": "AAPL",
"action": "openLong",
"accountId": "your-account-id",
"quantity": 100
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
cURL
curl -X POST https://api.universaltrademanager.com/api/v1/signals/ingest \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"symbol": "AAPL",
"action": "openLong",
"accountId": "your-account-id",
"quantity": 100
}'
JavaScript
const response = await fetch(
"https://api.universaltrademanager.com/api/v1/signals/ingest",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your-api-key"
},
body: JSON.stringify({
symbol: "AAPL",
action: "openLong",
accountId: "your-account-id",
quantity: 100
})
}
);
const data = await response.json();
console.log(data);
Rate Limits
Webhook requests are rate limited:
| Limit | Window |
|---|---|
| 100 requests | per minute |
See Rate Limits for details.
Error Codes
| Code | Description |
|---|---|
INVALID_API_KEY | API key is missing or invalid |
VALIDATION_ERROR | Request payload validation failed |
ACCOUNT_NOT_FOUND | Target account doesn't exist |
MODE_MISMATCH | Trading mode doesn't match account type |
RATE_LIMIT_EXCEEDED | Too many requests |
BROKER_ERROR | Broker rejected the order |
Testing
Use paper trading accounts to test your webhook integration:
- Create a paper trading account in UTM
- Get the account ID from the Accounts page
- Send test signals with paper mode enabled
- Verify signals appear in the Signals page
Best Practices
- Use HTTPS - Always send webhooks over HTTPS
- Handle errors - Check response codes and retry on failures
- Validate locally - Validate signal data before sending
- Log requests - Keep logs for debugging
- Use idempotency - Include unique IDs to prevent duplicates
- Test first - Use paper trading before live trading