Liquidity Checker API Reference
Overview
The Ediphy Liquidity Checker API enables programmatic access to our collaborative trading blotter system, allowing trading teams to manage declared interest, monitor liquidity conditions, and seamlessly transition to firm order execution.
Product Coverage: Fixed Income Bonds (Corporate Credit, Government, Emerging Markets)
Why the Liquidity Checker API?
- Team Collaboration — Shared blotter visibility across your trading desk with user and team view modes
- Liquidity Intelligence — Real-time liquidity scores, trade counts, and alternative instrument suggestions
- Flexible Workflow — Progress from soft interest to firm orders when market conditions are favorable
- Bulk Operations — Sync your internal order management system via CSV upload or batch API
- Real-Time Updates — WebSocket streaming delivers instant blotter updates across connected clients
- Full Audit Trail — Every change is logged with provenance tracking (GUI vs sync)
1. Key Concepts
1.1 Interest Lifecycle
The Liquidity Checker manages declared interest — bonds you're interested in trading but haven't yet committed to as firm orders. Interest progresses through states based on user actions and market conditions.
Interest States (Firmness):
| State | Description |
|---|---|
Inactive |
Interest exists but not actively monitored for opportunities |
Soft |
Active interest, system monitors for favorable liquidity conditions |
Firm |
Ready to trade — creates a live trading ticket in the EMS |
Filled |
Goal quantity has been fully executed |
Overfilled |
Executed quantity exceeds the declared goal (only possible if goal is reduced during execution) |
Typical flow: Add interest as Soft → Monitor liquidity indicators → When conditions are favorable, transition to Firm → Order executes via EMS → Interest becomes Filled.
1.2 User vs Team Scope
The blotter supports two visibility modes:
User Mode (Default)
- Shows only interest owned by the authenticated user
- All users can view and modify their own interest
- No special permissions required
Team Mode
- Shows interest for all users within the organization
- Requires
blotter.team.viewpermission - Modifying another user's interest requires
blotter.team.updatepermission
Team mode enables collaborative workflows where multiple traders can monitor and respond to the same set of trading opportunities.
1.3 Provenance Tracking
Every interest record tracks its provenance — the source of its most recent update:
| Provenance | Description |
|---|---|
sync |
Created or updated via CSV upload / batch API |
gui |
Created or updated via web interface or single-record API |
Why provenance matters:
- When a CSV sync is uploaded, it replaces all previous sync-sourced entries for that user
- GUI updates are preserved across syncs (firmness set via GUI survives re-sync)
- Audit trail shows whether changes came from automated systems or manual intervention
Provenance Override:
By default, when an API sync updates a record that was previously modified via GUI (prov: "gui"), certain fields may be preserved to prevent stale OMS data from overwriting recent manual changes.
To force an update regardless of provenance (when your OMS has authoritative data), use the force_overwrite: true flag:
JSON{ "inst_id": "US912828ZT77", "client_id": "my-order-001", "limit": 99.00, "force_overwrite": true }
When force_overwrite: true:
- All provided fields are updated regardless of current provenance
- The record's provenance is set to
prov: "sync" - The OMS effectively "reclaims" the record
Use force_overwrite carefully. It overrides any manual changes made by traders via the UI. Ensure your OMS has the authoritative data before using this flag.
1.4 Firm Orders and EMS Integration
When interest transitions to Firm status, the Liquidity Checker creates a live trading ticket in the Execution Management System (EMS). At this point, the order becomes visible and monitorable in both the Liquidity Checker and the EMS API/GUI.
Cross-System Visibility:
| System | What You See | Use Case |
|---|---|---|
| Liquidity Checker | High-level execution status: qty_traded, trading_status, firmness_pres |
Monitor execution progress alongside other soft/inactive interest on your blotter |
| EMS API/GUI | Full order lifecycle: live quotes, child orders, fills, routing decisions, execution quality | Detailed order management and execution monitoring |
Linking Records Across Systems:
The linked_interest_id field ties the two systems together:
- EMS orders include
linked_interest_idpointing back to the originating Liquidity Checker interest record - Use this field to correlate execution events in the EMS with the corresponding interest on your blotter
- When querying the EMS API for orders, filter by
linked_interest_idto find all executions related to a specific interest
After calling /go-firm, monitor execution via both systems:
- Use Liquidity Checker WebSocket or polling for blotter-wide status updates (see Section 6)
- Use EMS API for real-time fill notifications, routing decisions, and order state changes
The Liquidity Checker provides context ("which of my interests are actively trading?"), while the EMS provides depth ("what's happening with this specific order?").
When an order completes execution, the interest firmness transitions to Filled (or Overfilled if the goal was reduced mid-execution). The interest remains on the blotter for audit purposes and can be set back to Soft or Inactive if needed.
1.5 Interest Identification
Each interest record has multiple identifiers serving different purposes:
| Field | Scope | Description |
|---|---|---|
interest_id |
System-wide | Unique system-generated identifier (format: INTEREST_{uuid}) |
client_id |
Per-user | Client's internal order/reference ID. Used to correlate with external OMS. |
inst_id |
Instrument | ISIN of the bond (e.g., US912828ZT77) |
Client ID Behavior:
- If you provide a
client_idwhen adding interest, that ID is preserved - If omitted, the system generates a short random ID
- The
(owner_user, client_id)combination is used to determine whether an update creates new interest or modifies existing interest
Re-syncing with the same client_id updates the existing interest rather than creating a duplicate. This is intentional and enables OMS synchronization workflows.
1.6 Data Enrichment
The Liquidity Checker enriches each interest record with data from multiple sources to help traders assess market conditions and identify optimal execution windows.
1.6.1 MiFID Post-Trade Data
Market activity data derived from regulatory post-trade reporting (MiFID II transparency regime):
| Field | Description |
|---|---|
notional_amount_usd |
Total traded volume in USD over the last 60 days |
count |
Total trade count over the last 60 days |
med_y |
Median traded yield from recent transactions |
fairmark_price |
Ediphy's dynamic end-of-day mark price |
fairmark_date |
Date of the most recent mark |
MiFID post-trade data is sourced from regulatory trade reports and updated daily. This provides an objective view of recent market activity independent of any single dealer's flow.
1.6.2 Liquidity Scores
Proprietary liquidity metrics calculated from historical trading patterns:
Trade Count Metrics:
| Metric | Description |
|---|---|
tc5 |
Number of trades in the last 5 days |
tc20 |
Number of trades in the last 20 days |
Lookback Metrics (Lower = More Liquid):
| Metric | Description |
|---|---|
lb5 |
Days of lookback required to find 5 trades |
lb20 |
Days of lookback required to find 20 trades |
lb50 |
Days of lookback required to find 50 trades |
lb1mm |
Days of lookback required to accumulate 1MM USD volume |
lb10mm |
Days of lookback required to accumulate 10MM USD volume |
lb50mm |
Days of lookback required to accumulate 50MM USD volume |
Lookback metrics indicate how "deep" into history you need to go to find meaningful trading activity. A bond with lb5 = 2 (found 5 trades within 2 days) is more liquid than one with lb5 = 30 (took 30 days to find 5 trades). Lower values indicate more liquid instruments.
Alternative Instruments:
| Metric | Description |
|---|---|
alt_count |
Number of liquid alternative instruments available |
The system identifies similar bonds (same issuer, comparable maturity, similar characteristics) that may offer better liquidity if your target instrument is illiquid.
1.6.3 Live Market Data
Real-time pricing from Ediphy's trading venues:
| Field | Description |
|---|---|
livemid |
Current live mid-price (when available from active quoting) |
flags_tradable |
Whether the instrument is currently available for trading on Ediphy |
1.6.4 Liquidity Check Status
The liq_check_status field provides a composite assessment combining the above metrics:
| Status | Meaning | Typical Conditions |
|---|---|---|
CAN TRADE NOW |
High liquidity, favorable conditions | Recent trades, good volume, active market |
TRY NOW |
Moderate liquidity, worth attempting | Some recent activity, may find counterparty |
WAIT |
Low liquidity, unfavorable conditions | Sparse trading, consider waiting or alternatives |
ENTER INFO |
Missing required fields | Side or quantity not specified |
The liquidity status is recalculated periodically as market conditions change. WebSocket subscribers receive liquidity_update messages when status changes.
2. Authentication & Authorization
2.1 Authentication
The API uses Bearer token authentication. Include your API key in the Authorization header:
Authorization: Bearer <api_key>
API keys are managed through the Ediphy client portal. See the EMS Client API documentation for details on key management and rotation.
2.2 Required Permissions
| Permission | Description |
|---|---|
ems.trader |
Required to add/update/remove interest |
blotter.team.view |
View team blotter (all users in organization) |
blotter.team.update |
Modify another user's interest |
3. API Design
3.1 Base URL Structure
Production: https://api.ediphy.io/blotter/v1
Sandbox: https://api-sandbox.ediphy.io/blotter/v1
3.2 Common Headers
Request:
Content-Type: application/json
Authorization: Bearer <api_key>
Response:
Content-Type: application/json
X-Ediphy-Request-Id: <uuid>
3.3 Error Response Format
JSON{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid ISIN format", "field": "inst_id", "request_id": "req_abc123" } }
Error Codes:
| Code | Description |
|---|---|
AUTHENTICATION_FAILED |
Invalid or missing credentials |
PERMISSION_DENIED |
Not authorized for action |
VALIDATION_ERROR |
Invalid request parameters |
INVALID_ISIN |
ISIN format invalid or unrecognized |
INVALID_VERB |
Verb must be buy, sell, or null |
INVALID_FIRMNESS |
Firmness must be Soft, Inactive, or null |
INVALID_QUANTITY |
Quantity must be a positive number |
INVALID_LIMIT |
Limit price must be a positive number |
INTEREST_NOT_FOUND |
Interest record does not exist |
RATE_LIMIT_EXCEEDED |
Too many requests |
INTERNAL_ERROR |
Server-side issue |
3.4 HTTP Status Codes
| Status Code | Meaning | When Used |
|---|---|---|
200 OK |
Success | Request processed successfully |
400 Bad Request |
Malformed request | Invalid JSON, missing required fields |
401 Unauthorized |
Authentication failed | Invalid/missing credentials |
403 Forbidden |
Permission denied | Valid auth but not authorized for action |
404 Not Found |
Resource not found | Unknown interest_id |
429 Too Many Requests |
Rate limit exceeded | See rate limiting section |
500 Internal Server Error |
Server error | Unexpected failure |
4. Interest Endpoints
4.1 Add or Update Interest
Creates new interest or updates existing interest for a bond. If interest already exists for the (owner_user, client_id) combination, the existing record is updated.
Request Body
JSON{ "inst_id": "US912828ZT77", "client_id": "my-order-001", "verb": "buy", "qty": 5000000, "limit": 99.50, "firmness": "Soft", "comment": "Opportunistic add" }
Field Definitions
| Field | Required | Type | Description |
|---|---|---|---|
inst_id |
Yes | string | ISIN of the bond. Must be a valid 12-character ISIN. |
client_id |
No | string | Client's internal reference ID. If omitted, system generates a random 8-character ID. Used to identify the interest for subsequent updates. |
verb |
No | string | Trade direction: "buy" or "sell". Can be set later via update. |
qty |
No | integer | Goal quantity in base currency units. E.g., 5000000 for 5MM. Can be set later via update. |
limit |
No | number | Price limit. Can be set later via update. |
firmness |
No | string | Interest state: "Soft" (default), "Inactive". To transition to "Firm", use POST /interest/{interest_id}/go-firm. |
comment |
No | string | Free-form note for reference (e.g., "Recommended by research"). |
force_overwrite |
No | boolean | If true, updates all provided fields regardless of current provenance. Sets prov: "sync" on the record. Default: false. See Provenance Override below. |
All quantities are in base currency units (not millions) in both requests and responses. For example, 5000000 represents 5MM USD notional. This applies to qty, qty_traded, and all quantity-related fields throughout the API.
Response (Success - 200 OK)
JSON{ "status": "success", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "client_id": "my-order-001", "inst_id": "US912828ZT77", "message": "Interest added successfully" }
Update Semantics
When updating existing interest:
- Provided fields are updated to the new values
- Omitted fields retain their existing values
- Null fields clear the existing value
JSON{ "inst_id": "US912828ZT77", "client_id": "my-order-001", "limit": 99.75 }
This updates only the limit price; verb, qty, firmness, and comment remain unchanged.
When re-syncing via batch upload, firmness set via the GUI is preserved. This allows traders to manually set firmness while automated systems sync quantity and limit updates.
4.2 Remove Interest
Marks interest as Inactive with status Inactive. The record is not deleted but is excluded from active blotter views.
Request Body
JSON{ "inst_id": "US912828ZT77", "client_id": "my-order-001" }
| Field | Required | Description |
|---|---|---|
inst_id |
Yes | ISIN of the bond |
client_id |
Yes | Client's reference ID for the interest to remove |
Response (Success - 200 OK)
JSON{ "status": "success", "message": "Removed my-order-001" }
Removing interest sets status: "Inactive". The record remains in the audit trail. To permanently clear all interest, use the Clear All endpoint.
4.3 Clear All Interest
Removes all active interest for the authenticated user. Team administrators with appropriate permissions can clear interest for other users.
Request Body (Optional)
JSON{ "on_behalf_of_ediphy_user": "jsmith", "on_behalf_of_ediphy_org": "acme-trading" }
| Field | Required | Description |
|---|---|---|
on_behalf_of_ediphy_user |
No | Clear interest for this user (requires admin permission) |
on_behalf_of_ediphy_org |
No | Clear interest for this organization (requires admin permission) |
If no parameters provided, clears all interest for the authenticated user.
Response (Success - 200 OK)
JSON{ "status": "success", "message": "Cleared" }
This operation is immediate and cannot be undone. All active interest for the specified scope is marked as inactive.
4.4 Batch Upload
Upload multiple interest records in a single request. Ideal for syncing with external order management systems.
Request Body
JSON{ "mode": "replace", "force_overwrite": false, "rows": [ { "inst_id": "US912828ZT77", "client_id": "order-001", "verb": "buy", "qty": 5000000, "limit": 99.50 }, { "inst_id": "US037833EK23", "client_id": "order-002", "verb": "sell", "qty": 10000000, "limit": 101.25 } ] }
Batch-Level Parameters
| Field | Required | Description |
|---|---|---|
mode |
No | Upload mode: "replace" (default) or "merge". See below. |
force_overwrite |
No | If true, updates all fields regardless of provenance. Default: false. |
rows |
Yes | Array of interest records to upload. |
Upload Modes:
| Mode | Behavior |
|---|---|
replace |
Removes all existing sync-sourced entries for the user, then inserts the batch. This is the default and enables full OMS synchronization. |
merge |
Upserts records by client_id. Existing entries not in the batch are preserved. Use this when multiple systems sync different subsets of interest. |
Field Definitions (per row)
| Field | Required | Description |
|---|---|---|
inst_id / isin |
Yes | ISIN of the bond (either field name accepted) |
client_id |
No | Client's internal reference ID |
verb |
No | "buy" or "sell" |
qty / quantity |
No | Goal quantity in base currency units |
limit |
No | Price limit |
firmness |
No | "Soft" or "Inactive" |
comment |
No | Free-form note |
Response (Success - 200 OK)
JSON{ "status": "success", "message": "ISIN list uploaded successfully.", "rows_processed": 2 }
Batch Upload Semantics
In replace mode (default), batch uploads remove all previous sync-sourced entries for the user before inserting. Only the records in the current batch will have prov: "sync" after upload.
Example workflow (replace mode):
- User has 10 interest records from previous sync
- User uploads batch with 8 records (mode:
replace) - Result: 8 records from new batch (sync), plus any GUI-modified records preserved
Example workflow (merge mode):
- User has 10 interest records from previous sync
- User uploads batch with 3 records (mode:
merge) - Result: 3 records upserted, 7 original records preserved
Use merge mode when multiple internal systems sync different instruments to the same user's blotter. For example, a Rates algo and Credit algo can coexist without overwriting each other's entries.
GUI modifications (firmness changes made via UI) are preserved across syncs because they have prov: "gui". Use force_overwrite: true to override this behavior.
4.5 Get Interest (User Scope)
Returns all active interest for the authenticated user, enriched with liquidity metrics and reference data.
Query Parameters
| Parameter | Description |
|---|---|
status |
Filter by status: Active (default), Inactive |
inst_id |
Filter by ISIN |
verb |
Filter by side: buy, sell |
firmness |
Filter by firmness: Soft, Inactive, Firm |
Response (Success - 200 OK)
JSON{ "interest": [ { "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "client_id": "my-order-001", "inst_id": "US912828ZT77", "short_name": "T 2.5 05/15/30", "legal_name": "US TREASURY N/B", "currency_rd": "USD", "maturity": "2030-05-15", "verb": "buy", "qty": 5000000, "limit": 99.50, "firmness": "Soft", "firmness_pres": "Soft", "liq_check_status": "CAN TRADE NOW", "livemid": 99.625, "flags_tradable": true, "tc5": 12, "lb5": 2, "lb20": 5, "lb1mm": 3, "lb10mm": 8, "alt_count": 4, "prov": "gui", "owner_user": "jsmith", "ts_captured": "2025-01-15T10:30:00.123Z", "ticket_id": null, "qty_traded": 0, "ticket_count": 0 } ] }
Key Response Fields
| Field | Description |
|---|---|
interest_id |
System-generated unique identifier |
client_id |
Client's reference ID |
inst_id |
ISIN |
short_name |
Bond short name (e.g., "T 2.5 05/15/30") |
legal_name |
Issuer legal name |
currency_rd |
Currency code |
maturity |
Maturity date |
verb |
Trade direction (buy/sell) |
qty |
Goal quantity in base currency units |
limit |
Price limit |
firmness |
Raw firmness state |
firmness_pres |
Presentation firmness (accounts for trading state) |
liq_check_status |
Liquidity indicator |
livemid |
Current mid-price |
flags_tradable |
Whether instrument is available for trading on Ediphy |
tc5, lb5, etc. |
Liquidity metrics (see Section 1.6) |
alt_count |
Number of liquid alternatives |
prov |
Provenance (sync or gui) |
owner_user |
Username who owns this interest |
ts_captured |
Timestamp of last update |
ticket_id |
Active trading ticket ID (if firm) |
qty_traded |
Quantity already executed (base currency units) |
ticket_count |
Number of tickets created for this interest |
All quantities (requests and responses) are in base currency units. For example, 5000000 represents 5MM.
4.6 Get Interest (Team Scope)
Returns all active interest for the authenticated user's organization. Requires blotter.team.view permission.
Query Parameters
Same as user scope endpoint.
Response (Success - 200 OK)
Same structure as user scope, but includes interest from all team members. Each record includes owner_user to identify the owner.
4.7 Get Latest Changes
Returns the most recent changes to interest records within the current hour. Useful for polling updates without fetching the full blotter.
Response (Success - 200 OK)
JSON{ "changes": [ { "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "inst_id": "US912828ZT77", "status": "Active", "verb": "buy", "qty": 5000000, "limit": 99.75, "firmness": "Soft", "ts_captured": "2025-01-15T10:45:00.123Z" } ], "timestamp": "2025-01-15T10:46:00.000Z" }
Poll this endpoint every few seconds to receive incremental updates. Compare ts_captured to detect new changes since your last poll.
5. Trading Integration
5.1 Transitioning to Firm
Interest can transition to Firm via the API using the POST /interest/{interest_id}/go-firm endpoint or via the trading cockpit UI. The transition:
- Validates trading permissions
- Applies price protection settings
- Creates an EMS order linked to this interest
Workflow (API):
1. Add interest via API (firmness: "Soft")
2. Monitor liq_check_status via polling or WebSocket
3. When conditions favorable, call POST /interest/{interest_id}/go-firm
4. System creates EMS order with linked_interest_id
5. Interest shows ticket_id, firmness_pres: "FIRM"
6. Fills execute via EMS, qty_traded updates
7. When qty_traded >= qty, firmness_pres becomes "FILLED"
Workflow (UI):
1. Add interest via API (firmness: "Soft")
2. Monitor liq_check_status via polling or WebSocket
3. When conditions favorable, user clicks "Go Firm" in UI
4. System creates EMS order with linked_interest_id
5. Same as above...
5.2 Linked Ticket Fields
When interest has an active trading ticket:
| Field | Description |
|---|---|
ticket_id |
Active EMS ticket identifier |
trading_limit |
Current limit on the live ticket |
trading_mkt_quantity |
Remaining quantity working in market |
trading_status |
Ticket status |
trading_user |
User who owns the firm order |
qty_traded |
Total quantity filled across all tickets |
ticket_count |
Number of tickets created for this interest |
5.3 Actions Field
The actions field in the response indicates available UI actions:
| Value | Meaning |
|---|---|
Go Firm |
Interest is soft, can transition to firm |
Update Firm |
Interest has active ticket, can modify |
5.4 Go Firm Endpoint
Transitions soft interest to a firm order. Creates an EMS order linked to this interest record.
Path Parameters
| Parameter | Description |
|---|---|
interest_id |
The interest to transition (e.g., INTEREST_7f3a9b2c-...) |
Request Body (Optional)
JSON{ "limit": 99.50, "time_in_force": "GTT", "expire_at": "2025-01-15T16:00:00Z", "price_protection": "market" }
| Field | Required | Description |
|---|---|---|
limit |
No | Override the interest's limit price for the firm order |
time_in_force |
No | "GTT" (default), "GTC", "EOD" |
expire_at |
No | Expiry time (required if time_in_force is GTT) |
price_protection |
No | Price protection level: "passive", "market" (default), "aggressive", "off" |
If no body is provided, the order uses the interest's existing limit and default time-in-force settings.
Response (Success - 202 Accepted)
JSON{ "status": "success", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "order_id": "ord_abc123", "ticket_id": "TICKET_xyz789", "message": "Interest transitioned to firm. EMS order created.", "links": { "interest": "/interest/INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "order": "https://api.ediphy.io/ems/v1/orders/ord_abc123" } }
Error Responses
| Status | Code | Description |
|---|---|---|
400 |
MISSING_REQUIRED_FIELDS |
Interest missing verb or qty |
400 |
ALREADY_FIRM |
Interest already has an active ticket |
403 |
PERMISSION_DENIED |
Not authorized to trade this instrument |
404 |
INTEREST_NOT_FOUND |
Interest does not exist |
After going firm, monitor the order via both the Liquidity Checker (interest updates show qty_traded, trading_status) and the EMS API (full order state, fills). The linked_interest_id field on the EMS order ties them together.
6. WebSocket Streaming
6.1 Overview
For real-time blotter updates, connect to the WebSocket stream. Updates are pushed when any interest record changes.
Production: wss://api.ediphy.io/blotter/v1/stream
Sandbox: wss://api-sandbox.ediphy.io/blotter/v1/stream
6.2 Connection & Authentication
Connect to the WebSocket endpoint and send an authentication message within 5 seconds:
JSON{"type": "auth", "api_key": "<api_key>"}
Server response (success):
JSON{ "type": "connected", "session": "2025-01-15", "scope": "user", "timestamp": "2025-01-15T10:30:00.123Z" }
6.3 Subscribe to Team Updates
After authentication, optionally subscribe to team-wide updates:
JSON{"type": "subscribe", "scope": "team"}
Server response:
JSON{ "type": "subscribed", "scope": "team", "timestamp": "2025-01-15T10:30:01.123Z" }
Requires blotter.team.view permission.
6.4 Heartbeat Protocol
Both client and server must send heartbeats to maintain the connection.
| Direction | Interval | Timeout |
|---|---|---|
| Client → Server | Every 30 seconds | 90 seconds |
| Server → Client | Every 30 seconds | 90 seconds |
Client heartbeat:
JSON{"type": "heartbeat"}
Server heartbeat:
JSON{"type": "heartbeat", "timestamp": "2025-01-15T10:30:00.123Z"}
6.5 Server Messages
Interest Update
Sent when any interest record changes:
JSON{ "type": "interest_update", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "timestamp": "2025-01-15T10:32:15.789Z", "data": { "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "inst_id": "US912828ZT77", "short_name": "T 2.5 05/15/30", "verb": "buy", "qty": 5000000, "limit": 99.75, "firmness": "Soft", "liq_check_status": "CAN TRADE NOW", "owner_user": "jsmith", "ts_captured": "2025-01-15T10:32:15.789Z" } }
Interest Removed
Sent when interest is removed or marked inactive:
JSON{ "type": "interest_removed", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "timestamp": "2025-01-15T10:35:00.123Z" }
Liquidity Update
Sent when liquidity metrics change (batched, typically every few seconds):
JSON{ "type": "liquidity_update", "timestamp": "2025-01-15T10:32:20.000Z", "updates": [ { "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "liq_check_status": "CAN TRADE NOW", "livemid": 99.65, "tc5": 13 } ] }
Trading Update
Sent when trading state changes (ticket created, fill received):
JSON{ "type": "trading_update", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "timestamp": "2025-01-15T10:40:00.123Z", "data": { "ticket_id": "TICKET_abc123", "firmness_pres": "FIRM", "qty_traded": 2500000, "trading_status": "WORKING" } }
6.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 /interestto sync state - Resume normal operation
The WebSocket stream does not replay missed messages. After reconnection, clients must use the REST API to query current state.
7. CSV File Format
7.1 Supported Formats
The batch upload endpoint and UI sync feature accept:
- CSV files (
.csv) - Excel files (
.xlsx,.xls)
7.2 Required Columns
| Column | Description |
|---|---|
isin |
ISIN of the bond (required) |
7.3 Optional Columns
| Column | Description |
|---|---|
client_id |
Your internal order/reference ID |
verb |
buy or sell |
quantity |
Goal quantity in base currency units |
limit |
Price limit |
7.4 Example CSV
CSVisin,client_id,verb,quantity,limit US912828ZT77,order-001,buy,5000000,99.50 US037833EK23,order-002,sell,10000000,101.25 XS1234567890,order-003,buy,2000000,
The UI provides automatic column mapping with fuzzy matching. Column headers like "ISIN", "Isin", "isin" are all recognized. You can also manually map columns if automatic detection fails.
8. Client Integration Patterns
8.1 OMS Synchronization
Sync your internal order management system with the Liquidity Checker:
PYTHONimport requests import csv API_BASE = "https://api.ediphy.io/blotter/v1" API_KEY = "ak_live_..." headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } # Export orders from your OMS def export_from_oms(): # Your OMS export logic return [ {"isin": "US912828ZT77", "client_id": "ORD-001", "verb": "buy", "qty": 5000000}, {"isin": "US037833EK23", "client_id": "ORD-002", "verb": "sell", "qty": 10000000}, ] # Sync to Liquidity Checker def sync_to_blotter(): orders = export_from_oms() payload = {"rows": orders} response = requests.post( f"{API_BASE}/interest/batch", json=payload, headers=headers ) response.raise_for_status() print(f"Synced {len(orders)} orders") # Run sync periodically (e.g., every 5 minutes) sync_to_blotter()
8.2 Liquidity Monitoring
Monitor liquidity conditions and alert when favorable:
PYTHONimport requests import time API_BASE = "https://api.ediphy.io/blotter/v1" API_KEY = "ak_live_..." headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } def check_liquidity(): response = requests.get(f"{API_BASE}/interest", headers=headers) response.raise_for_status() for interest in response.json()["interest"]: if interest["liq_check_status"] == "CAN TRADE NOW": if interest["firmness"] == "Soft": print(f"ALERT: {interest['short_name']} ready to trade!") print(f" Livemid: {interest['livemid']}") print(f" Your limit: {interest['limit']}") print(f" Trade count (5d): {interest['tc5']}") # Poll every 30 seconds while True: check_liquidity() time.sleep(30)
8.3 WebSocket Integration
Real-time blotter monitoring:
PYTHONimport websocket import json import threading API_KEY = "ak_live_..." def on_message(ws, message): data = json.loads(message) if data["type"] == "interest_update": interest = data["data"] print(f"Update: {interest['short_name']} - {interest['liq_check_status']}") elif data["type"] == "trading_update": filled_mm = data['data']['qty_traded'] / 1_000_000 print(f"Trading: {data['data']['firmness_pres']} - filled {filled_mm}MM") def on_open(ws): # Authenticate ws.send(json.dumps({"type": "auth", "api_key": API_KEY})) # Start heartbeat thread def heartbeat(): while True: ws.send(json.dumps({"type": "heartbeat"})) time.sleep(25) threading.Thread(target=heartbeat, daemon=True).start() ws = websocket.WebSocketApp( "wss://api.ediphy.io/blotter/v1/stream", on_message=on_message, on_open=on_open ) ws.run_forever()
9. Rate Limiting
9.1 Default Limits
| Endpoint | Rate Limit |
|---|---|
POST /interest |
10/second |
POST /interest/batch |
1/second |
POST /interest/remove |
10/second |
POST /interest/clear-all |
1/minute |
POST /interest/{id}/go-firm |
5/second |
GET /interest |
10/second |
GET /interest/team |
5/second |
GET /interest/latest |
20/second |
GET /audit |
5/second |
Need higher limits? Contact support@ediphymarkets.com to discuss increased rate limits for high-volume use cases.
9.2 Response Headers
X-Ediphy-RateLimit-Limit: 10
X-Ediphy-RateLimit-Remaining: 8
X-Ediphy-RateLimit-Reset: 2025-01-15T10:31:00Z
9.3 Rate Limit Exceeded (429)
JSON{ "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests", "retry_after": 5 } }
10. Security Considerations
10.1 Transport Security
- TLS 1.3 required for all connections
- Certificate pinning recommended for production integrations
10.2 Data Isolation
- User-scope endpoints only return the authenticated user's data
- Team-scope endpoints require explicit permission
- Cross-organization access is not permitted
10.3 Concurrency Model
The Liquidity Checker uses a last-write-wins concurrency model. When multiple users or systems update the same interest record simultaneously, the most recent write takes precedence.
- No optimistic locking (ETags, version numbers) is enforced
- Conflicting updates are resolved by timestamp
- All changes are recorded in the audit trail for forensic review
For team blotters with high concurrency, coordinate updates via client_id prefixes or establish conventions for which systems own which records.
10.4 Audit Trail
All API requests are logged with:
- Timestamp
- User identity
- Request payload
- Response status
- Provenance tracking
Query Audit Log
Query the audit trail for interest changes. Useful for compliance, debugging, and understanding change history.
Query Parameters
| Parameter | Description |
|---|---|
interest_id |
Filter by specific interest record |
client_id |
Filter by client reference ID |
inst_id |
Filter by ISIN |
user |
Filter by user who made the change |
from |
Start of time range (ISO8601) |
to |
End of time range (ISO8601) |
limit |
Max results (default 100, max 1000) |
cursor |
Pagination cursor |
Response (Success - 200 OK)
JSON{ "audit_entries": [ { "entry_id": "audit_abc123", "timestamp": "2025-01-15T10:32:15.789Z", "user": "jsmith", "action": "update", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "client_id": "my-order-001", "inst_id": "US912828ZT77", "changes": { "limit": { "old": 99.50, "new": 99.75 }, "prov": { "old": "sync", "new": "gui" } }, "source": "api", "request_id": "req_xyz789" }, { "entry_id": "audit_def456", "timestamp": "2025-01-15T10:30:00.123Z", "user": "oms_service", "action": "create", "interest_id": "INTEREST_7f3a9b2c-4d5e-6f7a-8b9c-0d1e2f3a4b5c", "client_id": "my-order-001", "inst_id": "US912828ZT77", "changes": { "qty": { "old": null, "new": 5000000 }, "verb": { "old": null, "new": "buy" }, "limit": { "old": null, "new": 99.50 } }, "source": "batch", "request_id": "req_batch_001" } ], "pagination": { "total": 2, "limit": 100, "has_more": false } }
Audit Entry Fields
| Field | Description |
|---|---|
entry_id |
Unique audit entry identifier |
timestamp |
When the change occurred |
user |
User or service account that made the change |
action |
Type of change: create, update, remove, go_firm |
interest_id |
Affected interest record |
client_id |
Client reference ID |
inst_id |
ISIN |
changes |
Object showing old and new values for each changed field |
source |
Origin of change: api, batch, gui, system |
request_id |
Associated API request ID (for tracing) |
11. Endpoint Summary
| Method | Endpoint | Description |
|---|---|---|
POST |
/interest |
Add or update interest |
POST |
/interest/remove |
Remove interest |
POST |
/interest/clear-all |
Clear all interest |
POST |
/interest/batch |
Batch upload |
POST |
/interest/{id}/go-firm |
Transition interest to firm order |
GET |
/interest |
List user's interest |
GET |
/interest/team |
List team's interest |
GET |
/interest/latest |
Get recent changes |
GET |
/audit |
Query audit trail |
WSS |
/stream |
WebSocket for real-time updates |
12. Appendix: Field Reference
12.1 Interest Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
inst_id |
string | Yes | ISIN (12 characters) |
client_id |
string | No | Client reference ID (max 64 chars) |
verb |
string | No | "buy", "sell", or null |
qty |
integer | No | Quantity in base currency units |
limit |
number | No | Price limit |
firmness |
string | No | "Soft", "Inactive" |
comment |
string | No | Free-form note |
status |
string | No | "Active" (default), "Inactive" |
12.2 Interest Response Fields
Core Interest Fields:
| Field | Type | Description |
|---|---|---|
interest_id |
string | System-generated unique ID |
client_id |
string | Client reference ID |
inst_id |
string | ISIN |
verb |
string | "buy", "sell", or null |
qty |
number | Quantity in base currency units |
limit |
number | Price limit |
firmness |
string | Raw firmness state |
firmness_pres |
string | Presentation firmness (accounts for trading state) |
comment |
string | User-provided note |
prov |
string | Provenance ("sync", "gui") |
owner_user |
string | Owner username |
originator_user |
string | User who created the interest |
ts_captured |
string | Last update timestamp |
Reference Data Fields:
| Field | Type | Description |
|---|---|---|
short_name |
string | Bond short name (e.g., "T 2.5 05/15/30") |
legal_name |
string | Issuer legal name |
coupon |
number | Coupon rate |
currency_rd |
string | Currency code |
maturity |
string | Maturity date (ISO format) |
MiFID Post-Trade Data:
| Field | Type | Description |
|---|---|---|
notional_amount_usd |
number | Total traded volume (USD) in last 60 days |
count |
integer | Total trade count in last 60 days |
med_y |
number | Median traded yield from recent transactions |
fairmark_price |
number | Ediphy dynamic end-of-day mark price |
fairmark_date |
string | Date of the most recent mark |
Liquidity Score Fields:
| Field | Type | Description |
|---|---|---|
liq_check_status |
string | Composite liquidity indicator |
tc5 |
integer | Trade count in last 5 days |
tc20 |
integer | Trade count in last 20 days |
lb5 |
integer | Days lookback to find 5 trades |
lb20 |
integer | Days lookback to find 20 trades |
lb50 |
integer | Days lookback to find 50 trades |
lb1mm |
integer | Days lookback to find 1MM USD volume |
lb10mm |
integer | Days lookback to find 10MM USD volume |
lb50mm |
integer | Days lookback to find 50MM USD volume |
alt_count |
integer | Number of liquid alternative instruments |
Live Market Data:
| Field | Type | Description |
|---|---|---|
livemid |
number | Current live mid-price (when available) |
flags_tradable |
boolean | Whether tradable on Ediphy |
Trading Status Fields:
| Field | Type | Description |
|---|---|---|
ticket_id |
string | Active trading ticket ID (if firm) |
qty_traded |
number | Total quantity filled (base currency units) |
ticket_count |
integer | Number of tickets created |
trading_limit |
number | Limit on active ticket |
trading_mkt_quantity |
number | Quantity working in market |
trading_status |
string | Trading ticket status |
trading_user |
string | User who owns firm order |
actions |
string | Available action: "Go Firm", "Update Firm" |