Skip to Content

Orders

Place and cancel orders on the matching engine. Authenticate with your API key from the web app API section.

Endpoints

MethodPathDescription
POST/api/orders/Create order
POST/api/orders/approvePre-approve spend for a property
POST/api/orders/cancelCancel order
POST/api/orders/cancel-allCancel all open orders
POST/api/orders/conditionalCreate a stop or take order. See Stop & take orders.
POST/api/orders/conditional/cancelCancel a stop or take order. See Stop & take orders.

Create order

POST /api/orders/

Submits an order for the authenticated user.

Nonce is no longer required. Do not call POST /api/orders/nonce and do not send nonce on create.

Request body

Type: OrderRequestBody (@loafmarkets/shared-types)

interface OrderRequestBody { tokenName: string; // lowercase slug, e.g. "opera" — not the ticker price: number; quantity: number; side: 'BUY' | 'SELL'; type: 'MARKET' | 'LIMIT'; timeInForce: 'GTC'; deadline: number; tpPrice?: number; // BUY only: attach a take-profit slPrice?: number; // BUY only: attach a stop-loss }

Request

import axios from 'axios'; import type { OrderRequestBody } from '@loafmarkets/shared-types'; const body: OrderRequestBody = { tokenName: 'opera', price: 125.5, quantity: 10, side: 'BUY', type: 'LIMIT', timeInForce: 'GTC', deadline: 0, }; const response = await axios.post('https://api.loafmarkets.com/api/orders/', body, { headers: { Authorization: `Bearer ${process.env.LOAF_API_KEY}` }, }); console.log(response.data);

Identify the market with lowercase tokenName (e.g. opera), not the short ticker (OPR) and not propertyId. For a market order, set "type": "MARKET" and "price": 0. See the Python bot template  for a higher-level SDK.

Minimum order notional is 10 USDC (price × quantity), waived only for a SELL that closes your entire position.

Parameters

ParameterTypeRequiredDescription
tokenNamestringYes(body) Lowercase property tokenName (letters a-z only, max 20). Not the ticker.
pricenumberYes(body) Limit price in USDC. Use 0 for market orders (MARKET_ORDER_PRICE).
quantitynumberYes(body) Order size in tokens (max 1 decimal place).
side'BUY' | 'SELL'Yes(body) Order side.
type'MARKET' | 'LIMIT'Yes(body) Order type.
timeInForce'GTC'Yes(body) Time in force (currently GTC only).
deadlinenumberYes(body) Unix timestamp (seconds). Use 0 for standard GTC orders.
tpPricenumberNo(body) BUY only. Trigger price of a take-profit SELL for the full quantity (max 2 decimal places).
slPricenumberNo(body) BUY only. Trigger price of a stop-loss SELL for the full quantity (max 2 decimal places).

tpPrice and slPrice create a linked take-profit and stop-loss. When one of them triggers, Loaf cancels the other one. Omit both fields for a normal order. See Attach take-profit and stop-loss to a buy for the rules.

Response

Type: OrderApiResponse

interface OrderApiResponse { success: boolean; orderId: number; errorMessage?: string; }

Example response:

{ "success": true, "orderId": 9001 }

Errors

StatusCodeDescription
400validation_errorRequest failed schema validation.
401unauthorizedMissing or invalid authentication.
403—Trading closed, halted, ineligible for competition, or world gate rejected the property.
404not_foundUnknown tokenName.
503—Matching engine unreachable or did not confirm — see callout below.
500internal_errorUnexpected server error.

503 on create: do not blind-retry. If the engine is unreachable before commit, the order was not placed (safe to retry after backoff). If the transport fails after commit, funds may already be frozen and the order may still be processing. Check open orders / portfolio before sending another identical order.

Requires API key authentication.


Approve trading

POST /api/orders/approve

Pre-approves spend allowances for a property ahead of the first order (BUY and SELL sides). Identify the market with lowercase tokenName.

Request body

Type: ApproveTradingRequestBody

interface ApproveTradingRequestBody { tokenName: string; }

Request

import axios from 'axios'; import type { ApproveTradingRequestBody } from '@loafmarkets/shared-types'; const body: ApproveTradingRequestBody = { tokenName: 'opera' }; const response = await axios.post('https://api.loafmarkets.com/api/orders/approve', body, { headers: { Authorization: `Bearer ${process.env.LOAF_API_KEY}` }, }); console.log(response.data);

Response

Type: ApproveTradingResponse

interface ApproveTradingResponse { approved: true; results: { BUY: { alreadyApproved: boolean }; SELL: { alreadyApproved: boolean }; }; }

alreadyApproved: true means the wallet already held a sufficient allowance (no on-chain tx sent for that side).

Errors

StatusCodeDescription
400validation_errorRequest failed schema validation.
401unauthorizedMissing or invalid authentication.
404not_foundUnknown tokenName.
500internal_errorUnexpected server error.

Cancel order

POST /api/orders/cancel

Cancels an existing order via the matching engine.

To cancel a stop or take order that has not triggered, use Cancel a stop or take order.

Request body

Type: CancelOrderRequestBody (@loafmarkets/shared-types)

interface CancelOrderRequestBody { orderId: number; }

Request

import axios from 'axios'; import type { CancelOrderRequestBody } from '@loafmarkets/shared-types'; const body: CancelOrderRequestBody = { orderId: 9001, }; const response = await axios.post('https://api.loafmarkets.com/api/orders/cancel', body, { headers: { Authorization: `Bearer ${process.env.LOAF_API_KEY}` }, }); console.log(response.data);

Parameters

ParameterTypeRequiredDescription
orderIdnumberYes(body) ID of the order to cancel.

Response

Type: CancelOrderResponse

interface CancelOrderResponse { success: boolean; orderId: number; errorMessage?: string; }

Example response:

{ "success": true, "orderId": 9001 }

Errors

StatusCodeDescription
400validation_errorRequest failed schema validation.
401unauthorizedMissing or invalid authentication.
404not_foundResource not found (where applicable).
500internal_errorUnexpected server error.

Requires API key authentication.


Cancel all orders

POST /api/orders/cancel-all

Cancels every open order for the authenticated user by relaying a cancel request to the matching engine for each one.

It also cancels your stop and take orders with status PENDING or ARMED. Their ids come first in cancelledOrderIds, and requestedCount includes them.

Request

import axios from 'axios'; const response = await axios.post('https://api.loafmarkets.com/api/orders/cancel-all', undefined, { headers: { Authorization: `Bearer ${process.env.LOAF_API_KEY}` }, }); console.log(response.data);

Parameters

ParameterTypeRequiredDescription
None-NoNo parameters for this endpoint.

Response

Type: CancelAllOrdersResponse (@loafmarkets/shared-types)

interface CancelAllOrdersResponse { requestedCount: number; cancelledOrderIds: number[]; failedOrders: Array<{ orderId: number; errorMessage: string }>; }

Example response:

{ "requestedCount": 2, "cancelledOrderIds": [9001, 9002], "failedOrders": [] }

Errors

StatusCodeDescription
401unauthorizedMissing or invalid authentication.
503service_unavailableMatching engine unavailable for all cancels.
500internal_errorUnexpected server error.

Requires API key authentication. Partial success is possible: check failedOrders when cancelledOrderIds does not cover every open order.

Last updated on