Paradigm API v1
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
Introduction
Paradigm has three major products, Multi-Dealer RFQ (DRFQ), Global RFQ (GRFQ), and the Future Spread Dashboard (FSPD).
These three products are separate and require separate authenticated interaction via their specific version & product connections URLs.
Paradigm uses RESToverHTTP and JSON-RPCoverWebSockets as our API interfaces to be consistent with the broader crypto space.
Feel free to reach out for any technical support as we would love to help!
DRFQ - Brief Overview
Multi Dealer RFQ (DRFQ) is to be used when you wish to request a quote for a specific size and from a specific group of counterparties. DRFQs are short-lived and designed to be executed within a short time window.
DRFQ will be sunset & deprecated in the future with DRFQv2 taking it's place. Dates will be communicated in advance & DRFQ will be backwards compatible with DRFQv2 for a reasonable period.
To be a party to a DRFQ, you must either be the Initiator (Taker) or a requested counterparty (Maker). DRFQs can be created on a disclosed or anonymous basis, but Makers' desk names are always & only disclosed to the DRFQ Taker.
Makers are unable to see competing Quotes or information relating to the Taker's intended execution side.
If you would like to be recognized as a "Liquidity Provider" or a Maker, please reach out to our Sales team.
Deribit, Bit.com, and the CME are available as venues.
GRFQ - Brief Overview
Global RFQ (GRFQ) is to be used when you wish to contribute to a public auction for a specific RFQ. GRFQ RFQs are long-lived and are only canceled after the expiry of the underlying instruments or the inactivity of the RFQ.
Anyone is able to participate in a GRFQ RFQ and act as a Taker or a Maker. All GRFQ RFQ Quotes, Orders, Trades, and interactions are anonymous to everyone but the users who are directly a part of each interaction.
Deribit, Bit.com, and Bybit are available as venues.
FSPD - Brief Overview
The Future Spread Dashboard (FSPD) is to be used to trade Future Spreads using a central limit Order Book. This product allows you to trade spreads as a single Strategy, priced at the Strategy level without any leg risk.
Anyone is able to participate in the Order Book of a Strategy as either a Taker or a Maker. All Orders, Trades and interactions are on an anonymous basis.
FTX, Deribit, and Bybit are available as venues.
API Connection URLs
The API is available on Paradigm's Live and Test environments.
Base URL | Live Environment
- RESToverHTTP:
https://api.chat.paradigm.co
JSON-RPCoverWebSocket:
wss://ws.api.chat.paradigm.co
FSPD ONLY: RESToverHTTP:
https://api.fs.chat.paradigm.co
FSPD ONLY: JSON-RPCoverWebSocket:
wss://ws.api.fs.chat.paradigm.co
Base URL | Test Environment
- RESToverHTTP:
https://api.test.paradigm.co
JSON-RPCoverWebSocket:
wss://ws.api.test.paradigm.co
FSPD ONLY: RESToverHTTP:
https://api.fs.test.paradigm.co
FSPD ONLY: JSON-RPCoverWebSocket:
wss://ws.api.fs.test.paradigm.co
Product & Version
You must concatenate the Base URL with the Version & Product URLs to access specific endpoints.
- DRFQ:
/v1/drfq
- GRFQ:
/v1/grfq
- FSPD:
/v1/fs
Examples
- DRFQ - [GET]
/counterparties/
- Example: [GET]https://api.test.paradigm.co/v1/drfq/counterparties/
DRFQ - WS Subscribe URL - Example:
wss://ws.api.test.paradigm.co/v1/drfq/
GRFQ - [GET]
/rfqs/
- Example: [GET]https://api.test.paradigm.co/v1/grfq/rfqs/
GRFQ - WS Subscribe URL - Example:
wss://ws.api.test.paradigm.co/v1/grfq/
FSPD - [GET]
/instruments
- Example: [GET]https://api.fs.test.paradigm.co/v1/fs/instruments
FSPD - WS Subscribe URL - Example:
wss://ws.api.fs.test.paradigm.co/v1/fs/
Rate Limits
DRFQ
RESToverHTTP requests are rate limited to 30 requests per second per desk across all API Keys.
You cannot horizontally scale your rate limit per desk by using multiple API Keys.
GRFQ
RESToverHTTP requests are rate limited to 500 requests per second per desk across all API Keys.
You cannot horizontally scale your rate limit per desk by using multiple API Keys.
FSPD
RESToverHTTP requests are rate limited per desk and by group. By default, the read-only GET requests are rate limited to 100 requests per second and all other requests, such as POST, PATCH, and DELETE are limited to 10 requests per second. Paradigm can customize these limits by desk depending on the desk's volume of operations. The desk administrator may request a limit increase by contacting support.
You cannot horizontally scale your rate limit per desk by using multiple API Keys.
On-boarding
We can create as many Paradigm test environment accounts as you like. We would love to create a Taker and a Maker account, functionally no different to each other, so you can test the workflows end-to-end.
For test environment accounts, all you need to do is:
- Contact your Sales representative with your account creation request.
- Provide a unique email address for each Paradigm test account as well as the First and Last Name to be associated.
- Upon account creation by the Sales representative, enter testnet Venue API credentials to your Paradigm test Client Admin Dashboard.
As a note, you will need to enter different Venue API Credentials on your Taker and Maker Paradigm accounts as you cannot trade against yourself.
Exchange Testnet URLs
- Deribit's Testnet: test.deribit.com
- Bit.com's Testnet: beta.bitexch.dev
- Bybit's Testnet: testnet.bybit.com
Helpful Reminders
- You CANNOT RFQ, Quote, or Trade yourself across any of Paradigm's Products.
- All instruments on Paradigm are the same instruments you trade on the underlying venue. This means:
- Instruments on Paradigm can only be traded to the minimum tick size specified by the underlying venue's contract specifications.
- Instruments on Paradigm can only be traded to the minimum order/contract size specified by the underlying venue's contract specifications.
- Supported Venue & Instrument Contract Specifications
High Level Implementation Notes
These notes relate to DRFQ, GRFQ, and FSPD Products.
You should use your connection to Paradigm through the JSON-RPCoverWebSockets interface to receive updates relating to RFQs, Quotes, Orders (GRFQ+FSPD), and Trades.
You should use our RESToverHTTP endpoints to interact with Paradigm for all actions such as, but not limited to, Creating RFQs, Creating Quotes, Canceling Quotes, Creating Orders, and Canceling Orders.
Your solution should
- For JSON-RPCoverWebSocket connections, ensure a
heartbeat
has been initiated and is being maintained. - Ensure each request has the necessary authentication attributes as each request must be authenticated.
- For DRFQs, be subscribed to the
rfq
,quote
,trade
, andtrade_confirmation
JSON-RPCoverWebSockets Notification channels to receive updates relating to those events. - For GRFQs, be subscribed to the
grfq
,quote_book
,quote
,order
,trade
, andtrade_tape
JSON-RPCoverWebSockets Notification channels to receive updates relating to those events. - For FSPD, be subscribed to the
strategy_state.{venue}.{kind}
,order_book.{strategy_id}.{level}
,trades.{venue}.{kind}.{strategy_id}
,trade_tape.{venue}.{kind}.{strategy_id}
, andplatform_state
JSON-RPCoverWebSockets Notification channels to receive updates relating to those events. - Wait for responses to RESToverHTTP requests to confirm successful or erroneous interactions.
Your solution should not
- Use RESToverHTTP endpoints to frequently request updates relating to RFQs, Quotes, Orders (GRFQ+FSPD) or Trades.
- Use JSON-RPCoverWebSockets to send RESToverHTTP requests to Paradigm.
Market Maker Protection (MMP)
Paradigm's Market Maker Protection (MMP) program is designed to protect Makers and limits the number of executions possible across a desk across a period of time.
All of a Maker's Desk's existing Quotes will be canceled and the Maker's Desk will be prevented from creating additional Quotes if two executions occur within one second. To remove this protection, the user can send a successful RESToverHTTP [PATCH] /v1/{product}/mmp/status/
request. The MMP protection is automatically removed within 10 seconds of triggering by Paradigm without any interaction necessary by the user.
Takers are only able to create one market every three seconds in MDRFQ & GRFQ.
Takers are only able to execute once every two seconds in MDRFQ & GRFQ.
This feature is enabled for all Paradigm clients and cannot be disabled. The conditions of MMP being triggered cannot be configured by the user.
MMP is across all of your Desk's Paradigm API Keys. MMP protections and workflows are shared across DRFQ+GRFQ products.
This means, upon MMP being triggered by either DRFQ or GRFQ, the Maker's Desk will be unable to create any additional quotes and all existing quotes will be canceled irrespective of whether you are using DRFQ or GRFQ until a [PATCH] /v1/drfq/mmp/status/
or [PATCH] /v1/grfq/mmp/status/
request is successful. Desk interactions with FSPD will remain unaffected.
MMP functionality is not applied for FSPD.
Errors
All RESToverHTTP error responses follow the same basic format. An Error object is returned in response to an erroneous RESToverHTTP request, accompanied by an HTTP status code of 400.
Specific error codes are listed with each RESToverHTTP endpoint.
Error Object
An example of an erroneous Response message
{
"code": 1002,
"message": "Invalid enumeration set value",
"data": {
"member": "side",
"value": "CROSS"
}
}
The Error object is expressed as a single JSON Object, with the following members:
Member | Type | Req | Description |
---|---|---|---|
code | number | Y | The type of error that occurred. |
message | string | Y | A short description of the error. |
data | object | N | Additional structured information about the error. The value is determined by the specific member invoked and may not be present if the error does not require it. |
Error Codes
The following general error codes are supported by Paradigm:
Code | Message | Meaning |
---|---|---|
-32700 | Parse error | Invalid JSON received by the server. |
-32600 | Invalid Request | The JSON sent is not a valid Request object. |
-32601 | Method not found | The method does not exist / is not available. |
-32602 | Invalid params | Invalid method parameter(s). |
-32603 | Internal error | Internal JSON-RPC error. |
429 | Desk's ratelimit reached. Expected available in 1 second. | Refer to Rate Limit section above. |
1001 | Insufficient permissions | The user does not have sufficient permissions to execute the method. |
1002 | Invalid enumeration set value | The enumeration set value is invalid for the specified field. |
Authentication
All Paradigm API endpoints are considered private and require authentication.
Paradigm uses token-based authentication for API access to both the RESToverHTTP and JSON-RPCoverWebSocket API endpoints.
As an additional protection measure against replay attacks in environments where SSL trust is not properly configured, Paradigm requires all RESToverHTTP requests to be signed using your Paradigm API Key's <secret-key>
.
Important Notes:
- Paradigm does not currently provide fine-grained token scopes or permissions. Please ensure your API credentials are stored securely.
- If you have an IP whitelist set for your Venue API Keys, on the Venue, you will need to include Paradigm's IP addresses in your Venue API Key whitelists.
There are a number of Authentication methods available across both the RESToverHTTP and JSON-RPCoverWebSocket interfaces, these include:
- Token-based Authentication
- HTTP Header
- Cookie
- Query String Parameter (JSON-RPCoverWebSocket only)
Error Codes
The following error codes relate to Authentication Errors:
Code | Message | Meaning |
---|---|---|
401 | API Key is not enabled or has been revoked. | Paradigm API Key is Inactive or has been Deleted. |
401 | Invalid API Access Key. | Paradigm API Access Key is invalid or incorrect. |
403 | Request signature verification failed. | Paradigm API Secret Key is invalid, incorrect or you have not properly created the signature. |
Generating a Paradigm API Key
Before accessing any RESToverHTTP or JSON-RPCoverWebSocket API endpoints, you must generate the necessary Paradigm API credentials. This can be accomplished via the Paradigm Admin Dashboard.
You use the same Paradigm API <access-key>
& <secret-key>
to authenticate requests for all Paradigm products.
Live Environment
Paradigm Admin Dashboard URL: https://admin.chat.paradigm.co/
Test Environment
Paradigm Admin Dashboard URL: https://admin.test.paradigm.co/
Once Created
When you have generated Paradigm API credentials, you will be presented with two keys:
- Access Key: used to authenticate the API.
- Secret Key: used to sign requests against the API.
Be sure to save these two keys somewhere secure as both the Access Key and the Secret Key will only be visible once during creation.
If you lose either the <access-key>
or the <secret-key>
, you will need to generate a new Paradigm API Key via the Admin Dashboard.
Token-based Authentication
Only the <access-key>
is needed for authenticating requests. The different methods are presented below in order of our preference.
HTTP Header
Authorization example with an HTTP Header
{
"Authorization": "Bearer SXDlhLKYX6GH6InhBxcCzoW4"
}
When possible, authentication should be performed using the Authorization HTTP header. The header should supply the Paradigm API <access-key>
in plain text, preceded by the text "Bearer ".
Authorization: Bearer <access-key>
Cookie
In some cases, providing custom HTTP headers may not be possible. This is particularly true when connecting to JSON-RPCoverWebSockets via browser APIs.
In these cases, the Paradigm API Key Access Key may be provided by a special HTTP cookie. The cookie should be defined as follows:
Paradigm-API-Key = <access-key>
Query String Parameter (for JSON-RPCoverWebSocket connections only)
In the unlikely scenario that you are unable to use HTTP headers or Cookies for authentication against the JSON-RPCoverWebSocket API, Paradigm supports a special HTTP query parameter.
The query parameter can be provided as part of the WebSocket connection URL.
Live Environment | URL Examples
DRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/v1/drfq/?api-key=<access-key>
GRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/v1/grfq/?api-key=<access-key>
VRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/v1/vrfq/?api-key=<access-key>
FSPD - JSON-RPCoverWebSocket Connection URL: wss://ws.api.fs.chat.paradigm.co/v1/fs/?api-key=<access-key>
Test Environment | URL Examples
DRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.test.paradigm.co/v1/drfq/?api-key=<access-key>
GRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.test.paradigm.co/v1/grfq/?api-key=<access-key>
VRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.test.paradigm.co/v1/vrfq/?api-key=<access-key>
FSPD - JSON-RPCoverWebSocket Connection URL: wss://ws.api.fs.test.paradigm.co/v1/fs/?api-key=<access-key>
Signing Requests
Paradigm requires all RESToverHTTP requests to be signed.
GET RESToverHTTP example demonstrating signing of requests
# A GET RESToverHTTP sample demonstrating the generation of signatures and signing of requests.
import base64
import hmac
import time
from urllib.parse import urljoin
import requests
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
access_key = '<access-key>'
secret_key = '<secret-key>'
host = 'https://api.test.paradigm.co'
# GET example
method = b'GET'
path = b'/v1/drfq/instruments/?venue=DBT&asset=BTC'
body = b''
timestamp, signature = sign_request(secret_key, method, path, body)
headers = {
'Authorization': 'Bearer {}'.format(access_key),
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
}
url = urljoin(host, path.decode())
response = requests.get(url, headers=headers)
print(response.status_code)
print(response.text)
POST RESToverHTTP example demonstrating signing of requests
# A POST RESToverHTTP sample demonstrating the generation of signatures and signing of requests.
import base64
import hmac
import json
import time
from urllib.parse import urljoin
import requests
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
access_key = '<access-key>'
secret_key = '<secret-key>'
host = 'https://api.test.paradigm.co'
# POST example
method = b'POST'
path = b'/v1/echo/'
data = {'message': 'hello'}
body = json.dumps(data).encode('utf-8')
timestamp, signature = sign_request(secret_key, method, path, body)
headers = {
'Authorization': 'Bearer {}'.format(access_key),
'Paradigm-API-Signature': signature,
'Paradigm-API-Timestamp': timestamp,
'Accept': 'application/json',
}
url = urljoin(host, path.decode())
response = requests.post(url, headers=headers, json=data)
print(response.status_code)
print(response.text)
Important Note: Signing is not currently supported for JSON-RPCoverWebSocket API endpoints.
Request signatures are generated by applying the HMAC-SHA256 function to your Paradigm API <secret-key>
and a concatenated message consisting of the request timestamp, request method, request path, query parameters, and body. The key provided to the HMAC function must be the base64-decoded version of the <secret-key>
. The signature must then be base64-encoded and passed via a special header value.
Some important considerations are:
- The timestamp must be a UNIX timestamp (milliseconds since epoch in UTC).
- The request method must be capitalized (e.g.
GET
). - The request path must include the entire base path of the request (e.g.
/rfq/
). - The request parameters must include
?
(e.g.?cursor=a2Ed&venue=DBT
) unless none are used. - The request body should be substituted with an empty string for
GET
requests.
Once the signature is generated, the timestamp and signature should be provided as HTTP headers:
Header Name | Header Value |
---|---|
Paradigm-API-Signature | The generated signature |
Paradigm-API-Timestamp | The timestamp used when generating the signature |
Note: Signed requests are only valid for 30 seconds from when the timestamp is captured. Requests received after the 30-second window are rejected.
JSON-RPC over WebSocket
JSON-RPC
JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol. It uses JSON (RFC 4627) as the data format.
All member names exchanged between the Client and the Server that are considered for matching of any kind should be considered to be case-sensitive. The Client is defined as the origin of Request objects and the handler of Response objects. The Server is defined as the origin of Response objects and the handler of Request objects. A trader using the API can fill both the role of the Client and the Server depending on the Request.
Error Codes
The following error codes relate to establishing a JSON-RPCoverWebSocket connection:
Code | Meaning |
---|---|
HTTP 403 | An invalid or incorrect Paradigm API Access Key was used to authenticate the JSON-RPCoverWebSocket connection. |
HTTP 403 | Incorrect connection query string used. |
Cancel on Disconnect
Cancel on Disconnect mode is enabled on all JSON-RPCoverWebSocket connections by default. Cancel on Disconnect mode will cancel all outstanding RFQs (solely for DRFQ), Quotes (DRFQ+GRFQ+VRFQ) and Orders (FSPD) that have been sent with the Paradigm API Key used to authenticate the WebSocket session when all associated WebSocket connections disconnect.
If multiple WebSocket connections are authenticated with the same API Key at the same time, then RFQs (solely for DRFQ), Quotes (DRFQ+GRFQ+VRFQ) and Orders (FSPD) will only be canceled when the last connection with Cancel on Disconnect mode enabled disconnects.
To disable Cancel on Disconnect mode, specify cancel_on_disconnect=false
as a query string parameter when connecting to the JSON-RPCoverWebSocket interface.
Live Environment | Cancel on Disconnect Examples
DRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/v1/drfq/?api-key=<access-key>&cancel_on_disconnect=false
GRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/v1/grfq/?api-key=<access-key>&cancel_on_disconnect=false
FSPD - JSON-RPCoverWebSocket Connection URL: wss://ws.api.fs.chat.paradigm.co/v1/fs/?api-key=<access-key>&cancel_on_disconnect=false
Test Environment | Cancel on Disconnect Examples
DRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.test.paradigm.co/v1/drfq/?api-key=<access-key>&cancel_on_disconnect=false
GRFQ - JSON-RPCoverWebSocket Connection URL: wss://ws.api.test.paradigm.co/v1/grfq/?api-key=<access-key>&cancel_on_disconnect=false
FSPD - JSON-RPCoverWebSocket Connection URL: wss://ws.api.fs.test.paradigm.co/v1/fs/?api-key=<access-key>&cancel_on_disconnect=false
Request Objects
An example of a JSON-RPCoverWebSocket Request message
{
"id": "1",
"jsonrpc": "2.0",
"method": "subscribe",
"params": {
"channel": "rfq"
}
}
An RPC call is represented by sending a Request object to a Server.
The Request object has the following members:
Member | Type | Req | Description |
---|---|---|---|
id | string or number | N | An identifier established by the Client. The id is omitted if the method is a Notification. |
jsonrpc | string | Y | The version of the JSON-RPC protocol. Always "2.0". |
method | string | Y | The name of the method to be invoked. |
params | object | N | The parameter values to be used during the invocation of the method. This field may be omitted if the method has no parameters. |
Response Objects
An example of a Successful Response message
{
"id": "1",
"jsonrpc": "2.0",
"result": ["rfq", "trade"]
}
An example of an Erroneous Response message
{
"id": "1",
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "method not found",
"data": {
"method": "unsubscribe-all",
"timestamp": 1597326842.415
}
}
}
When an RPC call is made, the Server replies with a Response, except for in the case of Notifications. The Response is expressed as a single JSON Object, with the following members:
Member | Type | Req | Description |
---|---|---|---|
id | string or number | N | The same value of the id field specified on the Request object. The value is null if there is an error parsing the Request object. The value is omitted in a Notification. |
jsonrpc | string | Y | The version of the JSON-RPC protocol. Always "2.0". |
result | object | N | The result of a successful request. The value is determined by the specific method invoked. Not present if there is an erroneous result. |
error | Error object | N | The result of an erroneous request. Not present if there is a successful result. |
> code | number | N | Error code. |
> message | string | N | Error message. |
> data | object | N | Array of information relating to error. |
>> method | string | N | Erroneous request method. |
>> timestamp | decimal | N | The time the error occurred as the number of unix milliseconds since epoch (January 1, 1970). |
Session Methods
heartbeat
An example of a JSON-RPCoverWebSocket heartbeat Request Object
{
"id": 1,
"jsonrpc": "2.0",
"method": "heartbeat"
}
An example of a JSON-RPCoverWebSocket heartbeat Response Object
{
"id": 1,
"jsonrpc": "2.0"
}
The client is required to regularly send heartbeat Requests to the user over a WebSocket connection at least once every 10 seconds.
If the user does not send a heartbeat in a given 10-second window, the WebSocket connection will be closed by Paradigm.
Paradigm will respond to a heartbeat Request with a heartbeat Response.
Note: The Request does not have a params object and the Response does not have a results object.
Error Codes
The following error code relates to maintaining a heartbeat:
Code | Meaning |
---|---|
4005 | Paradigm did not receive a heartbeat from the WebSocket connection within the past 10 seconds. |
Subscription Methods
Subscriptions work as Notifications, so users will automatically (after subscribing) receive messages from the server.
They are the primary means through which you should intend to receive updates regarding RFQs, Quotes, Orders (GRFQ+FSPD) and Trades.
Subscriptions are only available through WebSockets as these are sent asynchronously from Paradigm to the user as they happen.
Subscription Notification objects have the following members:
Member | Type | Req | Description |
---|---|---|---|
jsonrpc | string | Y | Always "2.0" . |
method | string | Y | Always subscription . |
params | object | Y | Array of returned data. |
> channel | string | Y | The name of the channel. |
> data | object | Y | Data specific to the channel. |
subscribe
An example of a
subscribe
Request Object
{
"id": 123,
"jsonrpc": "2.0",
"method": "subscribe",
"params": {
"channel": "rfq"
}
}
An example of a
subscribe
Response Object
{
"id": 123,
"jsonrpc": "2.0",
"result": ["rfq", "trade"]
}
For DRFQ, there are four subscription channels you can subscribe to: rfq
, quote
, trade
, and trade_confirmation
.
For GRFQ, there are six subscription channels you can subscribe to: rfq
, quote_book
, order
, quote
, trade
, and trade_tape
.
For VRFQ, there are three subscription channels you can subscribe to: rfq
, quote
, and trade
.
For FSPD, there are six subscription channels you can subscribe to: strategy_state.{venue}.{kind}
, order_book.{strategy_id}.{level}
, orders.{venue}.{kind}.{strategy_id}
, trades.{venue}.{kind}.{strategy_id}
, trade_tape.{venue}.{kind}.{strategy_id}
, and venue_bbo.{strategy_id}
.
To subscribe to multiple channels, send a separate subscribe request for each channel.
Note: The Response result is a JSON array of all channels currently subscribed to (DRFQ+GRFQ).
The Request params object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The channel to subscribe to. |
data | object | N | An channel-specific object that specifies parameters for the channel. |
unsubscribe
An example of an
unsubscribe
Request Object
{
"id": 123,
"jsonrpc": "2.0",
"method": "unsubscribe",
"params": {
"channel": "rfq"
}
}
An example of an
unsubscribe
Response Object
{
"id": 123,
"jsonrpc": "2.0",
"result": ["trade"]
}
To unsubscribe from multiple channels, send a separate unsubscribe request for each channel.
Note: The Response result is a JSON array of all channels currently subscribed to.
The Request params object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The channel to unsubscribe from. |
Notification Channels
A Notification is a Request object without an id
member. A Request object that is a Notification signifies the Client's lack of interest in the corresponding Response object, and as such no Response object needs to be returned to the client. The Server must not reply to a Notification, including those that are within a batch request.
Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params", "Internal error").
The Notification Channels are the primary means by which your solution should be expected to be updated regarding RFQs, Quotes, Orders(GRFQ+FSPD) and Trades.
Key Note: DRFQ, GRFQ, and FSPD are separate products with separate JSON-RPCoverWebSocket subscriptions required. You must subscribe to the specific channels of each product you would like to receive notifications from.
DRFQ WebSocket Notification Channels
DRFQ JSON-RPCoverWebSocket notification channels are:
rfq
- Private Updates relating to the creation, expiration, cancellation and fill of RFQs.quote
- Private Updates relating to RFQ quotes including creation, expiration, cancellation, pending_fill and fills of.trade
- Public Updates regarding all completed DRFQ trades on Paradigm even if you are not an included counterparty.trade_confirmation
- Private Updates relating to the successful clearing & settlements of trades upon the underlying venue.market_maker_protection
- Private Updates relating to Market Maker Protection being triggered.
GRFQ WebSocket Notification Channels
GRFQ JSON-RPCoverWebSocket notification channels are:
rfq
- Public Updates relating to the creation and expiration of RFQs.quote_book
- Public Updates relating to the creation and availability of Quotes.order
- Private Updates relating to the creation and execution of Orders upon Quotes.quote
- Private Updates relating to creation, execution, and cancellation of Quotes upon RFQs.trade
- Private Updates relating to executions solely involving the Taker and Maker.trade_tape
- Public Updates relating to all completed Trades on Paradigm through GRFQ.market_maker_protection
- Private Updates relating to Market Maker Protection being triggered.
VRFQ WebSocket Notification Channels
VRFQ JSON-RPCoverWebSocket notification channels are:
rfq
- Public Updates relating to the creation and expiration of RFQs.quote
- Private Updates relating to creation, execution, and cancellation of Quotes upon RFQs.trade
- Private Updates relating to executions solely involving the Taker and Maker.
FSPD WebSocket Notification Channels
FSPD JSON-RPCoverWebSocket notification channels are:
strategy_state.{venue}.{kind}
- Public Updates relating to the creation, settlement, and expiration of Strategies.order_book.{strategy_id}.{level}
- Public Updates relating to delta of Orders being added and removed from the Order Book.orders.{venue}.{kind}.{strategy_id}
- Private Updates relating to the creation, cancellation and interactions of the user's Orders.trades.{venue}.{kind}.{strategy_id}
- Private Updates relating to success or rejected of the user's Trades.trade_tape.{venue}.{kind}.{strategy_id}
- Public Updates relating to all completed Trades on Paradigm through FSPD.venue_bbo.{strategy_id}
- Public Updates relating to the prices+amounts of the Strategies from the underlying venue.
Shared - REST Endpoints
The following REST Endpoints have no Product Identifier in the Connection URL as they are shared across the Paradigm API.
[POST] /echo/
/echo/ Request example
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/echo/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
const inputBody = `{"message": "string"}`;
const headers = {
"Content-Type": "application/json",
Authorization: "Bearer <access-key>",
};
fetch("https://api.test.paradigm.co/v1/echo/", {
method: "POST",
body: inputBody,
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
import json
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# POST /echo/
method = 'POST'
path = '/v1/echo/'
body = b''
payload = {
"message": "this is a test echo message"
}
json_payload = json.dumps(payload).encode('utf-8')
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
message += json_payload
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(urljoin(host, path),
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Authorization": []string{"Bearer <acces-key>"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("POST", "https://api.test.paradigm.co/v1/echo/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
/echo/ Response example
{
"message": "this is a test echo message"
}
A [POST] /echo/
request returns the message specified in the request.
It is designed to allow users to test their authentication as well as connection to Paradigm's API.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
body | body | object | true | none |
message | body | string | false | none |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
message | string | true | Returns the string from the request. |
Shared - WebSocket Notification Channels
market_maker_protection
An example of MMP being triggered
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "market_maker_protection",
"data": {
"kind": "TRIGGERED"
}
}
}
An update is sent to the market_maker_protection
WebSocket Notification Channel when MMP has been triggered. There is no message when it has been reset.
You must subscribe to this channel using the Connection URL with the Version and Product URL suffix of the respective products below. For example: wss://ws.api.test.paradigm.co/v1/grfq
.
If MMP is triggered from the DRFQ product, you will be notified on the market_maker_protection
channel even if you subscribed using the GRFQ Version and Product URL.
The response "params" data object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The notification channel the message was delivered upon. |
data | array | Y | |
> kind | string | Y | Status of MMP. Valid values include TRIGGERED . |
DRFQ - API Workflows
We have Auto-Market Makers running on our Test environment. You are able to request any RFQ from them, and they will respond with a number of quotes promptly.
Their desk names are "DSK2", "DSK3", "DSK4", "DSK5", and "MT2". They are a part of the 'LP' counterparty list returned from [GET] /counterparties/
.
DRFQ will be sunset & deprecated in the future with DRFQv2 taking it's place. Dates will be communicated in advance & DRFQ will be backwards compatible with DRFQv2 for a reasonable period.
High Level
DRFQ is centred around the concepts of "RFQs", "Quotes" and "Trades":
- RFQs are strategies comprised of one or more instruments with Taker defined attributes. RFQs are to be Quoted upon by the requested Makers.
- Quotes are created by the Maker in response to a requested RFQ.
- Trades occur when the Taker executes upon an existing Quote on an RFQ.
At a high level, the DRFQ workflow is:
- Taker creates an RFQ and chooses which counterparties to send it too.
- Maker(s) quotes the RFQ.
- Taker receives the quote(s).
- Taker chooses to execute upon the best quote and the trade is sent to the underlying venue for clearing & settlement.
- Taker & Maker receive confirmation that the trade's execution has successfully cleared & settled or been rejected by the underlying venue.
Key DRFQ Concepts
In DRFQ,
- Specific counterparties must be selected by the Taker to participate in the RFQ.
- There are NO partial fills. You must quote and execute the full RFQ size.
- There is NO concept of a Quote Book or a public auction.
- Takers can choose to RFQ on a disclosed or an anonymous basis.
- It is possible to have an execution Rejected by the underlying venue for a number of reasons (eg, Margin or API Key issues).
Taker's Perspective
Important Note: Both the Taker and the Maker will receive all updates through the JSON-RPCoverWebSockets Notification channels for events relating to RFQs, Quotes, and Trades.
- Taker creates an RFQ using [POST]
/rfq/create/
. You can pull available instruments from [GET]/instruments/
and counterparties from [GET]/counterparties/
. - Taker is able to cancel an RFQ if they wish to do so with [POST]
/rfq/cancel/
. - Maker, who is a requested counterparty to the RFQ, and is notified over the
rfq
JSON-RPCoverWebSockets Notification channel, is then able to provide a quote to the RFQ. - Taker, who will be notified of quotes on the
quote
JSON-RPCoverWebSockets Notification channel, is able to execute upon the best quote with [POST]/quote/execute/
. - Taker will receive confirmation of the trade's successful/rejected clearing & settlement on the
trade_confirmation
JSON-RPCoverWebSockets Notification channel. - Taker will also receive confirmation of the trade being completed on the
trade
JSON-RPCoverWebSockets Notification channel as well as all other DRFQ trades on Paradigm.
Maker's Perspective
Important Note: Both the Taker and the Maker will receive all updates through the JSON-RPCoverWebSockets Notification channels for events relating to RFQs, Quotes,and Trades.
- Taker will create an RFQ and the Maker will be notified on the
rfq
JSON-RPCoverWebSockets Notification channel. - Maker is able to create a one way quote using [POST]
/quote/create/
. - Maker is able to cancel an existing quote with [POST]
/quote/cancel/
. A Maker must cancel any existing quote on an RFQ before they are able to update their quote. - Taker chooses to execute upon an available quote.
- Maker will receive an update of their Quote being executed upon from the
quote
JSON-RPCoverWebSockets Notification channel with the statuspending_fill
. - Maker will receive finality around successful/rejected clearing & settlement from the
trade_confirmation
JSON-RPCoverWebSockets Notification channel. - Maker will receive confirmation of the trade being completed on the
trade
JSON-RPCoverWebSockets Notification channel as well as all other DRFQ trades on Paradigm.
DRFQ - Code Examples
Reach out if you ever need any help! We are more than happy to help.
You will need to update the provided Code Examples with your own Paradigm Access Key and Secret Key.
You can find all existing examples on our GitHub: https://github.com/tradeparadigm/code-samples
DRFQ will be sunset & deprecated in the future with DRFQv2 taking it's place. Dates will be communicated in advance & DRFQ will be backwards compatible with DRFQv2 for a reasonable period.
Note: All examples in this section are in Python3.
JSON-RPCoverWebSockets
Authentication + Subscribe & Unsubscribe to Notification Channels
- Authenticate, establish a heartbeat and Subscribe to the
rfq
,quote
,trade
, andtrade_confirmation
JSON-RPCoverWebSockets Notification Channels.
RESToverHTTP
All Interactions
Takers and Makers should both be subscribed to the rfq
, quote
, trade
, and trade_confirmation
JSON-RPCoverWebsockets Notification channels to receive the required information to use the RESToverHTTP endpoints.
Both Makers and Takers
- [GET] -
/instruments/
- A simple code example demonstrating how to pull the instruments available on Paradigm. - [GET] -
/counterparties/
- A simple code example demonstrating how to pull your available counterparties' information. - [GET] -
/rfq/
- A simple code example demonstrating how to pull information relating to RFQs you are a participant in. - [GET] -
/rfq/
- A more comprehensive example demonstrating pagination and the use of parameters.
Taker Specific
- [POST] -
/rfq/create/
- A simple code example demonstrating how to create an RFQ. - [POST] -
/rfq/cancel/
- A simple code example demonstrating how to cancel an RFQ. - [POST] -
/quote/execute/
- A simple code example demonstrating how to execute a provided Quote.
Maker Specific
- [POST] -
/quote/create/
- A simple code example demonstrating how to create a Quote. - [POST] -
/quote/cancel/
- A simple code example demonstrating how to cancel an already created Quote.
Auto-Market Makers
We encourage you to RFQ all counterparties marked as an "LP" from the [GET] /counterparties/
as this includes all of Paradigm's Auto-Market Makers.
The desk names of some Auto-Marker Makers are "DSK2", "DSK3", "DSK4", "DSK5", and "MT2" on the Test environment.
If you would like to run your own Auto-Market Maker, here is a link to the code and dockerfile: https://github.com/tradeparadigm/code-samples/tree/main/python/api/drfq/market_maker
Auto-Takers
We also have Auto-Taker code examples to help Maker's test their solutions.
- Auto-Taker-Creator - Creates RFQs every 10 seconds: https://github.com/tradeparadigm/code-samples/tree/main/python/api/drfq/auto_taker
- Auto-Taker-Executor - Executes the best received quote every 5 seconds: https://github.com/tradeparadigm/code-samples/tree/main/python/api/drfq/market_taker
DRFQ - WebSocket Notification Channels
rfq
An example, as the Taker, of the
rfq
notification received when an RFQ is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"created": 1611022135830.395,
"desk": "DSK2",
"rfq_id": 22523,
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "",
"legs": [
{
"instrument": "BTC-19JAN21-32000-C",
"quantity": 25.0,
"side": "SELL",
"venue": "DBT"
},
{
"instrument": "BTC-20JAN21-36000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "ACTIVE",
"valid_until": 1611108535827.299,
"counterparties": ["DSK1", "DSK3", "DSK4", "DSK5"]
}
}
}
An example, as the Taker, of the
rfq
notification received when an RFQ is canceled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"created": 1611022135830.395,
"desk": "DSK2",
"rfq_id": 22523,
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "",
"legs": [
{
"instrument": "BTC-19JAN21-32000-C",
"quantity": 25.0,
"side": "SELL",
"venue": "DBT"
},
{
"instrument": "BTC-20JAN21-36000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "CANCELED",
"valid_until": 1611108535827.299,
"counterparties": ["DSK1", "DSK3", "DSK4", "DSK5"]
}
}
}
An example, as the Taker, of the
rfq
notification received when an RFQ is filled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"created": 1611023461827.417,
"desk": "DSK2",
"rfq_id": 22527,
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "",
"legs": [
{
"instrument": "BTC-19JAN21-32000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "FILLED",
"valid_until": 1611023489464.3481,
"counterparties": ["DSK1", "DSK3", "DSK4", "DSK5"]
}
}
}
An example, as the Maker, of the
rfq
notification received when an RFQ is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"created": 1611022135830.395,
"desk": "DSK2",
"rfq_id": 22523,
"legs": [
{
"instrument": "BTC-19JAN21-32000-C",
"quantity": 25.0,
"side": "SELL",
"venue": "DBT"
},
{
"instrument": "BTC-20JAN21-36000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "ACTIVE",
"valid_until": 1611108535827.299
}
}
}
An example, as the Maker, of the
rfq
notification received when an RFQ is canceled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"created": 1611022135830.395,
"desk": "DSK2",
"rfq_id": 22523,
"legs": [
{
"instrument": "BTC-19JAN21-32000-C",
"quantity": 25.0,
"side": "SELL",
"venue": "DBT"
},
{
"instrument": "BTC-20JAN21-36000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "CANCELED",
"valid_until": 1611108535827.299
}
}
}
An example, as the Maker, of the
rfq
notification received when an RFQ is filled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"created": 1611023461827.417,
"desk": "DSK2",
"rfq_id": 22527,
"legs": [
{
"instrument": "BTC-19JAN21-32000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "FILLED",
"valid_until": 1611023489464.3481
}
}
}
An update to an RFQ sent as an RFQ object with members the user is permissioned for. Users are sent RFQs in which they are a counterparty to.
Each RFQ has a globally unique identifier with the rfq_id
member.
The most recently received Notification with the same rfq_id
is the current state of the RFQ.
Important Note: Quotes in response to the RFQs are not sent through the rfq
notifications channel, but through the quote
notifications channel.
The response "params" data object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The notification channel the message was delivered upon. |
data | array | Y | An array of information relating to the specific RFQ. |
> created | decimal | Y | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
> desk | string | N | The Desk Name of Taker. |
> rfq_id | number | Y | The unique identifier of the RFQ. Paradigm creates this value. |
> account | object | N | An array present as the Taker detailing the Paradigm API Key Name or "CME" related information. |
>> name | string | N | Name of the Paradigm API Key used. |
>> clearing_account_name | string | N | Clearing Account Name related to trades executed upon the "CME". |
>> trader_id | string | N | Trader ID related to trades executed upon the "CME". |
> client_order_id | string | Y | User determined unique identifier. Empty if the RFQ is created using the GUI. |
> legs | array of objects | Y | An array of instruments that comprise the RFQ. |
>> instrument | string | Y | The leg's instrument name. |
>> price | decimal | N | The price of the leg if specified. |
>> quantity | decimal | Y | The number of contracts of the leg. |
>> venue | string | Y | The venue the RFQ will be executed on. |
> status | string | Y | The status of the RFQ. Values can include: ACTIVE , CANCELED , FILLED , TRD_AWAY . |
> counterparties | [strings] | N | As the Taker, the other counterparties involved in the RFQ. |
> valid_until | decimal | N | The time the RFQ expires in the number of milliseconds since epoch (January 1, 1970). |
quote
An example, as the Taker, of the
quote
notification received when a Quote is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"desk": "DSK1",
"valid_until": 1611024209158.0242,
"created": 1611024112328.771,
"legs": [
{
"price": 0.1294,
"quantity": 25.0,
"instrument": "BTC-19JAN21-32000-C",
"side": "SELL",
"venue": "DBT"
},
{
"price": 0.0302,
"quantity": 25.0,
"instrument": "BTC-20JAN21-36000-C",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84032,
"rfq_id": 22530,
"side": "SELL",
"status": "ACTIVE"
}
}
}
An example, as the Taker, of the
quote
notification received when a Quote is canceled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"desk": "DSK1",
"valid_until": null,
"created": 1611024112328.771,
"legs": [
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-19JAN21-32000-C",
"side": "SELL",
"venue": "DBT"
},
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-20JAN21-36000-C",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84032,
"rfq_id": 22530,
"side": "SELL",
"status": "CANCELED"
}
}
}
An example, as the Taker, of the
quote
notification received when a Quote is executed
{
"desk": "DSK2",
"valid_until": 1616995320247.1162,
"created": 1616995218247.1162,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": 55084.4,
"quantity": 20000.0,
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 1541710,
"rfq_id": 244484,
"side": "SELL",
"status": "PENDING_FILL"
}
An example, as the Maker, of the
quote
notification received when a Quote is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"desk": "DSK1",
"valid_until": 1611024209158.0242,
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": "DSK1738007604",
"created": 1611024112328.771,
"legs": [
{
"price": 0.1294,
"quantity": 25.0,
"instrument": "BTC-19JAN21-32000-C",
"side": "SELL",
"venue": "DBT"
},
{
"price": 0.0302,
"quantity": 25.0,
"instrument": "BTC-20JAN21-36000-C",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84032,
"rfq_id": 22530,
"side": "SELL",
"status": "ACTIVE"
}
}
}
An example, as the Maker, of the
quote
notification received when a Quote is canceled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"desk": "DSK1",
"valid_until": null,
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": "DSK1738007604",
"created": 1611024112328.771,
"legs": [
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-19JAN21-32000-C",
"side": "SELL",
"venue": "DBT"
},
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-20JAN21-36000-C",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84032,
"rfq_id": 22530,
"side": "SELL",
"status": "CANCELED"
}
}
}
An example, as the Maker, of the
quote
notification received when a Quote is filled
{
"desk": "DSK2",
"valid_until": 1616995442399.624,
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "DSK2572194009",
"created": 1616995359399.624,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": 55063.79,
"quantity": 20000.0,
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 1541712,
"rfq_id": 244485,
"side": "SELL",
"status": "PENDING_FILL"
}
An update to a Quote sent in response to an RFQ sent as a Quote object with members the user is permissioned for. Users are sent quotes in which they are a counterparty to.
Each Quote has a globally unique identifier with the quote_id
member.
The most recently received Notification with the same quote_id
is the current state of the RFQ & Quote.
As Takers, you are able to see all Quotes provided to you and the desk name of the counterparty.
As Makers, you are only able to see your Quote and the desk name of the Taker if the RFQ is on a disclosed basis.
The response params data object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The channel name the message was received upon. |
data | array | Y | An array containing information relating to the Quote(s) of a specific RFQ. |
> desk | string | N | The Paradigm desk name of the Taker. |
> valid_until | decimal | Y | The time at which the Quote expires in the number of milliseconds since epoch (January 1, 1970). |
> created | decimal | Y | The time the Quote was executed in the number of milliseconds since epoch (January 1, 1970). |
> legs | array of objects | Y | An array of legs that comprise the RFQ. |
>> price | decimal | Y | The price of the leg if one is quoted |
>> quantity | decimal | Y | The quantity of the leg if one is quoted. |
>> side | string | Y | The direction of the leg. Values can be BUY and SELL . |
>> venue | string | Y | The venue which the RFQ will be executed upon. |
> price | decimal | N | The calculated spread price, if applicable. |
> quote_id | string | Y | The unique identifier of the Quote. Paradigm creates this value. |
> rfq_id | string | Y | The unique identifier of the RFQ. Paradigm creates this value. |
> side | string | Y | Side being quoted. Valid values include "BUY" and "SELL". |
trade
An example, as the Taker or the Maker, of the
trade
notification received when a trade is completed
{
"created": 1616995466611.969,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": 54608.22,
"quantity": 20000.0,
"venue": "DBT",
"trade_id": 44290
}
],
"price": 54608.22,
"quote_id": 1541713,
"rfq_id": 244486
}
Trades are sent for all executions on the Paradigm platform after the trade is confirmed by the Exchange.
The response params data object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The channel upon which the notification was delivered. |
data | array | Y | An array of information relating to the completed Trade of the RFQ. |
> created | decimal | Y | The time the Trade was executed in the number of milliseconds since epoch (January 1, 1970). |
> legs | array of objects | Y | An array of legs that comprise the RFQ. |
>> instrument | string | Y | The leg's instrument name. |
>> price | decimal | Y | The price of the leg. |
>> quantity | decimal | Y | The number of contracts of the leg. |
>> venue | string | Y | The venue the RFQ was executed on. |
>> trade_id | decimal | Y | The unique identifier of the trade. Paradigm determines this. |
> price | decimal | N | The calculated spread price, if applicable. |
> quote_id | string | Y | The unique identifier of the Quote executed. Paradigm determines this. |
> rfq_id | string | Y | The unique identifier of the RFQ executed. Paradigm determines this. |
trade_confirmation
An example, as the Taker or the Maker, of the
trade_confirmation
notification received when a trade is completed
{
"account": {
"name": "ParadigmTestTwo"
},
"created": 1616995466611.969,
"desk": "DSK2",
"exec_id": "68454170",
"instrument": "BTC-PERPETUAL",
"venue": "DBT",
"price": 54608.22,
"quantity": 20000.0,
"side": "BUY",
"quote_id": 1541713,
"rfq_id": 244486,
"trade_id": 44290
}
Trade Confirmations are sent for executions the user is involved in when the Exchange confirms the Trade.
Trade Confirmations are published for each individual leg executed.
The Request params data object has the following members:
Member | Type | Req | Description |
---|---|---|---|
channel | string | Y | The notification channel the message was received upon. |
data | array | Y | An array of trade confirmation information relating to a specific RFQ. |
> account | object | N | An array present as the Taker detailing the Paradigm API Key Name or "CME" related information. |
>> name | string | N | Name of the Paradigm API Key used. |
>> clearing_account_name | string | N | Clearing Account Name related to trades executed upon the "CME". |
>> trader_id | string | N | Trader ID related to trades executed upon the "CME". |
> created | decimal | Y | The time the instrument was executed at the exchange in the number of milliseconds since epoch (January 1, 1970). |
> desk | string | Y | The Paradigm Desk Name involved in the trade (your API Key's desk). |
> exec_id | string | N | Venue-specific field. The venue's unique identifier for the trade. The venue determines this value. |
> instrument | string | Y | The instrument name executed. |
> venue | string | Y | The venue the trade was executed on. |
> price | number | Y | The execution price of the instrument name. |
> quantity | number | Y | The number of contracts executed. |
> side | string | Y | The direction of the trade. Valid values can include "BUY" and "SELL". |
> quote_id | string | Y | The unique identifier for the quote that corresponds to the trade. Paradigm determines this value. |
> rfq_id | string | Y | The unique identifier for the RFQ that corresponds to the trade. Paradigm determines this value. |
> trade_id | string | Y | The unique identifier for the trade that corresponds to the trade. Paradigm determines this value. |
DRFQ - REST Endpoints
[GET] /instruments/
/instruments/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/drfq/instruments/ \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const headers = {
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/instruments/", {
method: "GET",
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# GET /instruments/
method = 'GET'
path = '/v1/drfq/instruments/?venue=DBT'
body = b''
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(urljoin(host, path),
headers=headers)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("GET", "https://api.test.paradigm.co/v1/drfq/instruments/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [GET] /instruments/
request returns the instruments that are supported for trading on Paradigm. They follow the same naming conventions as the venue they are traded upon.
If the resulting returned list of instruments is too large, it is divided into pages. Each request returns a single page.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
asset | query | string | false | Type of currency. Valid values include "BCH", "BTC" or "ETH". |
cursor | query | string | false | The next or previous cursor from the paginated result set. |
type | query | string | false | Type of instrument. Valid values include "FUTURE" or "OPTION". |
venue | query | string | false | Venue to return instruments for. Value values include "BIT", "CME", or "DBT" |
/instruments/ Response example
200 Response
{
"count": 895,
"next": "c12dEx=",
"results": [
{
"name": "BTC-19JAN21-32000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-32000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-34000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-34000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-35000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-35000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-36000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-36000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-36500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-36500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-37000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-37000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-38000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-38000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-40000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-19JAN21-40000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-36000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-36000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-37000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-37000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-38000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-38000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-40000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-20JAN21-40000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-25000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-25000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-25500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-25500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-26000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-26000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-26500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-26500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-27000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-27000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-27500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-27500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-28000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-28000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-28500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-28500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-29000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-29000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-29500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-29500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-30000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-30000-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-30500-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-30500-C",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-31000-P",
"type": "OPTION",
"venue": "DBT"
},
{
"name": "BTC-22JAN21-31000-C",
"type": "OPTION",
"venue": "DBT"
}
]
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
count | number | Y | None | Number of available instruments. |
next | string | Y | None | Cursor to use to retrieve the next page of results. Equal to "null" if there are no more pages. |
results | array of objects | Y | None | Array of objects of instruments and their details. |
> name | string | Y | None | Name of the instrument. |
> type | string | Y | None | Type of instrument. |
> venue | string | Y | None | Venue the instrument is available upon. |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | 101 | Unknown type | An invalid Type key value was provided. |
400 | 102 | Unknown venue | An invalid Venue key value was provided. |
404 | Invalid cursor | An invalid cursor value was provided. |
[GET] /counterparties/
/counterparties/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/drfq/counterparties/ \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const headers = {
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/counterparties/", {
method: "GET",
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# GET /counterparties/
method = 'GET'
path = '/v1/drfq/counterparties/'
body = b''
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(urljoin(host, path),
headers=headers)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("GET", "https://api.chat.paradigm.co/counterparties/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [GET] /counterparties/
request returns the counterparties that the user is permissioned to trade with on Paradigm.
If the resulting returned list of counterparties is too large, it is divided into pages. Each request returns a single page.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | The next or previous cursor from the paginated result set. |
type | query | string | false | Use 'LP' to filter only Liquidity Providers. |
/counterparties/ Response example
200 Response
{
"count": 176,
"next": "c12dEx=",
"results": [
{
"firm_name": "0420",
"ticker": "APR",
"venues": ["DBT"]
},
{
"firm_name": "0420",
"ticker": "MAY",
"venues": ["DBT"]
},
{
"firm_name": "0420",
"ticker": "MAY01",
"venues": ["CME"]
},
{
"firm_name": "062020",
"ticker": "JUN11",
"venues": ["CME", "DBT"]
},
{
"firm_name": "062020",
"ticker": "05J2",
"venues": ["CME", "DBT"]
},
{
"firm_name": "062020",
"ticker": "05J3",
"venues": ["CME", "DBT"]
},
{
"firm_name": "17bits",
"ticker": "17B",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "Alpha5",
"ticker": "ALP5",
"venues": ["DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "SHIVA",
"venues": ["DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "SAMBO",
"venues": ["DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "RUDRA",
"venues": ["DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "HARA",
"venues": ["DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "NATA",
"venues": ["DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "BHOLE",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "KEDAR",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "APEX(Stage)",
"ticker": "BADRI",
"venues": ["BIT"]
},
{
"firm_name": "Bloomberg",
"ticker": "CRYPT",
"venues": ["DBT"]
},
{
"firm_name": "Bloomberg",
"ticker": "GBLOP",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "Champagne Trust",
"ticker": "DOM",
"venues": ["CME", "DBT"]
},
{
"firm_name": "DARKO",
"ticker": "DARKO",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "DARKO1",
"ticker": "DARK1",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "Dragonfly Capital",
"ticker": "DFLY",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP10",
"ticker": "DSK10",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP2",
"ticker": "DSK2",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP3",
"ticker": "DSK3",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP4",
"ticker": "DSK4",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP5",
"ticker": "DSK5",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP6",
"ticker": "DSK6",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP7",
"ticker": "DSK7",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP8",
"ticker": "DSK8",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP9",
"ticker": "DSK9",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "EP99",
"ticker": "DSK99",
"venues": ["BIT", "CME", "DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK4",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK5",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK6",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK7",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK8",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK9",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK10",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK11",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK12",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK13",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK14",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK18",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK19",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK20",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK21",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK22",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK23",
"venues": ["DBT"]
},
{
"firm_name": "Epam_Maker",
"ticker": "MAK24",
"venues": ["DBT"]
}
]
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
count | number | Y | None | Number of available counterparties. |
next | string | Y | None | Cursor to use to retrieve the next page of results. Equal to "null" if there are no more pages. |
results | array of objects | Y | None | Array of objects of counterparties. |
> firm_name | string | Y | None | Name of counterparty on Paradigm. |
> ticker | string | Y | None | Desk Name on Paradigm. |
> venues | [string] | Y | None | List of strings of venue counterparty is available upon. |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
404 | Invalid cursor | An invalid cursor value was provided. |
[POST]/rfq/create/
/rfq/create/ Request example
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/drfq/rfq/create/ \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const inputBody = `{
"account": {
"name": "string",
"clearing_account_name": "string",
"trader_id": "string"
},
"client_order_id": "string",
"anonymous": true,
"counterparties": [
"strin"
],
"expires_in": 1800,
"legs": [
{
"price": "string",
"quantity": "string",
"side": "BUY",
"instrument": "string",
"venue": "BIT"
}
]
}`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/rfq/create/", {
method: "POST",
body: inputBody,
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
import json
from random import randint
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# POST /rfq/create/
method = 'POST'
path = '/v1/drfq/rfq/create/'
body = b''
client_order_id_random = randint(1, 1000000000)
# print('Client_Order_Id: {}'.format(client_order_id_random))
payload = {
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": client_order_id_random,
"anonymous": "false",
"counterparties": [
"DSK4", "DSK5"
],
"expires_in": 120,
"legs": [
{
"quantity": "25",
"side": "BUY",
"instrument": "BTC-31DEC21-36000-C",
"venue": "DBT"
}
]
}
json_payload = json.dumps(payload).encode('utf-8')
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
message += json_payload
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(urljoin(host, path),
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("POST", "https://api.test.paradigm.co/v1/drfq/rfq/create/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [POST] /rfq/create/
request creates an RFQ.
An /rfq/create/ request has the following workflow:
- The Taker sends an /rfq/create/ request to Paradigm.
- Paradigm sends an /rfq/create/ response to the Taker.
- If the /rfq/create/ request is valid, the RFQ object is returned to the Taker.
- If the /rfq/create/ request is invalid, an Error object is returned to the Taker.
- If the /rfq/create/ request is valid, Paradigm sends a Notification on the
rfq
notification channel to the Taker & the counterparties listed in the RFQ specifying the details of the new RFQ.
Note: You are able to find the instrument names from the [GET] /instruments/
request or the name returned from the exchanges. You are able to pull counterparties desk tickers from [GET] /counterparties/
. Takers are only able to RFQ up to 60 counterparties at the present moment.
The Auto-Market Makers on the Test Environment have the desk names are "DSK2", "DSK3", "DSK4", "DSK5", and "MT2".
/rfq/create/ Body parameter example
{
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": 123,
"anonymous": "false",
"counterparties": ["DSK4", "DSK5"],
"expires_in": 120,
"legs": [
{
"quantity": "25",
"side": "BUY",
"instrument": "BTC-31DEC21-36000-C",
"venue": "DBT"
}
]
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
account | body | object | Y | Object of Paradigm Account information |
> name | body | string | Y | Paradigm API Key name. |
> clearing_account_name | body | string | N | Required value if using "CME" as a venue. |
> trader_id | body | string | N | Required value if using "CME" as a venue. |
client_order_id | body | string | Y | Unique identifier created by the user. |
anonymous | body | boolean | N | Submit RFQ on a disclosed or anonymous basis. |
counterparties | body | [string] | Y | List of strings of the Desk Names of the other counterparties to the RFQ. |
expires_in | body | integer | N | Length in seconds the RFQ is available for. Valid values are between 60-120. |
legs | body | array of objects | Y | An array of objects containing each leg of the RFQ. |
> price | body | decimal | N | Requested price of leg for hedge RFQs. |
> quantity | body | decimal | Y | Number of contracts of the leg. |
> side | body | string | Y | Direction of the RFQ leg. Valid values include "BUY" and "SELL". |
> instrument | body | string | Y | Instrument name, for example: "BTC-PERPETUAL". |
> venue | body | string | Y | Exchange to send the RFQ. Valid values include "DBT", "BIT", and "CME". |
/rfq/create/ Response example
201 Response
{
"created": 1611033737572.134,
"desk": "DSK2",
"rfq_id": 22534,
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "769195219",
"legs": [
{
"instrument": "BTC-31DEC21-36000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "ACTIVE",
"valid_until": 1611033857557.6538,
"counterparties": ["DSK4", "DSK5"]
}
Response Schema
Status Code 201
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
created | decimal | Y | None | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
desk | string | Y | None | The desk name which created the RFQ. |
rfq_id | number | Y | None | The unique identifier of the RFQ. This value is determined by Paradigm. |
account | object | Y | None | An object of the account information relating to the creation of the RFQ. |
> name | string | Y | None | The Paradigm API Key name. |
> clearing_account_name | string | N | None | Only present if using "CME" as the venue. |
> trader_id | string | N | None | Only present if using "CME" as the venue. |
client_order_id | string | Y | none | Unique identifier created by user. |
legs | array of objects | Y | None | Array of objects of the legs of the RFQ. |
> instrument | string | Y | None | The leg's instrument name. |
> price | decimal | N | none | Price of leg if a hedge has been added. |
> quantity | decimal | Y | None | The number of contracts of the leg. |
> side | string | Y | None | The Direction of leg. Valid values include "BUY" and "SELL". |
> venue | string | Y | None | The Exchange the RFQ was created upon. |
status | string | Y | None | The Status of the RFQ. Valid values include "ACTIVE", "CANCELED", "FILLED" |
valid_until | decimal | Y | None | The time the RFQ will expire in the number of milliseconds since epoch (January 1, 1970). |
counterparties | [string] | Y | None | List of strings of the other Counterparties of the RFQ. |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | 'Anonymous' key Must be a valid boolean. | Anonymous key must be a valid boolean. | |
400 | Future leg price is outside exchange price bands. | The hedge leg's price is outside the exchange's accepted price bands. | |
400 | 1301 | Duplicate client_order_id | Non-Unique client_order_id value provided. |
400 | 1302 | Invalid account information | Invalid account information provided. |
400 | 1303 | No counterparties specified | No counterparties specified in request. |
400 | 1304 | Invalid counterparty | Invalid or duplicate counterparty(ies) requested. |
400 | 1305 | Invalid expires_in | Invalid expires_in value provided. Too small (<60) or too large. |
400 | 1306 | Invalid instrument | Invalid instrument provided as part of request. |
400 | 1308 | Invalid Price | Invalid price provided as part of request. |
400 | 1309 | Negative quantity | Negative quantity value was provided as part of request. |
400 | 1310 | Invalid quantity | Invalid quantity specified in leg array. |
400 | 1311 | Unknown Venue | Invalid venue provided as part of request. |
400 | 1312 | Invalid price for instrument | You are unable to request a price for single-leg instrument RFQ. |
400 | 1313 | Quantity below minimum block size | Request RFQ below Exchange's set minimum block size. |
400 | 1314 | Maximum 60 counterparties allowed | More than 60 counterparties requested to be part of the RFQ. |
[POST]/rfq/cancel/
/rfq/cancel/ Request example
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/drfq/rfq/cancel/ \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const inputBody = `{"rfq_id": 0}`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/rfq/cancel/", {
method: "POST",
body: inputBody,
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
import json
from random import randint
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# POST /rfq/cancel/
method = 'POST'
path = '/v1/drfq/rfq/cancel/'
body = b''
client_order_id_random = randint(1, 1000000000)
# print('Client_Order_Id: {}'.format(client_order_id_random))
payload = {
"rfq_id": 22535
}
json_payload = json.dumps(payload).encode('utf-8')
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
message += json_payload
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(urljoin(host, path),
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("POST", "https://api.test.paradigm.co/v1/drfq/rfq/cancel/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [POST] /rfq/cancel/
request cancels an existing RFQ you created.
An /rfq/cancel/ request has the following workflow:
- The creator of an RFQ sends a /rfq/cancel/ request to Paradigm.
- Paradigm sends an /rfq/cancel/ response to the creator.
- If the /rfq/cancel/ request is valid, the RFQ object is returned to the creator.
- If the /rfq/cancel/ request is invalid, an Error object is returned to the creator.
- If the /rfq/cancel/ request is valid, Paradigm sends a Notification on the
quote
notification channel to the counterparties with active Quotes specifying that the Quotes are now canceled. - If the /rfq/cancel/ request is valid, Paradigm sends a Notification on the
rfq
notification channel to the RFQ counterparties and members of the user's desk specifying that the RFQ is now canceled.
/rfq/cancel/ Body parameter example
{
"rfq_id": 22535
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
body | body | object | Y | none |
rfq_id | body | number | Y | The rfq_id value created by Paradigm. |
/rfq/cancel/ Response example
200 Response
{
"created": 1611034695052.4731,
"desk": "DSK2",
"rfq_id": 22535,
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "641457979",
"legs": [
{
"instrument": "BTC-31DEC21-36000-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"status": "CANCELED",
"counterparties": ["DSK4", "DSK5"],
"updated": 1611034702624.0151
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
created | decimal | Y | None | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
desk | string | Y | None | The Paradigm Desk Name of the creator of the RFQ. |
rfq_id | number | Y | None | The RFQ unique identifier. This value is created by Paradigm. |
account | array | Y | None | An array of attributes related to the account which created the RFQ. |
> name | string | Y | None | The creator's Paradigm API Key name. |
> clearing_account_name | string | N | None | Only present if using "CME" as a venue. |
> trader_id | string | N | None | Only present if using "CME" as a venue. |
client_order_id | string | Y | None | Unique identifier created by user. |
legs | array of objects | Y | None | Array of objects containing the leg information of the RFQ. |
> instrument | string | Y | None | The leg's instrument name. |
> price | decimal | N | None | Price of leg if a hedge has been added. |
> quantity | decimal | Y | None | The number of contracts of the leg. |
> side | string | Y | None | The Direction of leg. Valid values include "BUY" and "SELL". |
> venue | string | Y | None | The Exchange the RFQ would have been executed on. |
status | string | Y | None | The status of the RFQ. Valid values include "ACTIVE", "CANCELED", and "FILLED". |
counterparties | [string] | Y | None | List of strings of the other counterparties involved in the RFQ. |
updated | decimal | Y | None | The time the RFQ was last updated in the number of milliseconds since epoch (January 1, 1970). |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | 1401 | Unknown rfq_id | Invalid rfq_id provided as part of request. |
400 | 1402 | Too late to cancel. | RFQ has already expired or been filled. |
[GET] /rfq/
/rfq/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/drfq/rfq/ \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const headers = {
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/rfq/", {
method: "GET",
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# GET /rfq/
method = 'GET'
path = '/v1/drfq/rfq/?venue=DBT&asset=BTC'
body = b''
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(urljoin(host, path),
headers=headers)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("GET", "https://api.test.paradigm.co/v1/drfq/rfq/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [GET] /rfq/
request returns the current state of RFQs that the user is a counterparty to (either as the creator or the receiver).
If the resulting returned list of RFQs is too large, it is divided into pages. Each request can return a single page.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
client_order_id | query | string | N | The client's unique identifier for the RFQ. |
cursor | query | string | N | The next or previous cursor from the paginated result set. |
rfq_id | query | string | N | Paradigm's unique identifier for the RFQ. |
status | query | string | N | The status of the RFQ. Values are "ACTIVE", "CANCELED", and "FILLED". |
/rfq/ Example response
200 Response
{
"count": 2441,
"next": "c12dEx=",
"results": [
{
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": "",
"counterparties": ["MSTL1", "DSK2", "DSK3", "DSK4", "DSK5"],
"created": 1608267227834.84,
"desk": "DSK1",
"fills": [],
"legs": [
{
"instrument": "BTC-18DEC20-13250-C",
"quantity": 25.0,
"side": "SELL",
"venue": "DBT"
},
{
"instrument": "BTC-19DEC20-21125-C",
"quantity": 25.0,
"side": "BUY",
"venue": "DBT"
}
],
"quotes": [
{
"desk": "DSK5",
"valid_until": null,
"created": 1608267227854.909,
"legs": [
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-18DEC20-13250-C",
"side": "SELL",
"venue": "DBT"
},
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-19DEC20-21125-C",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 25092,
"rfq_id": 18753,
"side": "SELL",
"status": "CANCELED"
},
{
"desk": "DSK4",
"valid_until": null,
"created": 1608267227869.377,
"legs": [
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-18DEC20-13250-C",
"side": "SELL",
"venue": "DBT"
},
{
"price": null,
"quantity": 25.0,
"instrument": "BTC-19DEC20-21125-C",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 25093,
"rfq_id": 18753,
"side": "SELL",
"status": "CANCELED"
}
]
}
]
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
count | number | Y | None | Number of available RFQs. |
next | string | Y | None | Cursor to use to retrieve the next page of results. Equal to "null" if there are no more pages. |
results | array of objects | Y | None | An array of objects of RFQs. |
> account | array | Y | None | Array of information about the creator of the RFQ. |
>> name | string | N | None | The venue API Key name. |
>> clearing_account_name | string | N | None | "CME" venue clearing account name. |
>> trader_id | string | N | None | "CME" venue trader_id value. |
> client_order_id | string | Y | None | Client created unique identifier. |
> counterparties | [string] | Y | None | Counterparties involved with the RFQ. |
> created | decimal | Y | None | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
> desk | string | N | None | Paradigm Desk name of the RFQ creator. |
> fills | array of objects | N | None | Array of objects of the fills. |
> legs | array of objects | Y | None | Array of objects containing the legs of the RFQ. |
>> instrument | string | Y | None | The leg's instrument name. |
>> quantity | decimal | Y | None | The size in contracts of the leg. |
>> side | string | Y | None | The Direction of the leg. Valid values include "BUY" and "SELL". |
>> venue | string | Y | None | Venue of RFQ. |
> quotes | array of objects | N | None | Array of objects containing the quotes provided for the RFQ. |
>> desk | string | N | None | Paradigm Desk name of the Quote creator. |
>> valid_until | decimal | Y | None | The time until the Quote expires in the number of milliseconds since epoch (January 1, 1970). |
>> created | decimal | Y | None | The time the Quote was created in the number of milliseconds since epoch (January 1, 1970). |
>> legs | array of objects | Y | None | An array of objects containing the Quotes of the individual legs. |
>>> instrument | string | Y | None | The leg's instrument name. |
>>> price | decimal | N | None | The price of the leg. |
>>> quantity | decimal | N | None | The size in contracts of the leg. |
>>> side | string | Y | None | The direction of the leg. Valid values include "BUY" and "SELL". |
>>> venue | string | Y | None | The venue the RFQ would be executed on. Valid values include "DBT", "CME", and "BIT". |
>> quote_id | integer | Y | None | The unique identifier of the quote. Paradigm determines this value. |
>> rfq_id | integer | Y | None | Unique of the RFQ determined by Paradigm. |
>> side | string | Y | None | Side being quoted. Valid values include "BUY" and "SELL". |
>> status | string | Y | None | The status of the Quote. Valid values are "ACTIVE", "CANCELED", "EXPIRED", "FILLED". |
> rfq_id | integer | Y | None | Unique of the RFQ determined by Paradigm. |
> status | string | Y | None | The status of the Quote. Valid values are "ACTIVE", "CANCELED", "EXPIRED", "FILLED", "TRD AWAY". |
> valid_until | decimal | N | None | The time until the RFQ expires in the number of milliseconds since epoch (January 1, 1970). |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | 2103 | Unavailable RFQ. | Unavailable RFQ. |
404 | Invalid cursor. | Invalid cursor value requested. |
[POST]/quote/create/
/quote/create/ Request examples
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/drfq/quote/create/ \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const inputBody = `{
"account": {
"name": "string",
"clearing_account_name": "string",
"trader_id": "string"
},
"client_order_id": "string",
"expires_in": 10,
"legs": [
{
"side": "BUY",
"instrument": "string",
"venue": "BIT",
"price": "string",
"quantity": "string"
}
],
"rfq_id": 0,
"side":"SELL"
}`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/quote/create/", {
method: "POST",
body: inputBody,
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
import json
from random import randint
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# POST /quote/create/
method = 'POST'
path = '/v1/drfq/quote/create/'
body = b''
client_order_id_random = randint(1, 1000000000)
# print('Client_Order_Id: {}'.format(client_order_id_random))
payload = {
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": client_order_id_random,
"expires_in": 60,
"legs": [
{
"price": 39450,
"quantity": 20000,
"instrument": "BTC-PERPETUAL",
"side": "BUY",
"venue": "DBT"
},
{
"price": 47000,
"quantity": 20000,
"instrument": "BTC-25JUN21",
"side": "SELL",
"venue": "DBT"
}
],
"rfq_id": 22539,
"side":"SELL"
}
json_payload = json.dumps(payload).encode('utf-8')
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
message += json_payload
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(urljoin(host, path),
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("POST", "https://api.test.paradigm.co/v1/drfq/quote/create/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [POST] /quote/create/
request allows you to Quote an RFQ you are a counterparty to.
A Quote represents a single side of the trade, either the "BUY" or "SELL", specified by the top-level "side" field.
To quote both sides of an RFQ, two quotes would need to be created, each with its own unique "client_order_id".
A /quote/create/ request has the following workflow:
- The receiver of an RFQ sends a /quote/create/ request to Paradigm.
- Paradigm sends a /quote/create/ response to the RFQ receiver.
- If the /quote/create/ request is valid, the Quote object is returned to the RFQ receiver.
- If the /quote/create/ request is invalid, an Error object is returned to the RFQ receiver.
- If the /quote/create/ request is valid, Paradigm sends a Notification on the
quote
JSON-RPCoverWebSockets Notification channel to the creator of the RFQ and other members of the user's desk specifying a new response to the RFQ.
Important Notes:
- You must quote the entire RFQ and not part of the legs or only part of the quantity.
- If a Future Hedge Leg is included as apart of the RFQ you must price the Future leg with the provided price in the RFQ.
/quote/create/ Body parameter example
{
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": "123",
"expires_in": "60",
"legs": [
{
"price": 39450,
"quantity": 20000,
"instrument": "BTC-PERPETUAL",
"side": "BUY",
"venue": "DBT"
}
],
"rfq_id": 22539,
"side": "SELL"
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
account | body | object | Y | Paradigm Account information of Quote creator. |
> name | body | string | Y | The Name of Paradigm API Key. |
> clearing_account_name | body | string | N | Required if venue is "CME". |
> trader_id | body | string | N | Required if venue is "CME". |
client_order_id | body | string | Y | Client determined unique identifier. |
expires_in | body | integer | Y | Number of seconds quote is available for. Valid values between 10-120. |
legs | body | array of objects | Y | An array of objects of each leg of the RFQ. |
> price | body | decimal | Y | The price of the leg. |
> quantity | body | decimal | Y | The size of the leg in contracts. |
> instrument | body | string | Y | The leg's instrument name. |
> side | body | string | Y | Direction of the leg. Valid values include "BUY" and "SELL". |
> venue | body | string | Y | Venue of the RFQ. Valid values include "DBT", "BIT", "CME". |
rfq_id | body | integer | Y | Unique identifier of RFQ. Paradigm determines this value. |
side | body | string | Y | Side being quoted. Valid values include "BUY" and "SELL". |
/quote/create/ Example response
200 Response
{
"desk": "DSK1",
"valid_until": 1611038442838.6272,
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": "49826055",
"created": 1611038342698.2578,
"legs": [
{
"price": 39450.0,
"quantity": 20000.0,
"instrument": "BTC-PERPETUAL",
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84069,
"rfq_id": 22537,
"side": "SELL",
"status": "ACTIVE"
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
desk | string | Y | None | The Paradigm Desk name of the Quote creator. |
valid_until | decimal | Y | None | The time the Quote is valid until in the number of milliseconds since epoch (January 1, 1970). |
account | object | Y | None | An object of account information about the creator of the Quote. |
> name | string | Y | None | The Name of the Paradigm API Key. |
> clearing_account_name | string | N | None | Account identifier if venue is "CME". |
> trader_id | string | N | None | Account identifier if venue is "CME". |
client_order_id | string | Y | None | Client determined unique identifier. |
created | decimal | Y | None | The time the Quote was created in the number of milliseconds since epoch (January 1, 1970). |
expires_in | integer | N | None | Maximum number of seconds the Quote is available for. |
legs | array of objects | Y | None | An array of objects of the legs of the Quote. |
> instrument | string | Y | None | The leg's instrument name. |
> price | decimal | N | None | The price of the leg. |
> quantity | decimal | N | None | The number of contracts of the leg. |
> side | string | Y | None | Direction of the quoted leg. |
> venue | string | Y | None | Venue of the RFQ. |
rfq_id | integer | Y | None | Unique identifier of the RFQ. Paradigm determines this value. |
quote_id | integer | Y | None | Unique identifier of the Quote. Paradigm determines this value. |
side | string | Y | None | Side being quoted. Valid values include "BUY" and "SELL". |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | 1 | Invalid desk product configuration | Likely expires_in band outside of values set in your admin dashboard or missing key from payload in request. Leg Prices can also not be negative. Bid can also not be greater than offer. |
400 | 1302 | Invalid account information | Invalid account information provided in request. |
400 | 2101 | Duplicate client_order_id | Duplicate client_order_id provided in request. |
400 | 2102 | Unknown rfq_id | Incorrect or missing rfq_id key from request. |
400 | 2103 | Unavailable RFQ | RFQ is unavailable to be quoted upon. The RFQ is likely expired, filled or traded away. |
400 | 2104 | Invalid leg parameters | Invalid payload provided in request. Likely wrong key value. |
400 | 2105 | Cannot change fixed leg price | Hedge leg price must be the same as in the RFQ. |
400 | 2106 | Must specify bid or offer | Please provide a price in the request. |
400 | 2107 | Invalid quote parameters | Invalid /quote/create request. |
400 | 2109 | This RFQ already has an active quote for that side. Please cancel it before re-quoting. | There is an ACTIVE existing quote for this side of the RFQ. |
403 | Maker Execution Limit Reached. | MMP has been triggered and the user must [PATCH] /v1/mmp/status to reset the protection to be able to quote. |
[POST]/quote/cancel/
/quote/cancel/ Request example
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/drfq/quote/cancel/ \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const inputBody = `{"quote_id": 0}`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/quote/cancel/", {
method: "POST",
body: inputBody,
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
import json
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# POST /quote/cancel/
method = 'POST'
path = '/v1/drfq/quote/cancel/'
body = b''
payload = {
"quote_id": 84063
}
json_payload = json.dumps(payload).encode('utf-8')
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
message += json_payload
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(urljoin(host, path),
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("POST", "https://api.test.paradigm.co/v1/drfq/quote/cancel/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [POST] /quote/cancel/
request cancels an existing Quote you have created upon an RFQ.
A /quote/cancel/ request has the following workflow:
- The creator of the quote sends a /quote/cancel/ request to Paradigm.
- Paradigm sends a /quote/cancel/ response to the creator.
- If the /quote/cancel/ request is valid, the Quote object is returned to the creator.
- If the /quote/cancel/ request is invalid, an Error object is returned to the creator.
- If the /quote/cancel/ request is valid, Paradigm sends a Notification on the
quote
JSON-RPCoverWebSockets Notifications channel to the creator of the RFQ and other members of the creator's desk specifying the quote is no longer available.
/quote/cancel/ Body parameter
{
"quote_id": 2156
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
body | body | object | true | |
quote_id | body | integer | Y | The quote_id of the already provided quote. |
/quote/cancel/ Response Example
200 Response
{
"desk": "DSK1",
"valid_until": null,
"account": {
"name": "ParadigmTestOne"
},
"client_order_id": "613310893",
"created": 1611038225971.4749,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": null,
"quantity": 20000.0,
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84063,
"rfq_id": 22537,
"side": "SELL",
"status": "CANCELED",
"updated": 1611038331810.966
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
desk | string | Y | None | The desk name of the Quote creator. |
valid_until | decimal or null | Y | None | null if the quote has been successfully canceled. |
account | object | Y | None | An object of the Quote creator's account information. |
> name | string | Y | None | The Paradigm API Key name. |
> clearing_account_name | string | N | None | Account information if venue is "CME". |
> trader_id | string | N | None | Account information if venue is "CME". |
client_order_id | string | Y | None | User determined unique identifier. |
created | decimal | Y | None | The time the Quote was created in the number of milliseconds since epoch (January 1, 1970). |
legs | array of objects | Y | None | An array of objects of the legs of the Quote. |
> instrument | string | Y | None | The leg's instrument name. |
> price | decimal | N | None | The price of the leg. |
> quantity | decimal | N | None | The contract size of the leg. |
> side | string | Y | None | The Direction of the leg. |
> venue | string | Y | None | The Venue of the RFQ. |
quote_id | integer | Y | None | Unique identifier of the Quote. Paradigm determines this value. |
rfq_id | integer | Y | None | Unique identifier of RFQ. Paradigm determines this value. |
side | string | Y | None | Side being quoted. Valid values include "BUY" and "SELL". |
status | string | Y | None | Status of the Quote. |
updated | decimal | Y | None | The time the Quote is was last updated in the number of milliseconds since epoch (January 1, 1970). |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | 2201 | Unknown quote_id | Unknown quote_id. |
400 | 2202 | Too late to cancel | Quote is expired, filled, or does not exist. |
[POST]/quote/execute/
/quote/execute/ Request example
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/drfq/quote/execute/ \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer ACCESS_KEY'
const inputBody = `{
"rfq_id": 0,
"legs": [
{
"price": "string",
"quantity": "string",
}
],
"quote_id": 0
}`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: "Bearer ACCESS_KEY",
};
fetch("https://api.test.paradigm.co/v1/drfq/quote/execute/", {
method: "POST",
body: inputBody,
headers: headers,
})
.then(function (res) {
return res.json();
})
.then(function (body) {
console.log(body);
});
# built ins
import base64
import hmac
import time
from urllib.parse import urljoin
import json
# installed
import requests
access_key = '<access-key>'
secret_key = '<secret-key>'
signing_key = base64.b64decode(secret_key)
print('Paradigm Account Access Key: {}'.format(access_key))
print('Paradigm Account Secret Key: {}'.format(signing_key))
# Request Body
host = 'https://api.test.paradigm.co'
# POST /quote/execute/
method = 'POST'
path = '/v1/drfq/quote/execute/'
body = b''
payload = {
"rfq_id": 22540,
"legs": [
{
"price": "38226.8",
"quantity": "20000",
}
],
"quote_id": 84073
}
json_payload = json.dumps(payload).encode('utf-8')
message = method.encode('utf-8') + b'\n'
message += path.encode('utf-8') + b'\n'
message += json_payload
timestamp = str(int(time.time() * 1000))
message = timestamp.encode('utf-8') + b'\n' + message
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(urljoin(host, path),
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
package main
import (
"bytes"
"net/https"
)
func main() {
headers := map[string][]string{
"Content-Type": []string{"application/json"},
"Accept": []string{"application/json"},
"Authorization": []string{"Bearer ACCESS_KEY"},
}
data := bytes.NewBuffer([]byte{jsonReq})
req, err := https.NewRequest("POST", "https://api.test.paradigm.co/v1/drfq/quote/execute/", data)
req.Header = headers
client := &https.Client{}
resp, err := client.Do(req)
// ...
}
A [POST] /quote/execute/
request executes a Quote. It is only used by the creator of the RFQ, the Taker.
A /quote/execute/ request has the following workflow:
- The creator of the RFQ sends a /quote/execute/ request to Paradigm.
- Paradigm sends a /quote/execute/ response to the creator.
- If the /quote/execute/ request is valid, the RFQ object is returned to the creator.
- If the /quote/execute/ response is invalid, an Error object is returned to the creator. A /quote/execute/ request is invalid if the RFQ or Quote has already expired or been canceled.
- If the /quote/execute/ request is valid, Paradigm sends a Notification on the
quote
JSON-RPCoverWebSocket Notification channel to the creator of the RFQ and the creator of the Quote specifying that a fill is pending.- If the exchange confirms the trade, another Notification on the
quote
channel is sent to all parties listed above that the Trade has been completed and the Quote is filled. - If the exchange rejects the trade, another Notification on the
quote
channel is sent to all parties listed above that the Trade could not be executed and the Quote is rejected. A Trade is all or nothing and a rejection of one leg of the trade will cause the rejection of all legs.
- If the exchange confirms the trade, another Notification on the
- If the Trade has been confirmed, Paradigm sends a Notification on the
quote
JSON-RPCoverWebSocket Notification channel to other desks that responded to the quote specifying that the quote has been canceled. - If the Trade has been confirmed, Paradigm sends a Notification on the
rfq
JSON-RPCoverWebSocket Notification channel to all RFQ counterparties specifying that the rfq has been filled.
Important Notes:
- We will follow the convention from the Maker's (dealer's) perspective regarding which
quote
for the Taker to execute. - As the Taker if you wish to "BUY" the RFQ'd structure, you should execute upon the received Quote which has the
side
key with the property "SELL". - Following this, if as the Taker you wish to "SELL" the RFQ'd structure, you should execute upon the received Quote which has the
side
key with the property "BUY". - Takers are only able to execute upon the best priced quote they receive. After you execute upon a quote, Paradigm checks to ensure the quote is the best available quote. It is critically important you only assume a Trade is completed after you receive confirmation over the
trade
andtrade_confirmation
WebSocket Notification channels. - Takers are only able to execute two times every five seconds due to Paradigm's Market Maker Protection feature.
/quote/execute/ Body parameter example
{
"rfq_id": 22540,
"legs": [
{
"price": "38226.8",
"quantity": "20000"
}
],
"quote_id": 84073
}
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
rfq_id | body | integer | Y | Unique Identifier of the RFQ. Paradigm determines this value. |
legs | body | array of objects | Y | An array of objects of the legs. |
> price | body | decimal | Y | The Price of the leg. |
> quantity | body | decimal | Y | The Size of the leg. |
quote_id | body | integer | Y | Unique Identifier of Quote. Paradigm determines this value. |
/quote/execute/ Response example
200 Response
{
"account": {
"name": "ParadigmTestTwo"
},
"client_order_id": "838781960",
"counterparties": ["DSK1", "DSK4", "DSK5"],
"created": 1611038577702.458,
"desk": "DSK2",
"fills": [
{
"created": 1611038629260.88,
"legs": [
{
"price": 38226.8,
"quantity": 20000.0,
"side": "BUY"
}
],
"quote_id": 84073,
"rfq_id": 22540,
"desk": "DSK1"
}
],
"legs": [
{
"instrument": "BTC-PERPETUAL",
"quantity": 20000.0,
"side": "BUY",
"venue": "DBT"
}
],
"quotes": [
{
"desk": "DSK1",
"valid_until": 1611038679969.7102,
"created": 1611038577707.4758,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": 37469.84,
"quantity": 20000.0,
"side": "BUY",
"venue": "DBT"
}
],
"quote_id": 84073,
"rfq_id": 22540,
"side": "SELL",
"status": "PENDING_FILL"
}
],
"rfq_id": 22540,
"status": "PENDING_FILL",
"valid_until": 1611038697689.463
}
Response Schema
Status Code 200
Name | Type | Required | Restrictions | Description |
---|---|---|---|---|
account | object | Y | None | |
> name | string | Y | None | The Name of Paradigm API Key. |
> clearing_account_name | string | N | None | Required if venue is "CME". |
> trader_id | string | N | None | Required if venue is "CME". |
client_order_id | string | Y | None | Client determined unique identifier. |
counterparties | [string] | Y | None | List of strings of counterparties involved in the RFQ. |
created | decimal | Y | None | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
desk | string | Y | None | The desk name of the creator of the RFQ. |
fills | array of objects | Y | None | An array of the fills of the RFQ. |
>created | decimal | Y | None | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
>legs | array of objects | Y | None | An array of objects of the RFQ that were filled. |
>> price | decimal | Y | None | The price of the filled leg. |
>> quantity | decimal | Y | None | The size of the filled leg. |
>> side | string | Y | None | The direction of the leg. |
>quote_id | integer | Y | None | The unique identifier of the Quote of the Filled leg. |
>rfq_id | integer | Y | None | The unique identifier of the RFQ. |
>desk | string | Y | None | The desk name of the creator of the RFQ. |
legs | array of objects | Y | None | An array of objects the legs of the RFQ. |
>instrument | string | Y | None | The leg's instrument name. |
>quantity | decimal | Y | None | The size in contracts of the leg. |
>side | string | Y | None | The direction of the leg. |
>venue | string | Y | None | The venue the RFQ is executed on. |
quotes | array of objects | Y | None | An array of the Quotes of the RFQ. |
>desk | string | Y | None | The desk name of the creator of the RFQ. |
>valid_until | decimal | Y | None | The time the RFQ is valid until in the number of milliseconds since epoch (January 1, 1970). |
>created | decimal | Y | None | The time the RFQ was created in the number of milliseconds since epoch (January 1, 1970). |
>legs | array of objects | Y | None | An array of objects of the legs of the Quote. |
>>instrument | string | Y | None | The leg's instrument name. |
>>price | decimal | Y | None | The price of the leg. |
>>quantity | decimal | Y | None | The size of the leg. |
>>side | string | Y | None | The direction of the leg. |
>>venue | string | Y | None | The venue the RFQ is executed on. |
>quote_id | integer | Y | None | The unique identifier of the Quote. |
>rfq_id | integer | Y | None | The unique identifier of the RFQ. |
>status | string | Y | None | The status of the Quote. |
rfq_id | integer | Y | None | Unique Identifier of the RFQ. |
side | string | Y | None | Side being quoted. Valid values include "BUY" and "SELL". |
status | string | Y | None | The status of the RFQ. |
valid_until | decimal | Y | None | The time the RFQ is valid until in the number of milliseconds since epoch (January 1, 1970). |
Error Codes
HTTP Status Code | Paradigm Code | Message | Meaning |
---|---|---|---|
400 | RFQ doesn't have a quote for this side of the trade. | Or RFQ has been canceled, expired. | |
400 | 2104 | Invalid leg parameters | Provided payload is missing or contains incorrect values. |
400 | 2201 | Unknown quote_id | Unknown quote_id value. |
400 | 2205 | Unable to execute an expired quote | Quote has expired. |
400 | 2302 | Invalid leg price | Leg price in payload must match quote provided. |
[GET] /mmp/status/
/mmp/status/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/drfq/mmp/status/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/drfq/mmp/status/
method = 'GET'
path = '/v1/drfq/mmp/status/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/mmp/status/ Response example
{
"rate_limit_hit": false
}
A [GET] /mmp/status/
request returns the desk's Market Maker Protection (MMP) status.
This endpoint takes no parameters as part of the request.
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
rate_limit_hit | bool | true | A flag indicating if rate limit was hit |
[PATCH] /mmp/status/
/mmp/status/ Request example
# You can also use wget
curl -X PATCH https://api.test.paradigm.co/v1/drfq/mmp/status/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# PATCH /v1/drfq/mmp/status/
method = 'PATCH'
path = '/v1/drfq/mmp/status/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.patch(host+path,
headers=headers)
print(response.status_code)
print(response.text)
A [PATCH] /mmp/status/
resets the Market Maker Protection (MMP) if triggered and enables the user to create new Quotes.
This endpoint takes no parameters as part of the request.
Response Schema
This request will return an HTTP Status Code of 204 to indicate success of operation.
Status Code 204
GRFQ - API Workflows
Paradigm operates Auto-Market Makers running on our Test environment. All available and created RFQs will have markets made upon them.
High Level
GRFQ is centred around the concepts of "RFQs", "Quotes", "Orders" and "Trades":
- RFQs are globally and publicly available strategies comprised of one or more instruments with specific quantity ratio attributes.
- Quotes are created by Takers and Makers as Quotes upon the Quote Book.
- Orders are created by Takers to execute upon existing Quotes.
- Trades occur when Orders (from Takers) and Quotes (from Makers) are matched and sent for clearing & settlement.
At a high level, the GRFQ workflow is:
- Taker creates an RFQ with the desired Instruments and quantity ratios.
- Makers Quote the RFQ.
- Takers can execute an Order upon an RFQ and consume Quotes which suit the set Limit Price & venue enforced "Block Size Minimums".
- Once a Quote and an Order are matched, the executions are sent to the underlying venue for clearing & settlement.
- Taker and Maker of the trade receive confirmation if clearing & settlement was successful or rejected.
- All Paradigm users are able to see cleared & settled Trades, but NOT the counterparties or the traded RFQ/Order/Quote
side
.
Key GRFQ Concepts
In GRFQ,
- RFQs are public auctions and all have open Quote Books.
- You do NOT select counterparties, anyone is able to contribute/execute upon the Quote Book.
- All trades are on an anonymous basis with no participant or directional information revealed.
- All resulting executions are subject to some venues' determined "Block Size Minimum". Paradigm will enforce this validation at the Quote & Order Execution level.
- There are partials fills of both Quotes and Orders.
- It is possible to have multiple trades where a number of Quotes are consumed by a single Order.
- WebSocket messages will contain two keys,
kind
andstatus
. You should use these keys to know the status and finality of the concept it's referring too.
Common Workflows
Important Note: Both the Taker and the Maker will receive all updates through the JSON-RPCoverWebSockets Notification channels for events relating to RFQs, Quotes, Orders and Trades.
A user is only a Maker where their Quote is executed upon by an Order. A user is only a Taker if they submit an Order which crosses an existing Quote.
Create/Check for RFQ
If you would like to create an RFQ or check if one exists, you should request the RESToverHTTP [POST] /rfqs/
endpoint.
Pull available Quotes on an RFQ
Each RFQ is composed of Quotes. Quotes are NOT aggregated by Price levels as is usual in centralized Quote Book.
Makers submit Quotes on RFQs and Paradigm returns them individually to all users as children of the RFQ primarily because of workflow complications relating to some venues' "Block Size Minimum" rules.
You should request the RESToverHTTP [GET] /quotes/
endpoint.
Submit a non-crossing Quote on an RFQ
Users are NOT able to submit Quotes which cross an existing resting Quote on an RFQ.
You should request the RESToverHTTP [POST] /rfqs/{rfq_id}/quotes/
endpoint.
Submit a crossing Quote/execute upon a Quote with an Order
Users are able to submit a Quote which crosses an existing Quote on an RFQ.
You should request the RESToverHTTP [POST] /rfqs/{rfq_id}/quotes/
.
Replace an existing Quote on an RFQ
Users are able to replace a previously submitted Quote for an existing RFQ.
You should request the RESToverHTTP [PUT] /rfqs/{rfq_id}/quotes/{quote_id}
endpoint.
Cancel a requested Order on an RFQ
Takers are not able to cancel a requested Order. You will receive a successful/erroneous response from the RESToverHTTP [POST] /rfqs/{rfq_id}/orders/
request with information regarding the outcome.
Executable Quote Book
RFQs are comprised of individual Quotes which are not aggregated by price level as is usual with standard centralized Quote Books. This was principally done to accommodate venue created & enforced "Block Size Minimums".
Not all venues have "Block Size Minimums", most notably Bybit, but the workflows for ranking+aggregating what is actually executable is the same for all venues with GRFQ.
So as the user, you are likely to have the following questions:
- Q: "What's the priority of Quotes as part of an RFQ?"
- A: Paradigm prioritises Quotes based upon Price & Time priority. This is the same prioritization mechanism as centralized Quote Books.
- Q: "How does the Block Size Minimum affect what I can execute?"
- A: As Paradigm must conform to the venue enforced Block Size Minimum, so too must you. This means a number of things:
- All Quotes must meet the Block Size Minimum Quantity requirement.
- All Orders must meet the Block Size Minimum Quantity requirement.
- Paradigm will consume multiple Quotes as part of a single Order Execution. If part of a Quote is consumed and the remaining quantity is below the Block Size Minimum, this Quote will be canceled.
- Orders will consume Quotes up to the specified Limit Price, but may not be able to execute the complete requested quantity.
Workflow to create+manage your Quote Book
- Subscribe to the
quote_book
JSON-RPCoverWebSockets Notification Channel to receive updates relating to Quotes upon RFQs. - Request the RESToverHTTP [GET]
/quotes/
endpoint to return all existing Quotes on RFQs. - ADD/REMOVE/UPDATE your locally stored Quotes as updates are received through the
quote_book
WS Channel.
Workflow to create+manage your Executable Quote Book:
- Subscribe to the
quote_book
JSON-RPCoverWebSockets Notification Channel to receive updates relating to Quotes upon RFQs. - Request the RESToverHTTP [GET]
/quotes/
endpoint to return all existing Quotes on RFQs. - ADD/REMOVE/UPDATE your locally stored Quotes as updates are received through the
quote_book
WS Channel. - Determine the Block Size Minimum requirement for the RFQ you are trading upon. This will be the minimum executable quantity.
- For Deribit, this is 25BTC for BTC Options RFQs and $200kUSD for Futures RFQs.
- For Bybit, this is $1USD for Futures RFQs.
- Create levels in your Executable Quote Book by the Block Size minimum quantity size to ascertain the size & price levels.
Helpful perspectives:
- GRFQ is fantastic if you want to trade large size and have a target price in mind. The ability to submit "Limit Orders" as either resting Quotes or Orders with a limit price enables this.
- Thinking in terms of size & price levels is the best way.
- When you submit an Order, Paradigm, depending on the size of your Order and the Quote Book at the time, will likely consume multiple Quotes. This means you will have to wait for multiple trades to clear on the underlying venue.
Comprehensive API Workflow Paths
RFQ Created
Taker's & Maker's Perspective:
- Subscribed to
rfq
WS Channel. - Receives WS message with
kind
==ADDED
,status
==ACTIVE
.
RFQ Expires
Taker's & Maker's Perspective:
- Subscribed to
rfq
WS Channel. - Receives WS message with
kind
==REMOVED
,status
==EXPIRED
.
Quote Created
Taker's & Maker's Perspective:
- Subscribed to the
quote
andquote_book
WS Channels. - Asynchronously:
- Receives WS messages on
quote_book
WS Channel withkind
==ADDED
andstatus
==OPEN
. - Maker only, receives WS messages on
quote
WS Channel withkind
==NEW
andstatus
==OPEN
.
- Receives WS messages on
Quote Canceled
Taker's & Maker's Perspective:
- Subscribed to the
quote
andquote_book
WS Channels. - Asynchronously:
- Receives WS messages on
quote_book
WS Channel withkind
==REMOVED
andstatus
==CLOSED
. - Maker only, receives WS messages on
quote
WS Channel withkind
==CANCELED
andstatus
==CLOSED
.
- Receives WS messages on
Matched Quote and Order
Taker's Perspective:
- Subscribed to
quote_book
,order
,trade
andtrade_tape
WS Channels. - Asynchronously:
- Receives a single WS message on
order
WS Channel withkind
==PENDING_FILL
andstatus
==OPEN
. - Receives a WS message on the
quote_book
WS Channel:- If Quote is completely consumed
kind
==REMOVED
. - If Quote is partially consumed
kind
==UPDATED
.
- If Quote is completely consumed
- Receives a single WS message on
- Asynchronously:
- If Trade execution is successful at clearing & settlement:
- Receives WS messages on
trade
WS channel withkind
==CONFIRMATION
for each successful trade execution as part of the Order. - Receives WS messages on
trade_tape
WS channel withkind
==COMPLETED
for each successful trade execution through Paradigm.
- Receives WS messages on
- If Trade execution is rejected at clearing & settlement:
- Receives WS messages on
trade
WS channel withkind
==REJECTION
for each rejected trade execution as part of the Order.
- Receives WS messages on
- In the event of Successful/Rejected executions at clearing & settlement:
- Receives WS messages on
order
on WS channel withkind
==SUMMARY
andstatus
==CLOSED
.
- Receives WS messages on
- If Trade execution is successful at clearing & settlement:
Maker's Perspective:
- Subscribed to
quote_book
,quote
,trade
andtrade_tape
WS Channels. - Asynchronously:
- Receives a single WS message on
quote
WS Channel:- If Quote is completely consumed
kind
==PENDING_FILL
andstatus
==CLOSED
. - Also occurs if the Remaining Quantity is below the venue's enforced "Block Size Minimum".
- If Quote is partially consumed
kind
==PENDING_FILL
andstatus
==OPEN
.
- If Quote is completely consumed
- Receives a WS message on the
quote_book
WS Channel:- If Quote is completely consumed
kind
==REMOVED
. - If Quote is partially consumed
kind
==UPDATED
.
- If Quote is completely consumed
- Receives a single WS message on
- Asynchronously:
- If Trade execution is successful at clearing & settlement:
- Receives WS messages on
trade
WS channel withkind
==CONFIRMATION
for each successful trade execution as part of the Order. - Receives WS messages on
trade_tape
WS channel withkind
==COMPLETED
for each successful trade execution through Paradigm. - If a Quote is only partially consumed at execution, meaning there is remaining available quantity:
- Receives a WS message on the
quote
WS Channel withkind
==PARTIALLY_FILLED
andstatus
==OPEN
. - If a Quote is only completely consumed at execution, meaning there is NO remaining available quantity:
- Receives a WS message on the
quote
WS Channel withkind
==FILLED
andstatus
==OPEN
.
- Receives WS messages on
- If Trade execution is rejected at clearing & settlement:
- Receives WS messages on
trade
WS channel withkind
==REJECTION
for each rejected trade execution as part of the Order. - Receives a WS message on the
quote
WS Channel withkind
==CANCELED
andstatus
==CLOSED
.
- Receives WS messages on
- If Trade execution is successful at clearing & settlement:
GRFQ - Code Examples
Reach out if you ever need any help! We are more than happy to help.
You will need to update the provided Code Examples with your own Paradigm Access Key and Secret Key.
You can find all existing examples on our GitHub: https://github.com/tradeparadigm/code-samples
Note: All examples in this section are in Python3.
JSON-RPCoverWebSockets
Authentication + Subscribe & Unsubscribe to Notification Channels
- Authenticate, establish a heartbeat and Subscribe to the
rfq
,quote_book
,quote
,order
,trade
, andtrade_tape
JSON-RPCoverWebSockets Notification Channels.
GRFQ - WebSocket Notifications Channels
rfq
An example of the
rfq
notification received when an RFQ is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"kind": "ADDED",
"rfq": {
"id": 1232,
"created": 1628038165427.771,
"description": "Call 4 Aug 21 39000",
"last_trade": null,
"latest_activity": 1628038165427.839,
"product_codes": ["DO"],
"status": "ACTIVE",
"venue": "DBT",
"legs": [
{
"instrument": "BTC-4AUG21-39000-C",
"product_code": "DO",
"ratio": "1",
"venue_instrument": "BTC-4AUG21-39000-C",
"side": "BUY"
}
]
}
}
}
}
An example of the
rfq
notification received when an RFQ expires
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"kind": "REMOVED",
"rfq": {
"id": 589,
"venue": "DBT",
"created": 1625191497588.2312,
"description": "FSpd 2 Jul 21 / 25 Mar 22",
"last_trade": null,
"latest_activity": 1625191497588.316,
"legs": [
{
"instrument": "BTC-2JUL21",
"venue_instrument": "BTC-2JUL21",
"product_code": "CF",
"ratio": "1",
"side": "SELL"
},
{
"instrument": "BTC-25MAR22",
"venue_instrument": "BTC-25MAR22",
"product_code": "CF",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["CF"],
"status": "EXPIRED"
}
}
}
}
All updates relating to RFQs are sent through the rfq
WebSocket Notifications channel.
This is a public channel and consumable by all.
Notifications received through the rfq
WebSocket channel can include RFQ creations, expirations, and updates. Updates are used to update the latest_activity
and last_trade
fields while the rfq
is active.
Member | Type | Required | Description |
---|---|---|---|
channel | string | true | WebSocket Notification Channel message is received upon. Valid value is rfq . |
data | object | true | |
> kind | string | true | WS Action. Valid values include ADDED , REMOVED , UPDATED . |
> rfq | object | true | |
>> id | int | true | The Paradigm created unique identifier of the RFQ. |
>> venue | string | true | The underlying venue the RFQ is cleared & settled upon. Valid values include DBT , BIT , and BYB . |
>> created | number | true | Time in unix milliseconds since the epoch when the RFQ was created. |
>> description | string | true | Paradigm created description of the RFQ. |
>> last_trade | object | true | null if RFQ has not been traded. |
>>> traded | number | false | Time in unix milliseconds since the epoch when the the Trade occurred. |
>>> quantity | string | false | The size of the trade in the contract units of the RFQ. |
>>> price | string | false | The price the RFQ was Traded at. |
>> latest_activity | number | true | Time in unix milliseconds since the epoch when the RFQ was last acted upon. |
>> legs | array of objects | true | |
>>> instrument | string | true | The Paradigm standardized name of the Instrument. |
>>> venue_instrument | string | true | The name of the Instrument per the underlying venue's naming convention. |
>>> product_code | string | true | The Paradigm created product code of the Instrument. |
>>> ratio | string | true | The quantity multiple relative to other legs. |
>>> price | string | false | The price of the Instrument in the Quote Currency of the RFQ. |
>>> side | string | true | The direction of the leg. Valid values include BUY and SELL . |
>> product_codes | array of strings | true | Paradigm created product codes being traded in the RFQ. |
>> status | string | true | Status of the RFQ. Valid values include ACTIVE and EXPIRED . |
quote_book
An example of the
quote_book
notification received when a Quote is newly added to the Quote Book
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote_book",
"data": {
"kind": "ADDED",
"quote": {
"remaining_quantity": "20000",
"side": "BUY",
"rfq_id": 816,
"id": 482396,
"price": "-9",
"status": "OPEN",
"created": 1626155549137.585
}
}
}
}
An example of the
quote_book
notification received when a Quote is removed from the Quote Book
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote_book",
"data": {
"kind": "REMOVED",
"quote": {
"id": 482395,
"side": "SELL",
"created": 1626155407461.441,
"rfq_id": 816,
"status": "CLOSED",
"price": "-13",
"remaining_quantity": "20000"
}
}
}
}
An example of the
quote_book
notification received when a Quote is updated in the Quote Book
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote_book",
"data": {
"kind": "UPDATED",
"quote": {
"remaining_quantity": "1990000",
"side": "SELL",
"rfq_id": 816,
"id": 482399,
"price": "9",
"status": "OPEN",
"created": 1626155762785.2932
}
}
}
}
Updates relating to Quotes upon RFQs are sent through the quote_book
WebSocket Notifications channel.
This is a public channel and is consumable by all. This is the channel you should use to create your own Quote Book & Executable Quote Book.
Updates received through the quote_book
WebSocket Notification channel can include newly created quotes, removed quotes as well as updates to existing Quotes.
Member | Type | Required | Description |
---|---|---|---|
channel | string | true | WebSocket Notification Channel message is received upon. |
data | object | true | |
> kind | string | true | The action of the message. Valid values include ADDED , REMOVED , UPDATED . |
> quote | object | true | |
> side | string | true | The side of the Quote from the Maker's perspective. Valid values include BUY and SELL . |
> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
> id | int | true | The Paradigm created unique identifier of the Quote. |
> price | string | true | The price in the Quote Currency of the RFQ. |
> status | string | true | The status of the Quote. Valid values include OPEN , CLOSED . |
> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
> remaining_quantity | string | true | The remaining Quantity upon the Quote in contract units of the RFQ. |
quote
An example of the
quote
notification received when a Quote is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "NEW",
"quote": {
"id": 709037,
"status": "OPEN",
"maker": "DSK95",
"created": 1628041444199.396,
"original_quantity": "50",
"rfq_id": 1232,
"price": "0.004",
"remaining_quantity": "50",
"side": "BUY",
"client_order_id": ""
}
}
}
}
An example of the
quote
notification received when a Quote is canceled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "CANCELED",
"quote": {
"id": 2776215,
"order": {
"id": 266357,
"client_order_id": "st121221",
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "0.06",
"requested_quantity": "50",
"rfq_id": 2073,
"side": "SELL",
"status": "OPEN",
"venue": "DBT"
},
"status": "CLOSED",
"maker": "DSK95",
"remaining_quantity": "22",
"side": "SELL",
"created": 1631590685753.57,
"original_quantity": "22",
"client_order_id": "st12122",
"rfq_id": 2073,
"price": "0.06"
}
}
}
}
An example of the
quote
notification received when a Quote is being executed upon
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "PENDING_FILL",
"quote": {
"original_quantity": "34",
"order": {
"id": 266376,
"client_order_id": "st12122121",
"filled_quantity": "26",
"filled_average_price": "0.0904",
"limit_price": "0.1",
"requested_quantity": "60",
"rfq_id": 2073,
"side": "BUY",
"status": "CLOSED",
"venue": "DBT"
},
"id": 2776296,
"side": "BUY",
"price": "0.1",
"rfq_id": 2073,
"created": 1631591051681.613,
"status": "OPEN",
"client_order_id": "st121221",
"remaining_quantity": "7",
"maker": "DSK95"
}
}
}
}
An example of the
quote
notification received when a Quote has been partially filled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "PARTIALLY_FILLED",
"quote": {
"rfq_id": 816,
"id": 482399,
"remaining_quantity": "1990000",
"status": "OPEN",
"client_order_id": "",
"price": "9",
"side": "SELL",
"created": 1626155762785.2932,
"maker": "DSK95",
"original_quantity": "2000000"
}
}
}
}
An example of the
quote
notification received when a Quote has been partially filled & is partially executed again
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "PENDING_FILL",
"quote": {
"maker": "DSK95",
"rfq_id": 816,
"client_order_id": "",
"price": "-13",
"side": "SELL",
"id": 482407,
"created": 1626156440976.632,
"status": "OPEN",
"original_quantity": "50000",
"remaining_quantity": "20000"
}
}
}
}
An example of the
quote
notification received when a Quote has been completely executed upon
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "PARTIALLY_FILLED",
"quote": {
"side": "BUY",
"rfq_id": 2073,
"maker": "DSK95",
"status": "CLOSED",
"id": 2776296,
"created": 1631591051681.613,
"remaining_quantity": "7",
"order": {
"id": 266376,
"client_order_id": "st12",
"filled_quantity": "26",
"filled_average_price": "0.0904",
"limit_price": "0.1",
"requested_quantity": "60",
"rfq_id": 2073,
"side": "BUY",
"status": "CLOSED",
"venue": "DBT"
},
"price": "0.1",
"original_quantity": "34",
"client_order_id": "st12"
}
}
}
}
All updates relating to Quotes upon RFQs are sent through the quote
WebSocket Notifications channel.
This is a private channel and only provides updates to the Maker who created the Quote.
Updates received through the quote
WebSocket Notification channel can include newly created quotes, removed quotes, quotes pending settlement & clearing, quotes which are partially filled as well as quotes which are completely filled.
Quotes which are executed upon and a rejection occurs at the underlying venue are canceled upon rejected. The remaining_quantity
of the Quote is no longer available on the Quote Book. It does not matter which party is to blame, the Quote is kind
== CANCELED
and status
== CLOSED
.
Quotes which have been [PATCH] /rfqs/{rfq_id}/quotes/{quote_id}/
have the original quote kind
== CANCELED
and status
== CLOSED
and a new Quote with kind
== NEW
and status
== OPEN
.
Workflow Steps:
- Maker creates Quote.
kind
==NEW
&status
==OPEN
. - Taker partially executes upon Quote.
kind
==PENDING_FILL
&status
==OPEN
.- Upon finality at settlement & clearing, Maker receives
kind
==PARTIALLY_FILLED
&status
==OPEN
.
- Upon finality at settlement & clearing, Maker receives
- Taker partially executes upon already partially executed Quote.
kind
==PENDING_FILL
&status
==OPEN
.- Upon finality at settlement & clearing, Maker receives
kind
==PARTIALLY_FILLED
&status
==OPEN
.
- Upon finality at settlement & clearing, Maker receives
- Taker executes upon a Quote, but the Trade is rejected by the underlying venue.
kind
==CANCELED
&status
==CLOSED
. - Taker completely executes quote as so there is
0
remaining_quantity
.kind
==FILLED
&status
==CLOSED
.
Member | Type | Required | Description |
---|---|---|---|
channel | string | true | WebSocket Notification Channel message is received upon. |
data | object | true | |
> kind | string | true | The action of the message. Valid values include NEW , CANCELED , PENDING_FILL , PARTIALLY_FILLED , FILLED . |
> quote | object | true | |
>> order | object | false | Present if Quote crosses the existing market. |
>>> id | int | false | The Paradigm created unique identifier of the Order. |
>>> client_order_id | string | false | A unique user created identifier for the Order. |
>>> filled_quantity | string | false | The filled quantity of the Order in the contract units of the RFQ. |
>>> filled_average_price | string | false | The average filled price of the Order in the quote currency of the RFQ. |
>>> limit_price | string | false | The price of the Order in quote currency of the RFQ. |
>>> requested_quantity | string | false | The requested crossing quantity of the Order. |
>>> rfq_id | int | false | The Paradigm created unique identifier of the RFQ the Order is a child of. |
>>> side | string | false | The direction of the Order. Valid values include BUY and SELL . |
>>> status | string | false | The current status of the Order. Valid values include OPEN and CLOSED . |
>>> venue | string | false | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
>> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
>> client_order_id | string | false | A unique user created identifier for the Quote. Not present if th subscribed user is not the Maker. |
>> id | int | true | The Paradigm created unique identifier of the Quote. |
>> maker | string | true | The Paradigm desk name of the Maker. |
>> original_quantity | string | true | The initial available quantity of the Quote in the contract units of the RFQ. |
>> price | string | true | The price of the Quote in the Quote Currency of the RFQ. |
>> remaining_quantity | string | true | The remaining available quantity of the Quote in the contract units of the RFQ. |
>> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
>> side | string | true | The side of the Quote. Valid values include BUY and SELL . |
>> status | string | true | The status of the Quote. Valid values include OPEN and CLOSED . |
venue_error | object | false | |
> message | string | false | Example: "Deribit error: Trade rejected" |
order
An example of the
order
notification received when an Order is Pending Fill
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "order",
"data": {
"kind": "PENDING_FILL",
"order": {
"id": 1113,
"client_order_id": "",
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "0.0054",
"requested_quantity": "25",
"rfq_id": 1232,
"side": "BUY",
"status": "OPEN",
"venue": "DBT"
}
}
}
}
An example of the
order
notification received when an Order has reached finality
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "order",
"data": {
"kind": "SUMMARY",
"order": {
"id": 1113,
"client_order_id": "",
"filled_quantity": "25",
"filled_average_price": "0.0054",
"limit_price": "0.0054",
"requested_quantity": "25",
"rfq_id": 1232,
"side": "BUY",
"status": "CLOSED",
"venue": "DBT"
}
}
}
}
All updates relating to Orders upon RFQs are sent through the order
WebSocket Notifications channel.
This is a private channel and only provides updates to the Taker who submitted the Order.
Updates received through the order
WebSocket Notification channel can include a pending fill notification as well as a summary of an order's execution at finality. You will receive a single kind
== PENDING_FILL
and kind
== SUMMARY
per order execution regardless of the number of Quotes consumed.
It is important to be aware that executions can be rejected by exchanges. You should the difference between the requested_quantity
and the filled_quantity
in the messages to be aware of the success of the execution(s).
Member | Type | Required | Description |
---|---|---|---|
channel | string | true | WebSocket Notification Channel message is received upon. |
data | object | true | |
> kind | string | true | The action of the message. Valid values include PENDING_FILL , SUMMARY . |
> order | object | true | |
>> id | int | true | The Paradigm created unique identifier of the Order. |
>> client_order_id | string | true | The user created unique value associated with the Order. |
>> filled_quantity | string | true | The filled quantity upon finality of the Order. |
>> filled_average_price | string | true | The average price of the filled quantity of the Order upon finality. |
>> limit_price | string | true | The price in the Quote currency of the RFQ of the Order. |
>> requested_quantity | string | true | The requested quantity of the Order in the contract units of the RFQ. |
>> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
>> side | string | true | The direction of the Order. Valid values include BUY and SELL . |
>> status | string | true | The status of the Order. Valid values include OPEN , CLOSED . |
>> venue | string | true | The underlying venue the trade was settled upon. Valid values include DBT , BIT , BYB . |
trade
An example of the
trade
notification received when a Trade successfully settles and clears
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "trade",
"data": {
"kind": "CONFIRMATION",
"trade": {
"quote_id": 709033,
"action": "BUY",
"id": 1257,
"rfq_id": 1232,
"order_id": 1120,
"quantity": "25",
"product_codes": ["DO"],
"traded": 1628040498333.169,
"api_credential": "ParadigmTestNinetySix",
"price": "0.0055",
"client_order_id": "",
"status": "COMPLETED",
"legs": [
{
"id": 2044,
"instrument": "BTC-4AUG21-39000-C",
"price": "0.0055",
"product_code": "DO",
"quantity": "25",
"ratio": "1",
"side": "BUY",
"action": "BUY",
"exec_id": "78144401"
}
],
"venue": "DBT",
"mark_price": "0.0054",
"quote_currency": "BTC",
"description": "Call 4 Aug 21 39000"
}
}
}
}
An example of the
trade
notification received when a Trade is rejected at settlement and clearing
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "trade",
"data": {
"kind": "REJECTION",
"trade": {
"order_id": 1121,
"quote_currency": "BTC",
"id": 1258,
"mark_price": "0.0054",
"client_order_id": "",
"price": "0.0055",
"quote_id": 709033,
"quantity": "25",
"traded": 1628040604131.9612,
"action": "BUY",
"api_credential": "ParadigmTestNinetySix",
"status": "REJECTED",
"description": "Call 4 Aug 21 39000",
"product_codes": ["DO"],
"legs": [
{
"id": 2045,
"instrument": "BTC-4AUG21-39000-C",
"price": "0.0055",
"product_code": "DO",
"quantity": "25",
"ratio": "1",
"side": "BUY",
"action": "BUY",
"exec_id": null
}
],
"venue": "DBT",
"rfq_id": 1232
}
},
"venue_error": {
"message": "DBT Error: Trade refused by exchange"
}
}
}
Updates relating to Trades upon RFQs are sent through the trade
WebSocket Notifications channel.
This is a private channel and only provides updates to the Taker & Maker of the Trade (matching of an Order and a Quote).
Updates received through the trade
WebSocket Notification channel can include trade success and rejection at clearing & settlement.
Member | Type | Required | Description |
---|---|---|---|
channel | string | true | WebSocket Notification Channel message is received upon. |
data | object | true | |
> kind | string | true | The action of the WS Message. Valid values include CONFIRMATION and REJECTION . |
> trade | object | true | |
>> api_credential | string | false | The name given the to the Exchange API Key entered on the Paradigm Client Admin dashboard. |
>> description | false | true | The Paradigm created description of the RFQ. |
>> client_order_id | string | true | A unique user created identifier for the Quote (Maker) or trade Order (Taker). |
>> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
>> id | int | true | The Paradigm created unique identifier of the Trade. |
>> mark_price | string | false | The calculated mark price of the RFQ from the underlying venue's mark prices in the Quote Currency of the RFQ. |
>> order_id | int | false | The Paradigm created unique identifier of the Order that triggered execution. |
>> price | string | false | The price the Trade was executed at in the Quote Currency of the RFQ. |
>> product_codes | array of strings | false | The Paradigm created Product Codes of the trade. |
>> quantity | string | false | The size of the trade in contracts units of the RFQ. |
>> quote_currency | string | false | The Quote Currency of the RFQ executed upon. |
>> quote_id | int | false | The Paradigm created unique identifier of the Quote executed upon. |
>> action | string | false | The direction of the Trade from the perspective of the User. Valid values include BUY and SELL . |
>> status | string | true | Trade status. Valid values include COMPLETED , REJECTED . |
>> traded | number | false | The time in unix milliseconds since the epoch when the trade was cleared & settled. |
>> venue | string | true | Venue the underlying RFQ clears and settles upon. Valid values include DBT , BIT , BYB . |
>> legs | array of objects | true | |
>>> id | int | true | The Paradigm created unique individual leg trade identifier. |
>>> exec_id | string | false | The venue created leg trade execution identifier. Only available to participants of the trade. |
>>> instrument | string | true | The Paradigm standardized name of the Instrument. |
>>> quantity | string | true | The size of the leg traded in contract unit terms. |
>>> price | string | true | The price of the leg traded in the Quote Currency of the RFQ. |
>>> product_code | string | true | The Paradigm created product code of the Instrument traded. |
>>> ratio | string | true | The quantity multiplier relative to other Instrument legs. |
>>> side | string | true | The direction of the leg of the RFQ. Valid values include BUY , SELL . |
>>> action | string | true | The direction of the leg from the user's perspective Traded. Valid values include BUY , SELL . |
venue_error | object | false | Only present if the Trade was rejected by the underlying venue. |
> message | string | false | Reason the trade was rejected by the underlying venue. |
trade_tape
An example of the
trade_tape
notification received when a trade settles & clears
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "trade_tape",
"data": {
"kind": "COMPLETED",
"trade": {
"id": 1260,
"description": "Call 4 Aug 21 39000",
"mark_price": "0.0054",
"price": "0.0054",
"product_codes": ["DO"],
"quantity": "25",
"quote_currency": "BTC",
"rfq_id": 1232,
"traded": 1628041230769.151,
"venue": "DBT"
}
}
}
}
All updates relating to Trades upon RFQs are sent through the trade_tape
WebSocket Notifications channel.
This is a public channel and provides updates about all Trades which are executed through Paradigm & successfully clear and settle on the underlying venue.
All notifications through the trade_tape
WebSocket channel do not reveal Taker or Maker information or the side
/action
the RFQ/Order/Quote was executed.
Member | Type | Required | Description |
---|---|---|---|
channel | string | true | WebSocket Notification Channel message is received upon. |
data | object | true | |
> kind | string | true | The action of the WS Message. Valid values include COMPLETED . |
> trade | object | true | |
>> id | int | true | The Paradigm created unique identifier of the Trade. |
>> description | string | true | The Paradigm created description of the RFQ. |
>> mark_price | string | true | The calculated mark price of the RFQ from the underlying venue's mark prices in the Quote Currency of the RFQ. |
>> price | string | true | The price the Trade was executed at in the Quote Currency of the RFQ. |
>> product_codes | array of strings | true | The Paradigm created Product Codes of the trade. |
>> quantity | string | true | The size of the trade in contracts units of the RFQ. |
>> quote_currency | string | true | The Quote Currency of the RFQ executed upon. |
>> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
>> traded | number | true | The time in unix milliseconds since the epoch when the trade was cleared & settled. |
>> venue | string | true | Venue the underlying RFQ clears and settles upon. Valid values include DBT , BIT , BYB . |
GRFQ - REST Endpoints
[GET] /instruments/
/instruments/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/instruments/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/v1/instruments/
method = 'GET'
path = '/v1/grfq/instruments/?asset=BTC&kind=FUTURE'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/instruments/ Response example
{
"count": 1341,
"next": "cD05NjE0Nw==",
"results": [
{
"option_kind": "PUT",
"name": "BTC-3JUL21-28000-P",
"strike": "28000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "BTC-3JUL21-28000-C",
"strike": "28000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-45000-P",
"strike": "45000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-45000-C",
"strike": "45000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-40000-P",
"strike": "40000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-40000-C",
"strike": "40000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-38000-P",
"strike": "38000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-38000-C",
"strike": "38000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-36000-P",
"strike": "36000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-36000-C",
"strike": "36000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-34000-P",
"strike": "34000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-34000-C",
"strike": "34000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-32000-P",
"strike": "32000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-32000-C",
"strike": "32000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-30000-P",
"strike": "30000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-30000-C",
"strike": "30000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-28000-P",
"strike": "28000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-28000-C",
"strike": "28000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-26000-P",
"strike": "26000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-26000-C",
"strike": "26000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "BTC-23JUL21-25000-P",
"strike": "25000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "BTC-23JUL21-25000-C",
"strike": "25000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2400-P",
"strike": "2400",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2400-C",
"strike": "2400",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2300-P",
"strike": "2300",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2300-C",
"strike": "2300",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2200-P",
"strike": "2200",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2200-C",
"strike": "2200",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2150-P",
"strike": "2150",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2150-C",
"strike": "2150",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2100-P",
"strike": "2100",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2100-C",
"strike": "2100",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2050-P",
"strike": "2050",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2050-C",
"strike": "2050",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-2000-P",
"strike": "2000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-2000-C",
"strike": "2000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-1950-P",
"strike": "1950",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-1950-C",
"strike": "1950",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-1900-P",
"strike": "1900",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-1900-C",
"strike": "1900",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-3JUL21-1800-P",
"strike": "1800",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "CALL",
"name": "ETH-3JUL21-1800-C",
"strike": "1800",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1625299200000.0
},
{
"option_kind": "PUT",
"name": "ETH-23JUL21-3200-P",
"strike": "3200",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "ETH-23JUL21-3200-C",
"strike": "3200",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "ETH-23JUL21-3000-P",
"strike": "3000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "ETH-23JUL21-3000-C",
"strike": "3000",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "ETH-23JUL21-2800-P",
"strike": "2800",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "ETH-23JUL21-2800-C",
"strike": "2800",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "PUT",
"name": "ETH-23JUL21-2600-P",
"strike": "2600",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
},
{
"option_kind": "CALL",
"name": "ETH-23JUL21-2600-C",
"strike": "2600",
"kind": "OPTION",
"venue": "BIT",
"expiration": 1627027200000.0
}
]
}
A [GET] /instruments/
request allows you to return all available Instruments upon Paradigm. Instruments are the legs part of an RFQ.
Instrument names match the naming conventions of the underlying venue.
You must paginate to return the complete results.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | Cursor value used to paginate through pages. |
asset | query | string | false | Base Currency of Instrument. Valid values include BTC , ETH , BCH , XRP , EOS . |
ordering | query | string | false | How returned Instruments are sorted. Valid values include creation , expiration , and default . |
page_size | query | string | false | Number of Instruments returned per pagination. |
kind | query | string | false | The type of Instrument. Valid values include FUTURE and OPTION . |
venue | query | string | false | The underlying venue the Instrument is cleared & settled upon. Valid values include DBT , BIT , BYB . |
name | query | [string] | false | Paradigm Name of Instruments. Example /v1/grfq/instruments/?name=BTC-PERPETUAL,ETH-PERPETUAL . |
include_greeks | query | boolean | false | Include greeks in the response. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of Instruments to paginate. |
next | string | true | Pagination cursor value. |
results | array of objects | true | |
> option_kind | string | true | The kind of Option. null if instrument is not an Option. Valid values include CALL , PUT , null . |
> name | string | true | The Paradigm standardized name of the Instrument. |
> strike | string | true | Option Instrument Strike Price. null if kind == FUTURE . |
> kind | string | true | The type of Instrument. Valid values include FUTURE and OPTION . |
> venue | string | true | Underlying venue Instrument is cleared & settled upon. Valid values include DBT , BIT , BYB . |
> expiration | number | true | Instrument expiration timestamp in unix milliseconds since the epoch. null if Instrument does not have an expiration. |
> venue_name | string | true | The name of the Instrument per the underlying venue's naming conventions. |
> greeks | object | false | The greeks of the Instrument. |
>> delta | string | true | The delta of the Instrument. |
>> gamma | string | true | The gamma of the Instrument. |
>> theta | string | true | The theta of the Instrument. |
>> vega | string | true | The vega of the Instrument. |
>> mark_price | string | true | The mark price of the Instrument. |
>> last_updated_at | int | true | The timestamp in unix milliseconds since the epoch when the greek values were last updated. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
404 | N/A | "Invalid cursor" | Use the string value from the next key in the first response to paginate. |
[GET] /instruments/{venue}/{instrument_name}/
/instruments/{venue}/{instrument_name}/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/instruments/DBT/BTC-PERPETUAL/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/instruments/{venue}/{instrument_name}
method = 'GET'
path = '/v1/grfq/instruments/DBT/BTC-PERPETUAL/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/instruments/{venue}/{instrument_name}/ Response example
{
"option_kind": null,
"name": "BTC-4JUN21",
"strike": null,
"kind": "FUTURE",
"venue": "DBT",
"expiration": 1622793600000.0
}
A [GET] /instruments/{venue}/{instrument_name}/
allows you to return information about a specific available Instrument.
Instruments are the legs part of an RFQ.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
venue | query | string | true | The underlying venue the Instrument is cleared & settled upon. Valid values include DBT , BIT , BYB . |
name | query | string | true | Paradigm Instrument Name. |
include_greeks | query | boolean | false | Include greeks in the response. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of Instruments to paginate. |
next | string | true | Pagination cursor value. |
results | array of objects | true | |
> option_kind | string | true | The kind of Option. null if instrument is not an Option. Valid values include CALL , PUT , null . |
> name | string | true | The Instrument name per the underlying venue's naming convention. |
> strike | string | true | Option Instrument Strike Price. null if kind == FUTURE . |
> kind | string | true | The type of Instrument. Valid values include FUTURE and OPTION . |
> venue | string | true | Underlying venue Instrument is cleared & settled upon. Valid values include DBT , BIT , BYB . |
> expiration | number | true | Instrument expiration timestamp in unix milliseconds since the epoch. null if Instrument does not have an expiration. |
> venue_name | string | true | The name of the Instrument per the underlying venue's naming conventions. |
> greeks | object | false | The greeks of the Instrument. |
>> delta | string | true | The delta of the Instrument. |
>> gamma | string | true | The gamma of the Instrument. |
>> theta | string | true | The theta of the Instrument. |
>> vega | string | true | The vega of the Instrument. |
>> mark_price | string | true | The mark price of the Instrument. |
>> last_updated_at | int | true | The timestamp in unix milliseconds since the epoch when the greek values were last updated. |
Error Codes
HTTP Status Code | Message | Meaning |
---|---|---|
401 | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
[GET] /orders/
/orders/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/orders/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/orders/
method = 'GET'
path = '/v1/grfq/orders/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/orders/ Response example
{
"count": 2,
"next": null,
"results": [
{
"client_order_id": "",
"rfq_id": 551,
"id": 379,
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "0.1645",
"requested_quantity": "25",
"status": "CLOSED",
"side": "BUY",
"venue": "DBT"
},
{
"client_order_id": "",
"rfq_id": 551,
"id": 378,
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "0.0642",
"requested_quantity": "25",
"satus": "CLOSED",
"side": "BUY",
"venue": "DBT"
}
]
}
A [GET] /orders/
request will return all the requesting user's and trading desks' Orders.
Orders are Taker interactions with the Quote Book. Quotes can be Taker & Maker interactions with the Quote Book.
You must paginate to return the complete series of results.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | The pagination cursor value. |
page_size | query | string | false | Number of orders to return per page. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | The total number of Orders available from request. |
next | string | true | The next pagination cursor. This value is null if there are no more pages. |
results | array of objects | true | |
> client_order_id | string | true | A unique user created identifier for the Order. |
> rfq_id | int | true | The Paradigm created unique identifier of the parent RFQ. |
> id | int | true | The Paradigm created unique identifier of the Order. |
> filled_quantity | string | true | The amount of the Order cleared & settled in the contract units of the RFQ. |
> filled_average_price | string | true | The average price of the filled quantity in the Quote Currency of the RFQ. |
> limit_price | string | true | The price of the submitted Order in the Quote Currency of the RFQ. |
> requested_quantity | string | true | The size of the Order in contract units of the RFQ. |
> side | string | true | The direction the Order executed upon the RFQ. Valid values include BUY and SELL . |
> status | string | true | The current status of the Order. Valid values include CLOSED . |
> venue | string | true | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
404 | N/A | "Invalid cursor" | Use the string value from the next key in the first response to paginate. |
[GET] /orders/{order_id}/
/orders/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/orders/62/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/orders/{order_id}/
method = 'GET'
path = '/v1/grfq/orders/62/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/orders/ Response example
{
"client_order_id": "",
"rfq_id": 589,
"id": 432,
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "2498",
"requested_quantity": "50000000000",
"side": "SELL",
"status": "CLOSED",
"venue": "DBT",
"trades": [
{
"product_code": "CF",
"quantity": "50000000000",
"price": "2498",
"id": 479,
"mark_price": "2498.93",
"traded": 1625193887212.47,
"action": "SELL",
"quote_currency": "USD",
"quote_id": 152838,
"api_credential": "ParadigmTestNinetyFive"
}
]
}
A [GET] /orders/{order_id}/
request will one of the requesting user's and trading desks' Orders.
Orders are Taker interactions with the Quote Book. Quotes can be Taker & Maker interactions with the Quote Book.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The Paradigm created unique identifier of the Order. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
client_order_id | string | true | A unique user created identifier for the trade Order. |
rfq_id | int | true | The Paradigm created unique identifier of the parent RFQ. |
id | int | true | The Paradigm created unique identifier of the Order. |
filled_quantity | string | true | The amount of the Order filled in the contract units of the RFQ. |
filled_average_price | string | true | The average price of the filled quantity in the Quote Currency of the RFQ. |
limit_price | string | true | The price of the submitted Order in the Quote Currency of the RFQ. |
requested_quantity | string | true | The size of the Order in contract units of the RFQ. |
side | string | true | The execution side of the Order on the RFQ. Valid values include BUY and SELL . |
status | string | true | The current status of the Order. Valid values include CLOSED . |
venue | string | true | Underlying venue Instrument is cleared & settled upon. Valid values include DBT , BIT , BYB . |
trades | array of objects | true | |
> product_codes | array of strings | true | The Paradigm Product Codes of the Trade. |
> quantity | string | true | The amount of contracts of the RFQ traded. |
> price | string | true | The price in the Quote Currency of the RFQ of the Trade. |
> id | int | true | The Paradigm created unique identifier of the Trade. |
> mark_price | string | true | The calculated mark price of the RFQ using the Venue's mark prices. |
> traded | number | true | The time in unix milliseconds since the epoch when the trade was cleared & settled. |
> action | string | true | The action taken on the Trade. valid values include BUY and SELL . |
> quote_currency | string | true | The asset which is the Quote Currency of the RFQ. |
> quote_id | int | true | The Paradigm created unique identifier of the Quote. |
> api_credential | string | true | The name given the to the Exchange API Key entered on the Paradigm Client Admin dashboard. |
> status | string | true | The status of the Trade. Valid values include PENDING , COMPLETED , REJECTED . |
Error Codes
HTTP Status Code | Message | Meaning |
---|---|---|
401 | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
[GET] /quotes/
/quotes/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/quotes/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/quotes/
method = 'GET'
path = '/v1/grfq/quotes/?page_size=10&side=BUY'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/quotes/ Response example
{
"count": 5755,
"next": "cD0yMDIxLTA3LTI2KzA2JTNBMjMlM0ExOC4xMTc1NDMlMkIwMCUzQTAw",
"results": [
{
"id": 2775578,
"created": 1631587522444.227,
"maker": "DSK95",
"price": "0.08",
"remaining_quantity": "0",
"side": "SELL",
"status": "CLOSED",
"client_order_id": "",
"original_quantity": "25",
"rfq_id": 2073
},
{
"id": 2775577,
"created": 1631587522410.562,
"maker": "DSK95",
"price": "0.0795",
"remaining_quantity": "0",
"side": "BUY",
"status": "CLOSED",
"client_order_id": "",
"original_quantity": "25",
"rfq_id": 2073
},
{
"id": 2775572,
"created": 1631587470993.799,
"maker": "DSK95",
"price": "0.09",
"remaining_quantity": "24",
"side": "BUY",
"status": "CLOSED",
"client_order_id": "",
"order": {
"id": 266218,
"client_order_id": "",
"filled_quantity": "26",
"filled_average_price": "0.0879",
"limit_price": "0.09",
"requested_quantity": "50",
"rfq_id": 2073,
"side": "BUY",
"status": "CLOSED",
"venue": "DBT"
},
"original_quantity": "24",
"rfq_id": 2073
},
{
"id": 2775564,
"created": 1631587437845.888,
"maker": "DSK95",
"price": "0.0879",
"remaining_quantity": "50",
"side": "SELL",
"status": "CLOSED",
"client_order_id": "",
"original_quantity": "50",
"rfq_id": 2073
}
]
}
A [GET] /quotes/
request will return all the requesting user's and trading desks' Quotes.
Orders are Taker interactions with the Quote Book. Quotes can be Taker & Maker interactions with the Quote Book.
You must paginate to return the complete series of results.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | The pagination cursor value. |
page_size | query | string | false | Number of Quotes to return per page. |
rfq_id | query | string | false | The Paradigm created unique identifier of the RFQ. |
side | query | string | false | The direction of the Quotes. Valid values include BUY and SELL . |
status | query | string | false | The status of the Quotes. Valid values include OPEN and CLOSED . |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | The total number of Quotes available to paginate over. |
next | string | true | The next pagination cursor. This value is null if there are no more pages. |
results | array of objects | true | |
> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
> last_activity | number | true | The time in unix milliseconds since the epoch when the Quote was updated. |
> id | int | true | The Paradigm created unique identifier of the Quote. |
> maker | string | true | The Paradigm desk name of the Maker. |
> price | string | true | The price of the Quote in the Quote Currency of the Strategy. |
> remaining_quantity | string | true | The total remaining Quote size in contract units of the RFQ. |
> side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
> type | string | true | The Quote OrderType. Valid values include LIMIT . |
> description | string | true | The RFQ strategy description. |
> product_codes | array of strings | true | The RFQ product codes. |
> status | string | true | The status of the Quote. Valid values include OPEN and CLOSED . |
> client_order_id | string | true | A unique user created identifier for the Quote. |
> order | object | false | Present if Quote crosses the existing market. |
>> id | int | false | The Paradigm created unique identifier of the Order. |
>> client_order_id | string | false | A unique user created identifier for the Order. |
>> filled_quantity | string | false | The filled quantity of the Order in the contract units of the RFQ. |
>> filled_average_price | string | false | The average filled price of the Order in the quote currency of the RFQ. |
>> limit_price | string | false | The price of the Order in quote currency of the RFQ. |
>> requested_quantity | string | false | The requested crossing quantity of the Order. |
>> rfq_id | int | false | The Paradigm created unique identifier of the RFQ the Order is a child of. |
>> side | string | false | The direction of the Order. Valid values include BUY and SELL . |
>> status | string | false | The current status of the Order. Valid values include OPEN and CLOSED . |
>> venue | string | false | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
> rfq_id | int | true | The Paradigm created unique identifier of the RFQ the Quote is a child of. |
> original_quantity | string | true | The original Quote size in contract units of the RFQ. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
404 | N/A | "Invalid cursor" | Use the string value from the next key in the first response to paginate. |
[GET] /quotes/{quote_id}/
/quotes/{quote_id}/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/quotes/482199/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/quotes/{quote_id}/
method = 'GET'
path = '/v1/grfq/quotes/152780/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/quotes/{quote_id}/ Response example
{
"id": 2775572,
"created": 1631587470993.799,
"maker": "DSK95",
"price": "0.09",
"remaining_quantity": "24",
"side": "BUY",
"status": "CLOSED",
"client_order_id": "",
"order": {
"id": 266218,
"client_order_id": "",
"filled_quantity": "26",
"filled_average_price": "0.0879",
"limit_price": "0.09",
"requested_quantity": "50",
"rfq_id": 2073,
"side": "BUY",
"status": "CLOSED",
"venue": "DBT"
},
"original_quantity": "24",
"rfq_id": 2073,
"canceled": 1631587471003.939
}
A [GET] /quotes/{quote_id}/
request will return the requesting user's and trading desks' specified Quote.
Orders are Taker interactions with the Quote Book. Quotes can be Taker & Maker interactions with the Quote Book.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The Paradigm created unique Quote identifier. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
id | int | true | The Paradigm created unique identifier of the Quote. |
maker | string | true | The Paradigm desk name of the Maker who created the Quote. |
price | string | true | Price of the Quote in the Quote currency of the RFQ. |
remaining_quantity | string | true | The total remaining size of the Quote in contract units of the RFQ. |
side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
status | string | true | The status of the quote. Valid values include OPEN and CLOSED . |
client_order_id | string | true | A unique user created identifier for the Quote. |
order | object | false | Present if Quote crosses the existing market. |
> id | int | false | The Paradigm created unique identifier of the Order. |
> client_order_id | string | false | A unique user created identifier for the Order. |
> filled_quantity | string | false | The filled quantity of the Order in the contract units of the RFQ. |
> filled_average_price | string | false | The average filled price of the Order in the quote currency of the RFQ. |
> limit_price | string | false | The price of the Order in quote currency of the RFQ. |
> requested_quantity | string | false | The requested crossing quantity of the Order. |
> rfq_id | int | false | The Paradigm created unique identifier of the RFQ the Order is a child of. |
> side | string | false | The direction of the Order. Valid values include BUY and SELL . |
> status | string | false | The current status of the Order. Valid values include OPEN and CLOSED . |
> venue | string | false | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
rfq_id | int | true | The Paradigm created unique identifier of the RFQ the Quote is a child of. |
original_quantity | string | true | The original size of the Quote in contract units of the RFQ. |
canceled | number | true | The time in unix milliseconds since the epoch when the Quote was canceled. null if Quote has not been canceled. |
Error Codes
HTTP Status Code | Message | Meaning |
---|---|---|
401 | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
[DELETE] /quotes/
/quotes/ Request example
# You can also use wget
curl -X DELETE https://api.test.paradigm.co/v1/grfq/quotes/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# DELETE /v1/grfq/quotes/
method = 'DELETE'
path = '/v1/grfq/quotes/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.delete(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/quotes/ Response example
{
"successes": {
"count": 2,
"details": [152799, 152798]
},
"failures": {
"count": 0,
"details": []
}
}
A [DELETE] /quotes/
request cancels all existing Quotes.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
rfq_id | query | string | false | The Paradigm created unique identifier of the RFQ. |
side | query | string | false | Cancel all Quotes by side. Valid values include BUY and SELL . Cancels all Quotes regardless of side if not specified. |
price | query | decimal | false | Cancel all Quotes matching the given price. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
successes | array of objects | true | Information about successful Quote cancellations. |
> count | int | true | The number of OPEN Quotes that have now been canceled. |
> details | array of objects | true | |
>> id | int | true | The Paradigm created unique identifier of the Quote. |
>> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
>> price | string | true | The price in the Quote Currency of the RFQ of the Quote. |
>> remaining_quantity | string | true | The remaining quantity of the Quote in the contract units of the Quote. |
>> side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
>> status | string | true | The status of the Quote. Valid values include CLOSED . |
failures | array of objects | true | Information about unsuccessful Quote cancellations. |
> count | int | true | The number of OPEN Quotes that have failed to be canceled. |
> details | array of objects | true | |
>> id | int | true | The Paradigm created unique identifier of the Quote. |
>> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
>> price | string | true | The price in the Quote Currency of the RFQ of the Quote. |
>> remaining_quantity | string | true | The remaining quantity of the Quote in the contract units of the Quote. |
>> side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
>> status | string | true | The status of the Quote. Valid values include OPEN . |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 3305 | "Invalid RFQ ID" | Unavailable/Invalid RFQ Id requested. |
400 | 3301 | "Invalid quote side. Must either be BUY or SELL." | Requested side query string value must be BUY or SELL . |
[DELETE] /quotes/{quote_id}/
/quotes/{quote_id}/ Request example
# You can also use wget
curl -X DELETE https://api.test.paradigm.co/v1/grfq/quotes/15/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# DELETE /v1/grfq/quotes/{quote_id}/
method = 'DELETE'
path = '/v1/grfq/quotes/152797/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
response = requests.delete(host+path,
headers=headers)
print(response.status_code)
print(response.text)
A [DELETE] /quotes/{quote_id}/
request cancels an existing OPEN
Quote created by the requesting user or user's trading desk.
You cannot cancel multiple Quotes with a single request using this endpoint.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The Paradigm unique identifier of the Quote the user would like to cancel. |
Response Schema
This request will return an HTTP Status Code of 204 to indicate success of operation.
Status Code 204
Schema below is solely for if the request resulted in a failed operation.
Name | Type | Required | Description |
---|---|---|---|
code | int | true | Error Code. |
message | string | true | The reason the request was unsuccessful. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 3306 | "Too late to cancel." | The requested quote_id is already CLOSED or unavailable to cancel. |
400 | 3308 | "Unavailable quote | You are not the desk who created the Quote. |
[GET] /rfqs/
/rfqs/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/rfqs/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/rfqs/
method = 'GET'
path = '/v1/grfq/rfqs/?rfq_id=57'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/rfqs/ Response example
{
"count": 13,
"next": null,
"results": [
{
"id": 586,
"venue": "DBT",
"created": 1625183214149.205,
"description": "Put 9 Jul 21 32000",
"last_trade": null,
"latest_activity": 1625183931073.739,
"legs": [
{
"instrument": "BTC-9JUL21-32000-P",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 585,
"venue": "DBT",
"created": 1625182846124.338,
"description": "PFly 3 Jul 21 32000/33000/34000",
"last_trade": null,
"latest_activity": 1625183645052.5972,
"legs": [
{
"instrument": "BTC-3JUL21-32000-P",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
},
{
"instrument": "BTC-3JUL21-33000-P",
"product_code": "DO",
"ratio": "2",
"side": "SELL"
},
{
"instrument": "BTC-3JUL21-34000-P",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 583,
"venue": "DBT",
"created": 1625181172208.664,
"description": "Call 3 Jul 21 32000",
"last_trade": null,
"latest_activity": 1625182827211.0642,
"legs": [
{
"instrument": "BTC-3JUL21-32000-C",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 584,
"venue": "DBT",
"created": 1625182630789.73,
"description": "Call 16 Jul 21 34000",
"last_trade": null,
"latest_activity": 1625182651464.818,
"legs": [
{
"instrument": "BTC-16JUL21-34000-C",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 573,
"venue": "DBT",
"created": 1625159972983.593,
"description": "Put 16 Jul 21 34000",
"last_trade": null,
"latest_activity": 1625182626036.611,
"legs": [
{
"instrument": "BTC-16JUL21-34000-P",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 576,
"venue": "DBT",
"created": 1625163614843.893,
"description": "CFly 3 Jul 21 31000/32000/33000",
"last_trade": null,
"latest_activity": 1625180836165.132,
"legs": [
{
"instrument": "BTC-3JUL21-31000-C",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
},
{
"instrument": "BTC-3JUL21-32000-C",
"product_code": "DO",
"ratio": "2",
"side": "SELL"
},
{
"instrument": "BTC-3JUL21-33000-C",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 581,
"venue": "BIT",
"created": 1625174242789.779,
"description": "Straddle 3 Jul 21 1900",
"last_trade": null,
"latest_activity": 1625180726439.838,
"legs": [
{
"instrument": "ETH-3JUL21-1900-P",
"product_code": "VT",
"ratio": "1",
"side": "BUY"
},
{
"instrument": "ETH-3JUL21-1900-C",
"product_code": "VT",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["VT"],
"status": "ACTIVE"
},
{
"id": 582,
"venue": "DBT",
"created": 1625178072216.012,
"description": "Cstm +1 Call 3 Jul 21 32000\n -2 Put 3 Jul 21 33000\n +2 Call 9 Jul 21 34000\n -1 Put 9 Jul 21 35000",
"last_trade": null,
"latest_activity": 1625178072216.1091,
"legs": [
{
"instrument": "BTC-3JUL21-32000-C",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
},
{
"instrument": "BTC-3JUL21-33000-P",
"product_code": "DO",
"ratio": "2",
"side": "SELL"
},
{
"instrument": "BTC-9JUL21-34000-C",
"product_code": "DO",
"ratio": "2",
"side": "BUY"
},
{
"instrument": "BTC-9JUL21-35000-P",
"product_code": "DO",
"ratio": "1",
"side": "SELL"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 575,
"venue": "DBT",
"created": 1625160866037.8489,
"description": "Call 9 Jul 21 32000",
"last_trade": null,
"latest_activity": 1625173436428.965,
"legs": [
{
"instrument": "BTC-9JUL21-32000-C",
"product_code": "DO",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["DO"],
"status": "ACTIVE"
},
{
"id": 578,
"venue": "DBT",
"created": 1625167876394.6099,
"description": "Future 16 Jul 21",
"last_trade": null,
"latest_activity": 1625172957461.732,
"legs": [
{
"instrument": "BTC-16JUL21",
"product_code": "CF",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["CF"],
"status": "ACTIVE"
},
{
"id": 580,
"venue": "DBT",
"created": 1625172668390.126,
"description": "FSpd 25 Mar 22 / 24 Jun 22",
"last_trade": null,
"latest_activity": 1625172668390.178,
"legs": [
{
"instrument": "BTC-25MAR22",
"product_code": "CF",
"ratio": "1",
"side": "SELL"
},
{
"instrument": "BTC-24JUN22",
"product_code": "CF",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["CF"],
"status": "ACTIVE"
},
{
"id": 579,
"venue": "DBT",
"created": 1625172652154.217,
"description": "FSpd Perpetual / 24 Jun 22",
"last_trade": null,
"latest_activity": 1625172652154.271,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"product_code": "CF",
"ratio": "1",
"side": "SELL"
},
{
"instrument": "BTC-24JUN22",
"product_code": "CF",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["CF"],
"status": "ACTIVE"
},
{
"id": 577,
"venue": "BYB",
"created": 1625164847566.429,
"description": "FSpd 24 Sep 21 / 31 Dec 21",
"last_trade": null,
"latest_activity": 1625164847566.4849,
"legs": [
{
"instrument": "BTCUSDU21",
"product_code": "BB",
"ratio": "1",
"side": "SELL"
},
{
"instrument": "BTCUSDZ21",
"product_code": "BB",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["BB"],
"status": "ACTIVE"
}
]
}
A [GET] /rfqs/
request returns information about ACTIVE
RFQs.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | Cursor value, from the next key in the response, used to paginate through pages. |
page_size | query | string | false | Number of RFQs to return per pagination. |
product_codes | query | string | false | Paradigm Product Codes involved in RFQ. There can be multiple product codes. Example: /v1/grfq/rfqs/?product_codes=DO,CF |
rfq_id | query | string | false | Paradigm created unique identifier for the RFQ. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of RFQs to paginate through from request. |
next | string | true | Pagination cursor value. null if no more pages are available. |
results | array of objects | true | |
> id | int | true | The Paradigm created unique identifier of the RFQ. |
> venue | string | true | The underlying venue the instruments are cleared & settled upon. Valid values include DBT , BIT , BYB . |
> created | number | true | Time in unix milliseconds since the epoch when the RFQ was created. |
> description | string | true | The description of the RFQ. |
> last_trade | object | true | null if RFQ has never been Traded. |
>> traded | number | false | Time in unix milliseconds since the epoch when the the Trade occurred. |
>> quantity | string | false | The size of the trade in the contract units of the RFQ. |
>> price | string | false | The price the RFQ was Traded at in the Quote Currency of the RFQ. |
> latest_activity | number | true | Time in unix milliseconds since the epoch when the RFQ, it’s quotes and trades were last updated. |
> legs | array of objects | true | |
>> instrument | string | true | The Paradigm standardized name of the Instrument. |
>> venue_instrument | string | true | Instrument name per the underlying venue's naming convention. |
>> product_code | string | true | Paradigm Product Code of the Instrument. |
>> ratio | string | true | The multiplier applied to the quantity that the quote applies. |
>> side | string | true | The direction of the leg. Valid values include BUY and SELL . |
> price | string | false | Price of Instrument if the Instrument is a hedge leg in RFQ. |
> product_codes | array of strings | true | Paradigm Product Codes involved in the GRFQ. |
> status | string | true | Status of the RFQ. Valid values include ACTIVE . |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
404 | N/A | "Invalid cursor" | Use the string value from the next key in the first response to paginate. |
[GET] /rfqs/{rfq_id}/
/rfqs/{rfq_id}/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/rfqs/20/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/rfqs/{rfq_id}/
method = 'GET'
path = '/v1/grfq/rfqs/581/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/rfqs/{rfq_id}/ Response example
{
"id": 581,
"venue": "BIT",
"created": 1625174242789.779,
"description": "Straddle 3 Jul 21 1900",
"last_trade": null,
"latest_activity": 1625180726439.838,
"legs": [
{
"instrument": "ETH-3JUL21-1900-P",
"product_code": "VT",
"ratio": "1",
"side": "BUY"
},
{
"instrument": "ETH-3JUL21-1900-C",
"product_code": "VT",
"ratio": "1",
"side": "BUY"
}
],
"product_codes": ["VT"],
"status": "ACTIVE"
}
A [GET] /rfqs/{rfq_id}/
request returns information about a specific RFQ.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The Paradigm created unique identifier of the RFQ. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
id | int | true | The Paradigm created unique identifier of the RFQ. |
venue | string | true | The underlying venue the instruments are cleared & settled upon. Valid values include DBT , BIT , BYB . |
created | number | true | Time in unix milliseconds since the epoch when the RFQ was created. |
description | string | true | The description of the RFQ. |
last_trade | object | true | null if the RFQ has never been Traded. |
> traded | number | false | Time in unix milliseconds since the epoch when the the Trade occurred. |
> quantity | string | false | The size of the trade in the contract units of the RFQ. |
> price | string | false | The price the RFQ was Traded at. |
latest_activity | number | true | Time in unix milliseconds since the epoch when the RFQ, it’s quotes and trades were last updated. |
legs | array of objects | true | |
> instrument | string | true | The Paradigm standardized name of the Instrument. |
> venue_instrument | string | true | Instrument name per the underlying venue's naming conventions. |
> price | string | false | Price of Instrument if the Instrument is a hedge leg in RFQ. |
> product_code | string | true | Paradigm Product Code of the Instrument. |
> ratio | string | true | The multiplier applied to the quantity that the quote applies. |
> side | string | true | The direction of the leg. Valid values include BUY and SELL . |
product_codes | array of strings | true | Paradigm Product Codes involved in the RFQ. |
status | string | true | Status of the RFQ. Valid values include ACTIVE and EXPIRED . |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 3300 | "Unavailable RFQ" | Unavailable/invalid RFQ Id provided in request. |
[POST] /rfqs/
/rfqs/ Request example
# built ins
import base64
import hmac
import json
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# POST /v1/grfq/rfqs/
method = 'POST'
path = '/v1/grfq/rfqs/'
payload = {
"venue":"DBT",
"legs":[
{
"instrument":"BTC-PERPETUAL",
"ratio":1,
"side":"BUY"
},
{
"instrument":"BTC-31DEC21",
"ratio":1,
"side":"SELL"
}
]
}
json_payload = json.dumps(payload)
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=json_payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(host+path,
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
/rfqs/ Response example
{
"id": 588,
"venue": "DBT",
"created": 1625187733890.315,
"description": "Cstm +1 Future Perpetual\n -1 Future 31 Dec 21",
"last_trade": null,
"latest_activity": 1625187733890.388,
"legs": [
{
"instrument": "BTC-PERPETUAL",
"product_code": "CF",
"ratio": "1",
"side": "BUY"
},
{
"instrument": "BTC-31DEC21",
"product_code": "CF",
"ratio": "1",
"side": "SELL"
}
],
"product_codes": ["CF"],
"status": "ACTIVE"
}
A [POST] /rfqs/
request allows a user to create a new RFQ and/or return the RFQ's information if one already exists.
The response schema and response is the same if the requester creates a new RFQ or an RFQ already exists.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
venue | body | string | true | The underlying venue the Instruments in the RFQ are cleared & settled upon. Valid values include DBT , BIT , BYB . |
legs | body | array of objects | true | The individual legs of the RFQ. |
> instrument | body | string | true | The name of the Instrument per the underlying venue's naming convention. |
> price | body | string | false | The price of the leg in the Quote Currency of the Instrument if the leg is a hedge leg. |
> ratio | body | sting | true | The quantity multiplier for the Strategy leg. |
> side | body | string | true | The direction of the leg. Valid values include BUY and SELL . |
Response Schema
Status Code 201
Name | Type | Required | Description |
---|---|---|---|
id | int | true | The Paradigm created unique identifier of the RFQ. |
venue | string | true | The underlying RFQ venue the instruments are cleared & settled upon. Valid values include DBT , BIT , and BYB . |
created | number | true | The time in unix milliseconds since the epoch when the RFQ was created. |
description | string | true | The description of the RFQ. |
last_trade | object | true | null if no Trades have occurred on the RFQ. |
> traded | number | false | Time in unix milliseconds since the epoch when the the Trade occurred. |
> quantity | string | false | The size of the trade in the contract units of the RFQ. |
> price | string | false | The price the RFQ was Traded at. |
latest_activity | number | true | The time in unix milliseconds since the epoch when the RFQ's quotes or trades were last updated. |
legs | array of objects | true | |
> instrument | string | true | The Paradigm standardized name of the RFQ leg. |
> venue_instrument | string | true | The name of the Instrument per the underlying venue's naming convention. |
> product_code | string | true | The Paradigm created product code of the Instrument in the leg. |
> ratio | number | true | The multiplier of the quantity of the Instrument in the leg. |
> side | string | true | The direction of the leg in the strategy. Valid values include BUY and SELL . |
> price | string | false | The price of the leg in the Quote Currency of the Instrument. Only returned if the leg is a Hedge leg. |
product_codes | array of strings | true | The Paradigm created product codes of the instrument legs. |
status | string | true | The status of the RFQ. Valid values include ACTIVE . |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
403 | N/A | "Your desk is not configured to trade in this venue's products" | Ensure you have the venue key in your request payload. If so, ask Sales to enable the payload for your Desk. |
400 | 1306 | "Invalid instrument" | An invalid Instrument name is part of the request. Use the Paradigm standardized instrument key value. |
400 | 3203 | "Invalid leg parameters" | There is an invalid leg parameter as part of your request. |
[POST] /rfqs/{rfq_id}/quotes/
/rfqs/{rfq_id}/quotes/ Request example
# built ins
import base64
import hmac
import time
import json
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# POST /v1/grfq/rfqs/{rfq_id}/quotes/
method = 'POST'
path = '/v1/grfq/rfqs/579/quotes/'
payload = {
"account": "ParadigmTestNinetyFive",
"client_order_id": "55",
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": "33000"
},
{
"instrument": "BTC-24JUN22",
"price": "33200"
}
],
"quantity": "1000000",
"side": "SELL"
}
json_payload = json.dumps(payload)
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=json_payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(host+path,
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
/rfqs/{rfq_id}/quotes/ Response example
{
"id": 2776054,
"created": 1631589942042.397,
"maker": "DSK95",
"price": "0.09",
"remaining_quantity": "24",
"side": "BUY",
"status": "CLOSED",
"client_order_id": "stri1231321232121223231321132312213ng",
"order": {
"id": 266318,
"client_order_id": "stri1231321232121223231321132312213ng",
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "0.09",
"requested_quantity": "50",
"rfq_id": 2073,
"side": "BUY",
"status": "OPEN",
"venue": "DBT"
},
"original_quantity": "24",
"rfq_id": 2073
}
A [POST] /rfqs/{rfq_id}/quotes/
request creates a Quote upon a specific RFQ.
Takers & Makers use this endpoint to cross the existing market or create a resting Limit Order. Remaining amounts of the Quote remain on the Quote Book in the event of crossing.
If post_only
== true
and the submitted Quote crosses the existing market, the Quote is canceled in its entirety. This ensures you are always a Maker.
If a user submits a Quote which crosses the existing market, you will receive messages on both the quote
and order
JSON-RPCoverWebSockets Notification channels.
Takers are only able to execute once every two seconds due to Paradigm's Market Maker Protection feature.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The unique Paradigm created identifier of the RFQ. |
ioc | body | boolean | false | Create Immediate or Cancel (IoC) quote. |
account | body | string | true | The name of the Exchange API Key entered on your Client Admin dashboard. |
client_order_id | body | string | true | A unique user created identifier for the Quote. |
legs | body | array of objects | true | Array of objects containing the strategy’s legs' quotes' attributes. |
> instrument | body | string | true | The Paradigm standardized name of the Instrument. |
> price | body | string | true | The price of the individual leg's Instrument. |
quantity | body | string | true | The total quantity of the strategy in contract units of the RFQ. |
side | body | string | true | The direction of the Quote. Valid values include BUY and SELL . |
post_only | body | boolean | false | If true , the quote is canceled and never enters the Quote Book if it crosses the existing market. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
id | int | true | The Paradigm created unique identifier of the Quote. |
created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
maker | string | true | The Paradigm desk name that created the Quote. |
price | string | true | The price of the strategy in the Quote Currency of the RFQ. |
remaining_quantity | string | true | Total size of the Quote in contract units of the RFQ remaining. |
side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
status | string | true | The status of the Quote. Valid values include OPEN , CLOSED . |
client_order_id | string | true | A unique user created identifier for the Quote. |
order | object | false | Present if Quote crosses the existing market. |
> id | int | false | The Paradigm created unique identifier of the Order. |
> client_order_id | string | false | A unique user created identifier for the Order. |
> filled_quantity | string | false | The filled quantity of the Order in the contract units of the RFQ. |
> filled_average_price | string | false | The average filled price of the Order in the quote currency of the RFQ. |
> limit_price | string | false | The price of the Order in quote currency of the RFQ. |
> requested_quantity | string | false | The requested crossing quantity of the Order. |
> rfq_id | int | false | The Paradigm created unique identifier of the RFQ the Order is a child of. |
> side | string | false | The direction of the Order. Valid values include BUY and SELL . |
> status | string | false | The current status of the Order. Valid values include OPEN and CLOSED . |
> venue | string | false | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
original_quantity | string | true | Initial size of the Quote in contract units of the RFQ. |
rfq_id | int | true | The Paradigm created unique identifier of the RFQ the Quote is a child of. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 100 | "Invalid parameters" | Invalid parameters in request such as a non-unique client_order_id value. |
400 | 1302 | "Invalid account information" | The value provided with the account key should match the name given to the Exchange API key on the Paradigm Client Admin Dashboard. |
400 | 3203 | "Invalid leg parameters" | Ensure you are attempting to quote on the correct RFQ. Check your request format is correct. |
400 | 3303 | "An active BUY(SELL)-side quote already exists. Please cancel that quote before submitting a new quote." | Refer to error message. |
400 | 3304 | "Your Bid/Ask was canceled. It crossed the available Ask/Bid." | This occurs when you specify post_only == true and the submitted Quote crosses the market or if you cross your own existing Quote. |
400 | 3304 | "{instrument_name}. Bid/Ask price cannot be greater than Ask/Bid Price." | This occurs when the Bid/Ask price of a leg in the submitted Quote is greater than the Ask/Bid price of the same leg in an existing Quote. |
403 | N/A | "Maker Execution Limit Reached." | MMP has been triggered and the user must [PATCH] /v1/mmp/status to reset the protection to be able to quote. |
[PUT] /rfqs/{rfq_id}/quotes/{quote_id}/
/rfqs/{rfq_id}/quotes/{quote_id}/ Request example
# built ins
import base64
import hmac
import time
import json
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# PUT /v1/grfq/rfqs/{rfq_id}/quotes/{quote_id}/
method = 'PUT'
path = '/v1/grfq/rfqs/1230/quotes/45678/'
payload = {
"account": "ParadigmTestNinetyFive",
"client_order_id": "1223322132123123321",
"quantity": "5000000",
"side": "BUY",
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": "38501"
}
],
"post_only": True
}
json_payload = json.dumps(payload)
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=json_payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.put(host+path,
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
/rfqs/{rfq_id}/quotes/{quote_id}/ Response example
{
"id":2776054,
"created":1631589942042.397,
"maker":"DSK95",
"price":"0.09",
"remaining_quantity":"24",
"side":"BUY",
"status":"CLOSED",
"client_order_id":"stri1231321232121223231321132312213ng",
"order":{
"id":266318,
"client_order_id":"stri1231321232121223231321132312213ng",
"filled_quantity":"0",
"filled_average_price":"0",
"limit_price":"0.09",
"requested_quantity":"50",
"rfq_id":2073,
"side":"BUY",
"status":"OPEN",
"venue":"DBT"
},
"original_quantity":"24",
"rfq_id":2073
}
A [PUT] /rfqs/{rfq_id}/quotes/{quote_id}/
request replaces an existing Quote upon a specific RFQ.
Takers & Makers use this endpoint to cross the existing market or update a resting Limit Order. Remaining amounts of the Quote remain on the Quote Book in the event of crossing.
If post_only
== true
and the submitted Quote crosses the existing market, the Quote is canceled in its entirety. This ensures you are always a Maker.
If a user submits a Quote which crosses the existing market, you will receive messages on both the quote
and order
JSON-RPCoverWebSockets Notification channels.
Important note: this endpoint serves as a replacement for both [PATCH] /rfqs/{rfq_id}/quotes/
, and [PATCH] /rfqs/{rfq_id}/quotes/{quote_id}/
which are proposed for deprecation.
The [PATCH] /rfqs/{rfq_id}/quotes/
endpoint is not able to process the replacement correctly when quote layering is enabled and more than one quote is active.
The current new endpoint takes also the quote_id
in the URL to handle the feature without any issues.
The [PATCH] /rfqs/{rfq_id}/quotes/{quote_id}/
endpoint is proposed for deprecation as a part of unification and standardization of methods used in our API.
We recommend to update all workflows in favor of this new version.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
rfq_id | endpoint | string | true | The unique Paradigm created identifier of the RFQ. |
quote_id | endpoint | string | true | The unique Paradigm created identifier of the Quote being replaced. |
account | body | string | true | The name of the Exchange API Key entered on your Client Admin dashboard. |
client_order_id | body | string | true | A unique user created identifier for the Quote. |
legs | body | array of objects | true | Array of objects containing the strategy’s legs' quotes' attributes. |
> instrument | body | string | true | The Paradigm standardized name of the Instrument. |
> price | body | string | true | The price of the individual leg's Instrument. |
quantity | body | string | true | The total quantity of the strategy in contract units of the RFQ. |
side | body | string | true | The direction of the Quote. Valid values include BUY and SELL . |
post_only | body | boolean | false | If true , the quote is canceled and never enters the Quote Book if it crosses the existing market. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
id | int | true | The Paradigm created unique identifier of the Quote. |
created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
maker | string | true | The Paradigm desk name that created the Quote. |
price | string | true | The price of the strategy in the Quote Currency of the RFQ. |
remaining_quantity | string | true | Total size of the Quote in contract units of the RFQ remaining. |
side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
status | string | true | The status of the Quote. Valid values include OPEN , CLOSED . |
client_order_id | string | true | A unique user created identifier for the Quote. |
order | object | false | Present if Quote crosses the existing market. |
> id | int | false | The Paradigm created unique identifier of the Order. |
> client_order_id | string | false | A unique user created identifier for the Order. |
> filled_quantity | string | false | The filled quantity of the Order in the contract units of the RFQ. |
> filled_average_price | string | false | The average filled price of the Order in the quote currency of the RFQ. |
> limit_price | string | false | The price of the Order in quote currency of the RFQ. |
> requested_quantity | string | false | The requested crossing quantity of the Order. |
> rfq_id | int | false | The Paradigm created unique identifier of the RFQ the Order is a child of. |
> side | string | false | The direction of the Order. Valid values include BUY and SELL . |
> status | string | false | The current status of the Order. Valid values include OPEN and CLOSED . |
> venue | string | false | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
original_quantity | string | true | Initial size of the Quote in contract units of the RFQ. |
rfq_id | int | true | The Paradigm created unique identifier of the RFQ the Quote is a child of. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 100 | "Invalid parameters" | Invalid parameters in request such as a non-unique client_order_id value. |
400 | 1302 | "Invalid account information" | The value provided with the account key should match the name given to the Exchange API key on the Paradigm Client Admin Dashboard. |
400 | 3203 | "Invalid leg parameters" | Ensure you are attempting to quote on the correct RFQ. Check your request format is correct. |
400 | 3303 | "An active BUY(SELL)-side quote already exists. Please cancel that quote before submitting a new quote." | Refer to error message. |
400 | 3304 | "Your Bid/Ask was canceled. It crossed the available Ask/Bid." | This occurs when you specify post_only == true and the submitted Quote crosses the market or if you cross your own existing Quote. |
400 | 3304 | "{instrument_name}. Bid/Ask price cannot be greater than Ask/Bid Price." | This occurs when the Bid/Ask price of a leg in the submitted Quote is greater than the Ask/Bid price of the same leg in an existing Quote. |
403 | N/A | "Maker Execution Limit Reached." | MMP has been triggered and the user must [PATCH] /v1/mmp/status to reset the protection to be able to quote. |
[PATCH] /rfqs/{rfq_id}/quotes/{quote_id}
/rfqs/{rfq_id}/quotes/ Request example
# built ins
import base64
import hmac
import time
import json
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# PATCH /v1/grfq/rfqs/{rfq_id}/quotes/{quote_id}/
method = 'PATCH'
path = '/v1/grfq/rfqs/1230/quotes/45678/'
payload = {
"account": "ParadigmTestNinetyFive",
"client_order_id": "1223322132123123321",
"quantity": "5000000",
"side": "BUY",
"legs": [
{
"instrument": "BTC-PERPETUAL",
"price": "38501"
}
],
"post_only": True
}
json_payload = json.dumps(payload)
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=json_payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.patch(host+path,
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
/rfqs/{rfq_id}/quotes/{quote_id}/ Response example
{
"id": 2776054,
"created": 1631589942042.397,
"maker": "DSK95",
"price": "0.09",
"remaining_quantity": "24",
"side": "BUY",
"status": "CLOSED",
"client_order_id": "stri1231321232121223231321132312213ng",
"order": {
"id": 266318,
"client_order_id": "stri1231321232121223231321132312213ng",
"filled_quantity": "0",
"filled_average_price": "0",
"limit_price": "0.09",
"requested_quantity": "50",
"rfq_id": 2073,
"side": "BUY",
"status": "OPEN",
"venue": "DBT"
},
"original_quantity": "24",
"rfq_id": 2073
}
Important note: this endpoint is proposed for deprecation, please use [PUT] /rfqs/{rfq_id}/quotes/{quote_id}/
instead.
A [PATCH] /rfqs/{rfq_id}/quotes/{quote_id}
request replaces an existing Quote upon a specific RFQ.
Takers & Makers use this endpoint to cross the existing market or update a resting Limit Order. Remaining amounts of the Quote remain on the Quote Book in the event of crossing.
If post_only
== true
and the submitted Quote crosses the existing market, the Quote is canceled in its entirety. This ensures you are always a Maker.
If a user submits a Quote which crosses the existing market, you will receive messages on both the quote
and order
JSON-RPCoverWebSockets Notification channels.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
rfq_id | endpoint | string | true | The unique Paradigm created identifier of the RFQ. |
quote_id | endpoint | string | true | The unique Paradigm created identifier of the Quote being replaced. |
account | body | string | true | The name of the Exchange API Key entered on your Client Admin dashboard. |
client_order_id | body | string | true | A unique user created identifier for the Quote. |
legs | body | array of objects | true | Array of objects containing the strategy’s legs' quotes' attributes. |
> instrument | body | string | true | The Paradigm standardized name of the Instrument. |
> price | body | string | true | The price of the individual leg's Instrument. |
quantity | body | string | true | The total quantity of the strategy in contract units of the RFQ. |
side | body | string | true | The direction of the Quote. Valid values include BUY and SELL . |
post_only | body | boolean | false | If true , the quote is canceled and never enters the Quote Book if it crosses the existing market. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
id | int | true | The Paradigm created unique identifier of the Quote. |
created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
maker | string | true | The Paradigm desk name that created the Quote. |
price | string | true | The price of the strategy in the Quote Currency of the RFQ. |
remaining_quantity | string | true | Total size of the Quote in contract units of the RFQ remaining. |
side | string | true | The direction of the Quote. Valid values include BUY and SELL . |
status | string | true | The status of the Quote. Valid values include OPEN , CLOSED . |
client_order_id | string | true | A unique user created identifier for the Quote. |
order | object | false | Present if Quote crosses the existing market. |
> id | int | false | The Paradigm created unique identifier of the Order. |
> client_order_id | string | false | A unique user created identifier for the Order. |
> filled_quantity | string | false | The filled quantity of the Order in the contract units of the RFQ. |
> filled_average_price | string | false | The average filled price of the Order in the quote currency of the RFQ. |
> limit_price | string | false | The price of the Order in quote currency of the RFQ. |
> requested_quantity | string | false | The requested crossing quantity of the Order. |
> rfq_id | int | false | The Paradigm created unique identifier of the RFQ the Order is a child of. |
> side | string | false | The direction of the Order. Valid values include BUY and SELL . |
> status | string | false | The current status of the Order. Valid values include OPEN and CLOSED . |
> venue | string | false | Underlying venue RFQ is cleared & settled upon. Valid values include DBT , BIT , BYB . |
original_quantity | string | true | Initial size of the Quote in contract units of the RFQ. |
rfq_id | int | true | The Paradigm created unique identifier of the RFQ the Quote is a child of. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 100 | "Invalid parameters" | Invalid parameters in request such as a non-unique client_order_id value. |
400 | 1302 | "Invalid account information" | The value provided with the account key should match the name given to the Exchange API key on the Paradigm Client Admin Dashboard. |
400 | 3203 | "Invalid leg parameters" | Ensure you are attempting to quote on the correct RFQ. Check your request format is correct. |
400 | 3303 | "An active BUY(SELL)-side quote already exists. Please cancel that quote before submitting a new quote." | Refer to error message. |
400 | 3304 | "Your Bid/Ask was canceled. It crossed the available Ask/Bid." | This occurs when you specify post_only == true and the submitted Quote crosses the market or if you cross your own existing Quote. |
400 | 3304 | "{instrument_name}. Bid/Ask price cannot be greater than Ask/Bid Price." | This occurs when the Bid/Ask price of a leg in the submitted Quote is greater than the Ask/Bid price of the same leg in an existing Quote. |
403 | N/A | "Maker Execution Limit Reached." | MMP has been triggered and the user must [PATCH] /v1/mmp/status to reset the protection to be able to quote. |
[POST] /pricing/
/pricing/ Request example
# built ins
import base64
import hmac
import time
import json
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# POST /v1/grfq/pricing/
method = 'POST'
path = '/v1/grfq/pricing/'
payload = {
"venue": "DBT",
"bid_price": "7950",
"ask_price": "9600",
"legs": [
{
"ratio": "1",
"instrument": "BTC-PERPETUAL",
"side": "BUY"
},
{
"ratio": "1",
"instrument": "BTC-31DEC21",
"side": "SELL"
}
]
}
json_payload = json.dumps(payload)
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=json_payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.post(host+path,
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
/pricing/ Response example
{
"bid_prices": ["32655.32", "24705.32"],
"ask_prices": ["33606.76", "24006.76"]
}
A [POST] /pricing/
request will return the individual leg prices of a proposed Quote.
This endpoint does not create a Quote or complete any operation upon the matching engine.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
venue | body | string | true | The underlying venue the Instruments in the RFQ are cleared & settled upon. Valid values include DBT , BIT , and BYB . |
bid_price | body | string | true | The total price of the Quote when the side is equal to BUY . |
ask_price | body | string | true | The total price of the Quote when the side is equal to SELL . |
legs | body | array of objects | true | The individual legs of the RFQ. |
> ratio | body | string | true | The quantity multiplier for the Strategy leg. |
> instrument | body | string | true | The name of the leg's Instrument per the underlying venue's naming convention. |
> side | body | string | true | The direction of the leg. Valid values include BUY and SELL . |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
bid_prices | array of numbers | true | The individual leg prices of the BUY sided quote in the order legs proposed in the user’s request. |
ask_prices | array of numbers | true | The individual leg prices of the SELL sided quote in the order legs proposed in the user’s request. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 3002 | "Invalid leg pricing parameters" | Invalid leg pricing parameters was requested. |
400 | 3304 | "Quote price {-2100.32 } outside strategy price bands ({7902.18 } / {9627.5 })" |
Quote must be within these price bands. |
[GET] /rfqs/{rfq_id}/bbo
/rfqs/{rfq_id}/bbo Request example
# You can also use wget
curl -X POST https://api.test.paradigm.co/v1/grfq/rfqs/131/bbo/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = 'Z9gBdD05yiHLotRCxrSeFTfC'
secret_key = b'9qgG7DU0XNaqF9n5Q35iQtL5Bv7JFNUffagT7/qC9jlH0exj'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.nightly.paradigm.co'
# GET /v1/grfq/rfqs/{rfq_id}/bbo
method = 'GET'
path = '/v1/grfq/rfqs/579/bbo'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/rfqs/{rfq_id}/bbo Response example
{
"venue": "DBT",
"best_bid": {
"price": "-33118.5",
"quantity": "0"
},
"best_ask": {
"price": "-1118",
"quantity": "148640"
},
"leg_prices": [
{
"instrument": "BTC-PERPETUAL",
"best_bid_price": "33118",
"best_bid_quantity": "148640",
"best_ask_price": "33118.5",
"best_ask_quantity": "491190",
"mark_price": "33077.21",
"timestamp": 1625189984659
},
{
"instrument": "BTC-24JUN22",
"best_bid_price": "0",
"best_bid_quantity": "0",
"best_ask_price": "32000",
"best_ask_quantity": "990000",
"mark_price": "31948.95",
"timestamp": 1625189984174
}
],
"mark_price": "-1128.26",
"product_code": "CF"
}
A [GET] /rfqs/{rfq_id}/bbo
request returns the best Bid/Offer information from the underlying venue for a specific RFQ.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The Paradigm created unique identifier of the RFQ. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
venue | string | true | The underlying venue where the RFQ's Instruments are cleared & settled upon. Valid values include DBT , BIT , and BYB . |
best_bid | array of objects | true | |
> price | string | true | The calculated best bid price of the RFQ’s strategy per the legs' underlying screen price in the Quote Currency of the RFQ. |
> quantity | string | true | The calculated best bid price of the RFQ’s strategy per the legs' underlying screen quantity in contract units of the RFQ. |
best_ask | array of objects | true | |
> price | string | true | The calculated best ask price of the RFQ’s strategy per the legs' underlying screen price in the Quote Currency of the RFQ. |
> quantity | string | true | The calculated best ask price of the RFQ’s strategy per the legs' underlying screen quantity in contract units of the RFQ. |
leg_prices | array of objects | true | |
> instrument | string | true | The Paradigm standardized name of the Instrument. |
> best_bid_price | string | true | The best bid on the underlying exchange’s Instrument Quote Book in the Quote Currency of the Instrument. |
> best_bid_quantity | string | true | The best bid’s quantity on the underlying exchange’s Instrument Quote Book in contract units of the RFQ. |
> best_ask_price | string | true | The best ask on the underlying exchange’s Instrument Quote Book in the Quote Currency of the Instrument. |
> best_ask_quantity | string | true | The best ask’s quantity on the underlying exchange’s Instrument Quote Book in contract units of the RFQ. |
> mark_price | string | true | The Mark price from the underlying exchange for specific Instrument in the Quote Currency of the Instrument. |
> timestamp | number | true | The time in unix milliseconds since the epoch when the data was returned from the underlying venue. |
mark_price | string | true | The calculated Mark Price of the strategy in the Quote Currency of the RFQ. |
product_code | string | true | The Paradigm created Product Code of in the Instruments involved in the RFQ. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
400 | 3300 | "Unavailable RFQ" | RFQ is unavailable to be priced. |
[GET] /rfqs/{rfq_id}/quotes/
/rfqs/{rfq_id}/quotes/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/rfqs/131/quotes/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/rfqs/{rfq_id}/quotes/
method = 'GET'
path = '/v1/grfq/rfqs/576/quotes/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/rfqs/{rfq_id}/quotes/ Response example
{
"id": 576,
"bids": [
{
"created": 1625167826211.088,
"id": 152748,
"price": "0.0078",
"remaining_quantity": "29943.7",
"side": "BUY",
"status": "OPEN",
"legs": [
{ "price": "1234", "side": "SELL" },
{ "price": "1235", "side": "BUY" }
]
}
],
"asks": [
{
"created": 1625173113830.57,
"id": 152762,
"price": "0.0084",
"remaining_quantity": "33.7",
"side": "SELL",
"status": "OPEN",
"legs": [
{ "price": "1234", "side": "SELL" },
{ "price": "1235", "side": "BUY" }
]
}
]
}
A [GET] /rfqs/{rfq_id}/quotes/
request returns the OPEN
Quotes upon the RFQ.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | endpoint | string | true | The Paradigm created unique identifier of the RFQ. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
id | int | true | The Paradigm created unique identifier of the RFQ. |
bids | array of objects | true | Empty array if no Quotes are available. |
> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
> id | int | true | The Paradigm created unique identifier of the Quote. |
> maker | string | false | The Paradigm Desk Name of the Maker who created the quote. Only visible if requester is the Maker. |
> remaining_quantity | string | true | The total remaining size of the Quote in the contract units of the RFQ. |
> price | string | true | The price of the Quote in the Quote Currency of the RFQ. |
> side | string | true | The direction of the Quote. Valid values include BUY . |
> status | string | true | The status of the Quote. Valid values include OPEN |
> legs | array of objects | true | The price and side of the legs |
>> price | string | true | The price of individual legs |
>> side | string | true | The BUY or SELL side of the individual legs |
asks | array of objects | true | Empty array if no Quotes are available. |
> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
> id | int | true | The Paradigm created unique identifier of the Quote. |
> maker | string | false | The Paradigm Desk Name of the Maker who created the quote. Only visible if requester is the Maker. |
> remaining_quantity | string | true | The total remaining size of the Quote in the contract units of the RFQ. |
> price | string | true | The price of the Quote in the Quote Currency of the RFQ. |
> side | string | true | The direction of the Quote. Valid values include SELL . |
> status | string | true | The status of the Quote. Valid values include OPEN |
> legs | array of objects | true | The price and side of the legs |
>> price | string | true | The price of individual legs |
>> side | string | true | The BUY or SELL side of the individual legs |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials |
400 | 3300 | "Unavailable RFQ" | RFQ is unavailable to be priced. |
[GET] /trades/
/trades/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/trades/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
import json
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/trades/
method = 'GET'
path = '/v1/grfq/trades/'
payload = {}
json_payload = json.dumps(payload)
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=json_payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers,
json=payload)
print(response.status_code)
print(response.text)
/trades/ Response example
{
"count": 909,
"next": "cD0yMDIxLTA3LTI3KzE2JTNBMjElM0EyMC40MTQ3MjMlMkIwMCUzQTAw",
"results": [
{
"id": 1221,
"description": "FSpd Perpetual / 31 Dec 21",
"mark_price": "1544.18",
"order_id": 1094,
"price": "1550",
"product_codes": ["CF"],
"quantity": "10000",
"quote_currency": "USD",
"quote_id": 616016,
"rfq_id": 1178,
"traded": 1627440685659.369,
"venue": "DBT",
"action": "BUY",
"api_credential": "ParadigmTestNinetyFive",
"client_order_id": "",
"status": "COMPLETED"
},
{
"id": 1219,
"description": "Cstm -13.3 Future Perpetual\n +1 Future 30 Jul 21\n +19.9 Future 6 Aug 21",
"mark_price": "289592.31",
"price": "289467.236",
"product_code": "CF",
"quantity": "586",
"quote_currency": "USD",
"rfq_id": 1176,
"traded": 1627419839512.485,
"venue": "DBT"
},
{
"id": 1217,
"description": "Cstm +1 Put 30 Jul 21 38000\n -1 Put 30 Jul 21 40000",
"mark_price": "-0.0285",
"price": "-0.0005",
"product_code": "DO",
"quantity": "13",
"quote_currency": "BTC",
"rfq_id": 1174,
"traded": 1627418321044.7131,
"venue": "DBT"
},
{
"id": 1216,
"description": "Cstm +1 Future Perpetual\n +1.7 Future 31 Dec 21\n +2.8 Future 24 Sep 21",
"mark_price": "210922.959",
"price": "211492",
"product_code": "BB",
"quantity": "5",
"quote_currency": "USD",
"rfq_id": 1172,
"traded": 1627402886964.928,
"venue": "BYB"
},
{
"id": 1215,
"description": "Cstm +1 Future Perpetual\n +1.7 Future 31 Dec 21\n +2.8 Future 24 Sep 21",
"mark_price": "211042.936",
"price": "211492",
"product_code": "BB",
"quantity": "4",
"quote_currency": "USD",
"rfq_id": 1172,
"traded": 1627402880414.723,
"venue": "BYB"
}
]
}
A [GET] /trades/
request returns all completed Trades on Paradigm.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | The pagination page to return. Valid determined by the next key value in the response. |
hide_public | query | string | false | Hide non-participant trades from results. Valid values include true and false . |
page_size | query | string | false | The number of Trades to return per pagination. |
status | query | string | false | The state of the Trades to return. Valid values include PENDING , COMPLETED , REJECTED . |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of Trades to paginate through from request. |
next | string | true | null if no more pages to paginate. The value used for the cursor query string parameter to paginate pages. |
results | array of objects | true | |
> id | int | true | The Paradigm created unique identifier of the Trade. |
> description | string | true | The description of the RFQ. |
> mark_price | string | true | The mark price of the RFQ at execution in the Quote Currency of the RFQ using the underlying venue's mark price(s) of the RFQ. |
> order_id | int | false | The Paradigm created unique identifier of the Order if the user is the Taker of the Trade. |
> price | string | true | The price in the Quote Currency of the RFQ of the Trade. |
> product_codes | array of strings | true | The Paradigm created product codes being traded in the RFQ. |
> quantity | string | true | The size of the trade in contract units of the RFQ. |
> quote_currency | string | true | The Quote Currency of the RFQ. |
> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
> status | string | true | Trade status. Valid values include PENDING , COMPLETED , REJECTED . |
> traded | number | true | The time in unix milliseconds since the epoch when the was cleared & settled at. |
> venue | string | true | The underlying venue the Trade was cleared & settled upon. Valid values include DBT , BIT , BYB . |
> action | string | false | The side of the Order. Only available if the requester is the Taker of the Trade. Valid values include BUY and SELL . |
> api_credential | string | false | The name of the exchange API key used to execute upon the Quote. Only available if the requester is the Taker to the Trade. |
> client_order_id | string | false | The user created Order label if the user is the Taker of the Trade. |
> quote_id | int | false | The Paradigm created unique identifier of the executed Quote. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
404 | N/A | "Invalid cursor" | Use the string value from the next key in the first response to paginate. |
[GET] /trades/{trade_id}/
/trades/{trade_id}/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/trades/50/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/trades/{trade_id}/
method = 'GET'
path = '/v1/grfq/trades/473/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/trades/{trade_id}/ Response example - User's Trade
COMPLETED
{
"id": 1221,
"description": "FSpd Perpetual / 31 Dec 21",
"mark_price": "1544.18",
"order_id": 1094,
"price": "1550",
"product_codes": ["CF"],
"quantity": "10000",
"quote_currency": "USD",
"quote_id": 616016,
"rfq_id": 1178,
"traded": 1627440685659.369,
"venue": "DBT",
"action": "BUY",
"api_credential": "ParadigmTestNinetyFive",
"client_order_id": "",
"status": "COMPLETED",
"legs": [
{
"id": 1989,
"instrument": "BTC-PERPETUAL",
"price": "39952.58",
"product_code": "CF",
"quantity": "10000",
"ratio": "1",
"side": "SELL",
"action": "SELL",
"exec_id": "77508944"
},
{
"id": 1990,
"instrument": "BTC-31DEC21",
"price": "41502.58",
"product_code": "CF",
"quantity": "10000",
"ratio": "1",
"side": "BUY",
"action": "BUY",
"exec_id": "77508943"
}
]
}
/trades/{trade_id}/ Response example - User's Trade
REJECTED
{
"id": 1220,
"description": "FSpd Perpetual / 31 Dec 21",
"mark_price": "1537.57",
"order_id": 1093,
"price": "1550",
"product_codes": ["CF"],
"quantity": "10000",
"quote_currency": "USD",
"quote_id": 616014,
"rfq_id": 1178,
"traded": 1627440566959.332,
"venue": "DBT",
"action": "BUY",
"api_credential": "ParadigmTestNinetyFive",
"client_order_id": "",
"status": "REJECTED",
"legs": [
{
"id": 1987,
"instrument": "BTC-PERPETUAL",
"price": "39900.66",
"product_code": "CF",
"quantity": "10000",
"ratio": "1",
"side": "SELL",
"action": "SELL",
"exec_id": null
},
{
"id": 1988,
"instrument": "BTC-31DEC21",
"price": "41450.66",
"product_code": "CF",
"quantity": "10000",
"ratio": "1",
"side": "BUY",
"action": "BUY",
"exec_id": null
}
]
}
/trades/{trade_id}/ Response example - User is not a counterparty on the trade, and trade is
COMPLETED
{
"id": 587,
"description": "Call 22 Oct 21 52000",
"mark_price": "0.0788",
"price": "0.09",
"product_codes": ["DO"],
"quantity": "25",
"quote_currency": "BTC",
"rfq_id": 1118,
"traded": 1634064072771.3809,
"venue": "DBT",
"legs": [
{
"id": 862,
"instrument": "BTC-22OCT21-52000-C",
"price": "0.09",
"product_code": "DO",
"quantity": "25",
"ratio": "1",
"side": "BUY"
}
]
}
A [GET] /trades/{trade_id}/
request returns a specific Trade on Paradigm.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
id | query | string | true | The Paradigm created unique identifier of the Trade. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of Trades to paginate through from request. |
next | string | true | null if no more pages to paginate. The value used for the cursor query string parameter to paginate pages. |
results | array of objects | true | |
> id | int | true | The Paradigm created unique identifier of the Trade. |
> description | string | true | The description of the RFQ. |
> mark_price | string | true | The mark price of the RFQ at execution in the Quote Currency of the RFQ using the underlying venue's mark price(s) of the RFQ. |
> price | string | true | The price in the Quote Currency of the RFQ of the Trade. |
> product_codes | array of strings | true | The Paradigm created product codes being traded in the RFQ. |
> quantity | string | true | The size of the trade in contract units of the RFQ. |
> quote_currency | string | true | The Quote Currency of the RFQ. |
> rfq_id | int | true | The Paradigm created unique identifier of the RFQ. |
> traded | number | true | The time in unix milliseconds since the epoch when the was cleared & settled at. |
> venue | string | true | The underlying venue the Trade was cleared & settled upon. Valid values include DBT , BIT , BYB . |
> legs | array of objects | true | |
>> id | int | false | The Paradigm created unique individual leg trade identifier. |
>> instrument | string | true | The Paradigm standardized name of the Instrument. |
>> quantity | string | true | The size of the leg traded in contract unit terms. |
>> price | string | true | The price of the leg traded in the Quote Currency of the RFQ. |
>> product_code | string | true | The Paradigm created product code of the Instrument traded. |
>> ratio | string | true | The quantity multiplier relative to other Instrument legs. |
>> side | string | false | The direction of the leg of the original RFQ. Valid values include BUY and SELL . This does not reveal the direction of the Trade. |
>> action | string | false | The direction of the user for the specific leg of the RFQ. Valid values include BUY and SELL . |
>> exec_id | string | false | The venue created unique identifier of the trade. |
> api_credentials | string | false | The name of venue API key used by the user in the Trade. |
> client_order_id | string | false | The user created unique identifier. |
> status | string | true | If the trade successfully cleared & settled on the underlying venue. Valid values include COMPLETED and REJECTED . |
Error Codes
HTTP Status Code | Message | Meaning |
---|---|---|
401 | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
404 | "Not found." | Invalid Trade Id value requested. |
[GET] /mmp/status/
/mmp/status/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/grfq/mmp/status/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/grfq/mmp/status/
method = 'GET'
path = '/v1/grfq/mmp/status/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(host+path,
headers=headers)
print(response.status_code)
print(response.text)
/mmp/status/ Response example
{
"rate_limit_hit": false
}
A [GET] /mmp/status/
request returns the desk's Market Maker Protection (MMP) status.
This endpoint takes no parameters as part of the request.
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
rate_limit_hit | bool | true | A flag indicating if rate limit was hit |
[PATCH] /mmp/status/
/mmp/status/ Request example
# You can also use wget
curl -X PATCH https://api.test.paradigm.co/v1/grfq/mmp/status/ \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# PATCH /v1/grfq/mmp/status/
method = 'PATCH'
path = '/v1/grfq/mmp/status/'
payload = ''
timestamp, signature = sign_request(secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.patch(host+path,
headers=headers)
print(response.status_code)
print(response.text)
A [PATCH] /mmp/status/
resets the Market Maker Protection (MMP) if triggered and enables the user to create new Quotes.
This endpoint takes no parameters as part of the request.
Response Schema
This request will return an HTTP Status Code of 204 to indicate success of operation.
Status Code 204
VRFQ - API Workflows
High Level
VRFQ is centred around the concepts of "RFQs", "Quotes", "Orders" and "Trades":
- RFQs are strategies comprised of one or more instruments with Taker defined attributes. RFQs are to be Quoted upon by the Makers.
- Quotes are created by the Maker in response to a requested RFQ.
- Orders are created by the Taker to execute upon existing Quotes.
- Trades occur when the Taker executes upon an existing Quote on an RFQ.
At a high level, the VRFQ workflow is:
- Taker creates an RFQ with the desired Instruments and quantity ratios.
- Makers Quote the RFQ.
- Takers can execute an Order upon an RFQ and consume the Quote which suits the set Limit Price & venue enforced "Block Size Minimums".
- Once a Quote and an Order are matched, the executions are sent to the underlying venue for clearing & settlement.
- The Maker receives confirmation if clearing & settlement was successful or rejected.
- All Makers are able to see cleared & settled Trades, but NOT the counterparties or the traded RFQ/Order/Quote
side
.
Key VRFQ Concepts
In VRFQ,
- All Users act as Makers and the RFQs are always settled by the Venue platform who acts as a Taker
- RFQs are public auctions and all quotes are blind.
- All trades are on an anonymous basis with no participant or directional information revealed.
- There aren't partials fills of Quotes and Orders, all orders or All-Or-None.
- It is not possible to have multiple Trades and a single Order can’t consume more than a Quote.
- WebSocket messages will contain two keys, kind and status. You should use these keys to know the status and finality of the concept it's referring too.
Common Workflows
Important Note: the _Maker will receive all updates through the JSON-RPCoverWebSockets Notification channels for events relating to RFQs, Quotes, Orders and Trades.
Check for RFQ
If you would like to check if an RFQ exists you should request the RESToverHTTP [GET] /rfqs/
endpoint.
Submit a Quote on an RFQ
Users are able to submit a Quote for an existing RFQ.
You should request the RESToverHTTP [POST] /rfqs/{rfq_id}/quotes/
endpoint.
Replace an existing Quote on an RFQ
Users are able to replace a previously submitted Quote for an existing RFQ.
You should request the RESToverHTTP [PUT] /rfqs/{rfq_id}/quotes/{quote_id}/
endpoint.
Cancel a Quote on an RFQ
Users are able to cancel their own Quotes.
You should request the RESToverHTTP [DELETE] /rfqs/{rfq_id}/quotes/
endpoint.
Pull available Quote on an RFQ
Users are able to fetch their own Quotes for an available RFQ.
You should request the RESToverHTTP [GET] /rfqs/{rfq_id}/quotes/
endpoint.
Comprehensive API Workflow Paths
RFQ Created
- Subscribed to
rfq
WS Channel. - Receives WS message with
kind
==ADDED
,status
==ACTIVE
.
RFQ Expires
- Subscribed to
rfq
WS Channel. - Receives a WS message with
kind
==REMOVED
,status
==EXPIRED
.
Quote Created
- Subscribed to the
quote
WS Channel. - Maker sends request to create a Quote
- Once quote is created, Maker will asynchronously receive a WS messages on
quote
WS Channel withkind
==NEW
andstatus
==OPEN
.
Quote Canceled
- Subscribed to the
quote
WS Channel. - Maker sends request to cancel a Quote
- Once quote is canceled, Maker will asynchronously receive a WS messages on
quote
WS Channel withkind
==CANCELED
andstatus
==CLOSED
.
Matched Quote and Order
- Subscribed to
quote
andtrade
WS Channels. - Asynchronously the Maker receives a WS message on
quote
WS Channel withkind
==PENDING_FILL
andstatus
==CLOSED
. - Trade is executed:
- If Trade execution is successful at clearing & settlement:
- Asynchronously the Maker receives a WS message on
trade
WS channel withkind
==COMPLETED
andstatus
==COMPLETED
. - Asynchronously the Maker receives a WS message on
quote
WS channel withkind
==FILLED
andstatus
==CLOSED
.
- Asynchronously the Maker receives a WS message on
- If Trade execution is rejected at clearing & settlement:
- Asynchronously the Maker receives WS messages on
trade
WS channel withkind
==REJECTION
andstatus
==REJECTED
. - Asynchronously the Maker receives WS messages on
quote
WS channel withkind
==CANCELED
andstatus
==CLOSED
.
- Asynchronously the Maker receives WS messages on
- If Trade execution is successful at clearing & settlement:
VRFQ - Code Examples
Reach out if you ever need any help! We are more than happy to help.
You will need to update the provided Code Examples with your own Paradigm Access Key and Secret Key.
You can find all existing examples on our GitHub: https://github.com/tradeparadigm/code-samples/tree/main/python/api/vrfq
Note: All examples in this section are in Python3.
VRFQ - WebSocket Notifications Channels
rfq
An example of the
rfq
notification received when an RFQ is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"kind": "ADDED",
"rfq": {
"auction": {
"swap_id": 30,
"seller": "0x...",
"offered_token": "0x...",
"bidding_token": "0x...",
"min_price": "0.000001",
"total_size": "5"
},
"created": 1659369985489.624,
"currency": "USDC",
"description": "Put 13 May 22 2000 0.01x",
"domain": {
"chain_id": 42,
"contract_name": "RIBBON SWAP",
"version": "1",
"verifying_contract": "0x..."
},
"id": 18,
"legs": [
{
"instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P",
"product_code": "USDC",
"ratio": "1",
"venue_instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P"
}
],
"min_tick_size": "0.1",
"product_name": "RBN - USDC Option (KVN)",
"quantity": "0.01000000",
"quote_currency": "USDC",
"referrer": "0x...",
"status": "ACTIVE",
"taker": "AAAA",
"venue": "RBN"
}
}
}
}
An example of the
rfq
notification received when an RFQ is removed
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"kind": "REMOVED",
"rfq": {
"auction": {
"swap_id": 30,
"seller": "0x...",
"offered_token": "0x...",
"bidding_token": "0x...",
"min_price": "0.000001",
"total_size": "5"
},
"created": 1659369880968.851,
"currency": "USDC",
"description": "Put 13 May 22 2000 0.01x",
"domain": {
"chain_id": 42,
"contract_name": "RIBBON SWAP",
"version": "1",
"verifying_contract": "0x..."
},
"id": 17,
"legs": [
{
"instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P",
"product_code": "USDC",
"ratio": "1",
"venue_instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P"
}
],
"min_tick_size": "0.1",
"product_name": "RBN - USDC Option (KVN)",
"quantity": "0.01000000",
"quote_currency": "USDC",
"referrer": "0x...",
"status": "CANCELED",
"taker": "AAAA",
"venue": "RBN",
"canceled": 1659369959411.0
}
}
}
}
An example of the
rfq
notification received when an RFQ is completed
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "rfq",
"data": {
"kind": "COMPLETED",
"rfq": {
"auction": {
"swap_id": 30,
"seller": "0x...",
"offered_token": "0x...",
"bidding_token": "0x...",
"min_price": "0.000001",
"total_size": "5"
},
"created": 1659369985489.624,
"currency": "USDC",
"description": "Put 13 May 22 2000 0.01x",
"domain": {
"chain_id": 42,
"contract_name": "RIBBON SWAP",
"version": "1",
"verifying_contract": "0x..."
},
"id": 18,
"legs": [
{
"instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P",
"product_code": "USDC",
"ratio": "1",
"venue_instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P"
}
],
"min_tick_size": "0.1",
"product_name": "RBN - USDC Option (KVN)",
"quantity": "0.01000000",
"quote_currency": "USDC",
"referrer": "0x...",
"status": "COMPLETED",
"taker": "PARA0",
"venue": "RBN"
}
}
}
}
All updates relating to RFQs are sent through the rfq
WebSocket Notifications channel.
This is a public channel and consumable by all the Makers.
Notifications received through the rfq
WebSocket channel can include RFQ creations, expirations, and completions.
Member | Type | Required | Description |
---|---|---|---|
jsonrpc | string | true | The version of the JSON-RPC protocol. Always "2.0". |
method | string | true | The name of the invoked method. Valid value is subscription . |
params | object | true | |
> channel | string | true | WebSocket Notification Channel message is received upon. Valid value is rfq . |
> data | object | true | |
>> kind | string | true | WS Action. Valid values include ADDED , COMPLETED , REMOVED . |
>> rfq | object | true | |
>>> auction | object | true | |
>>>> swap_id | number | true | The Paradigm created unique identifier of the auction. |
>>>> seller | string | true | Wallet address of the seller (the trader who initiates the auction). |
>>>> offered_token | string | true | Address of the token offered by the seller, in hex format with 0x prefix. |
>>>> bidding_token | string | true | Address of the token used by the buyer to bid for in the auction, in hex format with 0x prefix. |
>>>> min_price | string | true | The minimum price the RFQ can be Traded at. |
>>>> total_size | string | true | Total amount of contracts (tokens) of offered_token being sold in the auction. |
>>> created | number | true | Time in unix milliseconds since the epoch when the RFQ was created. |
>>> currency | string | true | The currency of the option being offered. |
>>> description | string | true | Paradigm created description of the RFQ. |
>>> domain | object | true | |
>>>> chain_id | number | true | The Paradigm unique identifier assigned to the blockchain (e.g. Ethereum, Avalanche, Solana). |
>>>> contract_name | string | true | Name of the venue's smart contract. |
>>>> version | string | true | Version of the venue's smart contract. |
>>>> verifying_contract | string | true | Address of the venue smart contract used to settle the transaction, in hex format with 0x prefix. |
>>> id | number | true | The Paradigm created unique identifier of the RFQ. |
>>> legs | array of objects | true | |
>>>> instrument | string | true | The Paradigm standardized name of the Instrument. |
>>>> product_code | string | true | The Paradigm created product code of the Instrument. |
>>>> ratio | string | true | The quantity multiple relative to other legs. |
>>>> venue_instrument | string | true | The name of the Instrument for the underlying venue's naming convention. |
>>> min_tick_size | string | true | Minimum tick size specified by the underlying venue's contract. |
>>> product_name | string | true | The Paradigm created product name for the Instrument. |
>>> quantity | string | true | The size of the trade in the contract units of the RFQ. |
>>> quote_currency | string | true | The currency which will be used to quote the RFQ. |
>>> referrer | string | true | Address of the Paradigm wallet used to receive the fee, in hex format with 0x prefix. |
>>> status | string | true | Status of the RFQ. Valid values include ACTIVE , CANCELED and COMPLETED . |
>>> taker | string | true | The Paradigm desk name of the Taker who created the RFQ. |
>>> venue | string | true | The underlying venue the RFQ is cleared and settled upon. Valid values include RBN. |
quote
An example of the
quote
notification received when a Quote is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "NEW",
"quote": {
"id": 12,
"created": 1659370032469.147,
"maker": "BLOO0",
"price": "0.10000000",
"quantity": "0.01000000",
"rfq_id": 18,
"status": "OPEN",
"signed_bid": {
"buy_amount": "1000000",
"nonce": "273494617",
"referrer": "0x...",
"sell_amount": "1000",
"signer_wallet": "0x...",
"signature": "...",
"swap_id": 123
}
}
}
}
}
An example of the
quote
notification received when an Order is created
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "PENDING_FILL",
"quote": {
"id": 12,
"created": 1659370032469.147,
"maker": "BLOO0",
"price": "0.10000000",
"quantity": "0.01000000",
"rfq_id": 18,
"status": "CLOSED",
"signed_bid": {
"buy_amount": "1000000",
"nonce": "273494617",
"referrer": "0x...",
"sell_amount": "1000",
"signer_wallet": "0x...",
"signature": "...",
"swap_id": 123
}
}
}
}
}
An example of the
quote
notification received when an Order is filled
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "quote",
"data": {
"kind": "FILLED",
"quote": {
"id": 12,
"created": 1659370032469.147,
"maker": "BLOO0",
"price": "0.10000000",
"quantity": "0.01000000",
"rfq_id": 18,
"status": "CLOSED",
"signed_bid": {
"buy_amount": "1000000",
"nonce": "273494617",
"referrer": "0x...",
"sell_amount": "1000",
"signer_wallet": "0x...",
"signature": "...",
"swap_id": 123
}
}
}
}
}
All updates relating to Quotes upon RFQs are sent through the quote
WebSocket Notifications channel.
This is a private channel and only provides updates to the Maker who created the Quote.
Updates received through the quote
WebSocket Notification channel can include newly created quotes, removed quotes, quotes pending settlement & clearing, quotes which are filled.
Workflow Steps:
- Maker creates Quote.
kind
==NEW
&status
==OPEN
. - Maker removes Quote.
kind
==CANCELED
&status
==CLOSED
. - Taker executes upon a Quote, but the Trade is rejected by the underlying venue.
kind
==CANCELED
&status
==CLOSED
. - Taker completely executes quote.
kind
==FILLED
&status
==CLOSED
.
Member | Type | Required | Description |
---|---|---|---|
jsonrpc | string | true | The version of the JSON-RPC protocol. Always "2.0". |
method | string | true | The name of the invoked method. Valid value is subscription . |
params | object | true | |
> channel | string | true | WebSocket Notification Channel message is received upon. Valid value is quote . |
> data | object | true | |
>> kind | string | true | The action of the message. Valid values include NEW , CANCELED , PENDING_FILL , FILLED . |
>> quote | object | true | |
>>> id | number | true | The Paradigm created unique identifier of the Quote. |
>>> created | number | true | The time in unix milliseconds since the epoch when the Quote was created. |
>>> maker | string | true | The Paradigm desk name of the Maker. |
>>> price | string | true | The price of the Quote in the Quote Currency of the RFQ. |
>>> quantity | string | true | The requested crossing quantity of the Quote. |
>>> rfq_id | number | true | The Paradigm created unique identifier of the RFQ the Quote is a child of. |
>>> status | string | true | The current status of the Quote. Valid values include OPEN and CLOSED . |
>>> signed_bid | object | ||
>>>> buy_amount | string | true | Total amount of contracts to be purchased by the buyer, typically the same as the total_size. |
>>>> nonce | string | true | Arbitrary random or pseudo-random number, to be used just once. |
>>>> referrer | string | true | Address of the Paradigm wallet used to receive the fee, in hex format with 0x prefix. |
>>>> sell_amount | string | true | Total amount of sold contracts. |
>>>> swap_id | number | true | The Paradigm created unique identifier of the auction. |
>>>> signer_wallet | string | true | Address of the wallet who signed the message, in hex format with 0x prefix. |
>>>> signature | string | true | ECDSA or EdDSA signature. |
trade
An example of the
trade
notification received when a Trade is completed
{
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "trade",
"data": {
"kind": "COMPLETED",
"trade": {
"id": 2,
"description": "Put 13 May 22 2000 0.01x",
"price": "0.1",
"product_name": "RBN - USDC Option (KVN)",
"quantity": "0",
"quote_id": 12,
"quote_currency": "USDC",
"rfq_id": 18,
"status": "COMPLETED",
"traded": 1659370234769.133
}
}
}
Updates relating to Trades upon RFQs are sent through the trade WebSocket Notifications channel.
This is a private channel and only provides updates to the Maker of the Trade (matching of an Order and a Quote).
Updates received through the trade WebSocket Notification channel can include trade success and rejection at clearing & settlement.
Member | Type | Required | Description |
---|---|---|---|
jsonrpc | string | true | The version of the JSON-RPC protocol. Always "2.0". |
method | string | true | The name of the invoked method. Valid value is subscription . |
params | object | true | |
> channel | string | true | WebSocket Notification Channel message is received upon. Valid value is trade . |
> data | object | true | |
>> kind | string | true | The action of the WS Message. Valid values include COMPLETED and REJECTION . |
>> trade | object | true | |
>>> id | number | true | The Paradigm created unique identifier of the Trade. |
>>> description | string | true | The Paradigm created description of the RFQ. |
>>> price | string | true | The price the Trade was executed at in the Quote Currency of the RFQ. |
>>> product_name | string | true | The Paradigm created product name for the Instrument. |
>>> quantity | string | true | The size of the trade in contracts units of the RFQ. |
>>> quote_id | number | true | The Paradigm created unique identifier of the Quote executed upon. |
>>> quote_currency | string | true | The Quote Currency of the RFQ executed upon. |
>>> rfq_id | number | true | The Paradigm created unique identifier of the RFQ. |
>>> status | string | true | Trade status. Valid values include COMPLETED , REJECTED . |
>>> traded | number | true | The time in unix milliseconds since the epoch when the trade was cleared and settled. |
VRFQ - REST Endpoints
[GET] /rfqs/
/rfqs/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/vrfq/rfqs/ \
-H 'Accept: application/json' \
-H 'Paradigm-API-Timestamp: <timestamp>' \
-H 'Paradigm-API-Signature: <signature>' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/vrfq/rfqs/
method = 'GET'
path = '/v1/vrfq/rfqs/'
payload = ''
timestamp, signature = sign_request(
secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(
f"{host}{path}",
headers=headers
)
print(response.status_code)
print(response.text)
{
"count": 2,
"next": null,
"results": [
{
"auction": {
"swap_id": 1234,
"seller": "0x...",
"offered_token": "0x...",
"bidding_token": "0x...",
"min_price": "0.000001",
"total_size": "5"
},
"created": 1659332627432.214,
"currency": "USDC",
"description": "Put 13 May 22 2000 0.01x",
"domain": {
"chain_id": 42,
"contract_name": "RIBBON SWAP",
"version": "1",
"verifying_contract": "0x..."
},
"id": 15,
"legs": [
{
"instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P",
"product_code": "USDC",
"ratio": "1",
"venue_instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P"
}
],
"min_tick_size": "0.1",
"product_name": "RBN - USDC Option (KVN)",
"quantity": "0.01000000",
"quote_currency": "USDC",
"referrer": "0x...",
"status": "ACTIVE",
"taker": "AAAA",
"venue": "RBN"
},
{
"auction": {
"swap_id": 1234,
"seller": "0x...",
"offered_token": "0x...",
"bidding_token": "0x...",
"min_price": "0.000001",
"total_size": "5"
},
"created": 1658999093574.449,
"currency": "USDC",
"description": "Put 13 May 22 2000 0.01x",
"domain": {
"chain_id": 42,
"contract_name": "RIBBON SWAP",
"version": "1",
"verifying_contract": "0x..."
},
"id": 14,
"legs": [
{
"instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P",
"product_code": "USDC",
"ratio": "1",
"venue_instrument": "DEFI-RBN-ETH-WETH-USDC-13May22-2000-P"
}
],
"min_tick_size": "0.1",
"product_name": "RBN - USDC Option (KVN)",
"quantity": "0.01000000",
"quote_currency": "USDC",
"referrer": "0x...",
"status": "CANCELED",
"taker": "AAAA",
"venue": "RBN"
}
]
}
A [GET] /rfqs/
request allows you to return a paginated list of RFQs.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | Cursor value used to paginate through pages. |
page_size | query | string | false | Number of RFQs returned per pagination. |
status | query | string | false | List of status separated by comma. Valid values are: ACTIVE,CANCELED,COMPLETED,EXPIRED. Example /v1/vrfq/rfqs/?status=ACTIVE,COMPLETED . |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of RFQs to paginate. |
next | string | true | Pagination cursor value. |
results | array of objects | true | |
> auction | object | true | |
>> swap_id | number | true | The Paradigm created unique identifier of the auction. |
>> seller | string | true | Wallet address of the seller (the trader who initiates the auction). |
>> offered_token | string | true | Address of the token offered by the seller, in hex format with 0x prefix. |
>> bidding_token | string | true | Address of the token used by the buyer to bid for in the auction, in hex format with 0x prefix. |
>> min_price | string | true | The minimum price the RFQ can be Traded at. |
>> total_size | string | true | Total amount of contracts (tokens) of offered_token being sold in the auction. |
> created | number | true | Time in unix milliseconds since the epoch when the RFQ was created. |
> description | string | true | Paradigm created description of the RFQ. |
> domain | object | true | |
>> chain_id | number | true | The Paradigm unique identifier assigned to the blockchain (e.g. Ethereum, Avalanche, Solana). |
>> contract_name | string | true | Name of the venue's smart contract. |
>> version | string | true | Version of the venue's smart contract. |
>> verifying_contract | string | true | Address of the venue smart contract used to settle the transaction, in hex format with 0x prefix. |
> id | number | true | The Paradigm created unique identifier of the RFQ. |
> legs | array of objects | true | |
>> instrument | string | true | The Paradigm standardized name of the Instrument. |
>> product_code | string | true | The Paradigm created product code of the Instrument. |
>> ratio | string | true | The quantity multiple relative to other legs. |
>> venue_instrument | string | true | The name of the Instrument for the underlying venue's naming convention. |
> min_tick_size | string | true | Minimum tick size specified by the underlying venue's contract. |
> product_name | string | true | The Paradigm created product name for the Instrument. |
> quantity | string | true | The size of the trade in the contract units of the RFQ. |
> referrer | string | true | Address of the Paradigm wallet used to receive the fee, in hex format with 0x prefix. |
> status | string | true | Status of the RFQ. Valid values include ACTIVE , CANCELED , COMPLETED and EXPIRED |
> taker | string | true | The Paradigm desk name of the Taker who created the RFQ. |
Error Codes
HTTP Status Code | Code | Message | Meaning |
---|---|---|---|
401 | N/A | "Authentication credentials provided were not provided." | You did not provide authentication credentials. |
401 | N/A | "Invalid API Access Key." | You provided an invalid API Access Key. |
404 | N/A | "Invalid cursor" | Use the string value from the next key in the first response to paginate. |
[GET] /quotes/
/quotes/ Request example
# You can also use wget
curl -X GET https://api.test.paradigm.co/v1/vrfq/quotes/ \
-H 'Accept: application/json' \
-H 'Paradigm-API-Timestamp: <timestamp>' \
-H 'Paradigm-API-Signature: <signature>' \
-H 'Authorization: Bearer <access-key>'
# built ins
import base64
import hmac
import time
# installed
import requests
access_key = '<access-key>'
secret_key = b'<secret-key>'
def sign_request(secret_key, method, path, body):
signing_key = base64.b64decode(secret_key)
timestamp = str(int(time.time() * 1000)).encode('utf-8')
message = b'\n'.join([timestamp, method.upper(), path, body])
digest = hmac.digest(signing_key, message, 'sha256')
signature = base64.b64encode(digest)
return timestamp, signature
# Request Host
host = 'https://api.test.paradigm.co'
# GET /v1/vrfq/quotes/
method = 'GET'
path = '/v1/vrfq/quotes/'
payload = ''
timestamp, signature = sign_request(
secret_key=secret_key,
method=method.encode('utf-8'),
path=path.encode('utf-8'),
body=payload.encode('utf-8'),
)
headers = {
'Paradigm-API-Timestamp': timestamp,
'Paradigm-API-Signature': signature,
'Authorization': f'Bearer {access_key}'
}
# Send request
response = requests.get(
f"{host}{path}",
headers=headers
)
print(response.status_code)
print(response.text)
/quotes/ Response example
{
"count": 2,
"next": null,
"results": [
{
"id": 9,
"created": 1659354419040.884,
"maker": "MMMM",
"price": "0.10000000",
"quantity": "0.01000000",
"rfq_id": 15,
"status": "OPEN",
"signed_bid": {
"buy_amount": "1000000",
"nonce": "132729633",
"referrer": "0x...",
"sell_amount": "1000",
"signer_wallet": "0x...",
"signature": "...",
"swap_id": 123
},
{
"id": 8,
"created": 1658999051597.919,
"maker": "MMMM",
"price": "0.10000000",
"quantity": "0.01000000",
"rfq_id": 13,
"status": "CLOSED",
"canceled": 1658999076341.906,
"canceled_reason": "RFQ_CANCELED",
"signed_bid": {
"buy_amount": "1000000",
"nonce": "397367878",
"referrer": "0x...",
"sell_amount": "1000",
"signer_wallet": "0x...",
"signature": "...",
"swap_id": 123
}
]
}
A [GET] /quotes/
request allows you to return a paginated list of all Quotes belonging to your trading desk.
Parameters
Name | In | Type | Required | Description |
---|---|---|---|---|
cursor | query | string | false | Cursor value used to paginate through pages. |
page_size | query | string | false | Number of Quotes returned per pagination. |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
count | int | true | Total number of Quotes to paginate. |
next | string | true | Pagination cursor value. |
results | array of objects | true | |
> id | number | true | The Paradigm created unique identifier of the Quote. |
> created | number | true | Time in unix milliseconds since the epoch when the Quote was created. |
> maker | string | true | The Paradigm desk name of the Maker who created the Quote. |
> price | string | true | The price of the Quote in the Quote Currency of the RFQ. |
> quantity | string | true | The requested crossing quantity of the Quote. |
> rfq_id | number | true | The Paradigm created unique identifier of the RFQ. |
> status | string | true | Status of the Quote. Valid values include OPEN and CLOSED . |
> canceled | number | false | The time in unix milliseconds since the epoch when the Quote was canceled. Missing if the Quote has not been canceled. |
> canceled_reason | string | false | The reason of the Quote cancellation. Valid values are API_CREDENTIAL_DELETED , FAILED_TO_EXECUTE , MAINTENANCE , NOT_ENOUGH_QUANTITY , REMOVED_BY_USER , REPLACED_BY_USER , RFQ_CANCELED , RFQ_COMPLETED , RFQ_EXPIRATION and WEBSOCKET_DISCONNECT . Missing if the Quote has not been canceled. |
> signed_bid | object | ||
>> buy_amount | string | true | Total amount of contracts to be purchased by the buyer, typically the same as the total_size. |
>> nonce | string | true | Arbitrary random or pseudo-random number, to be used just once. |
>> referrer | string | true | Address of the Paradigm wallet used to receive the fee, in hex format with 0x prefix. |
>> sell_amount | string | true | Total amount of sold contracts. |
>> swap_id | number | true |