All Musubi APIs follow the same conventions regardless of participant type.
Base URL
All endpoints are prefixed with /api/v1:
https://your-backend.example.com/api/v1/orders
Response Envelope
Every successful response wraps the payload in a standard envelope:
Single Resource
Paginated List
Error
{
"data": {
"intent_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "PENDING",
"source_currency": "JPYSC0",
"target_amount": "100000"
},
"meta": {
"request_id": "req_a1b2c3d4",
"timestamp": "2025-03-15T09:00:00.000Z"
}
}
{
"data": [
{ "intent_id": "f47ac10b-...", "status": "SETTLED" },
{ "intent_id": "8b3e7d1a-...", "status": "PENDING" }
],
"meta": {
"request_id": "req_e5f6g7h8",
"timestamp": "2025-03-15T09:00:01.000Z"
},
"pagination": {
"page": 1,
"page_size": 20,
"total_items": 42,
"total_pages": 3
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "target_amount must be a positive number",
"details": [
{ "field": "target_amount", "reason": "must be greater than 0" }
]
},
"meta": {
"request_id": "req_x9y0z1a2",
"timestamp": "2025-03-15T09:00:02.000Z"
}
}
Error Codes
| Code | HTTP Status | Description |
|---|
VALIDATION_ERROR | 400 | Missing or invalid request fields |
UNAUTHORIZED | 401 | Missing or invalid JWT token |
NOT_FOUND | 404 | Order, quote, or settlement not found |
CONFLICT | 409 | Invalid state transition (e.g., cancelling a SETTLED order) |
CANTON_ERROR | 502 | Settlement network unavailable |
INTERNAL_ERROR | 500 | Unexpected server error |
List endpoints accept these query parameters:
| Parameter | Default | Range | Description |
|---|
page | 1 | 1+ | Page number (1-indexed) |
page_size | 20 | 1-100 | Items per page |
Filtering & Sorting
Order list endpoints support:
| Parameter | Example | Description |
|---|
status | PENDING,QUOTED | Comma-separated status filter |
source_currency | JPYSC0 | Filter by source currency |
target_currency | USDCx | Filter by target currency |
created_after | 2025-03-01T00:00:00Z | Orders created after this timestamp |
created_before | 2025-03-31T23:59:59Z | Orders created before this timestamp |
sort_by | created_at | Sort field: created_at, target_amount, status, settled_at |
sort_order | desc | Sort direction: asc or desc |
| Type | Format | Example |
|---|
| Timestamps | ISO 8601 UTC | 2025-03-15T09:00:00.000Z |
| Decimal amounts | String | "10000000", "112.0" |
| IDs | UUID v4 | f47ac10b-58cc-4372-a567-0e02b2c3d479 |
| Party IDs | Canton format | SenderInstitution::209fa2c...b341 |
| Field names | snake_case | source_currency, intent_id |
Decimal amounts are strings to prevent floating-point precision loss. Always parse them as decimals in your application, not as floats.
Server-Sent Events (SSE)
Each participant API provides an SSE endpoint for real-time updates. Connect using EventSource:
const events = new EventSource(
'https://your-backend.example.com/api/v1/orders/events',
{ headers: { 'Authorization': `Bearer ${token}` } }
);
events.addEventListener('order_updated', (e) => {
const order = JSON.parse(e.data);
console.log(`Order ${order.intent_id} is now ${order.status}`);
});
events.addEventListener('heartbeat', () => {
// Keepalive every 30 seconds
});
| Behavior | Detail |
|---|
| Heartbeat | Every 30 seconds |
| Reconnection | Automatic via EventSource |
| Filtering | Optional intent_id query parameter to watch a specific order |
Currencies
The testnet supports two stablecoins:
| Code | Name | Peg |
|---|
JPYSC0 | Japanese Yen Stablecoin | 1:1 JPY |
USDCx | Canton-wrapped USDC | 1:1 USD |