accueil

API

Trading

Passer, grouper et annuler des ordres sur Seeryx : à cours limité, au marché, post-only, clés d’idempotence, expiration, scission et fusion, avec exemples.

Vue d’ensemble

Vous négociez avec POST /api/orders (un ordre) ou POST /api/orders/batch (jusqu’à 15), annulez avec DELETE /api/orders/:id ou DELETE /api/orders, et convertissez des liquidités en paires, et inversement, avec /api/split et /api/merge. Sur seeryx.com, chaque ordre, scission et fusion porte un objet signed produit par votre clé de session de trading : Signature des ordres explique comment ; les exemples de cette page s’en chargent pour vous.

En-têtes et idempotence

ChampTypeDescription
X-Auth-Tokenen-têteobligatoirestringLe jeton de connexion (ou Authorization: Bearer).
Idempotency-Keyen-têteobligatoirestringSur chaque POST et DELETE de trading : une valeur de 8 à 128 lettres, chiffres, _ ou -, nouvelle pour chaque intention. La même clé avec le même corps renvoie la réponse de la première requête et ne change rien ; avec un autre corps, elle est refusée. Les clés sont mémorisées pendant 24 heures.
Content-Typeen-têteobligatoirestringapplication/json avec un corps.

Types d’ordres

TypeChampsCe qui se passe
Limiteshares, limitS’exécute aussitôt contre ce qui est proposé à son prix ou mieux, et le reste demeure dans le carnet jusqu’à son exécution, son annulation ou la clôture de la manche.
Limite, Post-onlyshares, limit, postOnly: trueReste entièrement dans le carnet ou est refusé (400 would_take) : il ne prend jamais de liquidité et ne paie donc jamais les frais taker.
Achat au marchéamount, capDépense aussitôt jusqu’à amount USDC (frais compris) à des prix allant jusqu’à cap ; le reste est abandonné, jamais placé dans le carnet.
Vente au marchéshares, capVend aussitôt jusqu’à shares parts à des prix descendant jusqu’à cap ; le reste est abandonné.
ChampTypeDescription
slugobligatoirestringUne manche négociable (en cours ou à venir) ou un marché événementiel ouvert.
sideobligatoireup | downL’issue que vous négociez (dans un marché événementiel, Oui correspond à up et Non à down).
actionobligatoirebuy | sellUne vente nécessite des parts que vous détenez et qu’aucune autre vente en attente n’a réservées.
typeobligatoirelimit | marketVoir ci-dessus.
sharesfacultatifnumberOrdres à cours limité et toutes les ventes.
amountfacultatifnumberAchats au marché : le montant maximal en USDC à dépenser, frais taker compris.
limitfacultatifnumberOrdres à cours limité : le prix en cents.
capfacultatifnumberOrdres au marché : le pire prix en cents. Un achat ne paie pas plus, une vente n’accepte pas moins.
postOnlyfacultatifbooleanOrdres à cours limité uniquement.
signedfacultatifobjectL’ordre signé par votre clé de session (Signature des ordres).
Vous voulezCorps (plus slug et signed)
Acheter 10 parts Hausse à 45¢ ou mieux, en attente dans le carnet{"side":"up","action":"buy","type":"limit","shares":10,"limit":45}
Dépenser jusqu’à 5 $ en Baisse tout de suite, à 60¢ la part au plus{"side":"down","action":"buy","type":"market","amount":5,"cap":60}
Vendre 10 parts Hausse tout de suite, pour au moins 40¢{"side":"up","action":"sell","type":"market","shares":10,"cap":40}
Proposer 10 parts Hausse à 70¢, uniquement en tant que maker{"side":"up","action":"sell","type":"limit","shares":10,"limit":70,"postOnly":true}

La réponse

Réponses
{ "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 }
Un ordre à cours limité en attente ; un achat au marché de 5 $ exécuté ; un achat au marché dont le cap était inférieur au meilleur prix vendeur.
  • order est l’id de ce qui reste dans le carnet, null si rien n’y reste. filled est le nombre de parts négociées immédiatement ; spent et proceeds sont les USDC payés et reçus, frais compris.
  • Un ordre au marché ajoute requested, fee, avgPrice (en cents, hors frais), unspent ou unsold, status (filled, partial ou none) et, s’il n’a pas été entièrement exécuté, reason : no_liquidity, beyond_limit (avec bestPrice) ou share_limit.
  • Un ordre au marché qui n’exécute rien renvoie quand même un 200, pas une erreur.

Expiration et clôture

  • Les ordres à cours limité sont signés jusqu’à la clôture du marché (la fin de la manche, ou closesAt pour un événement) et restent dans le carnet jusque-là.
  • Les ordres au marché, les scissions et les fusions sont réglés en quelques secondes : signez-les donc pour 5 minutes, jamais au-delà de la clôture. Le serveur accepte une expiration comprise entre 5 secondes à partir de maintenant et la clôture.
  • Les 5 dernières secondes d’une manche n’acceptent aucun nouvel ordre (400 "Round is closing"). Les ordres en attente expirent à la clôture et apparaissent avec le type expire dans votre activité.
  • Manches à venir. Les dix prochaines manches de 5 min et de 15 min (une seule pour 1 h et 1 jour) acceptent déjà des ordres : un bot peut donc coter une manche avant son début.

Lots et annulations

POST /api/orders/batch passe jusqu’à 15 ordres en une requête, dans l’ordre donné, chacun avec ses propres vérifications : la réponse contient un { status, body } par ordre, exactement ce qu’aurait répondu POST /api/orders. L’ordre i est enregistré sous <your key>-<i> : renvoyer tout le lot avec la même clé ne passe donc rien deux fois. DELETE /api/orders annule tous vos ordres ouverts, ou avec ?slug= ceux d’un marché, en une seule transaction.

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]}

Scission et fusion

POST /api/split avec { slug, amount } transforme amount USDC en autant de parts Hausse et Baisse ; POST /api/merge avec { slug, shares } reconvertit les paires en 1,00 $ chacune. Sans frais ; au moins 5 paires ; signé avec un message PMS1 sur seeryx.com.

Liquidités et limites

  • Liquidités. Les achats en attente ne bloquent pas de liquidités, mais l’ensemble de vos achats ouverts sur un même marché, frais taker compris à leur prix limite, doit tenir dans vos liquidités disponibles. Les liquidités ne bougent qu’à l’exécution d’un ordre ; un achat que vous ne pouvez plus payer est annulé.
  • Vos propres ordres. Un ordre peut s’exécuter contre vos propres ordres en attente et paie alors les frais taker comme n’importe quel autre ; Post-only refuse un tel ordre à la place.
  • Ordres en attente. Au plus 200 par compte et 100 sur un même marché (400 open_orders_limit).
  • Fréquence des requêtes. 250 requêtes d’ordre, d’annulation, de scission et de fusion par tranche de 10 secondes et par compte ; chaque ordre d’un lot compte (429 rate_limited). Voir Limites de requêtes et erreurs.

Code

Ordres à cours limité, au marché et par lot, annulations, une scission et une fusion, avec seeryx.ts et chain.ts (ou leurs équivalents Python) à côté.

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) } });

Endpoints d’ordres

Chaque requête de cette section nécessite X-Auth-Token et un en-tête Idempotency-Key.

POST/api/orders

Passer un ordre

Connexion + Idempotency-Key
ChampTypeDescription
slugcorpsobligatoirestringUne manche négociable (en cours ou à venir) ou un marché événementiel ouvert
sidecorpsobligatoireup | downL’issue
actioncorpsobligatoirebuy | sellUne vente nécessite des parts que vous détenez et qu’aucune autre vente n’a réservées
typecorpsobligatoirelimit | marketUn ordre à cours limité reste dans le carnet ; un ordre au marché s’exécute aussitôt et abandonne le reste
sharescorpsfacultatifnumberOrdres à cours limité et toutes les ventes : parts, jusqu’à 4 décimales
amountcorpsfacultatifnumberAchats au marché : le montant maximal en USDC à dépenser, frais taker compris
limitcorpsfacultatifnumberOrdres à cours limité : le prix en cents (voir la grille de prix)
capcorpsfacultatifnumberOrdres au marché : le pire prix en cents, obligatoire avec les ordres signés
postOnlycorpsfacultatifbooleanOrdres à cours limité : refuser l’ordre si une partie s’en exécuterait aussitôt
signedcorpsfacultatifobjectL’ordre signé par votre clé de session de trading
Requête
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}'
Réponse
{ "order": 16901, "filled": 0, "remaining": 10, "spent": 0, "proceeds": 0 }
  • Lorsque GET /api/funds indique onChainTrading (toujours le cas sur seeryx.com), le corps contient aussi "signed", produit par votre clé de session de trading : voir Signature des ordres.
  • order est l’id de la partie qui reste dans le carnet, null si rien n’y reste. filled est le nombre de parts négociées immédiatement ; spent et proceeds sont les USDC payés et reçus, frais compris.
  • Un ordre au marché renvoie son résultat complet : requested, fee, avgPrice (en cents, hors frais), unspent (achat) ou unsold (vente), status "filled", "partial" ou "none" et, en cas d’exécution incomplète, un reason : "no_liquidity" (le carnet est épuisé), "beyond_limit" avec bestPrice (le reste est proposé au-delà de votre cap) ou "share_limit" (un achat au marché signé en parts a obtenu toutes ses parts sous son cap). Un ordre au marché qui n’exécute rien renvoie quand même un 200.
StatutCas
400Entrée invalide ("Invalid limit", "Invalid slug"), "Round is not live", "Round is closing", "Insufficient balance", "Insufficient free shares", un ordre signé qui ne correspond pas
400 below_minimumMoins de parts que minOrderShares ; la réponse ajoute "minimum"
400 would_takeUn ordre Post-only qui s’exécuterait aussitôt
400 open_orders_limitTrop d’ordres en attente ; la réponse ajoute "limit": { account, round }
400 trading_pausedLa clé de session qui l’a signé a été fermée : ouvrez une nouvelle session et signez de nouveau
429 rate_limitedPlus de requêtes d’ordre que le nombre autorisé par fenêtre ; attendez "retryAfter" secondes
503 trading_haltedLe trading est suspendu pour tous (voir GET /api/notice) ; les annulations fonctionnent toujours
503"Exchange clock unavailable" : le serveur ne peut pas confirmer l’heure de la manche ; réessayez dans quelques secondes
POST/api/orders/batch

Passer jusqu’à 15 ordres en une requête

Connexion + Idempotency-Key
ChampTypeDescription
orderscorpsobligatoirearrayDe 1 à 15 ordres, chacun exactement le corps de POST /api/orders avec son propre objet signed
Requête
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}]}'
Réponse
{ "results": [{ "status": 200, "body": { "order": 21306, "filled": 0, "remaining": 5, "spent": 0, "proceeds": 0 } },
  { "status": 400, "body": { "error": "Invalid limit" } }] }
  • Passés dans l’ordre donné, chacun avec ses propres vérifications ; un ordre refusé n’arrête pas les autres. Chaque ordre compte comme une requête dans la limite de requêtes.
  • L’ordre i est enregistré sous la clé d’idempotence <your key>-<i> (i à partir de 0 ; votre clé fait au plus 125 caractères) : renvoyer tout le lot ne passe donc rien deux fois.
StatutCas
400orders n’est pas une liste de 1 à 15 ordres
429 rate_limitedLe lot dépasserait le nombre de requêtes d’ordre autorisé par fenêtre
DELETE/api/orders/:id

Annuler un ordre ouvert

Connexion + Idempotency-Key
ChampTypeDescription
idcheminobligatoirenumberId de l’ordre
Requête
curl -X DELETE "https://seeryx.com/api/orders/16901" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
Réponse
{ "success": true }
StatutCas
400Ordre introuvable : il ne vous appartient pas ou n’est plus ouvert
DELETE/api/orders

Annuler tous vos ordres ouverts, ou ceux d’un marché

Connexion + Idempotency-Key
ChampTypeDescription
slugrequêtefacultatifstringUniquement cette manche ou ce marché événementiel
Requête
curl -X DELETE "https://seeryx.com/api/orders?slug=btc-updown-5m-1791916200" \
  -H "X-Auth-Token: $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
Réponse
{ "success": true, "cancelled": [21306, 21307] }
  • Une seule requête et une seule transaction, quel que soit le nombre d’ordres.
POST/api/split

Transformer des USDC en autant de parts Hausse et Baisse

Connexion + Idempotency-Key
ChampTypeDescription
slugcorpsobligatoirestringUn marché négociable
amountcorpsobligatoirenumberUSDC ; 1 USDC donne 1 part Hausse + 1 part Baisse
signedcorpsfacultatifobjectSigné par la clé de session (PMS1)
Requête
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}'
Réponse
{ "success": true }
  • Au moins minOrderShares paires. Sans frais.
StatutCas
400 below_minimumMoins de paires que le minimum
400"Insufficient balance", une requête signée qui ne correspond pas
POST/api/merge

Reconvertir des paires de parts Hausse et Baisse en USDC

Connexion + Idempotency-Key
ChampTypeDescription
slugcorpsobligatoirestringUn marché négociable
sharescorpsobligatoirenumberPaires à fusionner ; chacune rapporte 1,00 $
signedcorpsfacultatifobjectSigné par la clé de session (PMS1)
Requête
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}'
Réponse
{ "success": true }
  • Au moins minOrderShares paires, ou toutes les paires que vous détenez. Sans frais.