Orders are the core of OFFER-HUB. They represent a transaction between a buyer and seller, with funds protected by escrow until work is completed.
Order Lifecycle
Every order follows a strict state machine:
Creating an Order
curl -X POST http://localhost:4000/api/v1/orders \
-H "Authorization: Bearer ohk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"buyerId": "usr_buyer123",
"sellerId": "usr_seller456",
"amount": "100.00",
"currency": "USD",
"title": "Logo Design",
"description": "Design a modern logo for my tech startup"
}'
const order = await sdk.orders.create({
buyerId: 'usr_buyer123',
sellerId: 'usr_seller456',
amount: '100.00',
currency: 'USD',
title: 'Logo Design',
description: 'Design a modern logo for my tech startup'
});
{
"data": {
"id": "ord_xyz789",
"status": "ORDER_CREATED",
"buyerId": "usr_buyer123",
"sellerId": "usr_seller456",
"amount": "100.00",
"currency": "USD",
"title": "Logo Design",
"created_at": "2026-02-25T12:00:00.000Z"
}
}
Order with Milestones
For large projects, break payment into milestones:
const order = await sdk.orders.create({
buyerId: 'usr_buyer123',
sellerId: 'usr_seller456',
amount: '5000.00',
currency: 'USD',
title: 'Mobile App Development',
milestones: [
{ ref: 'design', title: 'UI/UX Design', amount: '1000.00' },
{ ref: 'backend', title: 'Backend Development', amount: '2000.00' },
{ ref: 'frontend', title: 'Frontend Development', amount: '1500.00' },
{ ref: 'testing', title: 'Testing & Launch', amount: '500.00' }
]
});
Milestone amounts must add up to the total order amount.
Reserving Funds
Before creating escrow, reserve the buyer's funds:
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/reserve \
-H "Authorization: Bearer ohk_live_..."
This moves funds from available to reserved:
Before After available: 100.00available: 0.00reserved: 0.00reserved: 100.00
Creating and Funding Escrow
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/escrow \
-H "Authorization: Bearer ohk_live_..."
This creates a smart contract on Stellar via Trustless Work.
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/escrow/fund \
-H "Authorization: Bearer ohk_live_..."
This sends USDC from the buyer's invisible wallet to the smart contract on-chain.
Funding is irreversible until release or refund. The order status becomes ESCROW_FUNDED, then IN_PROGRESS.
Releasing Funds (Happy Path)
When the buyer approves the work:
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/resolution/release \
-H "Authorization: Bearer ohk_live_..." \
-H "Content-Type: application/json" \
-d '{"requestedBy": "usr_buyer123"}'
This executes 3 on-chain transactions:
Release from contract to platform
Transfer to seller's wallet
Credit seller's balance
The seller's available balance is credited with the order amount.
Refunding (Without Dispute)
For direct refund from an IN_PROGRESS order:
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/resolution/refund \
-H "Authorization: Bearer ohk_live_..." \
-H "Content-Type: application/json" \
-d '{"reason": "Seller cancelled the order"}'
This refunds 100% to the buyer.
Canceling an Order
From ORDER_CREATED or FUNDS_RESERVED status:
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/cancel \
-H "Authorization: Bearer ohk_live_..."
You cannot cancel after escrow is funded (ESCROW_FUNDED or later).
Handling Disputes
curl -X POST http://localhost:4000/api/v1/orders/ord_xyz789/resolution/dispute \
-H "Authorization: Bearer ohk_live_..." \
-H "Content-Type: application/json" \
-d '{
"openedBy": "BUYER",
"reason": "QUALITY_ISSUE"
}'
Reasons: NOT_DELIVERED, QUALITY_ISSUE, OTHER
# Full release to seller
curl -X POST http://localhost:4000/api/v1/disputes/dsp_abc123/resolve \
-H "Authorization: Bearer ohk_live_..." \
-d '{"decision": "FULL_RELEASE"}'
# Full refund to buyer
curl -X POST http://localhost:4000/api/v1/disputes/dsp_abc123/resolve \
-H "Authorization: Bearer ohk_live_..." \
-d '{"decision": "FULL_REFUND"}'
# Split between both
curl -X POST http://localhost:4000/api/v1/disputes/dsp_abc123/resolve \
-H "Authorization: Bearer ohk_live_..." \
-d '{
"decision": "SPLIT",
"releaseAmount": "80.00",
"refundAmount": "20.00",
"note": "80% of work was completed"
}'
Listing Orders
# All orders
curl "http://localhost:4000/api/v1/orders" \
-H "Authorization: Bearer ohk_live_..."
# Filter by status
curl "http://localhost:4000/api/v1/orders?status=IN_PROGRESS" \
-H "Authorization: Bearer ohk_live_..."
# Filter by buyer
curl "http://localhost:4000/api/v1/orders?buyer_id=usr_buyer123" \
-H "Authorization: Bearer ohk_live_..."
# Pagination
curl "http://localhost:4000/api/v1/orders?limit=20&cursor=ord_lastid" \
-H "Authorization: Bearer ohk_live_..."
Events
Subscribe to order events via SSE:
const events = new EventSource(
'http://localhost:4000/api/v1/events',
{ headers: { Authorization: 'Bearer ohk_live_...' } }
);
events.onmessage = (e) => {
const event = JSON.parse(e.data);
switch (event.eventType) {
case 'order.created':
console.log('New order:', event.payload.orderId);
break;
case 'order.funds_reserved':
console.log('Funds reserved for:', event.payload.orderId);
break;
case 'order.escrow_funded':
console.log('Escrow funded:', event.payload.orderId);
break;
case 'order.released':
console.log('Funds released:', event.payload.orderId);
break;
case 'order.refunded':
console.log('Funds refunded:', event.payload.orderId);
break;
case 'order.closed':
console.log('Order closed:', event.payload.orderId);
break;
}
};
Best Practices
const balance = await sdk.balance.get(buyerId);
const amount = parseFloat(orderAmount);
if (parseFloat(balance.available) < amount) {
throw new Error('Insufficient funds');
}
const idempotentSdk = sdk.withIdempotencyKey(generateUUID());
const order = await idempotentSdk.orders.create({ ... });
3. Handle All States
switch (order.status) {
case 'ORDER_CREATED':
// Show "Waiting for funds" UI
break;
case 'FUNDS_RESERVED':
// Show "Creating escrow" UI
break;
case 'IN_PROGRESS':
// Show "Work in progress" UI
break;
case 'DISPUTED':
// Show "Under review" UI
break;
case 'CLOSED':
// Show "Completed" UI
break;
}
Next Steps
Escrow Guide - How blockchain escrow works
Disputes Guide - Handling disputes
Events Reference - All order events
API Reference - Full endpoint documentation