NAV
cURL JavaScript Python Go

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.

API Connection URLs

The API is available on Paradigm's Test and Live environments.

Live

Test

Rate Limits

RESToverHTTP requests are rate limited to 10 requests per second per desk across all API Keys.

This means you cannot horizontally scale your rate limit per desk by using multiple API Keys. Each desk has a collective rate limit of 10 requests per second.

Implementation Paths

This section will describe in brief detail the expected solution implementation paths & best practices when using the Paradigm API.

High Level

You should use your connection to Paradigm through JSON-RPCoverWebsockets to receive updates relating to RFQs, Quotes, 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.

As a Taker, you should expect to lift the full quantity of your RFQ. At the present moment it is not possible to only lift a partial amount.

As a Maker, you should expect to Quote the full quantity of each leg of the RFQ. At the present moment it is not possible to Quote only part of leg's quantity in the RFQ.

Your solution should:

Your solution should not:

API Workflows

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.

  1. Taker creates an RFQ using /rfq/create/.
  2. Taker is able to cancel an RFQ if they wish to do so with /rfq/cancel/.
  3. 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.
  4. Taker, who will be notified of quotes on the quote JSON-RPCoverWebSockets Notification channel, is able to execute upon the quote of their choice using with /quote/execute/.
  5. Taker, will receive confirmation of the trade's status on the trade_confirmation JSON-RPCoverWebSockets Notification channel.
  6. Taker, will receive confirmation of the trade being completed on the trade JSON-RPCoverWebSockets Notification channel.

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".

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.

  1. Taker will create an RFQ and the Maker will be notified on the rfq JSON-RPCoverWebSockets Notification channel.
  2. Maker is able to create a one or two-way quote using /quote/create/.
  3. Maker is able to cancel an existing quote with /quote/cancel/. A Maker must cancel any existing quote on an RFQ before they are able to update their quote.
  4. Taker, chooses to lift the quote.
  5. Maker, will receive confirmation of the trade's status on the trade_confirmation JSON-RPCoverWebSockets Notification channel.
  6. Maker, will receive confirmation of the trade being completed on the trade JSON-RPCoverWebSockets Notification channel.

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

  1. Authenticate, establish a heartbeat and Subscribe to the rfq, quote, trade, and trade_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

  1. POST - /echo/ - A simple code example demonstrating how to have the server respond with your requested message.
  2. GET - /instruments/ - A simple code example demonstrating how to pull the instruments available on Paradigm.
  3. GET - /counterparties/ - A simple code example demonstrating how to pull your available counterparties' information.
  4. GET - /rfq/ - A simple code example demonstrating how to pull information relating to RFQs you were aparty to.
  5. GET - /rfq/ - A more comprehensive example demonstrating pagination and the use of parameters.

Taker Specific

  1. POST - /rfq/create/ - A simple code example demonstrating how to create an RFQ.
  2. POST - /rfq/cancel/ - A simple code example demonstrating how to cancel an RFQ.
  3. POST - /quote/execute/ - A simple code example demonstrating how to execute a provided Quote.

Maker Specific

  1. POST - /quote/create/ - A simple code example demonstrating how to create a Quote.
  2. POST - /quote/cancel/ - A simple code example demonstrating how to cancel an already created Quote.

Auto-Market Makers

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.

The desk names of the 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/api/market_maker

Auto-Takers

We also have Auto-Taker code examples to help Maker's test their solutions.

  1. Auto-Taker-Creator - Creates RFQs every 5 seconds: https://github.com/tradeparadigm/code-samples/tree/main/api/auto_taker
  2. Auto-Taker-Executor - Executes the best received quote every 5 seconds: https://github.com/tradeparadigm/code-samples/tree/main/api/market_taker

Errors

All REST error responses follow the same basic format. An Error object is returned in response to an erroneous RESToverHTTP request, accompanied by a 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 occured.
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.
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 APIs.

As an additional protection measure against replay attacks in environments where SSL trust is not properly configured, Paradigm requires all HTTP requests to be signed using a secret key.

Important Note: Paradigm does not currently provide fine-grained token scopes or permissions. Please ensure your API credentials are stored securely.

There are a number of Authentication methods available across both the RESToverHTTP and JSON-RPCoverWebSocket protocols, these include: - Token-based Authentication - HTTP Header - Cookie - Query String Parameter (JSON-RPCoverWebSocket only)

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.

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:

  1. Access Key: used to authenticate the API.
  2. 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.

In all examples, replace <access-key> with your Paradigm API Key's Access Key generated from your admin dashboard during creation.

HTTP Header

Authorization example with a 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>

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 URL Example

JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/?api-key=<access-key>

Test URL Example

JSON-RPCoverWebSocket Connection URL: wss://ws.api.test.paradigm.co/?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 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'

# GET example
method = b'GET'
path = b'/instruments/'
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'/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 the 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:

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 the role of both the Client and the Server depending on the Request.

Cancel on Disconnect

Cancel on Disconnect mode is enabled on all JSON-RPCoverWebSocket connections by default. Cancel on Disconnect mode will cancel all outstanding quotes that have been sent with the API Key used to authenticate the WebSocket session when the WebSocket connection disconnects.

If multiple WebSocket connections are concurrently authenticated with the same API Key, then quotes 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 WebSocket endpoint.

Live Cancel on Disconnect Example

JSON-RPCoverWebSocket Connection URL: wss://ws.api.chat.paradigm.co/?cancel_on_disconnect=false

Test Cancel on Disconnect Example

JSON-RPCoverWebSocket Connection URL: wss://ws.test.paradigm.co/?cancel_on_disconnect=false

Request Objects

An example of a JSON-RPCoverWebSocket Request message

{
    "id": "1",
    "jsonrpc": "2.0",
    "method": "subscribe",
    "params": {
        "channel": "rfq"
    }
}

A 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 a 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 occuredin the number of seconds 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.

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 with regards to RFQs, Quotes, 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"
    ]
}

There are four subscription channels you can subscribe to: rfq, quote, trade, and trade_confirmation.

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.

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": {
      "channels": [
                  "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 with regards to RFQs, Quotes, and Trades.

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,
         "stream":false,
         "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,
         "stream":false,
         "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,
         "stream":false,
         "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,
         "stream":false
      }
   }
}

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,
         "stream":false
      }
   }
}

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,
         "stream":false
      }
   }
}

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 arrary of information relating to the specific RFQ.
> created decimal Y The time the RFQ was created in the number of seconds 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 instrument name of the leg.
>> 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.
> stream bool Y If the RFQ is an RFS stream.
> 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 seconds 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":[
            {
               "bid_price":0.1294,
               "bid_quantity":25.0,
               "instrument":"BTC-19JAN21-32000-C",
               "offer_price":0.1353,
               "offer_quantity":25.0,
               "side":"SELL",
               "venue":"DBT"
            },
            {
               "bid_price":0.0302,
               "bid_quantity":25.0,
               "instrument":"BTC-20JAN21-36000-C",
               "offer_price":0.031,
               "offer_quantity":25.0,
               "side":"BUY",
               "venue":"DBT"
            }
         ],
         "quote_id":84032,
         "rfq_id":22530,
         "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":"None",
         "created":1611024112328.771,
         "legs":[
            {
               "bid_price":"None",
               "bid_quantity":25.0,
               "instrument":"BTC-19JAN21-32000-C",
               "offer_price":"None",
               "offer_quantity":25.0,
               "side":"SELL",
               "venue":"DBT"
            },
            {
               "bid_price":"None",
               "bid_quantity":25.0,
               "instrument":"BTC-20JAN21-36000-C",
               "offer_price":"None",
               "offer_quantity":25.0,
               "side":"BUY",
               "venue":"DBT"
            }
         ],
         "quote_id":84032,
         "rfq_id":22530,
         "status":"CANCELED"
      }
   }
}

An example, as the Taker, of the quote notification received when a Quote is executed

{
  "DeveloperNote":"Will be updated shortly"
}

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":[
            {
               "bid_price":0.1294,
               "bid_quantity":25.0,
               "instrument":"BTC-19JAN21-32000-C",
               "offer_price":0.1353,
               "offer_quantity":25.0,
               "side":"SELL",
               "venue":"DBT"
            },
            {
               "bid_price":0.0302,
               "bid_quantity":25.0,
               "instrument":"BTC-20JAN21-36000-C",
               "offer_price":0.031,
               "offer_quantity":25.0,
               "side":"BUY",
               "venue":"DBT"
            }
         ],
         "quote_id":84032,
         "rfq_id":22530,
         "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":"None",
         "account":{
            "name":"ParadigmTestOne"
         },
         "client_order_id":"DSK1738007604",
         "created":1611024112328.771,
         "legs":[
            {
               "bid_price":"None",
               "bid_quantity":25.0,
               "instrument":"BTC-19JAN21-32000-C",
               "offer_price":"None",
               "offer_quantity":25.0,
               "side":"SELL",
               "venue":"DBT"
            },
            {
               "bid_price":"None",
               "bid_quantity":25.0,
               "instrument":"BTC-20JAN21-36000-C",
               "offer_price":"None",
               "offer_quantity":25.0,
               "side":"BUY",
               "venue":"DBT"
            }
         ],
         "quote_id":84032,
         "rfq_id":22530,
         "status":"CANCELED"
      }
   }
}

An example, as the Maker, of the quote notification received when a Quote is filled

{
  "DeveloperNote":"Will be updated shortly"
}

An example, as the Maker, of the quote notification received when an RFQ is Traded Away from another Maker's Quote

{
   "jsonrpc":"2.0",
   "method":"subscription",
   "params":{
      "channel":"quote",
      "data":{
         "desk":"DSK1",
         "valid_until":1611024258659.531,
         "account":{
            "name":"ParadigmTestOne"
         },
         "client_order_id":"",
         "created":1611024138391.082,
         "legs":[
            {
               "bid_price":0.1305,
               "bid_quantity":25.0,
               "instrument":"BTC-19JAN21-32000-C",
               "offer_price":0.1347,
               "offer_quantity":25.0,
               "side":"SELL",
               "venue":"DBT"
            },
            {
               "bid_price":0.0296,
               "bid_quantity":25.0,
               "instrument":"BTC-20JAN21-36000-C",
               "offer_price":0.0321,
               "offer_quantity":25.0,
               "side":"BUY",
               "venue":"DBT"
            }
         ],
         "quote_id":84034,
         "rfq_id":22530,
         "status":"TRD AWAY"
      }
   }
}

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 seconds since epoch (January 1, 1970).
> created decimal Y The time the Quote was executed in the number of seconds since epoch (January 1, 1970).
> legs array of objects Y An array of legs that comprise the RFQ.
>> bid_price decimal N The bid price of the leg if one is quoted
>> bid_quantity decimal N The bid quantity of the leg if one is quoted.
>> offer_price decimal N The offer price of the leg if one is quoted
>> offer_quantity decimal N The offer 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.

trade

An example, as the Taker or the Maker, of the trade notification received when a trade is completed

{
   "jsonrpc":"2.0",
   "method":"subscription",
   "params":{
      "channel":"trade",
      "data":{
         "created":1611030288712.3499,
         "legs":[
            {
               "instrument":"BTC-19JAN21-32000-C",
               "price":0.1258,
               "quantity":25.0,
               "venue":"DBT",
               "trade_id":35701
            },
            {
               "instrument":"BTC-20JAN21-36000-C",
               "price":0.0237,
               "quantity":25.0,
               "venue":"DBT",
               "trade_id":35702
            }
         ],
         "price":-0.1021,
         "quote_id":84037,
         "rfq_id":22532
      }
   }
}

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 seconds since epoch (January 1, 1970).
> legs array of objects Y An array of legs that comprise the RFQ.
>> instrument string Y The instrument name of the leg.
>> 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

{
   "jsonrpc":"2.0",
   "method":"subscription",
   "params":{
      "channel":"trade_confirmation",
      "data":{
         "account":{
            "name":"ParadigmTestOne"
         },
         "created":1611030288712.3499,
         "desk":"DSK1",
         "exec_id":"61672920",
         "instrument":"BTC-19JAN21-32000-C",
         "venue":"DBT",
         "price":0.1258,
         "quantity":25.0,
         "side":"SELL",
         "quote_id":84037,
         "rfq_id":22532,
         "trade_id":35701
      }
   }
}

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 seconds 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.

Platform REST Endpoints

/echo/ [POST]

/echo/ Request example

# You can also use wget
curl -X POST https://api.chat.paradigm.co/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.chat.paradigm.co/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 = '/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 ACCESS_KEY"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := https.NewRequest("POST", "http://api.chat.paradigm.co/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 for users to test the signing of requests.

Parameters

Name In Type Required Description
body body object true none
message body string false none

Responses

Status Meaning Description Schema
200 OK echoed request body None

/instruments/ [GET]

/instruments/ Request example

# You can also use wget
curl -X GET https://api.chat.paradigm.co/instruments/ \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer ACCESS_KEY'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer ACCESS_KEY'
};

fetch('https://api.chat.paradigm.co/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
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'

# GET /instruments/
method = 'GET'
path = '/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", "http://api.chat.paradigm.co/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 exchange they can be 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 "BTC" or "ETH".
order_by_recently_added query boolean false Order results by most recently added instruments. Defaults to false.
page query integer false A page number within 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":2,
   "previous":null,
   "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"
      }
   ]
}

Responses

Status Meaning Description Schema
200 OK none Inline

Response Schema

Status Code 200

Name Type Required Restrictions Description
count number Y None Total number of pages of instruments returned.
next number or string Y None Next Page's number. Will be "null" if one is not available.
previous number or string Y None Previous page's number.
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.

/counterparties/ [GET]

/counterparties/ Request example

# You can also use wget
curl -X GET https://api.chat.paradigm.co/counterparties/ \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer ACCESS_KEY'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer ACCESS_KEY'
};

fetch('https://api.chat.paradigm.co/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
import json

# installed
import requests


access_key = 'kNLMKQnbcM0xGSL2wOntLwpy'
secret_key = '8Ni+xM1Y8DJTvCw0e0Wv0623KStavy1tBzLP3Wh7dryMWwkj'

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 = '/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", "http://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
page query integer false A page number within the paginated result set.

/counterparties/ Response example

200 Response

{
   "count":176,
   "next":2,
   "previous":null,
   "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"
         ]
      }
   ]
}

Responses

Status Meaning Description Schema
200 OK none Inline

Response Schema

Status Code 200

Name Type Required Restrictions Description
count number or string Y None Number of pages returned from counterparties request. Equal to "null" if there are no more.
next number or string Y None Next page number to request. Equal to "null" if there are no more.
previous number or string Y None Previous page number in list of 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.

/rfq/create/ [POST]

/rfq/create/ Request example

# You can also use wget
curl -X POST https://api.chat.paradigm.co/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.chat.paradigm.co/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 = '/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", "http://api.chat.paradigm.co/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:

  1. The Taker sends an /rfq/create/ request to Paradigm.
  2. Paradigm sends an /rfq/create/ response to the Taker.
    1. If the /rfq/create/ request is valid, the RFQ object is returned to the Taker.
    2. If the /rfq/create/ request is invalid, an Error object is returned to the Taker.
  3. 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.

/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 true 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 Y 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 Y Length in seconds the RFQ is available for. Valid values are between 10-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,
   "stream":false,
   "counterparties":[
      "DSK4",
      "DSK5"
   ]
}

Responses

Status Meaning Description Schema
201 Created none Inline

Response Schema

Status Code 201

Name Type Required Restrictions Description
created decimal Y None The time the RFQ was created in the number of seconds 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 apart of the RFQ.
> price decimal N none Price of leg if a hedge has been added.
> instrument string Y None The Instrument Name.
> 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 seconds since epoch (January 1, 1970).
stream boolean Y None Indicates if the RFQ is an RFS stream or not.
counterparties [string] Y None List of strings of the other Counterparties apart of the RFQ.

/rfq/cancel/ [POST]

/rfq/cancel/ Request example

# You can also use wget
curl -X POST https://api.chat.paradigm.co/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.chat.paradigm.co/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 = '/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", "http://api.chat.paradigm.co/rfq/cancel/", data)
    req.Header = headers

    client := &https.Client{}
    resp, err := client.Do(req)
    // ...
}

A POST /rfq/cancel/ request cancels an exisitng RFQ you created.

An /rfq/cancel/ request has the following workflow:

  1. The creator of an RFQ sends a /rfq/cancel/ request to Paradigm.
  2. Paradigm sends an /rfq/cancel/ response to the creator.
    1. If the /rfq/cancel/ request is valid, the RFQ object is returned to the creator.
    2. If the /rfq/cancel/ request is invalid, an Error object is returned to the creator.
  3. 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.
  4. If the /rfq/cancel/ request is valid, Paradigm sends a Notification on the rfq notification channel to the counterparties aparty to the RFQ and other 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",
   "stream":false,
   "counterparties":[
      "DSK4",
      "DSK5"
   ],
   "updated":1611034702624.0151
}

Responses

Status Meaning Description Schema
200 OK none Inline

Response Schema

Status Code 200

Name Type Required Restrictions Description
created decimal Y None The time the RFQ was created in the number of seconds 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 Nnone 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.
> price decimal N None Price of leg if a hedge has been added.
> instrument string Y None The Instrument Name of the leg.
> 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".
stream boolean Y None Indicates if the RFQ is an RFS.
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 seconds since epoch (January 1, 1970).

rfq [GET]

/rfq/ Request example

# You can also use wget
curl -X GET https://api.chat.paradigm.co/rfq/ \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer ACCESS_KEY'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer ACCESS_KEY'
};

fetch('https://api.chat.paradigm.co/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
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'

# GET /rfq/
method = 'GET'
path = '/rfq/'

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", "http://api.chat.paradigm.co/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.
page query integer N A page number within 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 can include "ACTIVE", "CANCELED", and "FILLED".

/rfq/ Example response

200 Response

{
   "count":2441,
   "next":21,
   "previous":19,
   "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":[
                  {
                     "bid_price":null,
                     "bid_quantity":25.0,
                     "instrument":"BTC-18DEC20-13250-C",
                     "offer_price":null,
                     "offer_quantity":25.0,
                     "side":"SELL",
                     "venue":"DBT"
                  },
                  {
                     "bid_price":null,
                     "bid_quantity":25.0,
                     "instrument":"BTC-19DEC20-21125-C",
                     "offer_price":null,
                     "offer_quantity":25.0,
                     "side":"BUY",
                     "venue":"DBT"
                  }
               ],
               "quote_id":25092,
               "rfq_id":18753,
               "status":"CANCELED"
            },
            {
               "desk":"DSK4",
               "valid_until":null,
               "created":1608267227869.377,
               "legs":[
                  {
                     "bid_price":null,
                     "bid_quantity":25.0,
                     "instrument":"BTC-18DEC20-13250-C",
                     "offer_price":null,
                     "offer_quantity":25.0,
                     "side":"SELL",
                     "venue":"DBT"
                  },
                  {
                     "bid_price":null,
                     "bid_quantity":25.0,
                     "instrument":"BTC-19DEC20-21125-C",
                     "offer_price":null,
                     "offer_quantity":25.0,
                     "side":"BUY",
                     "venue":"DBT"
                  }
               ],
               "quote_id":25093,
               "rfq_id":18753,
               "status":"CANCELED"
            }
         ]
      }

Responses

Status Meaning Description Schema
200 OK none Inline

Response Schema

Status Code 200

Name Type Required Restrictions Description
count integer Y None The number of pages in response to the request.
next integer or string Y false None
previous integer Y false None
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 Paradigm API Key name aparty to the RFQ.
>> 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. This value for RFS is always empty.
> created decimal Y None The time the RFQ was created in the number of seconds 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 Instrument name of the leg.
>> quantity decimal Y None The size in contracts of the leg. This key is not present for RFS RFQs.
>> 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 seconds since epoch (January 1, 1970).
>> created decimal Y None The time the Quote was created in the number of seconds since epoch (January 1, 1970).
>> legs array of objects Y None An array of objects containing the Quotes of the individual legs.
>>> bid_price decimal N None The bid price of the leg.
>>> bid_quantity decimal N None The bid size in contracts of the leg.
>>> instrument string Y None The Instrument name of the leg.
>>> offer_price decimal N None The offer price of the leg.
>>> offer_quantity decimal N None The offer 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 Unqiue of the RFQ determined by Paradigm.
>> status string Y None The status of the Quote. Valid values include "ACTIVE", "EXPIRED".

/quote/create/ [POST]

/quote/create/ Request examples

# You can also use wget
curl -X POST https://api.chat.paradigm.co/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",
      "bid_price": "string",
      "offer_price": "string",
      "bid_quantity": "string",
      "offer_quantity": "string"
    }
  ],
  "rfq_id": 0
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer ACCESS_KEY'
};

fetch('https://api.chat.paradigm.co/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 = '/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": [
                {
                    "bid_price": 39450,
                    "bid_quantity": 20000,
                    "offer_price": 39460,
                    "offer_quantity": 20000,
                    "instrument": "BTC-PERPETUAL",
                    "side": "BUY",
                    "venue": "DBT"
                }
            ],
            "rfq_id": 22539
        }

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", "http://api.chat.paradigm.co/quote/create/", data)
    req.Header = headers

    client := &https.Client{}
    resp, err := client.Do(req)
    // ...
}


ETA for changes - Last Update: 2nd of January 2021 This endpoint is in development and will be changed to better accommodate industry expectations.

The workflow remains the same except that instead of quoting two sides when creating a quote, only one side at the moment can be quoted at a time.

A call to quote/create/ will in the future require a "side" to be provided ("BUY" or "SELL"). This indicates which side of the leg is being quoted. To quote both sides of an RFQ, two quotes would need to be created, each with it's own unique client_order_id.

Parameter changes: - A new side field will be added to the quote object to specify which side the quote is for. Similar to the leg side, this field can be set to "BUY" or "SELL". - bid_price and offer_price will be replaced by a single price field. - bid_quantity and offer_quantity will be replaced by a single quantity field.


A /quote/create/ request allows you to Quote an RFQ you are a counterparty to.

A /quote/create/ request has the following workflow:

  1. The receiver of an RFQ sends a /quote/create/ request to Paradigm.
  2. Paradigm sends a /quote/create/ response to the RFQ receiver.
    1. If the /quote/create/ request is valid, the Quote object is returned to the RFQ receiver.
    2. If the /quote/create/ request is invalid, an Error object is returned to the RFQ receiver.
  3. 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 Note: You must quote the entire RFQ and not part of the legs or only part of the quantity.

/quote/create/ Body parameter example

  {
    "account": {
        "name": "ParadigmTestOne"
    },
    "client_order_id": "123",
    "expires_in": "60",
    "legs": [
        {
          "bid_price": 39450,
          "bid_quantity": 20000,
          "offer_price": 39460,
          "offer_quantity": 20000,
          "instrument": "BTC-PERPETUAL",
          "side": "BUY",
          "venue": "DBT"
        }
    ],
    "rfq_id": 22539
  }

Parameters

Name In Type Required Description
account body object true 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 A list of dictionaries of each leg of the RFQ.
> bid_price body decimal N The bid price of the leg.
> bid_quantity body decimal N The bid size of the leg in contracts.
> offer_price body decimal N The offer price of the leg in .
> offer_quantity body decimal N The offer size of the leg 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 Unqiue identifier of RFQ. Paradigm determines this value.

/quote/create/ Example response

201 Response

{
   "desk":"DSK1",
   "valid_until":1611038442838.6272,
   "account":{
      "name":"ParadigmTestOne"
   },
   "client_order_id":"49826055",
   "created":1611038342698.2578,
   "legs":[
      {
         "bid_price":39450.0,
         "bid_quantity":20000.0,
         "instrument":"BTC-PERPETUAL",
         "offer_price":39460.0,
         "offer_quantity":20000.0,
         "side":"BUY",
         "venue":"DBT"
      }
   ],
   "quote_id":84069,
   "rfq_id":22537,
   "status":"ACTIVE"
}

Responses

Status Meaning Description Schema
201 Created none Inline

Response Schema

Status Code 201

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 seconds 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 seconds 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.
> bid_price decimal N None The bid price of the leg.
> bid_quantity decimal N None The bid number of contracts of the leg.
> instrument string Y None The Instrument Name of the leg.
> offer_price decimal N None The offer price of the leg.
> offer_quantity decimal N None The offer size 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 Unqiue identifier of the RFQ. Paradigm determines this value.

/quote/cancel/ [POST]

/quote/cancel/ Request example

# You can also use wget
curl -X POST https://api.chat.paradigm.co/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.chat.paradigm.co/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 = '/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", "http://api.chat.paradigm.co/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 for an ACTIVE RFQ.

A /quote/cancel/ request has the following workflow:

  1. The creator of the quote sends a /quote/cancel/ request to Paradigm.
  2. Paradigm sends a /quote/cancel/ response to the creator.
    1. If the /quote/cancel/ request is valid, the Quote object is returned to the creator.
    2. If the /quote/cancel/ request is invalid, an Error object is returned to the creator.
  3. 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 none
quote_id body integer Y none

/quote/cancel/ Response Example

200 Response

{
   "desk":"DSK1",
   "valid_until":null,
   "account":{
      "name":"ParadigmTestOne"
   },
   "client_order_id":"613310893",
   "created":1611038225971.4749,
   "legs":[
      {
         "bid_price":null,
         "bid_quantity":20000.0,
         "instrument":"BTC-PERPETUAL",
         "offer_price":null,
         "offer_quantity":20000.0,
         "side":"BUY",
         "venue":"DBT"
      }
   ],
   "quote_id":84063,
   "rfq_id":22537,
   "status":"CANCELED",
   "updated":1611038331810.966
}

Responses

Status Meaning Description Schema
200 OK none Inline

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 seconds since epoch (January 1, 1970).
legs array of objects Y None An array of objects of the legs of the Quote.
> bid_price decimal N None The bid price of the leg.
> bid_quantity decimal N None The bid contract size of the leg.
> instrument string Y None The Instrument Name of the leg.
> offer_price decimal N None The offer price of the leg.
> offer_quantity decimal N None The offer 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.
status string Y None Status of the Quote.
updated decimal Y None The time the Quote is was last updated in the number of seconds since epoch (January 1, 1970).

/quote/execute/ [POST]

/quote/execute/ Request example

# You can also use wget
curl -X POST https://api.chat.paradigm.co/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",
      "side": "BUY"
    }
  ],
  "quote_id": 0
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer ACCESS_KEY'
};

fetch('https://api.chat.paradigm.co/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
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/execute/
method = 'POST'
path = '/quote/execute/'

body = b''

payload = {
            "rfq_id": 22540,
            "legs": [
                {
                "price": "38226.8",
                "quantity": "20000",
                "side": "BUY"
                }
            ],
            "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", "http://api.chat.paradigm.co/quote/execute/", data)
    req.Header = headers

    client := &https.Client{}
    resp, err := client.Do(req)
    // ...
}

A POST /quote/execute/ request executes a Quote. Is only used by the creator of the RFQ, the Taker.

A /quote/execute/ request has the following workflow:

  1. The creator of the RFQ sends a /quote/execute/ request to Paradigm.
  2. Paradigm sends a /quote/execute/ response to the creator.
    1. If the /quote/execute/ request is valid, the RFQ object is returned to the creator.
    2. 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.
  3. 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.
    1. 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.
    2. 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.
  4. 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.
  5. If the Trade has been confirmed, Paradigm sends a Notification on the rfq JSON-RPCoverWebSocket Notification channel to all counterparties aparty in the RFQ specifying that the rfq has been filled

/quote/execute/ Body parameter example

{
  "rfq_id": 22540,
  "legs": [
      {
      "price": "38226.8",
      "quantity": "20000",
      "side": "BUY"
      }
  ],
  "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.
> side body string Y The Direction of the leg. Valid values include "BUY" and "SELL.
quote_id body integer Y Unqiue 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":[
            {
               "bid_price":37469.84,
               "bid_quantity":20000.0,
               "instrument":"BTC-PERPETUAL",
               "offer_price":38226.8,
               "offer_quantity":20000.0,
               "side":"BUY",
               "venue":"DBT"
            }
         ],
         "quote_id":84073,
         "rfq_id":22540,
         "status":"PENDING_FILL"
      }
   ],
   "rfq_id":22540,
   "status":"PENDING_FILL",
   "valid_until":1611038697689.463
}

Responses

Status Meaning Description Schema
201 Created none Inline

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 seconds 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 seconds 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 instrument name of the leg.
>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 seconds since epoch (January 1, 1970).
>created decimal Y None The time the RFQ was created in the number of seconds since epoch (January 1, 1970).
>legs array of objects Y None An array of objects of the legs of the Quote.
>>bid_price decimal Y None The bid price of the leg.
>>bid_quantity decimal Y None The bid size of the leg.
>>instrument string Y None The instrument name of the leg.
>>offer_price decimal Y None The offer price of the leg.
>>offer_quantity decimal Y None The offer quantity 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.
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 seconds since epoch (January 1, 1970).

RFS

Paradigm offers request-for-stream (RFS) as an extension of its multi-dealer request-for-quote (RFQ) API.

The primary advantages of RFS over an RFQ are:

Important Notes