главная

API

Торговля

Размещение, пакеты и отмена ордеров Seeryx: лимитные, рыночные, «Только мейкер», ключи идемпотентности, сроки, разделение и объединение, примеры кода.

Обзор

Ордера размещаются через POST /api/orders (один ордер) или POST /api/orders/batch (до 15), отменяются через DELETE /api/orders/:id или DELETE /api/orders, а средства превращаются в пары и обратно через /api/split и /api/merge. На seeryx.com каждый ордер, разделение и объединение содержит объект signed, созданный ключом вашей торговой сессии: как это сделать, показано на странице Подпись ордеров; примеры на этой странице делают это за вас.

Заголовки и идемпотентность

ПолеТипОписание
X-Auth-TokenзаголовокобязательноstringТокен входа (или Authorization: Bearer).
Idempotency-KeyзаголовокобязательноstringВ каждом торговом POST и DELETE: 8–128 букв, цифр, _ или -, новый для каждой операции. Тот же ключ с тем же телом возвращает тот же ответ, что и первый запрос, и ничего не меняет; с другим телом запрос отклоняется. Ключи хранятся 24 часа.
Content-Typeзаголовокобязательноstringapplication/json для запроса с телом.

Типы ордеров

ТипПоляЧто происходит
Лимитныйshares, limitСразу исполняется против того, что предлагается по его цене или лучше, а остаток стоит в стакане, пока не исполнится, пока вы его не отмените или пока раунд не закроется.
Лимитный, «Только мейкер»shares, limit, postOnly: trueВстаёт в стакан целиком или отклоняется (400 would_take): он никогда не забирает ликвидность, поэтому никогда не платит комиссию тейкера.
Рыночная покупкаamount, capСразу тратит до amount USDC (включая комиссию) по ценам не выше cap; остаток отбрасывается и никогда не встаёт в стакан.
Рыночная продажаshares, capСразу продаёт до shares долей по ценам не ниже cap; остаток отбрасывается.
ПолеТипОписание
slugобязательноstringРаунд, который торгуется (текущий или предстоящий), или открытый событийный рынок.
sideобязательноup | downИсход, которым вы торгуете (на событийном рынке «Да» — это up, «Нет» — down).
actionобязательноbuy | sellДля продажи нужны ваши доли, которые не зарезервированы другой продажей в стакане.
typeобязательноlimit | marketСм. выше.
sharesнеобязательноnumberЛимитные ордера и любые продажи.
amountнеобязательноnumberРыночные покупки: максимальная сумма в USDC, включая комиссию тейкера.
limitнеобязательноnumberЛимитные ордера: цена в центах.
capнеобязательноnumberРыночные ордера: худшая допустимая цена в центах. Покупка не заплатит больше, продажа не получит меньше.
postOnlyнеобязательноbooleanТолько для лимитных ордеров.
signedнеобязательноobjectОрдер, подписанный ключом вашей сессии (Подпись ордеров).
Вы хотитеТело (плюс slug и signed)
Купить 10 долей «Вверх» по 45¢ или дешевле, остаток — в стакан{"side":"up","action":"buy","type":"limit","shares":10,"limit":45}
Сразу потратить до 5 $ на «Вниз», не дороже 60¢ за долю{"side":"down","action":"buy","type":"market","amount":5,"cap":60}
Сразу продать 10 долей «Вверх», не дешевле 40¢{"side":"up","action":"sell","type":"market","shares":10,"cap":40}
Выставить на продажу 10 долей «Вверх» по 70¢, только как мейкер{"side":"up","action":"sell","type":"limit","shares":10,"limit":70,"postOnly":true}

Ответ

Ответы
{ "order": 16901, "filled": 0, "remaining": 10, "spent": 0, "proceeds": 0 }

{ "order": null, "filled": 10.6844, "remaining": 0, "spent": 4.999974, "proceeds": 0,
  "requested": 5, "fee": 0.18515, "avgPrice": 45.064056006888556, "unspent": 0.000026, "status": "filled" }

{ "order": null, "filled": 0, "remaining": 0, "spent": 0, "proceeds": 0, "requested": 5, "fee": 0, "avgPrice": null,
  "unspent": 5, "status": "none", "reason": "beyond_limit", "limit": 1, "bestPrice": 16 }
Лимитный ордер в стакане; исполненная рыночная покупка на 5 $; рыночная покупка, у которой cap ниже лучшей цены продажи.
  • order — id того, что стоит в стакане, или null, если в стакане ничего нет. filled — доли, исполненные сейчас; spent и proceeds — уплаченные и полученные USDC с учётом комиссий.
  • Рыночный ордер добавляет requested, fee, avgPrice (центы, без комиссии), unspent или unsold, status (filled, partial или none) и, если он исполнен не полностью, reason: no_liquidity, beyond_limit (с bestPrice) или share_limit.
  • Рыночный ордер, который ничего не исполнил, всё равно возвращает 200, а не ошибку.

Срок действия и закрытие

  • Лимитные ордера подписываются до закрытия рынка (конца раунда или closesAt события) и стоят в стакане до этого момента.
  • Рыночные ордера, разделения и объединения проходят расчёт за несколько секунд, поэтому подписывайте их на 5 минут, но никогда не позже закрытия. Сервер принимает срок действия от 5 секунд вперёд до закрытия.
  • В последние 5 секунд раунда новые ордера не принимаются (400 «Round is closing»). Ордера в стакане истекают при закрытии и отображаются в вашей активности с типом expire.
  • Будущие раунды. Следующие десять 5- и 15-минутных раундов (и один следующий для 1h и 1d) уже принимают ордера, поэтому бот может выставлять котировки в раунде ещё до его начала.

Пакеты и отмена

POST /api/orders/batch размещает до 15 ордеров одним запросом, в заданном порядке, каждый со своими проверками: ответ содержит по одному { status, body } на ордер — ровно то, что ответил бы POST /api/orders. Ордер i записывается под ключом <your key>-<i>, поэтому повтор всего пакета с тем же ключом ничего не разместит дважды. DELETE /api/orders отменяет все ваши открытые ордера, а с ?slug= — ордера одного рынка, одной транзакцией.

curl
# two orders in one request (on seeryx.com each also carries its own "signed")
curl -s -X POST https://seeryx.com/api/orders/batch \
  -H "X-Auth-Token: $TOKEN" -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
  -d '{"orders":[{"slug":"btc-updown-5m-1791916200","side":"up","action":"buy","type":"limit","shares":5,"limit":40},
                 {"slug":"btc-updown-5m-1791916200","side":"down","action":"buy","type":"limit","shares":5,"limit":40}]}'
# {"results":[{"status":200,"body":{"order":21306,...}},{"status":200,"body":{"order":21307,...}}]}

# cancel everything still resting in the round
curl -s -X DELETE "https://seeryx.com/api/orders?slug=btc-updown-5m-1791916200" -H "X-Auth-Token: $TOKEN" -H "Idempotency-Key: $(uuidgen)"
# {"success":true,"cancelled":[21306,21307]}

Разделение и объединение

POST /api/split с { slug, amount } превращает amount USDC в столько же долей «Вверх» и «Вниз»; POST /api/merge с { slug, shares } превращает пары обратно в 1,00 $ за каждую. Без комиссии; минимум — 5 пар; на seeryx.com подписывается сообщением PMS1.

Средства и лимиты

  • Средства. Покупки в стакане не блокируют средства, но все ваши открытые покупки на одном рынке вместе с комиссией тейкера по их лимитной цене должны укладываться в свободные средства. Средства списываются только при исполнении ордера; покупка, которую вы больше не можете оплатить, отменяется.
  • Ваши собственные ордера. Ордер может исполниться против ваших же ордеров в стакане и тогда платит комиссию тейкера, как любой другой; ордер «Только мейкер» в таком случае отклоняется.
  • Ордера в стакане. Не более 200 на аккаунт и 100 на одном рынке (400 open_orders_limit).
  • Частота запросов. 250 запросов на размещение, отмену, разделение и объединение за 10 секунд на аккаунт; каждый ордер пакета считается отдельно (429 rate_limited). См. Лимиты запросов и ошибки.

Код

Лимитные, рыночные и пакетные ордера, отмена, разделение и объединение; рядом должны лежать seeryx.ts и chain.ts (или их аналоги на Python).

trading.ts
// trading.ts: limit, market and batch orders, cancels, split and merge. npx tsx trading.ts
import { api, loadWallet, signIn, type Book, type Round } from './seeryx';
import { signOrder, signPair, tradingSession, type Funds, type Order } from './chain';

const wallet = await loadWallet();
await signIn(wallet);
const funds = await api<Funds>('/funds');
// where GET /api/funds says onChainTrading (always on seeryx.com) every order carries `signed`
const session = funds.mode === 'chain' && funds.onChainTrading ? await tradingSession(funds, wallet) : null;
const sign = async (order: Order) => (session ? signOrder(funds, session, wallet.address, order) : order);
const place = async (order: Order) =>
  api<{ order: number | null }>('/orders', { method: 'POST', body: await sign(order) });
const { slug } = await api<Round>('/markets/BTC/5m/current');
const up = await api<Book>(`/orderbook/${slug}?side=up`), down = await api<Book>(`/orderbook/${slug}?side=down`);
const below = (book: Book, cents: number) => Math.max(1, Math.floor(book.asks[0]?.[0] ?? 50) - cents); // under the best ask

// limit: buy 10 Up shares 5c under the best ask, resting in the book; postOnly refuses it if it would trade at once
const limit = await place({
  slug, side: 'up', action: 'buy', type: 'limit', shares: 10, limit: below(up, 5), postOnly: true,
});

// market: spend up to $5 on Down, paying at most 2c over the best ask; what the book cannot fill is dropped
const cap = Math.min(99, Math.ceil(down.asks[0]?.[0] ?? 50) + 2);
const market = await place({ slug, side: 'down', action: 'buy', type: 'market', amount: 5, cap });
console.log({ limit, market });

// up to 15 orders in one request, placed in this order; each answer is what POST /orders would have said
const orders = await Promise.all([
  sign({ slug, side: 'up', action: 'buy', type: 'limit', shares: 5, limit: below(up, 10) }),
  sign({ slug, side: 'down', action: 'buy', type: 'limit', shares: 5, limit: below(down, 10) }),
]);
console.log({ batch: await api('/orders/batch', { method: 'POST', body: { orders } }) });

// cancel one order, then everything still resting in this round
if (limit.order) await api(`/orders/${limit.order}`, { method: 'DELETE' });
console.log({ cancelled: await api(`/orders?slug=${slug}`, { method: 'DELETE' }) });

// split $5 into 5 Up + 5 Down shares, then merge them back into $5
const pair = (merge: boolean) =>
  (session ? signPair(funds, session, wallet.address, slug, merge, 5) : undefined);
await api('/split', { method: 'POST', body: { slug, amount: 5, signed: await pair(false) } });
await api('/merge', { method: 'POST', body: { slug, shares: 5, signed: await pair(true) } });

Эндпоинты ордеров

Каждому запросу здесь нужны X-Auth-Token и заголовок Idempotency-Key.

POST/api/orders

Разместить ордер

Вход + Idempotency-Key
ПолеТипОписание
slugтелообязательноstringРаунд, который торгуется (текущий или предстоящий), или открытый событийный рынок
sideтелообязательноup | downИсход
actionтелообязательноbuy | sellДля продажи нужны ваши доли, не зарезервированные другой продажей
typeтелообязательноlimit | marketЛимитный ордер встаёт в стакан; рыночный исполняется сразу, а остаток отбрасывает
sharesтелонеобязательноnumberЛимитные ордера и любые продажи: доли, до 4 знаков после запятой
amountтелонеобязательноnumberРыночные покупки: максимальная сумма в USDC, включая комиссию тейкера
limitтелонеобязательноnumberЛимитные ордера: цена в центах (см. шаг цены)
capтелонеобязательноnumberРыночные ордера: худшая допустимая цена в центах, обязательна для подписанных ордеров
postOnlyтелонеобязательноbooleanЛимитные ордера: отклонить ордер, если какая-либо его часть исполнилась бы сразу
signedтелонеобязательноobjectОрдер, подписанный ключом вашей торговой сессии
Запрос
curl -X POST "https://seeryx.com/api/orders" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"slug":"btc-updown-5m-1791916200","side":"up","action":"buy","type":"limit","shares":10,"limit":45,"postOnly":true}'
Ответ
{ "order": 16901, "filled": 0, "remaining": 10, "spent": 0, "proceeds": 0 }
  • Если GET /api/funds сообщает onChainTrading (на seeryx.com — всегда), тело также содержит "signed", созданный ключом вашей торговой сессии: см. раздел «Подпись ордеров».
  • order — id той части, что стоит в стакане, или null, если в стакане ничего нет. filled — доли, исполненные сейчас; spent и proceeds — уплаченные и полученные USDC с учётом комиссий.
  • Рыночный ордер возвращает полный результат: requested, fee, avgPrice (центы, без комиссии), unspent (покупка) или unsold (продажа), status "filled", "partial" или "none", а при неполном исполнении — reason: "no_liquidity" (в стакане закончилась ликвидность), "beyond_limit" с bestPrice (остаток стоит дальше вашего cap) или "share_limit" (рыночная покупка, подписанная в долях, получила их все по цене ниже своего cap). Рыночный ордер, который ничего не исполнил, всё равно возвращает 200.
СтатусКогда
400Неверные входные данные («Invalid limit», «Invalid slug»), «Round is not live», «Round is closing», «Insufficient balance», «Insufficient free shares», несовпадающий подписанный ордер
400 below_minimumМеньше долей, чем minOrderShares; ответ дополнительно содержит "minimum"
400 would_takeОрдер «Только мейкер», который исполнился бы сразу
400 open_orders_limitСлишком много ордеров в стакане; ответ дополнительно содержит "limit": { account, round }
400 trading_pausedКлюч сессии, подписавший ордер, был закрыт: откройте новую сессию и подпишите заново
429 rate_limitedПревышено допустимое число запросов на ордера за интервал; подождите "retryAfter" секунд
503 trading_haltedТорговля остановлена для всех (см. GET /api/notice); отмена ордеров по-прежнему работает
503«Exchange clock unavailable»: сервер не может подтвердить время раунда; повторите через несколько секунд
POST/api/orders/batch

Разместить до 15 ордеров одним запросом

Вход + Idempotency-Key
ПолеТипОписание
ordersтелообязательноarrayОт 1 до 15 ордеров, каждый — ровно тело POST /api/orders со своим объектом signed
Запрос
curl -X POST "https://seeryx.com/api/orders/batch" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"orders":[{"slug":"btc-updown-5m-1791916200","side":"up","action":"buy","type":"limit","shares":5,"limit":40},{"slug":"btc-updown-5m-1791916200","side":"down","action":"buy","type":"limit","shares":5,"limit":0}]}'
Ответ
{ "results": [{ "status": 200, "body": { "order": 21306, "filled": 0, "remaining": 5, "spent": 0, "proceeds": 0 } },
  { "status": 400, "body": { "error": "Invalid limit" } }] }
  • Размещаются в заданном порядке, каждый со своими проверками; отклонённый ордер не останавливает остальные. Каждый ордер считается одним запросом в лимите запросов.
  • Ордер i записывается под ключом идемпотентности <your key>-<i> (i с 0; ваш ключ — не длиннее 125 символов), поэтому повтор всего пакета ничего не разместит дважды.
СтатусКогда
400orders — не список от 1 до 15 ордеров
429 rate_limitedПакет превысил бы допустимое число запросов на ордера за интервал
DELETE/api/orders/:id

Отменить один открытый ордер

Вход + Idempotency-Key
ПолеТипОписание
idпутьобязательноnumberId ордера
Запрос
curl -X DELETE "https://seeryx.com/api/orders/16901" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
Ответ
{ "success": true }
СтатусКогда
400Ордер не найден: он не ваш или уже не открыт
DELETE/api/orders

Отменить все ваши открытые ордера или ордера одного рынка

Вход + Idempotency-Key
ПолеТипОписание
slugстрока запросанеобязательноstringТолько этот раунд или событийный рынок
Запрос
curl -X DELETE "https://seeryx.com/api/orders?slug=btc-updown-5m-1791916200" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
Ответ
{ "success": true, "cancelled": [21306, 21307] }
  • Один запрос и одна транзакция, сколько бы ни было ордеров.
POST/api/split

Превратить USDC в столько же долей «Вверх» и «Вниз»

Вход + Idempotency-Key
ПолеТипОписание
slugтелообязательноstringРынок, который торгуется
amountтелообязательноnumberUSDC; 1 USDC даёт 1 долю «Вверх» + 1 долю «Вниз»
signedтелонеобязательноobjectПодписывается ключом сессии (PMS1)
Запрос
curl -X POST "https://seeryx.com/api/split" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"slug":"btc-updown-5m-1791916200","amount":5}'
Ответ
{ "success": true }
  • Не меньше minOrderShares пар. Без комиссии.
СтатусКогда
400 below_minimumМеньше пар, чем минимум
400«Insufficient balance», несовпадающий подписанный запрос
POST/api/merge

Превратить пары долей «Вверх» и «Вниз» обратно в USDC

Вход + Idempotency-Key
ПолеТипОписание
slugтелообязательноstringРынок, который торгуется
sharesтелообязательноnumberПары для объединения; каждая приносит 1,00 $
signedтелонеобязательноobjectПодписывается ключом сессии (PMS1)
Запрос
curl -X POST "https://seeryx.com/api/merge" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"slug":"btc-updown-5m-1791916200","shares":5}'
Ответ
{ "success": true }
  • Не меньше minOrderShares пар или все ваши пары. Без комиссии.