Type/to search
Getting Started
Platform Basics
Writing Strategies
Development Tools
Backtesting System
Advanced Topics
Data and Research
Extended API Interface
AI Integration
Create ApiKey
Authentication Methods
Extended API Interface Details
GetAccount
GetNodeList
DeleteNode
GetExchangeList
GetPlatformList
GetStrategyList
GetRobotGroupList
GetRobotList
GetRobotDetail
GetRobotLogs
NewRobot
RestartRobot
StopRobot
CommandRobot
DeleteRobot
PluginRun
pub
Extended API Interface Return Codes
Live Trading Status Codes

Pushes a message to a channel subscribed by a running robot, so that systems outside the platform (TradingView webhook alerts, your own trading system, monitoring scripts and so on) can send data to the robot. The robot reads it with GetChannelData; for how channels work see Communication Between Live Trading Strategies.

Unlike the other methods, pub needs no API key and no signature: the request URL is https://www.fmz.com/api/v1?method=pub&robot={robotId}&channel={channel} and the message goes in the request body (POST). Anyone who knows the robot ID and the channel name can push, so use a hard-to-guess random string as the channel name, and have the strategy validate what it receives as untrusted input.

Examples

Receiving strategy: subscribe to the channel, parse the JSON messages it receives, and use id to tell new messages from old ones.

javascript
// receiving robot (assume its ID is 123456) var CHANNEL = "6BC42A119B5DBFA2188A8279DA3B5C30" function main() { var lastId = null while (true) { var msg = GetChannelData(CHANNEL) // the first call subscribes and returns null if (typeof msg == "string") { var obj = null try { obj = JSON.parse(msg) // parse again when the body is JSON text } catch (e) { Log("non-JSON message:", msg) } // the channel keeps only the latest message; use id to spot new ones if (obj && obj.id != lastId) { lastId = obj.id Log("external message received:", obj) } } Sleep(1000) } }
python
import json CHANNEL = "6BC42A119B5DBFA2188A8279DA3B5C30" def main(): lastId = None while True: msg = GetChannelData(CHANNEL) # the first call subscribes and returns None if isinstance(msg, str): try: obj = json.loads(msg) # parse again when the body is JSON text except ValueError: obj = None Log("non-JSON message:", msg) if isinstance(obj, dict) and obj.get("id") != lastId: lastId = obj.get("id") Log("external message received:", obj) Sleep(1000)

Returns

TypeDescription

object

On success code is 0 and the fields of data are in the attributes table below; when no robot subscribes to the channel (or the channel name is invalid, or robot is empty), the HTTP status is 500 and code is 5.

Arguments

NameTypeRequiredDescription

robot

number

Yes

ID of the robot that receives the message (URL parameter). The robot must be running and already subscribed to channel.

channel

string

Yes

Channel name (URL parameter); a 32-character random string (a UUID without hyphens) is recommended. It must not be all digits (that is taken as a robot ID, i.e. the robot's own channel); names shorter than 10 characters are not delivered.

message

string

No

Message content. For POST requests it is the whole request body, any text such as JSON or plain text; otherwise it is the URL parameter message.

Attributes

NameTypeDescription

data.status

string

ok on success.

data.robot

number

Echo of the request's robot parameter.

data.channel

string

Echo of the request's channel parameter.

data.message

string

The message pushed.

data.affected

number

Number of dockers that received the message.

Remarks

Delivery rules
  • Subscribe first, then push: the robot's first GetChannelData(channel) call subscribes to the channel (and returns a null value); the subscription is reported with the docker's heartbeat, so the external system can push successfully only after a short while. Requests fail while no robot subscribes.
  • The message is delivered to the docker of the robot robot, and every robot on that docker subscribed to the same channel receives it; robots on other dockers do not.
  • A channel keeps only the latest message, with no queue: GetChannelData() returns the most recent one each time, and reading does not clear it. To tell new messages from old ones, include an increasing number or a timestamp in the message.
  • Each robot can subscribe to at most 10 channels (other robots' channels included); beyond that GetChannelData() returns a null value and logs the error channel subscriber exceed limit.
  • The robot receives a string (the raw request body). When the body is JSON text, the strategy has to parse it again.

Example push request

An external system pushes a message:

bash
curl -X POST \ "https://www.fmz.com/api/v1?method=pub&robot=123456&channel=6BC42A119B5DBFA2188A8279DA3B5C30" \ -d '{"id": 1, "action": "buy", "symbol": "BTC_USDT"}'

In TradingView, put the URL above in the alert's webhook URL; the alert message becomes the request body.

Example response
json
{ "code": 0, "data": { "status": "ok", "robot": 123456, "channel": "6BC42A119B5DBFA2188A8279DA3B5C30", "message": "{\"id\": 1, \"action\": \"buy\", \"symbol\": \"BTC_USDT\"}", "affected": 1 } }

When no robot subscribes to the channel:

json
{ "code": 5, "error": "No subscribers for channel: 6BC42A119B5DBFA2188A8279DA3B5C30", "data": null }