GET /api/v1/mev/orders/:orderId
Poll the status of a submitted order to track its progress through MEV-protected execution.
Use this endpoint to monitor your order status from submission through confirmation. Poll every 5-10 seconds until reaching a terminal state.
Endpoint Details
GET https://api.unikron.ch/api/v1/mev/orders/:orderIdAuthentication Required: Yes (API Key via X-API-Key header)
Request Parameters
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | string | Yes | Order ID from submit response |
Headers
| Header | Required | Description | Example |
|---|---|---|---|
X-API-Key | Yes | Your UNIKRON API key | uk_live_abc123... |
Code Examples
JavaScript
JavaScript / TypeScript
const API_KEY = process.env.UNIKRON_API_KEY;
const API_URL = "https://api.unikron.ch";
async function getOrderStatus(orderId: string) {
const response = await fetch(`${API_URL}/api/v1/mev/orders/${orderId}`, {
headers: {
"X-API-Key": API_KEY,
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const { ok, data } = await response.json();
if (!ok) {
throw new Error(`API Error: ${data.error}`);
}
return data;
}
// Example: Poll until confirmed
async function waitForConfirmation(orderId: string) {
while (true) {
const order = await getOrderStatus(orderId);
console.log(`Status: ${order.status}`);
// Terminal states
if (order.status === "confirmed") {
console.log(" Transaction confirmed!");
console.log(`TX Hash: ${order.txHash}`);
console.log(`Block: ${order.blockNumber}`);
return order;
}
if (order.status === "failed") {
console.error(" Transaction failed");
throw new Error(order.error || "Transaction failed");
}
// Wait 10 seconds before next poll
await new Promise((resolve) => setTimeout(resolve, 10000));
}
}
// Usage
const orderId = "ord_abc123xyz";
try {
const result = await waitForConfirmation(orderId);
console.log("Order complete:", result);
} catch (error) {
console.error("Order failed:", error);
}Response Format
Success Response (200 OK)
{
"ok": true,
"data": {
"orderId": "ord_abc123xyz",
"status": "confirmed",
"txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"blockNumber": 18500000,
"gasUsed": "340196",
"effectiveGasPrice": "25000000000",
"createdAt": "2024-01-15T10:30:00Z",
"submittedAt": "2024-01-15T10:30:05Z",
"confirmedAt": "2024-01-15T10:32:15Z",
"orderParams": {
"fromToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"toToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "1000000000000000000",
"minReturnAmount": "3693000000"
}
}
}Response Fields Reference
| Field | Type | Description |
|---|---|---|
orderId | string | Unique order identifier |
status | string | Current order status (see status table below) |
txHash | string | Transaction hash (available after submission) |
blockNumber | number | Block number (available after confirmation) |
gasUsed | string | Gas used (available after confirmation) |
effectiveGasPrice | string | Actual gas price paid (available after confirmation) |
createdAt | string | ISO 8601 order creation timestamp |
submittedAt | string | ISO 8601 submission timestamp |
confirmedAt | string | ISO 8601 confirmation timestamp (if confirmed) |
orderParams | object | Original order parameters |
Order Status Values
Status Flow: pending → submitted → mining → confirmed ↓ failed
| Status | Description | Next Action | Duration |
|---|---|---|---|
pending | Waiting to submit to MEV Blocker | Keep polling | 0-5 seconds |
submitted | Sent to MEV Blocker | Keep polling | 5-15 seconds |
mining | Included in block builder auction | Keep polling | 15-45 seconds |
confirmed | Transaction confirmed on blockchain | Done - success | Terminal state |
failed | Transaction reverted or rejected | Check error, retry | Terminal state |
cancelled | Order cancelled by user or system | - | Terminal state |
Polling Best Practices
Recommended Polling Strategy:
- Poll every 5-10 seconds (10 seconds recommended)
- Stop polling after reaching terminal states:
confirmed,failed, orcancelled - Set a timeout of 5 minutes maximum
- Implement exponential backoff on API errors
- Cache the last status to avoid redundant processing
const POLLING_CONFIG = {
interval: 10000, // 10 seconds
timeout: 300000, // 5 minutes
maxRetries: 3, // Retry failed API calls
exponentialBackoff: true,
};
async function pollWithConfig(orderId) {
const startTime = Date.now();
let retries = 0;
while (true) {
// Check timeout
if (Date.now() - startTime > POLLING_CONFIG.timeout) {
throw new Error("Polling timeout exceeded");
}
try {
const status = await getOrderStatus(orderId);
// Terminal states
if (["confirmed", "failed", "cancelled"].includes(status.status)) {
return status;
}
// Reset retries on success
retries = 0;
} catch (error) {
retries++;
if (retries >= POLLING_CONFIG.maxRetries) {
throw error;
}
// Exponential backoff
const backoff = Math.pow(2, retries) * 1000;
await new Promise((r) => setTimeout(r, backoff));
continue;
}
// Wait before next poll
await new Promise((r) => setTimeout(r, POLLING_CONFIG.interval));
}
}Error Responses
404 Not Found - Order Not Found
{
"ok": false,
"error": "ORDER_NOT_FOUND",
"message": "Order with ID ord_abc123xyz not found",
"suggestion": "Check the order ID or ensure it was created by this API key"
}401 Unauthorized
{
"ok": false,
"error": "UNAUTHORIZED",
"message": "Invalid or missing API key",
"suggestion": "Check your X-API-Key header"
}Common Error Codes
| HTTP | Error Code | Reason | Solution |
|---|---|---|---|
| 401 | UNAUTHORIZED | Invalid/missing API key | Check X-API-Key header |
| 404 | ORDER_NOT_FOUND | Invalid order ID | Verify order ID is correct |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests | Increase polling interval |
| 500 | INTERNAL_SERVER_ERROR | Server error | Retry with backoff |
Integration Example
Complete Workflow
// 1. Submit order
const order = await submitOrder(quote, signer);
console.log(`Order submitted: ${order.order.orderId}`);
// 2. Poll for status
const finalStatus = await waitForConfirmation(order.order.orderId);
// 3. Handle result
if (finalStatus.status === "confirmed") {
console.log("Swap successful!");
console.log(
`View on Etherscan: https://etherscan.io/tx/${finalStatus.txHash}`
);
// Update UI with success
showSuccess({
txHash: finalStatus.txHash,
blockNumber: finalStatus.blockNumber,
});
} else {
console.error("Swap failed");
showError(finalStatus.error);
}GET /api/v1/mev/orders/user/:userAddress
Retrieve order history for a specific user address.
Get a paginated list of all orders submitted by a specific wallet address. Useful for building transaction history interfaces and order management dashboards.
Endpoint Details
GET https://api.unikron.ch/api/v1/mev/orders/user/:userAddressAuthentication Required: Yes (API Key via X-API-Key header)
Request Parameters
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userAddress | string | Yes | User’s wallet address (checksummed) |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | No | Max orders to return (default: 50, max: 200) |
offset | number | No | Number of orders to skip (default: 0) |
status | string | No | Filter by status (e.g., confirmed, failed) |
Headers
| Header | Required | Description | Example |
|---|---|---|---|
X-API-Key | Yes | Your UNIKRON API key | uk_live_abc123... |
Code Examples
JavaScript
JavaScript / TypeScript
const API_KEY = process.env.UNIKRON_API_KEY;
const API_URL = "https://api.unikron.ch";
async function getUserOrders(
userAddress: string,
limit: number = 50,
offset: number = 0,
status?: string
) {
const params = new URLSearchParams({
limit: limit.toString(),
offset: offset.toString(),
});
if (status) {
params.append("status", status);
}
const response = await fetch(
`${API_URL}/api/v1/mev/orders/user/${userAddress}?${params}`,
{
headers: {
"X-API-Key": API_KEY,
},
}
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const { ok, data } = await response.json();
if (!ok) {
throw new Error(`API Error: ${data.error}`);
}
return data;
}
// Example: Get recent orders
const userAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb";
try {
const orders = await getUserOrders(userAddress, 20);
console.log(`Total orders: ${orders.total}`);
console.log(`Showing: ${orders.orders.length}`);
console.log(`Has more: ${orders.hasMore}`);
orders.orders.forEach((order) => {
console.log(`\nOrder ID: ${order.orderId}`);
console.log(`Status: ${order.status}`);
console.log(`Created: ${order.createdAt}`);
console.log(`TX Hash: ${order.txHash || "pending"}`);
});
} catch (error) {
console.error("Failed to get orders:", error);
}Response Format
Success Response (200 OK)
{
"ok": true,
"data": {
"orders": [
{
"orderId": "ord_abc123xyz",
"status": "confirmed",
"txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"blockNumber": 18500000,
"createdAt": "2024-01-15T10:30:00Z",
"confirmedAt": "2024-01-15T10:32:15Z",
"summary": {
"sellToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"buyToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"sellAmount": "1000000000000000000",
"buyAmount": "3700000000"
}
},
{
"orderId": "ord_def456uvw",
"status": "pending",
"txHash": null,
"blockNumber": null,
"createdAt": "2024-01-15T11:00:00Z",
"confirmedAt": null,
"summary": {
"sellToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"buyToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"sellAmount": "5000000000",
"buyAmount": "1350000000000000000"
}
}
],
"total": 150,
"hasMore": true,
"pagination": {
"limit": 20,
"offset": 0,
"nextOffset": 20
}
}
}Response Fields Reference
Root Data Object
| Field | Type | Description |
|---|---|---|
orders | array | Array of order objects (see below) |
total | number | Total number of orders for this user |
hasMore | boolean | Whether more orders are available |
pagination | object | Pagination metadata |
Order Object
| Field | Type | Description |
|---|---|---|
orderId | string | Unique order identifier |
status | string | Order status |
txHash | string | Transaction hash (null if not submitted) |
blockNumber | number | Block number (null if not confirmed) |
createdAt | string | ISO 8601 order creation timestamp |
confirmedAt | string | ISO 8601 confirmation time (if confirmed) |
summary | object | Order summary with token details |
Summary Object
| Field | Type | Description |
|---|---|---|
sellToken | string | Token being sold (address) |
buyToken | string | Token being bought (address) |
sellAmount | string | Sell amount in smallest units |
buyAmount | string | Buy amount in smallest units |
Pagination
Pagination Best Practices:
- Use
limitto control page size (max 200) - Use
offsetto skip to specific pages - Check
hasMoreto determine if more pages exist - Use
pagination.nextOffsetfor the next page
Example: Paginated Fetching
async function getAllUserOrders(userAddress: string) {
const allOrders = [];
let offset = 0;
const limit = 100;
while (true) {
const data = await getUserOrders(userAddress, limit, offset);
allOrders.push(...data.orders);
console.log(
`Fetched ${data.orders.length} orders (total: ${allOrders.length}/${data.total})`
);
if (!data.hasMore) {
break;
}
offset = data.pagination.nextOffset;
}
return allOrders;
}Filtering by Status
Filter Options: Use the status query parameter to filter orders:
confirmed- Successfully completed ordersfailed- Failed orderspending- Orders waiting for submissionmining- Orders being mined
// Get only confirmed orders
const confirmed = await getUserOrders(userAddress, 50, 0, "confirmed");
// Get only failed orders
const failed = await getUserOrders(userAddress, 50, 0, "failed");Error Responses
400 Bad Request - Invalid Address
{
"ok": false,
"error": "INVALID_ADDRESS",
"message": "User address is not a valid Ethereum address",
"details": {
"address": "invalid_address",
"reason": "Invalid format"
}
}400 Bad Request - Invalid Limit
{
"ok": false,
"error": "INVALID_PARAMETER",
"message": "Limit must be between 1 and 200",
"details": {
"parameter": "limit",
"provided": 500,
"max": 200
}
}Common Error Codes
| HTTP | Error Code | Reason | Solution |
|---|---|---|---|
| 400 | INVALID_ADDRESS | Invalid wallet address | Use valid checksummed address |
| 400 | INVALID_PARAMETER | Invalid limit/offset | Use valid pagination values |
| 401 | UNAUTHORIZED | Invalid/missing API key | Check X-API-Key header |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests | Implement rate limiting |
Use Cases
Transaction History UI
// Build transaction history table
async function buildHistoryTable(userAddress: string) {
const orders = await getUserOrders(userAddress, 50);
const tableData = orders.orders.map((order) => ({
date: new Date(order.createdAt).toLocaleString(),
status: order.status,
from: formatToken(order.summary.sellToken),
to: formatToken(order.summary.buyToken),
amount: formatAmount(order.summary.sellAmount),
txHash: order.txHash ? (
<a href={`https://etherscan.io/tx/${order.txHash}`}>
{order.txHash.slice(0, 10)}...
</a>
) : (
"Pending"
),
}));
return tableData;
}Order Analytics
// Calculate user statistics
async function getUserStats(userAddress: string) {
const allOrders = await getAllUserOrders(userAddress);
const stats = {
total: allOrders.length,
confirmed: allOrders.filter((o) => o.status === "confirmed").length,
failed: allOrders.filter((o) => o.status === "failed").length,
pending: allOrders.filter((o) => o.status === "pending").length,
totalVolume: calculateTotalVolume(allOrders),
};
return stats;
}Related Endpoints
Related Operations
- GET /api/v1/mev/orders/:orderId - Get details for specific order (see above)
- POST /api/v1/mev/orders - Submit new order
- GET /api/v1/quote - Get quote for new swap