Authentication
Smart Balance OpenAPI is served through Themis broker with HMAC apiKey authentication. The same credentials and algorithm apply to REST endpoints and WebSocket handshake.
The Signalplus service platform requires partners to sign requests. The platform verifies the signature upon receiving the request. If the signature verification fails, the platform rejects the request and returns a 401 response.
Base URL
REST API:
| Env |
URL |
| Production |
https://tapi.signalplus.com |
| Testnet |
https://tapi.signalplus.net |
WebSocket:
| Env |
URL |
| Production |
wss://tt-ws.signalplus.com/production |
| Testnet |
wss://tt-ws.signalplus.net/test |
Signature Algorithm
content = `${timestamp}\n${nonce}`
signature = Base64( HmacSHA256( Base64Decode(apiSecret), content.getBytes("UTF-8") ) )
timestamp — current UTC milliseconds as string.
nonce — unique random string per request (UUID recommended).
apiSecret — issued by Signalplus, already Base64-encoded.
Timestamp tolerance: the server rejects requests when |now − timestamp| > 15_000 ms.
| Parameter |
Type |
Required |
Description |
| Authorization |
string |
true |
Bearer <apiKey> |
| Signalplus-API-Signature |
string |
true |
Base64-encoded HMAC signature |
| Signalplus-API-Nonce |
string |
true |
Unique nonce per request |
| Signalplus-API-Timestamp |
string |
true |
UTC milliseconds |
| Content-Type |
string |
true |
application/json for POST |
WebSocket Query String
WebSocket handshake carries the same four credentials in the connection URL:
wss://<base>/<stage>?apiKey=<apiKey>&signature=<URL-encoded>&nonce=<URL-encoded>×tamp=<timestamp>
All four parameters are mandatory. signature and nonce must be URL-encoded because they may contain /, +, =.
Signature Example (Kotlin)
val timestamp = System.currentTimeMillis().toString()
val nonce = UUID.randomUUID().toString()
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(Base64.getDecoder().decode(apiSecret), "HmacSHA256"))
val signature = Base64.getEncoder()
.encodeToString(mac.doFinal("$timestamp\n$nonce".toByteArray()))
Common Response Envelope
All REST responses wrap the payload in a uniform envelope:
{
"succ": true,
"code": 0,
"message": "",
"value": { }
}
| Name |
Type |
Description |
| succ |
boolean |
true on success, false on error |
| code |
int |
0 on success; non-zero Signalplus error code on failure |
| message |
string |
Empty on success; error description on failure |
| value |
object |
Endpoint payload on success; null on error |
Error example:
{
"succ": false,
"code": 1000,
"message": "Invalid signature",
"value": null
}
Enum Reference
Most numeric fields in Smart Balance payloads are enum codes, not arbitrary integers. Always use the values below.
side
| Code |
Enum |
Description |
| 1 |
BUY |
Buy |
| 2 |
SELL |
Sell |
type — order type
| Code |
Enum |
Description |
| 1 |
LIMIT |
Limit order |
| 2 |
MARKET |
Market order |
orderStatus / legStatus
| Code |
Description |
| 1 |
PENDING / ACTIVE / EDITING (not terminal) |
| 2 |
FILLED |
| 3 |
CANCELLED |
| 4 |
CANCELLING |
portfolioStatus (WebSocket push)
| Code |
Description |
| 1 |
ACTIVE |
| 2 |
FILLED |
| 3 |
CANCELLED |
| 4 |
CANCELLING |
| 6 |
PENDING |
kind — instrument kind
| Code |
Enum |
Description |
| 1 |
SPOT |
Spot |
| 2 |
U_DELIVERY |
USDT delivery futures |
| 3 |
U_PERPETUAL |
USDT perpetual |
| 4 |
C_DELIVERY |
Coin-margin delivery |
| 5 |
C_PERPETUAL |
Coin-margin perpetual |
| 6 |
U_OPTION |
USDT option |
| 7 |
C_OPTION |
Coin-margin option |
| 11 |
DRFQ |
DRFQ |
| 12 |
GRFQ |
GRFQ |
tradeMode
| Code |
Enum |
Description |
| 1 |
CASH |
Cash margin |
| 2 |
CROSS |
Cross margin |
| 3 |
ISOLATED |
Isolated margin |
positionSide
| Code |
Enum |
Description |
| 1 |
LONG |
Long |
| 2 |
SHORT |
Short |
| 3 |
NET |
Net |
timeInForce
| Code |
Enum |
Description |
| 1 |
GTC |
Good til cancelled |
| 2 |
IOC |
Immediate or cancel |
| 3 |
FOK |
Fill or kill |
| 4 |
GTD |
Good til day (Deribit only) |
placePriceLabel / priceLabel — dynamic price reference
| Code |
Enum |
Description |
| 1 |
MID |
Mid price |
| 2 |
MARK |
Mark price |
| 3 |
MODEL |
Model price |
| 4 |
BID_ASK |
Bid/ask |
totalEndAction
| Code |
Enum |
Description |
| 1 |
CANCEL_REMAINING |
Cancel unfilled parts at totalLimitMs |
| 2 |
FILL_REMAINING_BY_MARKET |
Market-fill the rest |
cancelType (order-level, push side)
| Code |
Description |
| 1 |
Cancelled by system |
| 2 |
Cancelled by user |
| 5 |
Cancelled by no dynamic price |
mode — PortfolioMode (appears in some WS payloads)
| Code |
Enum |
Description |
| 2 |
BALANCE_COMBO |
Smart Balance combo |
String Enums (no numeric encoding)
| Name |
Type |
Description |
| portfolioType |
string |
BALANCE |
| instrumentType |
string |
SPOT / OPTION / DELIVERY_FUTURES / PERPETUAL |
| priceType |
string |
LIMIT / MARKET / DYNAMIC |
| dynamicPriceStrategy |
string |
MID / MARK / MODEL / BID / ASK |
| exchange |
string |
DERIBIT |
| role |
string |
MAKER / TAKER |
Rate Limit
| Endpoint |
Limit |
/portfolios/submit |
10 requests / 2 seconds |
/portfolios/info |
10 requests / 2 seconds |
/portfolios/cancel |
10 requests / 2 seconds |
Exceeding a rate limit returns HTTP 429.
Error Codes
| Code |
Message |
Description |
| 0 |
(empty) |
Success |
| 1000 |
[Signalplus] Signature / nonce / timestamp validation failed |
HTTP 401 |
| 2xxx |
Business validation errors |
HTTP 4xx — invalid params, state transition rejected, etc. |
| 5xxx |
Server-side errors |
HTTP 5xx |
The numeric code in the response body mirrors the business meaning; HTTP status aligns by convention.
Constraints
| Parameter |
Constraint |
| customizedNote |
Max 100 characters |
| legs |
Minimum 1 leg; upper bound depends on exchange limits |
| parts |
Minimum 1 |
| eachLimitMs |
≥ 0; 0 disables per-part timeout |
| totalLimitMs |
≥ 0; 0 disables total timeout |
| timestampTolerance |
15 seconds (server-enforced) |