EMS Client API Reference
Overview
The Ediphy EMS Client API provides programmatic access to our execution management system, enabling you to seamlessly integrate order submission and management into your existing trading infrastructure.
Initial Product Coverage: IMM Swaps (IRS)
Why the Ediphy EMS API?
- Simple Integration — Clean REST interface with JSON payloads; no proprietary protocols or complex dependencies
- Real-Time Visibility — WebSocket streaming for instant order state updates and execution notifications
- Built-In Safety — Automatic heartbeat monitoring with configurable auto-cancel protects against runaway orders
- Full Audit Trail — Every request is logged and queryable, supporting your compliance and reconciliation workflows
- Flexible Order Management — Support for create, amend, cancel, and bulk operations with idempotency guarantees
- Sandbox Environment — Test your integration against a full-featured simulation before going live
1. Key Concepts
1.1 Connection Heartbeat & Safety
All order-management connections must maintain an active heartbeat. This is a safety mechanism to protect clients from runaway orders if they lose control of their connection.
Heartbeat Requirements:
- REST API clients must call any authenticated endpoint at least once every 60 seconds
- WebSocket clients must send heartbeat messages at least every 30 seconds (see Section 9.3)
Auto-Cancel on Heartbeat Failure:
- If no authenticated activity is received for 90 seconds, the gateway assumes the client has lost control
- By default, all non-GTC orders (GTT, EOD) are automatically cancelled
- GTC (good-till-cancel) orders are preserved across heartbeat failures
- Clients are notified via WebSocket (if connected) before auto-cancel executes
- This behavior can be configured per-client (contact support@ediphymarkets.com)
This safety mechanism prevents scenarios where a client submits orders, loses connectivity, and those orders continue trading without oversight. Most institutional trading systems implement similar protections.
Hybrid REST + WebSocket Clients:
If you use both REST and WebSocket connections (recommended: REST for trading, WebSocket for monitoring), each protocol maintains its own independent heartbeat:
- REST heartbeat (60s requirement) prevents auto-cancel of non-GTC orders
- WebSocket heartbeat (30s requirement) keeps the stream connection alive
- Activity on one protocol does not count toward the other's heartbeat requirement
- If REST becomes idle while WebSocket remains active, the REST auto-cancel logic will still trigger
Clients using both protocols must ensure each connection maintains its own heartbeat independently.
1.2 Eventual Consistency Model
The EMS operates on an eventually consistent model:
- Client submits a request (create, amend, cancel) describing the desired state
- The API persists the request and queues it for processing
- The EMS processes the latest request for each order when ready
- Client polls order state to observe changes
- Order state includes
completedflag (true = no further market exposure) andvalidation_errorfield
The EMS does not acknowledge individual requests. Multiple rapid requests for the same order will "collapse" - only the latest desired state is processed. When a request is superseded by a newer request for the same order, the original request's status in the request log will transition to superseded. Clients must monitor order state to understand outcomes.
1.3 Trading Session
A trading session is defined as the UTC 24-hour day period:
- Start: 00:00:00.000 UTC
- End: 23:59:59.999 UTC
Session boundaries affect:
- Request log retention: Requests are retained for the current session only
Idempotency-Keycache: The header-based idempotency cache resets at session start- Order listing:
GET /ordersreturns orders from the current session
Orders created in one session may remain active across session boundaries (e.g., GTC orders), but administrative data (request log, Idempotency-Key cache) resets at 00:00 UTC.
Cross-session order behavior: If a GTC order is created at 23:59 UTC and the client reconnects at 00:01 UTC the next day:
- The order is still active and can be queried via
GET /orders/{order_id} - The order appears in
GET /ordersfor the new session - The original creation request is not available via
GET /requests(request log was cleared) - The
client_order_idcannot be reused — it remains reserved by the active GTC order until that order completes - The
fillsarray will be empty — fills from previous sessions are not carried over. Clients requiring historical fill data should persist fills locally or request audit reports (see Section 11.4).
1.4 Order Creation Methods
Orders can be created in the EMS through two pathways:
1. Direct API Submission (POST /orders)
The standard method for programmatic order submission. Clients send order details directly to the EMS via the REST API. This is the primary integration point for most trading systems.
2. Liquidity Checker "Go Firm" Workflow
Orders can also originate from the Liquidity Checker, Ediphy's pre-trading blotter system for monitoring liquidity conditions before committing to firm orders. In this workflow:
- Traders add soft interest to the Liquidity Checker (bonds or swaps they're interested in trading)
- The system monitors liquidity indicators (trade counts, volumes, market activity)
- When conditions are favorable, traders transition the interest to Firm status via the Liquidity Checker API or GUI
- The system automatically creates a live EMS order linked to the original interest record
Cross-System Visibility:
Orders created via the Liquidity Checker workflow include a linked_interest_id field that ties the EMS order back to the originating interest record. This enables:
- Monitoring execution progress in both the Liquidity Checker (high-level blotter status) and EMS (detailed order lifecycle)
- Correlating fills and execution events with the original trading interest
- Maintaining audit trail from initial soft interest through final execution
Use direct POST /orders when you have firm trading decisions and want immediate order submission. Use the Liquidity Checker workflow when you want to monitor market conditions and liquidity before committing to firm orders. The Liquidity Checker is particularly useful for illiquid instruments where timing matters.
See the Liquidity Checker API documentation for details on the pre-trading workflow, liquidity scoring, and the /go-firm endpoint.
2. Authentication & Authorization
2.1 Authentication Model
The API supports two authentication methods: Bearer Token for standard integrations and Mutual TLS (mTLS) for clients requiring stronger security guarantees.
Bearer Token Authentication (Standard)
API keys are generated and managed through the Ediphy client portal. Include the API key in the Authorization header:
Authorization: Bearer <api_key>
- Simple integration — Works with any standard HTTP client
- No cryptographic operations — No signing or key management required client-side
- Suitable for most use cases — Protected by TLS encryption and idempotency keys
Mutual TLS Authentication (Enhanced Security)
For clients with stricter security requirements (regulatory compliance, enhanced audit trails, defense in depth), we support mutual TLS (mTLS) authentication.
How it works:
- Client generates an X.509 certificate and private key
- Client registers the certificate (or CA) via the Ediphy client portal
- TLS handshake authenticates both client and server
- No
Authorizationheader required — identity established at transport layer
Benefits:
- Stronger authentication — Cryptographic proof of client identity at connection time
- No shared secrets — Private key never leaves client infrastructure
- Connection-level security — Authentication happens before any application data is exchanged
- Standard tooling — Works with standard TLS libraries and infrastructure
How mTLS works with the API:
The API uses a single set of endpoints for both authentication methods. The server requests a client certificate during TLS handshake but does not require one:
- If a valid client certificate is presented → mTLS authentication is used; no
Authorizationheader required - If no certificate is presented → Bearer token authentication is required via the
Authorizationheader
This allows clients to choose their authentication method on a per-connection basis without changing endpoints.
Contact support@ediphymarkets.com for assistance with mTLS certificate registration and setup.
2.1.1 API Key Management
API keys are managed through the Ediphy client portal:
- Generate — Create new API credentials with a single click; the secret is shown once and must be saved securely
- Revoke — Immediately invalidate a compromised key
- Clone — Duplicate permissions from an existing key to a new key (useful when provisioning new systems)
Key rotation workflow: To rotate credentials safely, use the following client-side workflow:
- Generate a new key (old key remains active)
- Deploy the new key to your systems
- Revoke the old key once all systems are using the new credentials
This approach gives you full control over the rotation timing and ensures no service interruption.
Active connections: When a key is revoked, any active REST requests using that key will fail with 401 Unauthorized. WebSocket connections authenticated with the revoked key will receive a disconnecting message and be closed. Clients should reauthenticate with the new key.
2.2 Authorization Model
Permissions are hierarchical and additive:
client.<client_id>
├── products
│ ├── irs.imm # Can trade IMM swaps
│ ├── irs.spot # Can trade spot swaps
│ ├── irs.forward # Can trade forward starting swaps
│ ├── bonds.govt # Can trade government bonds
│ └── bonds.credit # Can trade credit bonds
├── currencies
│ ├── USD
│ ├── EUR
│ ├── GBP
│ └── JPY
├── actions
│ ├── order.create # Can create orders
│ ├── order.cancel # Can cancel orders
│ └── order.query # Can query order status
├── limits
│ ├── max_notional: 500 # Max notional per order (MM)
│ ├── max_daily: 5000 # Max daily notional (MM)
│ └── max_open_orders: 50 # Max concurrent open orders
└── allocations
├── FUND_ABC # Allowed allocation targets
└── FUND_XYZ
2.3 Permission Validation
The gateway validates all requests against your configured permissions before forwarding to the EMS. If a request fails validation, you receive a 403 Forbidden response with a specific error code indicating which permission check failed (product, currency, action, allocation, or limit).
3. API Design
3.1 Base URL Structure
Production: https://api.ediphy.io/ems/v1
Sandbox: https://api-sandbox.ediphy.io/ems/v1
3.2 Common Headers
Request (Bearer Token):
Content-Type: application/json
Authorization: Bearer <api_key>
Idempotency-Key: <uuid> # Required for POST/PATCH requests
Request (mTLS):
Content-Type: application/json
Idempotency-Key: <uuid> # Required for POST/PATCH requests
No Authorization header required — client identity established via TLS certificate.
Response:
Content-Type: application/json
X-Ediphy-Request-Id: <uuid> # For support/debugging
X-Ediphy-RateLimit-Remaining: 98
Idempotency-Key Header
The Idempotency-Key header is required for all POST and PATCH requests. This ensures network safety — if a request times out or fails ambiguously, the client can safely retry with the same key.
- Format: Any unique string up to 128 characters. Allowed characters: alphanumeric, hyphens, and underscores (
a-zA-Z0-9_-). UUIDs are recommended (e.g.,550e8400-e29b-41d4-a716-446655440000) - Scope: Session (resets at 00:00 UTC)
- Behavior: If the gateway receives a request with the same
Idempotency-Keywithin the same session, it returns the cached response from the original request - Uniqueness: Generate a new UUID for each distinct request; reuse the same UUID only when retrying a failed request
Idempotency-Key and client_order_id serve different purposes. The header provides network-level retry safety; the body field provides business-level order identification. See Section 4.1 for details.
3.3 Error Response Format
JSON{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid quantity: must be positive", "field": "quantity", "request_id": "req_abc123" } }
Error codes:
AUTHENTICATION_FAILED- Invalid credentialsPERMISSION_DENIED- Not authorized for action/productVALIDATION_ERROR- Invalid request parameters (gateway-level)DUPLICATE_CLIENT_ORDER_ID-client_order_idalready in use by an active orderLIMIT_EXCEEDED- Rate/size limit exceededINSTRUMENT_NOT_FOUND- Unknown instrumentORDER_NOT_FOUND- Order doesn't existNOTIONAL_CAP_EXCEEDED- DV01 conversion would exceed specified notional capRATE_LIMIT_EXCEEDED- Too many requests (see rate limiting)INTERNAL_ERROR- Server-side issue
Example Error Responses
Permission Denied (403):
JSON{ "error": { "code": "PERMISSION_DENIED", "message": "Client not authorized for product: irs_imm with currency JPY", "request_id": "req_xyz789" } }
Validation Error (400):
JSON{ "error": { "code": "VALIDATION_ERROR", "message": "Quantity exceeds maximum allowed: 500MM", "field": "quantity.value", "request_id": "req_abc456" } }
Duplicate Client Order ID (409):
JSON{ "error": { "code": "DUPLICATE_CLIENT_ORDER_ID", "message": "client_order_id 'my-order-12345' is already in use by active order ord_7f3a9b2c", "field": "client_order_id", "request_id": "req_def123", "existing_order_id": "ord_7f3a9b2c" } }
3.4 HTTP Status Codes
| Status Code | Meaning | When Used |
|---|---|---|
200 OK |
Success | GET requests returning data |
202 Accepted |
Request accepted for processing | POST/PATCH for orders (async processing) |
400 Bad Request |
Malformed request | Invalid JSON, missing required fields |
401 Unauthorized |
Authentication failed | Invalid/missing credentials, expired token |
403 Forbidden |
Permission denied | Valid auth but not authorized for action |
404 Not Found |
Resource not found | Unknown order_id, request_id |
409 Conflict |
Conflict with current state | Duplicate client_order_id |
429 Too Many Requests |
Rate limit exceeded | See rate limiting section |
500 Internal Server Error |
Server error | Unexpected gateway failure |
502 Bad Gateway |
Upstream error | EMS connection failure |
503 Service Unavailable |
Service unavailable | Maintenance or overload |
4. Order Endpoints
4.1 Create Order
Creates a new order. Supports market orders (no limit) and limit orders.
Orders can also be created via the Liquidity Checker API's /go-firm endpoint. This workflow is useful when you want to monitor liquidity conditions and market activity before committing to firm orders. Orders created via this path include a linked_interest_id field for cross-system tracking. See Section 1.4 and the Liquidity Checker API documentation for details.
Request Body
JSON{ "instrument": { "type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y" }, "side": "pay", "quantity": { "notional": 50000000 }, "limit": { "rate": 4.25 }, "time_in_force": "GTT", "expire_at": "2025-01-15T16:00:00Z", "allocation": "FUND_ABC", "client_order_id": "my-order-12345", "price_protection": "market", "metadata": { "trader": "jsmith", "desk": "rates-nyc" } }
Field Definitions
| Field | Required | Description |
|---|---|---|
instrument |
Yes | Instrument specification (see below) |
side |
Yes | "pay" or "receive" for IRS; "buy" or "sell" for bonds |
quantity |
Yes | Quantity specification (see below) |
quantity.notional |
Yes* | Absolute notional value in base currency units, not millions (e.g., 50000000 for 50MM USD) |
quantity.dv01 |
Yes* | DV01 in USD. See DV01 section below. |
quantity.notional_cap |
No | Maximum notional (in base units) when using DV01 specification. Only valid with dv01. If the DV01→notional conversion would exceed this cap, the order is rejected with NOTIONAL_CAP_EXCEEDED. Recommended for risk control. |
limit |
No | Price limit. Omit for market order. If omitted with price_protection: "off", the order executes as a classic market order with no price constraints. |
limit.rate |
If limit | For IRS: swap rate (e.g., 4.25) |
limit.price |
If limit | For bonds: clean price (e.g., 99.5) |
limit.yield |
If limit | For bonds: yield (e.g., 4.15) |
time_in_force |
No | "GTT" (good-till-time, default), "GTC" (good-till-cancel), "EOD" (end-of-day) |
expire_at |
If GTT | ISO8601 expiry time. Mutually exclusive with time_in_force: "GTC" or "EOD" — providing both is a validation error. |
allocation |
Yes | Fund/allocation target. Either a single fund ID string (e.g., "FUND_ABC") or an object mapping fund IDs to weights for multi-fund allocation (e.g., {"FUND_ABC": 0.5, "FUND_XYZ": 0.5}). All funds must be in client's allowed list. See Multi-Fund Allocations section below. |
client_order_id |
Yes | Client's business reference for the order (1-64 characters, alphanumeric, hyphens, underscores: a-zA-Z0-9_-). Must be unique among all active (non-completed) orders. See below for uniqueness semantics. |
price_protection |
No | Controls how far from the current market price the order is allowed to execute. Named levels in order of most to least protection: "passive" (tightest), "market" (default), "aggressive", "off" (no protection). The actual basis point thresholds for named levels are dynamic, calculated from live market data and conditions. Alternatively, specify a numeric value for explicit basis point tolerance (e.g., 5 for 5bps). |
metadata |
No | Free-form JSON object for client use (logged but not processed). Maximum size: 4KB. Maximum nesting depth: 3 levels. |
*Quantity must specify exactly one of notional or dv01.
Idempotency and Order Identification
Order creation uses two complementary mechanisms for safety:
Idempotency-Key Header (Network Safety)
The Idempotency-Key header (see Section 3.2) ensures safe retries at the network level:
- Generate a fresh UUID for each new order request
- If a request times out, retry with the same
Idempotency-Key - The gateway returns the cached response if the key was already processed
- Keys are session-scoped and reset at 00:00 UTC
client_order_id Field (Business Logic)
The client_order_id provides a meaningful business identifier for the order:
- Scope: Must be unique among all active (non-completed) orders for the client
- Collision handling: If you submit an order with a
client_order_idthat matches an existing active order, the request is rejected withDUPLICATE_CLIENT_ORDER_IDerror - Reuse after completion: Once an order reaches a terminal state (
FILLED,CANCELLED,EXPIRED,REJECTED), itsclient_order_idcan be reused for a new order
The Idempotency-Key handles transient network failures (retry the same request safely). The client_order_id prevents business-logic errors (accidentally creating duplicate orders with the same reference). A GTC order created Monday remains active Tuesday — the Idempotency-Key cache resets, but the client_order_id collision check protects you from accidentally duplicating the order.
Multi-Fund Allocations
Orders can be allocated to a single fund or split across multiple funds with weighted distribution.
Single Fund (Simple):
JSON{ "allocation": "FUND_ABC" }
The entire order is allocated to one fund.
Multi-Fund (Weighted):
JSON{ "allocation": { "FUND_ABC": 0.5, "FUND_XYZ": 0.3, "FUND_QRS": 0.2 } }
The order is split proportionally across multiple funds based on the specified weights.
Weight Normalization:
- Weights are normalized automatically — they don't need to sum to exactly 1.0
- Example:
{"FUND_ABC": 1, "FUND_XYZ": 1}becomes 50/50 split (each weight / sum of weights) - Example:
{"FUND_ABC": 2, "FUND_XYZ": 3}becomes 40/60 split - Weights must be positive numbers
- All specified funds must appear in the client's allowed allocation list (see
GET /allocations)
Fee Distribution:
When an order is allocated across multiple funds, execution fees and settlement fees are distributed using the fair split method by default:
- Execution fees: Split proportionally by weight
- Settlement fees: Split equally across all allocations (fair share per fund)
This ensures each fund pays a fair share of fixed settlement costs regardless of allocation size.
Multi-fund allocations are useful when trading on behalf of multiple client accounts or funds with a single order. The EMS handles the splits automatically, and each allocation receives separate post-trade reporting and settlement instructions.
If any fund ID in the allocation object is not in your allowed list, the entire order is rejected with a PERMISSION_DENIED error.
DV01 Quantity
When using dv01 to specify quantity, the gateway converts the DV01 value to notional using the instrument's current DV01 factor. This factor varies by instrument (tenor, currency, rate environment).
Request format:
JSON{ "quantity": { "dv01": 5500, "notional_cap": 50000000 } }
| Field | Required | Description |
|---|---|---|
dv01 |
Yes | Target DV01 in USD |
notional_cap |
No | Maximum notional (in base units) the client is willing to trade. If the conversion would exceed this cap, the order is rejected with NOTIONAL_CAP_EXCEEDED. Recommended for risk control. |
Conversion timing: The DV01→notional conversion is performed at order submission time. The DV01 factor is provided by the system when the gateway accepts the order, ensuring the notional amount is fixed regardless of subsequent market movements. The factor reflects current market conditions at the time of order creation.
Response includes conversion details:
The order response and state will include the conversion factor used and the resulting notional:
JSON{ "goal_quantity": { "dv01": 5500, "dv01_factor": 8750, "notional": 48125000 } }
dv01_factor— The factor used to convert DV01 to notional (notional per DV01 unit)notional— The actual notional being traded, calculated asdv01 × dv01_factor- DV01 factors are available via
GET /instruments/{instrument_id}(see Section 6.1) or in the Ediphy GUI under instrument details
Instrument Specifications
IRS IMM Swap:
JSON{ "type": "irs_imm", "currency": "USD", // USD, EUR, GBP, JPY "imm_date": "H25", // IMM code: H/M/U/Z + YY "tenor": "10Y" // 1Y, 2Y, 3Y, 5Y, 7Y, 10Y, 12Y, 15Y, 20Y, 25Y, 30Y }
IRS Spot Swap:
JSON{ "type": "irs_spot", "currency": "EUR", "tenor": "5Y" }
IRS Forward Starting:
JSON{ "type": "irs_forward", "currency": "GBP", "start": "1Y", "tenor": "10Y" }
Government Bond:
JSON{ "type": "govt_bond", "isin": "US912828ZT77", "maturity_date": "2030-05-15" // Optional but recommended }
Credit Bond:
JSON{ "type": "credit_bond", "isin": "US037833EK23", "maturity_date": "2028-02-01" // Optional but recommended }
| Field | Required | Description |
|---|---|---|
type |
Yes | "govt_bond" for government bonds, "credit_bond" for corporate/credit bonds |
isin |
Yes | ISIN of the bond (e.g., "US912828ZT77") |
maturity_date |
No | ISO8601 date (e.g., "2030-05-15"). Optional but recommended as a sanity check. |
Government and credit bonds are distinguished because they have different settlement workflows, custody arrangements, and internal permissions. This separation ensures proper routing and post-trade processing for each asset class.
While the ISIN uniquely identifies the bond, providing maturity_date acts as a safety check to catch errors. If the provided maturity doesn't match the ISIN's actual maturity, the order will be rejected with a validation error. This prevents accidental submission of orders for the wrong instrument due to ISIN typos or data errors.
Response (Success - 202 Accepted)
JSON{ "request_id": "req_abc123", "order_id": "ord_7f3a9b2c", "client_order_id": "my-order-12345", "status": "sent_to_ems", "message": "Request sent to execution system. Poll order state for updates.", "submitted_at": "2025-01-15T10:30:00.123Z", "links": { "order": "/orders/ord_7f3a9b2c", "request": "/requests/req_abc123" } }
202 Accepted means the gateway has accepted and forwarded the request. It does not mean the order is working or that you have market exposure. Poll GET /orders/{order_id} to observe actual order state.
4.2 Amend Order
Submits an amendment request for an order. The EMS will process the latest desired state.
Amendable Fields
| Field | Description |
|---|---|
limit |
Update price limit |
quantity |
Update goal quantity |
expire_at |
Extend or shorten expiry time |
price_protection |
Change price protection level |
Fields not listed above cannot be amended. To change instrument, side, or allocation, cancel and submit a new order.
Request Body
JSON{ "limit": { "rate": 4.30 }, "expire_at": "2025-01-15T18:00:00Z" }
Response (Success - 202 Accepted)
JSON{ "request_id": "req_def456", "order_id": "ord_7f3a9b2c", "status": "sent_to_ems", "message": "Amendment request sent to execution system. Poll order state for updates.", "submitted_at": "2025-01-15T10:33:00.123Z", "links": { "order": "/orders/ord_7f3a9b2c", "request": "/requests/req_def456" } }
Quantity amendments: If you amend quantity to 30MM but the order has already filled 35MM, the amendment is accepted (not an error) and the order will show filled 35MM with completed: true. This is normal behavior — quantity adjustments and fills occur asynchronously, and it's common for fills to outpace amendments during active trading.
Price amendments: When amending the limit price on a partially filled order, the new price applies only to the remaining unfilled quantity. Previously executed fills retain their original prices.
Atomic processing: The EMS processes amendments atomically — there are no partial amendment states visible. When you poll order state, you will see either the pre-amendment state or the fully-applied amendment, never an intermediate state.
Request collapsing: If multiple amendment requests are submitted in rapid succession, only the latest request is processed (see Section 1.2). If the order state shows no validation_error after polling, the most recently submitted amendment was successfully applied. The order's current goal_quantity, limit, and expire_at fields reflect the applied parameters.
4.3 Cancel Order
Submits a cancellation request for an order.
POST is used (rather than DELETE) to allow a request body for audit purposes and because cancellation is a state transition rather than resource deletion.
Request Body (Optional)
JSON{ "reason": "Client requested" }
Response (Success - 202 Accepted)
JSON{ "request_id": "req_ghi789", "order_id": "ord_7f3a9b2c", "status": "sent_to_ems", "message": "Cancel request sent to execution system. Poll order state for updates.", "submitted_at": "2025-01-15T10:35:00.456Z", "links": { "order": "/orders/ord_7f3a9b2c", "request": "/requests/req_ghi789" } }
4.4 Cancel All Orders
Submits a cancellation request for all working (non-completed) orders. Useful for emergency situations or end-of-day cleanup.
Request Body (Optional)
JSON{ "reason": "End of day cleanup", "filter": { "instrument_type": "irs_imm", "currency": "USD", "allocation": "FUND_ABC" } }
| Field | Required | Description |
|---|---|---|
reason |
No | Audit trail reason for bulk cancellation |
filter.instrument_type |
No | Only cancel orders for this instrument type |
filter.currency |
No | Only cancel orders for this currency |
filter.allocation |
No | Only cancel orders for this allocation target |
If no filter is provided, all non-completed orders are cancelled.
Response (Success - 202 Accepted)
JSON{ "request_id": "req_bulk_001", "status": "sent_to_ems", "message": "Bulk cancel request sent to execution system. Poll order states for updates.", "submitted_at": "2025-01-15T16:00:00.123Z", "orders_targeted": 12, "links": { "orders": "/orders?completed=false" } }
orders_targeted indicates how many orders matched the filter at the time of the request. Some may complete before the cancellation is processed.
4.5 Get Order State
Retrieves current state of an order from the EMS. This is the source of truth for order status.
Response (Success - 200 OK)
JSON{ "order_id": "ord_7f3a9b2c", "client_order_id": "my-order-12345", "status": "PARTIALLY_FILLED", "instrument": { "type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y", "description": "Mar 25 10Y USD vs SOFR" }, "side": "pay", "goal_quantity": { "notional": 50000000 }, "filled_quantity": { "notional": 20000000 }, "limit": { "rate": 4.25 }, "average_price": 4.2475, "price_protection": "market", "time_in_force": "GTT", "expire_at": "2025-01-15T16:00:00Z", "allocation": "FUND_ABC", "completed": false, "validation_error": null, "linked_interest_id": null, "created_at": "2025-01-15T10:30:00.123Z", "updated_at": "2025-01-15T10:32:15.789Z", "fills": [ { "fill_id": "fill_abc123", "quantity": { "notional": 20000000 }, "cumulative_quantity": { "notional": 20000000 }, "price": 4.2475, "filled_at": "2025-01-15T10:32:15.789Z", "venue": "D2D" } ], "links": { "self": "/orders/ord_7f3a9b2c", "cancel": "/orders/ord_7f3a9b2c/cancel", "requests": "/requests?order_id=ord_7f3a9b2c" } }
Key Fields
| Field | Description |
|---|---|
status |
Human-readable order status: NEW, WORKING, PARTIALLY_FILLED, FILLED, CANCELLED, EXPIRED, REJECTED. See state definitions below. |
completed |
true means order has no further market exposure (filled, cancelled, expired, or rejected). false means order may still trade. |
validation_error |
If not null, the EMS rejected something in the latest request for this order. Client should correct and resubmit. Cleared when a subsequent request for this order is processed successfully. |
linked_interest_id |
If this order was created via the Liquidity Checker's "go firm" workflow, contains the linked interest record ID (e.g., INTEREST_7f3a9b2c-...). Read-only; reserved for Ediphy system use. |
allocation |
Allocation target(s). Returns the same format submitted: either a single fund ID string or an object with fund weights. |
goal_quantity |
Current target quantity (reflects latest processed amendment) |
filled_quantity |
How much has traded |
Order State Machine
The status field reflects the current state of the order:
┌─────────────────────────────────────┐
│ │
▼ │
┌─────────────┐ EMS accepts ┌─────────────┐ partial fill ┌─────────────┐
│ │ ───────────────► │ │ ─────────────────► │ PARTIALLY │
│ NEW │ │ WORKING │ │ FILLED │──┐
│ │ │ │ ◄───────────────── │ │ │
└─────────────┘ └─────────────┘ amend processed └─────────────┘ │
│ │ │ │
│ validation_error │ │ │
▼ │ cancel │ │
┌─────────────┐ ▼ │ │
│ REJECTED │ ┌─────────────┐ │ │
│ │ │ CANCELLED │ │ │
└─────────────┘ └─────────────┘ │ │
│ expire │ final │
▼ │ fill │
┌─────────────┐ │ │
│ EXPIRED │ │ │
└─────────────┘ │ │
│ │
┌─────────────┐ │ │
│ FILLED │ ◄─────────────────────────┘ │
│ │ ◄───────────────────────────────────┘
└─────────────┘
Status Values:
| Status | completed |
Description |
|---|---|---|
NEW |
false |
Order created, awaiting EMS processing |
WORKING |
false |
Order active in market, no fills yet |
PARTIALLY_FILLED |
false |
Order has some fills, still working remaining quantity |
FILLED |
true |
Order fully filled |
CANCELLED |
true |
Order cancelled by client or system |
EXPIRED |
true |
Order expired (GTT/EOD time reached) |
REJECTED |
true |
Order rejected by EMS (check validation_error) |
Transition Triggers:
- NEW → WORKING: EMS accepts and activates the order
- NEW → REJECTED: EMS rejects order (invalid instrument, limit violation, etc.)
- WORKING → PARTIALLY_FILLED: First fill received
- PARTIALLY_FILLED → PARTIALLY_FILLED: Additional fills, or amendment processed
- WORKING/PARTIALLY_FILLED → FILLED: Goal quantity fully filled
- WORKING/PARTIALLY_FILLED → CANCELLED: Cancel request processed
- WORKING/PARTIALLY_FILLED → EXPIRED: Expiry time reached
Response with Validation Error
JSON{ "order_id": "ord_7f3a9b2c", "client_order_id": "my-order-12345", "status": "PARTIALLY_FILLED", "goal_quantity": { "notional": 50000000 }, "filled_quantity": { "notional": 30000000 }, "completed": false, "validation_error": { "code": "INVALID_QUANTITY_INCREMENT", "message": "Quantity must be in increments of 1MM", "field": "goal_quantity" }, "updated_at": "2025-01-15T10:32:15.789Z", "links": { "self": "/orders/ord_7f3a9b2c", "requests": "/requests?order_id=ord_7f3a9b2c" } }
The validation_error applies to the most recent amendment request. The order continues working at its previous parameters. When the client submits a corrected amendment and it processes successfully, the validation_error is cleared.
4.6 List Orders
Lists orders for the current session with filtering and pagination.
Query Parameters
| Parameter | Description |
|---|---|
completed |
Filter: true (terminal), false (still working) |
instrument_type |
Filter by type: irs_imm, irs_spot, etc. |
currency |
Filter by currency |
client_order_id |
Find by client reference |
limit |
Max results (default 50, max 200) |
cursor |
Pagination cursor |
Example
GET /orders?completed=false¤cy=USD&limit=10
Response (Success - 200 OK)
JSON{ "orders": [ { /* order object */ }, { /* order object */ } ], "pagination": { "total": 45, "limit": 10, "has_more": true, "next_cursor": "eyJpZCI6Im9yZF8xMjM0In0=" } }
5. Request Log Endpoints
The request log tracks all requests submitted by the client. Useful for:
- Confirming a request reached the gateway
- Debugging after disconnection/reconnection
- Audit trail
5.1 Get Request
Response (Success - 200 OK)
JSON{ "request_id": "req_abc123", "type": "create_order", "order_id": "ord_7f3a9b2c", "client_order_id": "my-order-12345", "status": "sent_to_ems", "submitted_at": "2025-01-15T10:30:00.123Z", "payload": { "instrument": { "type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y" }, "side": "pay", "quantity": { "notional": 50000000 }, "allocation": "FUND_ABC" }, "links": { "order": "/orders/ord_7f3a9b2c" } }
Request Statuses
| Status | Description |
|---|---|
rejected_by_gateway |
Gateway rejected request (auth, permissions, format) |
sent_to_ems |
Request forwarded to EMS |
superseded |
Request was superseded by a newer request for the same order before processing |
There is no processed or acknowledged status. Once sent_to_ems, the request outcome is observed via order state, not the request log. If a request is superseded by a subsequent request (e.g., Amendment A followed immediately by Amendment B), the earlier request will transition to superseded status.
5.2 List Requests
Query Parameters
| Parameter | Description |
|---|---|
order_id |
Filter by order |
type |
Filter: create_order, amend_order, cancel_order |
status |
Filter: rejected_by_gateway, sent_to_ems |
limit |
Max results (default 50, max 200) |
cursor |
Pagination cursor |
Response (Success - 200 OK)
JSON{ "requests": [ { "request_id": "req_abc123", "type": "create_order", "order_id": "ord_7f3a9b2c", "status": "sent_to_ems", "submitted_at": "2025-01-15T10:30:00.123Z", "links": { "order": "/orders/ord_7f3a9b2c" } }, { "request_id": "req_def456", "type": "amend_order", "order_id": "ord_7f3a9b2c", "status": "sent_to_ems", "submitted_at": "2025-01-15T10:33:00.123Z", "links": { "order": "/orders/ord_7f3a9b2c" } } ], "pagination": { "total": 2, "limit": 50, "has_more": false } }
6. Reference Data Endpoints
6.1 Get Instruments
List Instruments
Lists available tradeable instruments with optional filtering. Returns a curated subset of instruments.
Query Parameters:
| Parameter | Description |
|---|---|
type |
Filter by type: irs_imm, irs_spot, govt_bond, credit_bond, etc. |
currency |
Filter by currency (e.g., USD, EUR) |
Response (Success - 200 OK):
JSON{ "instruments": [ { "type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y", "description": "Mar 25 10Y USD vs SOFR", "index": "SOFR", "dv01_factor": 8750, "min_quantity": { "notional": 1000000 }, "quantity_increment": { "notional": 1000000 }, "price_increment": 0.0025, "tradeable": true } ] }
This endpoint returns a filtered subset of instruments. For reference data on specific instruments, use the single instrument lookup endpoint below.
Get Single Instrument
Retrieves reference data for a specific instrument, including DV01 factors.
Path Parameters:
| Parameter | Description |
|---|---|
instrument_id |
For bonds: ISIN (e.g., US912828ZT77). For swaps: encoded instrument identifier. |
Response (Success - 200 OK):
JSON{ "type": "govt_bond", "isin": "US912828ZT77", "maturity_date": "2030-05-15", "description": "US Treasury 2.875% May 2030", "coupon": 2.875, "currency": "USD", "dv01_factor": 876.50, "min_quantity": { "notional": 1000000 }, "quantity_increment": { "notional": 1000000 }, "price_increment": 0.015625, "tradeable": true }
For swaps:
JSON{ "type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y", "description": "Mar 25 10Y USD vs SOFR", "index": "SOFR", "dv01_factor": 8750, "min_quantity": { "notional": 1000000 }, "quantity_increment": { "notional": 1000000 }, "price_increment": 0.0025, "tradeable": true }
Use this endpoint to retrieve current DV01 factors before submitting orders with quantity.dv01. The factor returned here is what the EMS will use for conversion at order submission time (subject to market conditions).
This endpoint is rate limited to 10 requests per second per client to prevent bulk scraping. Use the filtered list endpoint for browsing multiple instruments.
6.2 Get Allocations
Lists allocation targets available to the client.
Response (Success - 200 OK)
JSON{ "allocations": [ { "id": "FUND_ABC", "name": "ABC Fixed Income Fund", "currency": "USD", "active": true }, { "id": "FUND_XYZ", "name": "XYZ Multi-Asset", "currency": "EUR", "active": true } ] }
Only allocations returned by this endpoint can be used in orders. Attempting to use an unlisted allocation will result in a permission error.
7. Health & Status Endpoints
GET /health
Simple health check for load balancers and monitoring. Returns 200 if the gateway is operational.
Response (Success - 200 OK)
JSON{ "status": "healthy", "timestamp": "2025-01-15T10:30:00.123Z" }
Response (Degraded - 503 Service Unavailable)
JSON{ "status": "unhealthy", "timestamp": "2025-01-15T10:30:00.123Z", "reason": "EMS connection unavailable" }
This endpoint does not require authentication and is intended for infrastructure monitoring.
GET /status
Detailed system status including EMS connectivity and current session info. Requires authentication.
Response (Success - 200 OK)
JSON{ "gateway": { "status": "healthy", "version": "1.2.3", "instance_id": "gw-us-east-1a-001" }, "ems": { "status": "connected", "latency_ms": 12 }, "session": { "current": "2025-01-15", "started_at": "2025-01-15T00:00:00.000Z", "ends_at": "2025-01-15T23:59:59.999Z" }, "client": { "client_id": "client_abc123", "open_orders": 5, "requests_today": 1247 }, "timestamp": "2025-01-15T10:30:00.123Z" }
8. Client Integration Pattern
8.1 Recommended Polling Strategy
1. Submit request (create/amend/cancel)
2. Receive 202 Accepted with request_id and order_id
3. Poll GET /orders/{order_id} at appropriate interval:
- Active trading: every 1-2 seconds
- Passive monitoring: every 5-10 seconds
4. Check order state:
- If validation_error is set → fix and resubmit
- If completed is true → order is done, record final state
- Otherwise → order still working, continue polling
8.2 Reconnection/Recovery
After disconnection or client restart:
1. Call GET /requests to see all requests sent this session
2. Call GET /orders?completed=false to see all working orders
3. For each working order, verify current state matches expectations
4. Resume normal polling
8.3 Example: Create and Monitor Order
PYTHONimport requests import time import uuid API_BASE = "https://api.ediphy.io/ems/v1" API_KEY = "ak_live_7f3a9b2c4d5e6f..." # Your API key headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } # 1. Create order order_payload = { "instrument": {"type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y"}, "side": "pay", "quantity": {"notional": 50000000}, # 50MM "allocation": "FUND_ABC", "client_order_id": "strategy-alpha-001", "time_in_force": "EOD", } response = requests.post( f"{API_BASE}/orders", json=order_payload, headers={**headers, "Idempotency-Key": str(uuid.uuid4())}, ) response.raise_for_status() order_id = response.json()["order_id"] # 2. Poll until complete while True: order = requests.get(f"{API_BASE}/orders/{order_id}", headers=headers).json() if order["status"] == "REJECTED": raise Exception(f"Order rejected: {order['validation_error']['message']}") if order["completed"]: filled = order["filled_quantity"]["notional"] / 1_000_000 print(f"Order complete: filled {filled}MM at avg {order['average_price']}") break # Still working filled = order["filled_quantity"]["notional"] / 1_000_000 goal = order["goal_quantity"]["notional"] / 1_000_000 print(f"Status: {order['status']} — filled {filled}MM of {goal}MM") time.sleep(2)
9. WebSocket Streaming
9.1 Overview
For clients requiring real-time updates, the gateway provides a WebSocket stream that delivers order updates and fills as they occur, eliminating the need for polling.
Production: wss://api.ediphy.io/ems/v1/stream
Sandbox: wss://api-sandbox.ediphy.io/ems/v1/stream
9.2 Connection & Authentication
Bearer Token Authentication
Connect to the WebSocket endpoint and send an authentication message within 5 seconds:
wss://api.ediphy.io/ems/v1/stream
Authentication message:
JSON{"type": "auth", "api_key": "<api_key>"}
mTLS Authentication
Connect to the same WebSocket endpoint with your client certificate:
wss://api.ediphy.io/ems/v1/stream
No authentication message required — if a valid client certificate is presented during the TLS handshake, identity is established at the transport layer. The server sends connected immediately after the connection is established.
Connection lifecycle:
- Client connects to WebSocket endpoint (with certificate for mTLS)
- For Bearer token: Client sends authentication message within 5 seconds
- Server validates credentials and sends
connectedmessage (or closes connection on failure) - Client receives updates for all orders in current session
- Both parties send heartbeats to maintain connection (see Section 9.3)
9.3 Heartbeat Protocol
Both client and server must send heartbeats to maintain the connection. This allows prompt detection of dead connections without relying on TCP timeouts.
| Direction | Interval | Timeout | Action on Timeout |
|---|---|---|---|
| Server → Client | Every 30 seconds | 90 seconds | Client should disconnect and reconnect |
| Client → Server | Every 30 seconds | 90 seconds | Server disconnects client |
Client heartbeat:
JSON{"type": "heartbeat"}
Server heartbeat:
JSON{"type": "heartbeat", "timestamp": "2025-01-15T10:30:00.123Z"}
If the server does not receive a client heartbeat within 90 seconds, the connection will be terminated. Conversely, if the client does not receive a server heartbeat within 90 seconds, it should assume the connection is dead, disconnect, and initiate reconnection (see Section 9.6). Clients should send heartbeats at least every 30 seconds to maintain the connection.
9.4 Server Messages
Connected
Sent after successful authentication:
JSON{ "type": "connected", "session": "2025-01-15", "timestamp": "2025-01-15T10:30:00.123Z" }
Order Update
Sent when any order state changes (new order, amendment processed, fill, cancellation, expiry):
JSON{ "type": "order_update", "order_id": "ord_7f3a9b2c", "timestamp": "2025-01-15T10:32:15.789Z", "data": { "order_id": "ord_7f3a9b2c", "client_order_id": "my-order-12345", "status": "PARTIALLY_FILLED", "instrument": { "type": "irs_imm", "currency": "USD", "imm_date": "H25", "tenor": "10Y" }, "side": "pay", "goal_quantity": { "notional": 50000000 }, "filled_quantity": { "notional": 20000000 }, "limit": { "rate": 4.25 }, "completed": false, "validation_error": null, "updated_at": "2025-01-15T10:32:15.789Z" } }
Fill
Sent when a fill occurs (in addition to the order_update):
JSON{ "type": "fill", "order_id": "ord_7f3a9b2c", "timestamp": "2025-01-15T10:32:15.789Z", "fill": { "fill_id": "fill_abc123", "quantity": { "notional": 20000000 }, "cumulative_quantity": { "notional": 20000000 }, "price": 4.2475, "filled_at": "2025-01-15T10:32:15.789Z", "venue": "D2D" } }
Field Definitions:
quantity— The size of this specific fill (delta/transaction amount)cumulative_quantity— The total filled quantity for the order after this fill
Fill messages are provided for convenience but can be safely ignored. The order_update message contains the complete order state including cumulative filled_quantity. Clients who only need to track order state can process order_update messages exclusively.
Error
Sent when an error occurs on the stream:
JSON{ "type": "error", "code": "INVALID_MESSAGE", "message": "Unrecognized message type", "timestamp": "2025-01-15T10:30:00.123Z" }
Disconnecting
Sent before server-initiated disconnect:
JSON{ "type": "disconnecting", "reason": "Session ended", "timestamp": "2025-01-15T23:59:59.000Z" }
9.5 Client Messages
| Type | Description |
|---|---|
auth |
Initial authentication |
heartbeat |
Keep-alive signal |
reauthenticate |
Re-authenticate with new credentials (e.g., after key rotation) |
Reauthentication (Bearer Token Only)
If API credentials are rotated while a WebSocket connection is active, clients using Bearer token authentication can reauthenticate without disconnecting:
JSON{"type": "reauthenticate", "api_key": "<new_api_key>"}
Server response on success:
JSON{"type": "reauthenticated", "timestamp": "2025-01-15T10:30:00.123Z"}
Server response on failure:
JSON{"type": "error", "code": "AUTHENTICATION_FAILED", "message": "Invalid credentials", "timestamp": "..."}
Failed reauthentication does not disconnect the session if the original credentials are still valid. The connection continues using the original authentication.
Reauthentication is not supported for mTLS connections. To rotate certificates, establish a new connection with the new certificate.
Unknown message types are ignored.
9.6 Reconnection
If the WebSocket connection drops:
- Wait 1 second, then attempt reconnect
- On failure, use exponential backoff (2s, 4s, 8s, max 30s)
- After reconnecting, call
GET /orders?completed=falseto sync state - Resume normal operation
The WebSocket stream does not replay missed messages. After reconnection, clients must use the REST API to query current order state.
Sequence Numbers:
WebSocket messages do not include sequence numbers. This design choice has the following implications:
- Gap detection: Clients cannot mathematically prove they haven't missed a message during a connection
- Reconnection strategy: After any disconnection, clients must poll the REST API (
GET /orders?completed=false) to establish current state as the source of truth - TCP guarantees: Within an active connection, TCP guarantees in-order delivery of all messages
- Recommendation: Treat WebSocket as a real-time notification channel; use REST API queries as the authoritative state snapshot when gaps are possible (reconnection, prolonged network instability)
9.7 Example Session
Client: connects to wss://api.ediphy.io/ems/v1/stream
Client: {"type": "auth", "api_key": "ak_live_7f3a9b2c..."}
Server: {"type": "connected", "session": "2025-01-15", "timestamp": "..."}
Client: {"type": "heartbeat"}
Server: {"type": "heartbeat", "timestamp": "..."}
[Client creates order via REST API]
Server: {"type": "order_update", "order_id": "ord_7f3a9b2c", "data": {...}}
[Fill occurs]
Server: {"type": "fill", "order_id": "ord_7f3a9b2c", "fill": {...}}
Server: {"type": "order_update", "order_id": "ord_7f3a9b2c", "data": {...}}
Client: {"type": "heartbeat"}
Server: {"type": "heartbeat", "timestamp": "..."}
[Session ending]
Server: {"type": "disconnecting", "reason": "Session ended", "timestamp": "..."}
Server: closes connection
10. Rate Limiting
10.1 Default Limits
Rate limits are applied per connection (i.e., per authenticated API key per TCP connection).
| Endpoint | Rate Limit |
|---|---|
POST /orders |
10/second, 100/minute |
PATCH /orders/{id} |
10/second |
POST /orders/{id}/cancel |
10/second |
GET /orders/{id} |
100/second |
GET /orders |
20/second |
GET /requests |
20/second |
GET /instruments |
10/second |
GET /instruments/{id} |
10/second |
GET /allocations |
10/second |
Rate limit breaches only affect new requests. Existing working orders are not impacted — they continue to trade normally regardless of the client's rate limit status.
Need higher limits? Contact support@ediphymarkets.com to discuss increased rate limits for algorithmic trading or high-volume use cases.
10.2 Response Headers
X-Ediphy-RateLimit-Limit: 100
X-Ediphy-RateLimit-Remaining: 95
X-Ediphy-RateLimit-Reset: 2025-01-15T10:31:00Z
10.3 Rate Limit Exceeded (429)
JSON{ "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests", "retry_after": 5 } }
11. Security Considerations
11.1 Transport Security
- TLS 1.3 required for all connections
- mTLS available for clients requiring mutual authentication (see Section 2.1)
- Certificate pinning recommended for high-security clients
- VPN connections available for high-volume clients (contact support@ediphymarkets.com)
11.2 Authentication Security
- Bearer tokens — Protected by TLS encryption; suitable for most integrations
- mTLS — Cryptographic client authentication at transport layer; recommended for high-security environments
- Idempotency keys (
client_order_id) prevent duplicate order creation
11.3 IP Allowlisting
- Clients can optionally register allowed IP ranges
- Requests from unknown IPs rejected
11.4 Audit Trail
All API requests are logged for compliance, dispute resolution, and regulatory reporting. Clients can request audit reports for any time period by contacting support@ediphymarkets.com.
12. Versioning & Compatibility
12.1 Version Policy
The API version is included in the URL path (e.g., /ems/v1). Ediphy maintains backwards compatibility within a major version.
Supported versions: Ediphy supports the current version and the immediately previous version. Clients are encouraged to migrate to the latest version when available.
Non-breaking changes (may be introduced without version bump):
- Adding new optional fields to responses
- Adding new optional parameters to requests
- Adding new endpoints
- Adding new enum values (clients should handle unknown values gracefully)
Breaking changes (require new version):
- Removing or renaming fields
- Changing field types
- Changing required/optional status of fields
- Removing endpoints
- Changing authentication mechanisms
12.2 Deprecation Process
When a breaking change is necessary:
- New version is released (e.g.,
/ems/v2) with changes documented - Clients are notified via email at least 90 days before old version sunset
- Previous version continues to function during migration period
- After sunset date, old version returns
410 Gone
Migration support: Ediphy will provide migration guides and support for version transitions. Contact support@ediphymarkets.com for assistance.
13. Sandbox Environment
The sandbox environment allows clients to:
- Test integration without real orders
- Use test instruments with simulated fills
- Validate authentication and permissions
Sandbox Behaviors:
- Orders accepted but routed to simulation
- Fills generated on schedule or via test endpoint
- No real market interaction
- Same permissions model as production
Test Endpoints (Sandbox Only):
POST /test/orders/{order_id}/fill # Simulate fill
POST /test/orders/{order_id}/expire # Simulate expiry
14. Endpoint Summary
| Method | Endpoint | Description |
|---|---|---|
POST |
/orders |
Create new order (202 Accepted) |
GET |
/orders |
List orders (current session) |
GET |
/orders/{id} |
Get order state (source of truth) |
PATCH |
/orders/{id} |
Amend order (202 Accepted) |
POST |
/orders/{id}/cancel |
Cancel single order (202 Accepted) |
POST |
/orders/cancel-all |
Cancel all working orders (202 Accepted) |
GET |
/requests |
List requests sent this session |
GET |
/requests/{id} |
Get request details |
GET |
/instruments |
List tradeable instruments |
GET |
/instruments/{id} |
Get single instrument reference data |
GET |
/allocations |
List client's allocation targets |
GET |
/health |
Gateway health check (no auth required) |
GET |
/status |
Detailed system status (auth required) |
WSS |
/stream |
WebSocket stream for real-time updates |