Create OTC Order Rule
Creates a rule that accepts or rejects incoming OTC offers on a node's tokens automatically. The node goes in the body (a rule has its own ID and lives at the collection root). The node must be inside your API key's node subtree; with token_id, so must the token's node.
How rules are applied: when a new offer is confirmed on-chain, one rule is picked for it, among the active rules (status 2) of the offer's node whose validity window contains the current time. A rule limited to the offer's token wins over a node-wide rule; then the lowest priority; then the newest. Only that rule is evaluated. If the offer's price and quantity match it, an accept (match_action 1) or a cancel (match_action 2) of the offer is started; otherwise the offer is left for manual handling with Accept or Cancel.
- Price check against the token's current unit price:
rule_type1matches any price;2matches a price no lower than the price minusbelow_percent% and no higher than the price plusabove_percent%;3does the same withbelow_amount/above_amount. A bound you leave out is not checked. A percent rule never matches while the token has no price. - Quantity check: the offer's
quantitymust be withinmin_offer_quantityandmax_offer_quantitywhen they are set. - At present only rules with
side1(both) are applied; rules withside2or3are stored but never match.
Required permission: otc-order-rule:upsert
Request
POST /v2/admin/otc-order-rules
Headers
| Name | Description |
|---|---|
Authorization | Required. Bearer <access_token> |
Content-Type | Required. application/json |
Body
| Field | Type | Required | Description |
|---|---|---|---|
node_id | string | Yes | Node the rule governs (24-character hex) |
name | string | Yes | Rule name |
side | integer | Yes | 1 both, 2 buy, 3 sell |
rule_type | integer | Yes | 1 unconditional, 2 percent, 3 absolute |
status | integer | Yes | 1 inactive, 2 active |
token_id | string | No | Limit the rule to this token of the node (24-character hex). Omit for a node-wide rule |
match_action | integer | No | 1 accept, 2 reject. Defaults to 1 |
above_percent | string | No | Percent rule: highest accepted price, as a percentage above the token's price. "0" to "100", at most one decimal |
below_percent | string | No | Percent rule: lowest accepted price, as a percentage below the token's price. "0" to "100", at most one decimal |
above_amount | string | No | Absolute rule: highest accepted price, as an amount above the token's price (decimal string) |
below_amount | string | No | Absolute rule: lowest accepted price, as an amount below the token's price (decimal string) |
min_offer_quantity | integer | No | Smallest matching offer quantity |
max_offer_quantity | integer | No | Largest matching offer quantity |
priority | integer | No | Lower values are tried first. Defaults to 0 |
valid_from | string | No | Start of the validity window (RFC 3339) |
valid_until | string | No | End of the validity window (RFC 3339) |
consume_on_match | boolean | No | Stored with the rule; not used when offers are evaluated at present |
Percentages and amounts are decimal strings; see Amounts and Percentages.
Example
curl --request POST \
--url '{{baseUrl}}/v2/admin/otc-order-rules' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '{
"node_id": "6901350deb7ed8c1c38de4e9",
"token_id": "6909ddb65b25a8f90960506a",
"name": "Example Rule",
"side": 1,
"rule_type": 2,
"status": 2,
"priority": 1,
"above_percent": "11",
"below_percent": "23",
"min_offer_quantity": 1,
"max_offer_quantity": 4
}'
Response
201 Created
{
"id": "69110fc4afcb084457294dbc",
"node_id": "6901350deb7ed8c1c38de4e9",
"token_id": "6909ddb65b25a8f90960506a",
"side": 1,
"rule_type": 2,
"match_action": 1,
"above_percent": "11",
"below_percent": "23",
"min_offer_quantity": 1,
"max_offer_quantity": 4,
"consume_on_match": false,
"priority": 1,
"status": 2,
"name": "Example Rule",
"created_by": "000000000000000000000000",
"created_at": "2025-11-10T01:03:48.892Z",
"updated_at": "2025-11-10T01:03:48.892Z",
"is_api": true
}
Response Fields
The created rule, with the same fields as a row of List OTC Order Rules: id, node_id, token_id, side, rule_type, match_action, the threshold and quantity fields that are set, consume_on_match, priority, status, valid_from / valid_until when set, name, created_by, created_at, updated_at and is_api (true).
Errors
| Status | Code | Description |
|---|---|---|
| 400 | 10015 | Validation failed — see details. Includes a missing node_id, name, side, rule_type or status, and a malformed percentage or amount |
| 400 | 10001 (domain 2) | Node not found |
| 400 | 10001 (domain 5) | Token not found |
| 403 | 10005 (domain 2) | The node, or the token's node, is outside your API key's node subtree |
| 500 | 10000 | Unexpected server error, including a token_id that is not a 24-character hex ID |
See Errors for the error format and common codes.