Orders
Place and cancel orders on the matching engine. Authenticate with your API key from the web app API section.
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /api/orders/nonce | Request order nonce |
POST | /api/orders/ | Create order |
POST | /api/orders/approve | Pre-approve spend for a property |
POST | /api/orders/cancel | Cancel order |
POST | /api/orders/cancel-all | Cancel all open orders |
Request order nonce
POST /api/orders/nonce
Issues a one-time nonce before submitting an order (anti-replay).
Request
import axios from 'axios';
const response = await axios.post('https://api.loafmarkets.com/api/orders/nonce', undefined, {
headers: { Authorization: `Bearer ${process.env.LOAF_API_KEY}` },
});
console.log(response.data);Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| None | - | No | No parameters for this endpoint. |
Response
Type: OrderNonceResponse
interface OrderNonceResponse {
nonce: string;
deadline: number; // Unix seconds
}Example response:
{
"nonce": "a1b2c3d4e5f6789012345678901234ab",
"deadline": 1893456000
}Errors
| Status | Code | Description |
|---|---|---|
400 | validation_error | Request failed schema validation. |
401 | unauthorized | Missing or invalid authentication. |
404 | not_found | Resource not found (where applicable). |
500 | internal_error | Unexpected server error. |
Requires API key authentication.
Create order
POST /api/orders/
Submits an order for the authenticated user.
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;
nonce: string;
}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,
nonce: 'a1b2c3d4e5f6789012345678901234ab',
};
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
| Parameter | Type | Required | Description |
|---|---|---|---|
tokenName | string | Yes | (body) Lowercase property tokenName (letters a-z only, max 20). Not the ticker. |
price | number | Yes | (body) Limit price in USDC. Use 0 for market orders (MARKET_ORDER_PRICE). |
quantity | number | Yes | (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). |
deadline | number | Yes | (body) Unix timestamp (seconds). Use 0 for standard GTC orders. |
nonce | string | Yes | (body) 32-character hex nonce from POST /api/orders/nonce. |
Response
Type: OrderApiResponse
interface OrderApiResponse {
success: boolean;
orderId: number;
errorMessage?: string;
}Example response:
{
"success": true,
"orderId": 9001
}Errors
| Status | Code | Description |
|---|---|---|
400 | validation_error | Request failed schema validation. |
401 | unauthorized | Missing or invalid authentication. |
403 | — | Trading closed, halted, ineligible for competition, or world gate rejected the property. |
404 | not_found | Unknown tokenName. |
503 | — | Matching engine unreachable or did not confirm — see callout below. |
500 | internal_error | Unexpected server error. |
503 on create: do not blind-retry. If the engine is unreachable before commit, the order was not placed (safe to retry with a fresh nonce 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
| Status | Code | Description |
|---|---|---|
400 | validation_error | Request failed schema validation. |
401 | unauthorized | Missing or invalid authentication. |
404 | not_found | Unknown tokenName. |
500 | internal_error | Unexpected server error. |
Cancel order
POST /api/orders/cancel
Cancels an existing order via the matching engine.
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
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | number | Yes | (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
| Status | Code | Description |
|---|---|---|
400 | validation_error | Request failed schema validation. |
401 | unauthorized | Missing or invalid authentication. |
404 | not_found | Resource not found (where applicable). |
500 | internal_error | Unexpected 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.
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| None | - | No | No 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
| Status | Code | Description |
|---|---|---|
401 | unauthorized | Missing or invalid authentication. |
503 | service_unavailable | Matching engine unavailable for all cancels. |
500 | internal_error | Unexpected server error. |
Requires API key authentication. Partial success is possible: check failedOrders when cancelledOrderIds does not cover every open order.