BSD Broker API

Download OpenAPI specification:Download

Introduction

This documentation is designed for our Business Partners, interested in electronically connecting with BSD Broker.

In general, BSD Broker accommodates two forms of service usage for the partners:

  • B2B: These partners use trading and other functionalities without individual user management.
  • B2B2C: Designed for those who require access on a per-user basis with user management functions.

Three environments are available to facilitate integration at different stages:

MiCA regulation:

General guidelines

Error handling

Specific endpoint errors are descibed under specific endpoints, some errors are common to all requests. When contacting BSD support please always provide value of trace response parameter so we can try to find more info about specific error in application logs

Status code Error code Description
401 Error indicates issues with authentication. Please check if you have valid token and create new token if expired
401 InvalidCredentials Error indicates that you provided invalid credentials for creating authentication token. Please check clientId and clientSecret
400 ValidationError Error indicates that input data is not valid. Please check errors property on response for more details
403 ActionNotAllowed Error indicates that requested user is authenticated but has insufficient permissions.
404 NotFound Error indicates that requested user id or partner id was not found on server or user is blocked. Please check details property on response for more details
500 InternalServerError Error indicates backend related error. Please contact BSD support with trace for more information

Error response types

Our API can return two types of error responses depending on the nature of the error encountered:

Standard errors

For other types of errors that do not involve validation, the response does not include an errors array. Instead, the response provides a clear message and code that indicate the nature of the error, along with other relevant details.

Example of a standard error response:

{
  "status": 422,
  "title": "Unprocessable Entity",
  "code": "AssetNotAvailable",
  "message": "Required currency/entity not available in this account",
  "detail": null,
  "errors": null,
  "instance": "/api/v1/user/data",
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1"
}

Validation errors

When a request fails due to validation errors, the response includes an errors array filled with all the validation issues encountered. This type of response typically occurs when input data does not meet the criteria set by the API's input validation rules.

Example of a validation error response:

{
  "status": 400,
  "title": "Bad Request",
  "code": "ValidationError",
  "message": "Parameters usage incorrect in the call, check the detail field",
  "detail": null,
  "errors": [
    {
      "code": "PredicateValidator",
      "field": "username",
      "message": "Username is required."
    },
    {
      "code": "PredicateValidator",
      "field": "email",
      "message": "Email address is invalid."
    }
  ],
  "instance": "/api/v1/partner/auth",
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1"
}

Testing edge cases

On sandbox and prelive environments, edge cases can be tested by placing 'special' values for certain fields when calling the API.

Endpoint Condition Effect
Create user externalReference ends with TST01 status code 200, user gets created, API response is delayed by 100s
Create user externalReference ends with TST02 status code 503, user does not get created, API response is delayed by 100s
Import user kyc data externalReference ends with TST03 status code 200, KycStatus will always be Pending
Import user kyc data externalReference ends with TST04 status code 200, KycStatus will be Confirmed, IsBlocked will be true
Import user kyc data externalReference ends with TST05 status code 503
Import user kyc data externalReference ends with TST06 status code 200, KycStatus will be Pending for 5 minutes, then it will set to Rejected
Request quote assetCode: ETH, amount: 0.001001 status code 503
Request quote assetCode: ETH, amount: 0.001002 status code 200, API response is delayed by 10s
Place order assetCode: ETH, amount: 0.001003 status code 410, QuoteExpired
Place order assetCode: ETH, amount: 0.001004 status code 422, UnstableMarket
Place order assetCode: ETH, amount: 0.001005 status code 503, ServiceUnavailable
Place order assetCode: ETH, amount: 0.001006 status code 200, Response is delayed by 100s (network timeout), Order is placed
Place order assetCode: ETH, amount: 0.001007 status code 503, Response is delayed by 100s (network timeout), Order is not placed
Place order assetCode: ETH, amount: 0.010008 status code 200, Response will return Failed status, but still place order

Order revoke and price improvement process

This process is initiated manually from the back office dashboard, usually triggered by an email or a support ticket.

In the revocation process, the existing order is put into 'Revoked' status. In addition, a new 'storno' order is created with the same amount and reversed side.

In the price improvement process, the revocation process is applied first. Then, an additional new order is created with the same side as the original order but with a better price.

Example - revoke

  1. Order (id:123) for BUY of 1 BTC for 50K € is executed with 'Completed' status.
  2. Order (id:123) is revoked with 'Revoked' status. Storno order (id:124) for SELL of 1 BTC for 50K € is executed with 'Completed' status.

Example - price improvement

  1. Order (id:123) for BUY of 1 BTC for 50K € is executed with 'Completed' status.
  2. Order (id:123) is revoked with 'Revoked' status. Storno order (id:124) for SELL of 1 BTC for 50K € is executed with 'Completed' status.
  3. Order (id:125) for BUY of 1 BTC for 49K € is executed with 'Completed' status.

Detecting and processing revokes (and price improvements) can be fully automated by the client backend.

Automatic processing of revoked and price improvement orders using REST API

To detect revoked orders partner should implement a process similar to the one bellow.


$lastProcessedId=id-of-last-processed-order-or-null

Every 5 min:

$revokedOrders = 'Get revoked orders'; startingAfter=$lastProcessedId

for $orderId in $revokedOrders:
{
  $stornoOrderId, $priceImprovementOrderId = 'Get an order'; orderId=$orderId
  $stornoOrder = 'Get an order'; orderId=$stornoOrderId
  
  if $priceImprovementOrderId != null:
    $priceImprovementOrder = 'Get an order'; orderId=$priceImprovementOrderId

  {Process everything}

  $lastProcessedId=$orderId
}

Please note, for brevity, the procedure described above does not include pagination, which a real implementation should include.

Automatic processing of revoked and price improvement orders using FIX API

The process is described in FIX section: Order revoke and price improvement process.

Crypto Assets

Currently supported crypto assets and their essential details.

Asset Code Name Amount Precision Price Precision Min. Withdrawal Amount
AAVE Aave 8 10 1
ADA Cardano 6 10 10
ALGO Algorand 6 10 100
AXS Axie Infinity Shards 8 10 2
BAT Basic Attention Token 8 10 50
BCH Bitcoin Cash 8 10 0.05
BTC Bitcoin 8 10 0.001
CHZ Chiliz 8 10 150
CRV Curve DAO Token 8 10 20
DOGE Dogecoin 8 10 100
DOT Polkadot 8 10 1
ETC Ethereum Classic 8 10 0.5
ETH Ethereum 8 10 0.01
GRT The Graph 8 10 100
LINK Chainlink 8 10 3
LTC Litecoin 8 10 0.1
MANA Decentraland 8 10 50
POL Polygon 8 10 5
QNT Quant 8 10 0.1
SAND The Sandbox 8 10 50
SHIB Shiba Inu 0 10 2500000
SOL Solana 8 10 0.05
UNI Uniswap 8 10 3
XLM Stellar Lumens 7 10 50
XRP XRP 6 10 10
XTZ Tezos 6 10 10

Asset Code

This is the code that is used by REST API where assetCode is required.

Amount precision

When specifying amount in crypto-currency (for orders, withdrawals and deposits), number of decimals should not exceed this.

Price precision

All quotes and orders returned from endpoints will have price rounded to 10 decimals.

Authentication

Get new access token

Use provided clientId and clientSecret to generate access token. Once you have your token, you must include it in every API request in the header.

If you submit an invalid or expired token in an API request, or forget to include the token in the header, then the API will respond with a 401 Unauthorized error. In this case, your application must call this endpoint to generate a new one.

Access tokens are valid for 1 hour.

path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
clientId
required
string non-empty

Client identifier provided by Boerse Stuttgart Digital

clientSecret
required
string non-empty

Client secret provided by Boerse Stuttgart Digital

Responses

Request samples

Content type
application/json
{
  • "clientId": "40633122a47c4f41b62830f1c0fe39c4",
  • "clientSecret": "GBAyfVL7YWtP6gudLIjbRZV..."
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

User

B2B & B2B2C PARTNER ENDPOINTS

The Get user info endpoint is available both for B2B and B2B2C partner users and has not further restrictions in terms of the partner type.

B2B2C ONLY PARTNER ENDPOINTS

The user management features, such as the endpoints for creating users, changing users, importing user KYC data, changing user KYC data, requesting user deletion are designed for the integration of our B2B2C partners. For B2B partners these endpoints of the API are restricted and will return an HTTP 403 (forbidden) response code.

Onboarding process

The diagram bellow illustrates the entire onboarding process for an end user in a B2B2C environment. The usage of BSDigital user API in the on-boarding process is highlighted within a boxed area.

sequenceDiagram
autonumber
    actor Enduser as Enduser
    Enduser->>Partner App: Register for crypto trading
    Partner App->>Partner Backend: Request KYC data sharability
    critical KYC data must be sharable
        Partner Backend->>+Partner Backend: Check KYC data sharability 
    option KYC data outdated / older than 24 hours
        Partner Backend->>+Partner App: KYC data outdated
        Partner App->>+Enduser: Review KYC data screen <br/> (First name, Last name, Address, Legitimation data, AML data,..etc)
        Enduser->>Partner App: Confirm/Update KYC data
        Partner App->>Partner Backend: Confirm up-to-date KYC
    option Validation Date of ID document outdated
        Partner Backend->>+Partner App: ID document validation outdated
        Partner App->>+Enduser: Upload new ID document screen
        Enduser->>Partner App: Upload ID document (e.g. via phonto or PDF or ...)
        Partner App->>Partner Backend: Forward ID document
        Partner Backend->>+Partner Backend: Store ID document
    end

    Partner Backend->>Partner App: Confirm KYC data sharability
    Partner App->>+Enduser: Success screen
    Enduser->>Partner App: Confirm to continue
    Partner App->>+Enduser: KYC data confirmation/update screen
    Enduser->>Partner App: Confirm/Update KYC data (T&Cs, non-Fatca user, etc.)

    Partner App->>+Partner Backend: KYC submit start
    Partner Backend->>+Partner Backend: Check all KYC data availability (T&C confirmation etc.)    
    Partner App->>+Enduser: KYC pending screen (up to X minutes)        

    rect rgba(102, 102, 255, 0.19)
        note right of Partner Backend: User creation (BSDigital User API)
        Partner Backend->>BSDigital Backend: Request Create user
        BSDigital Backend->>Partner Backend: Return created user ID
        Partner Backend->>Partner Backend: Link BS Digital User ID
        Partner Backend->>BSDigital Backend: Import user KYC data
        BSDigital Backend->>Partner Backend: KYC data has been imported<br/> and is being processed
        BSDigital Backend->>BSDigital Backend: Back office checks (AML, etc.)
        Note over BSDigital Backend,Partner Backend: After all checks have passed
        BSDigital Backend->>Partner Backend: Webhook notification (user_updated)    
    end       

    Partner Backend->>Partner App: KYC submit success
    Partner App->>Enduser: KYC success screen

The highlighted section is divided into three parts:

1. Create a new user at BSDigital

To create a new user you need to call Create a user endpoint. At this point you only need to provide reference data. The response will contain the newly created User-ID, which you need to store in your backend and is needed for all further API calls related to that User. If there is a network error during this call, the call can be repeated. If you wish to change some user data user the Change user endpoint.

2. Import KYC-data for that user

After user is successfully created, you have to import his KYC-data. To do so, you need to call Import user kyc data endpoint and provide user personal information, address and legitimization details as well as tax and AML relevant information. A successful response from this endpoint only means that provided KYC-data was accepted for processing. Trading is not possible yet, until the KYC-data has been processed successfully. You will receive a webhook notification when this happens. If you wish to change the imported kyc data use the Change user kyc data endpoint.

3. Consume webhook-notification

After the KYC has been successfully processed by the BSDigital back-office, a webhook-notification will be sent to your configured webhook-URL. This notification will contain the new KYC-Status of the user:

  • if the KYC-Status has been set to 'Confirmed', the user is now able to trade crypto,
  • if the KYC-Status has been set to 'Invalid', there is a problem with the KYC-data and you will need to contact us to resolve it.

Create a user

To create a new user, first use Create a user endpoint then use Import user kyc data to upload kyc data and initiate onboarding process.

Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
branch
string or null

Partner branch. Optional. Used for classifying user for example by bank branch, department or any other smaller divisions.

externalReference
string or null

External reference. Optional. Used for storing unique partner user identifier

tags
string or null

Partner tags. Reserved for custom user tags

Responses

Request samples

Content type
application/json
{
  • "branch": "StuttgartOffice",
  • "externalReference": "partner-df514599724248a3b14afde61d79c3e",
  • "tags": "Bucket123"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Change user data

Use this endpoint to modify user data after already Creating a user.

In the request body, include only the fields you wish to update, omit all others.

Example of changing user data:

{
    "branch": "StuttgartOffice"
}
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
branch
string or null

Partner branch. Optional. Used for classifying user for example by bank branch, department or any other smaller divisions.

externalReference
string or null

External reference. Optional. Used for storing unique partner user identifier

tags
string or null

Partner tags. Optional. Reserved for custom user tags

Responses

Request samples

Content type
application/json
{
  • "branch": "StuttgartOffice - Optional",
  • "externalReference": "partner-df514599724248a3b14afde61d79c3e - Optional",
  • "tags": "Bucket123 - Optional"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get user info

This allows you to get the users info by either the default User Id or External Reference.

When user kyc data is successfully processed, user status will be set to Confirmed.

This endpoint can be used to check user status and also to retrieve all the kyc data that was imported.

To use a different identifier, modify the UserId parameter.

The available options for UserIdType are:

  • UserId (default)
  • ExternalReference
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
userIdType
string

The type of the identifier. The given identifier can either be the default "UserId" or "ExternalReference"(Unique user identifier).

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Import user kyc data

Use this endpoint to upload kyc data and initiate onboarding process. After successfully importing the kyc data, it will be processed. If the data is processed successfully, you will receive a webhook notification and be able to trade. You can change the imported data via Change user kyc data endpoint.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
salutation
string or null

Optional. Salutation Mr or Ms

firstName
required
string [ 2 .. 50 ] characters

First name

lastName
required
string [ 2 .. 50 ] characters

Last name

required
object

Address

mobileNumber
string or null

Mobile phone number

birthDate
required
string <date-time> non-empty

Required. Birth date

birthCity
required
string [ 1 .. 35 ] characters

Required. Birth city

birthCountry
required
string = 2 characters

Required. Birth country (ISO 3166 alpha-2 Code)

nationality
required
string = 2 characters

Required. Nationality (ISO 3166 alpha-2 Code)

maritalStatus
string or null

Optional. Marital status (Divorced, Married, Single, Widowed)

pepRelevant
boolean or null

Optional. Customer is a political exposed person

fatcaRelevant
required
boolean

Default "false", no customers with positive FATCA status should be imported

fatcaCrsConfirmedAt
string or null <date-time>

Required when FatcaRelevant = false. UTC Timestamp (ISO 8601 format) from when the person verified their FATCA relevance

object or null

Optional. Legitimation details

taxId
string or null

Optional. Tax number

taxIdCountry
string or null

Optional. Tax residency country (ISO 3166 alpha-2 Code)

amlConfirmedAt
required
string <date-time> non-empty

Required. Last legitimation date (ISO 8601 UTC format) on which the user last confirmed his personal KYC data.

Responses

Request samples

Content type
application/json
{
  • "salutation": "Mr",
  • "firstName": "Max",
  • "lastName": "Mustermann",
  • "address": {
    },
  • "mobileNumber": "+4923423234",
  • "birthDate": "1990-12-05",
  • "birthCity": "Berlin",
  • "birthCountry": "DE",
  • "nationality": "DE",
  • "maritalStatus": "Single",
  • "pepRelevant": false,
  • "fatcaRelevant": false,
  • "fatcaCrsConfirmedAt": "2019-08-24T14:15:22Z",
  • "legitimation": {
    },
  • "taxId": "2454027948945",
  • "taxIdCountry": "DE",
  • "amlConfirmedAt": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Change user kyc data

Use this endpoint to modify existing kyc data that has already been imported using Import user kyc data. You can modify the data even if the kyc has not yet been processed.

In the request body, include only the fields you wish to update, omit all others. At least one field must be provided in the request body. Delete specific non user manditory fields by providing either "" for string fields, or "0001-01-01" for date fields.

Example of changing kyc data:

{
    "maritalStatus": "Married",
    "lastName": "Mustermann"
}
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
salutation
string or null

Optional. Salutation Mr or Ms

firstName
string or null

Optional. First name

lastName
string or null

Optional. Last name

object or null

Optional. Address

mobileNumber
string or null

Optional. Mobile phone number

nationality
string or null

Optional. Nationality (ISO 3166 alpha-2 Code)

maritalStatus
string or null

Optional. Marital status (Divorced, Married, Single, Widowed)

pepRelevant
boolean or null

Optional. Customer is a political exposed person

object or null

Optional. Legitimation details

taxId
string or null

Optional. Tax number

taxIdCountry
string or null

Optional. Tax residency country (ISO 3166 alpha-2 Code)

Responses

Request samples

Content type
application/json
{
  • "salutation": "Mr - Optional",
  • "firstName": "Max - Optional",
  • "lastName": "Mustermann - Optional",
  • "address": {
    },
  • "mobileNumber": "+4923423234 - Optional",
  • "nationality": "DE - Optional",
  • "maritalStatus": "Single - Optional",
  • "pepRelevant": false,
  • "legitimation": {
    },
  • "taxId": "2454027948945 - Optional",
  • "taxIdCountry": "DE - Optional"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Delete user request

This endpoint allows you to schedule a date for deleting a user by providing the desired date and an optional reason for deletion. If no date is specified, the deletion date will be set to the current day. If the endpoint is called again before the deletion date, it will update the date of deletion or the reason, if provided.

You can keep track of a user’s scheduled deletion date by calling the Get User Info endpoint.

There is a daily worker that checks if users are eligible for deletion and deletes them if they meet the criteria. To verify if a user has been deleted, call an endpoint such as the Get User Info endpoint. If the user does not exist, you will receive an error.

If a user’s account is not empty, or is faulty on the scheduled deletion day, the account will be blocked instead of deleted.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
reason
string or null

Optional. Account deletion reason

scheduledAt
string or null <date>

Optional. Scheduled date of deletion. If not provided then deletion set to today

deletedBy
string or null

Optional. Contract cancelled by Branch / Department / User

Responses

Request samples

Content type
application/json
{
  • "reason": "Account no longer needed",
  • "scheduledAt": "2024-12-31",
  • "deletedBy": "User"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Prices

Get prices

Returns current bid and ask prices for all assets (instruments) in Euros. These prices are calculated for an order size of 100 euro and are for informational purposes only.

Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
userId
string

Boerse Stuttgart Digital user identifier

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get price history

Returns historic mid prices for selected asset (instrument). The range is [present - periodLenght, present].

Authorizations:
Bearer
path Parameters
assetPair
required
string
Example: BtcEur

Asset pair for which price history will be returned

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
periodLength
required
number <double>
Example: periodLength=1

Time period, in days. Accepted values are:

  • 0.125 - 3 hours (30 sec buckets),
  • 1 - 1 day (5 min buckets),
  • 7 - 1 week (30 min buckets),
  • 30 - 30 days (2 hr buckets),
  • 365 - 1 year (24 hr buckets)
  • 3654 - 10 years (1 day bucket)

Responses

Response samples

Content type
application/json
{
  • "period": "1.00:00:00",
  • "bucketSize": "00:05:00",
  • "expireOn": "00:05:00",
  • "items": [
    ],
  • "eurDiff": 0,
  • "percentDiff": 0
}

Trading

We offer request for quote orders and market orders.

Request for quote (RFQ) orders

Issuing a request for quote order involves two steps:

  1. Calling 'Request a quote' with amount to buy/or sell. A quote with an offered price is returned.
  2. Calling 'Place an order', referencing the issued quote. Be aware that the quote is only valid for a limited amount of time (validUntil).
sequenceDiagram
autonumber
    Partner Backend->>BSDigital Backend: Request a quote
    BSDigital Backend->>Partner Backend: Return quote id and price
        
    Partner Backend->>BSDigital Backend: Place an order (quote id)
    BSDigital Backend->>Partner Backend: Return order Id

Some implementation details:

  • Specify either fiat-amount or amount. Max order value in EUR is as configured per partner's account. Max amount is limited by users portfolio. If the user requests 10 BTC for sell, but owns only 5 BTC the user will get back quote for 5 BTC.
  • A quote is valid for 15 seconds.
  • Both order amount and fiat-amount returned by 'Request a quote' must be submitted to 'Place on order'.
  • Quote id is same as order id, which means quote id can be used to check if an order was placed in case of network issues.

Market orders

Market orders always execute with current market price. The exact price of the trade is only known after the trade is done.

Issuing a market order involves only a single call to 'Place an order' endpoint.

sequenceDiagram
autonumber
    Partner Backend->>BSDigital Backend: Place an order (orderType=Market)
    BSDigital Backend->>Partner Backend: Return order Id

Some implementation details:

  • Specify order type: 'Market'
  • Specify either amount or fiatAmount, not both.
  • Use clientOrderId to recover from network issues.

Order statuses

Order status Description
Submitted the order has been submitted and is being processed
Completed the order is completed
Revoked the order has been revoked
Failed the order has failed

Handling application errors

The list of possible application errors and how to handle them is available at this error list. The following diagram shows how to handle most common ones.

sequenceDiagram
autonumber
    Note over Partner App, Partner Backend: reference to either buy or sell process,<br/> which is the same until this point
    Partner App->>Partner Backend: Place the order for the given quote ID
    Partner Backend->>BSDigital Backend: Place the order <br/> POST /api/v1/partner/{partnerId}/users/{userId}/orders<br/><br/> Both order amount and fiat-amount<br/> returned by request quote must be submitted.
    BSDigital Backend->>BSDigital Backend: Check order validity (See error handling for details)
    BSDigital Backend->>BSDigital Backend: Check if the user has been deleted or blocked in the meantime.
    alt 410 Quote expired
        BSDigital Backend->>Partner Backend: Return error
        Partner Backend->>Partner App: It took longer than 15 secs to<br/> place the order with the given quote ID<br/><br/> Display message that quote has expired. <br/><br/> Offer user to request a new quote<br/> with same quantities as before.<br/><br/> The process must start from the point<br/> of requesting a quote again. 
    else 422 Unstable market
        BSDigital Backend->>Partner Backend: Return error
        Partner Backend->>Partner App: The price offered by the quote<br/> and the current market price<br/> have diverged too much.<br/><br/> Display message that order cannot be executed<br/> because of volatile market.<br/><br/> Offer user to request a new quote<br/> with same quantities as before.<br/><br/> The process must start from the point<br/> of requesting a quote again.
    end

Handling network errors and timeouts

If the network connection fails in the process of placing an order (regardless of buy or sell), the order might still be processed by BSDigital backend. It is best to display a message to the user "Processing of order is taking a bit longer, we will notify you when its done". If the order is an buy order, you also have to "block" euros until you are sure of the order status on BSDigital backend. To check that, you need to periodically call GetOrder using the quote id, until it either returns "not found", or returns the placed order with a status corresponding to the statuses described in the Order statuses section. Depending on the response you either return the blocked Euros to the user or not and restart the entire order process from the "request a quote" point again. The following sequence diagram show a potential flow including the endpoint for getting an order list.

sequenceDiagram
autonumber
    Note over Partner App, Partner Backend: reference to either buy or sell process,<br/> which is the same until this point
    Partner App->>Partner Backend: Place the order for the given quote ID
    Partner Backend->>BSDigital Backend: Place the order <br/> POST /api/v1/partner/{partnerId}/users/{userId}/orders<br/><br/> Both order amount and fiat-amount<br/> returned by request quote must be submitted.
    BSDigital Backend->>BSDigital Backend: Check order validity (See error handling for details)
    BSDigital Backend->>BSDigital Backend: Check if the user has been deleted or blocked in the meantime.
    Note over Partner Backend, BSDigital Backend: network issues at this point of time
    BSDigital Backend-xPartner Backend: Connection issues or timeout
    loop check order existance / api recovery
        Partner Backend->>BSDigital Backend: get a the specific order by quote id<br/>/api/v1/partner/{partnerId}/users/{userId}/orders/{quoteId}<br/><br/> The orderId is the ID of the quote
        alt 200 OK and order status is either 'Submitted', 'Completed' or 'Revoked'
            BSDigital Backend->>Partner Backend: return the requested order
            Partner Backend->>Partner Backend: Order has successfully<br/> been placed<br/>Exit loop.
        else 404 and Error code 'NotFound' or status is "Failed"
            BSDigital Backend->>Partner Backend: Return error
            Partner Backend->>Partner Backend: No order with the<br/> given ID found.<br/>Exit loop.
        else Connection issues or timeout
            BSDigital Backend-xPartner Backend: Connection issues or timeout
            Partner Backend->>Partner Backend: Loop until connection issues persist
        end
        Partner Backend->>Partner Backend: check whether order was returned
    end
    alt Order has successfully been placed
        Partner Backend->>Partner App: Return the order
    else Order has not been placed
        Partner Backend->>Partner App: Order was not created.<br/> Start from the beginning with requesting a quote again<br/> and unblock user money
    end

Get crypto assets

This can be used to get all available crypto assets and their configurations. The assets returned are ordered by name in ascending order.

Please note that the response of this endpoint is paged.

Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
limit
integer <int32>

A limit on the number of objects to be returned, between 1 and 100. Default is 30.

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Request a quote

This request returns a buy or sell quote for either a chosen amount of crypto or the chosen euro amount. It should be used in connection with 'Place an order' endpoint.

While executing request some specific errors can occur:

Status code Error code Description
400 ValidationError Error indicates issues with input data. Validation check valid values for asset code, side and amounts, ..etc. Details about which field is not valid and why is available inside errors array in response
400 RoundingError Error indicates that input amount is not rounded properly
403 ActionNotAllowed Trading is disabled for this user
404 NotFound Error indicates that the given user has been blocked or deleted and the quote cannot be processed
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
assetCode
required
string non-empty

Asset code

amount
number or null <decimal>

The amount of the crypto asset to request a quote for Required unless you specified fiat amount

fiatAmount
number or null <decimal>

The fiat amount to request a quote to buy or sell Required unless you specified crypto amount

side
required
string non-empty

Enum: Buy or Sell.

Responses

Request samples

Content type
application/json
{
  • "assetCode": "string",
  • "amount": 0,
  • "fiatAmount": 0,
  • "side": "string"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Set order commission

This endpoint can be used to set the commission of price improved orders.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

orderId
required
string

Price improved order identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
commission
number <decimal> [ 0 .. 100000 ]

Updated commission. Fixed fiat fee in EUR with 2 decimals

Responses

Request samples

Content type
application/json
{
  • "commission": 2.22
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Place an order

Place an order request for the previously obtained quote or issue a market order.

While executing request some specific errors can occur:

Status code Error code Description
400 ValidationError Error indicates issues with request parameters please check errors array for details.
400 RoundingError Error indicates that input amount is not rounded properly. Please check valid decimal places for requested asset.
403 ActionNotAllowed Trading is disabled for this user.
404 NotFound Error indicates that the given user has been blocked or deleted and the order can not be placed.
410 QuoteExpired Error indicates that price changed too much and the quote cannot be accepted anymore. Please request a new quote.
422 NotEnoughAsset Error indicates that sell order can not be executed due not enough assets on users portfolio.
422 UnavailableCollateral Error indicates that the order was rejected due to insufficient collateral balance.
422 UnstableMarket Error indicates that order can not be executed due unstable market, so price changes to much from quoting time. Please request new quote.
422 ServiceUnavailable Error indicates that order can not be executed because one of external services was not available. Please request a new quote. If error persists for longer time period please contact BSD support.
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
orderType
string or null

Order type. Enum: Rfq or Market Defaul: Rfq

assetCode
required
string non-empty

Asset code

side
required
string non-empty

Enum: buy or sell.

price
number or null <decimal>

The execution price of the order. Required for a quote order and not allowed for a market order.

amount
number or null <decimal>

The amount or quantity of crypto asset to buy or sell. Required for a quote order. For Market orders you can use only Amount or FiatAmount.

fiatAmount
number or null <decimal>

The fiat amount of crypto asset to buy or sell. Required for a quote order. For Market orders you can use only Amount or FiatAmount.

quoteId
string or null

The quote identifier as received as response to quote obtained prior to the order. Required for a quote order and not allowed for a market order.

onBehalfOf
string or null <= 100 characters

Customer side identifier of user on behalf of order will be executed.

commission
number or null <decimal>

Fixed fiat fee in EUR with 2 decimals Can be different per customer once the customer is at a different bank (in our API documentation we call it "branch").

clientOrderId
string or null

The order-id of the client for which this order will be executed. Optional in quote order and required on Market order. Maximum length is 35 character May consist of alphanumerical characters (a-z, A-Z, 0-9) and underscores (_) only

secondaryClientOrderId
string or null

A secondary / additional order-id of the client for which this order will be executed. Optional. Maximum length is 35 character May consist of alphanumerical characters (a-z, A-Z, 0-9) and underscores (_) only

Responses

Request samples

Content type
application/json
{
  • "orderType": "BTC",
  • "assetCode": "BTC",
  • "side": "Buy",
  • "price": 0,
  • "amount": 0,
  • "fiatAmount": 0,
  • "quoteId": "string",
  • "onBehalfOf": "string",
  • "commission": 0,
  • "clientOrderId": "string",
  • "secondaryClientOrderId": "string"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get orders

This can be used to query previously executed orders. The orders returned are ordered by creation time in descending order (newest are returned first). Please note that the response of this endpoint is paged.

While executing request some specific errors can occur:

Status code Error code Description
400 ValidationError Error indicates issues with request parameters please check errors array for details
404 NotFound Error indicates that the given user has been blocked or deleted and orders cannot be retrieved
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
assetCode
string

Asset code

limit
integer <int32>

A limit on the number of objects to be returned, between 1 and 100. Default is 10.

startingAfter
string

A cursor for use in pagination. startingAfter is an object ID that defines your place in the list.

endingBefore
string

A cursor for use in pagination. endingBefore is an object ID that defines your place in the list.

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get revoked orders

This endpoint returns revoked orders for all partner users in ascending order of the revocation time. Please note that the response of this endpoint is paged.

While executing this request some specific errors can occur:

Status code Error code Description
400 ValidationError Error indicates issues with request parameters please check errors array for details
Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
limit
integer <int32>

A limit on the number of objects to be returned, between 1 and 100. Default is 10.

startingAfter
string

A cursor for use in pagination. startingAfter is an object ID that defines your place in the list.

endingBefore
string

A cursor for use in pagination. endingBefore is an object ID that defines your place in the list.

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get an order

Fetch an order using either the default Order/Quote ID or the Client Order ID.

To use a different identifier, modify the OrderIdType parameter.

The available options for OrderIdType are:

  • OrderId (default)
  • ClientOrderId

While executing request some specific errors can occur:

Status code Error code Description
404 NotFound Error indicates that order id does was not found on server. Please check if you have valid order identifier
404 NotFound Error indicates that the given user has been blocked or deleted and the order cannot be retrieved
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

orderId
required
string

The identifier of the order to retrieve. "OrderId"(default) or "ClientOrderId"

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
orderIdType
string

The type of the identifier. The given identifier can either be the default "OrderId"(Both the ID of the order or the quote may be used here) or "ClientOrderId"(Users own identifier).

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Transfers

This section covers endpoints related to crypto transfers (deposits and withdrawals).

Transaction history

In order to get a full transaction history, you can obtain that by calling the following endpoints:

Get the wallet address for crypto deposits

Use this endpoint to get the wallet address for crypto deposits.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

assetCode
required
string

Asset code

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get crypto deposits

Use this endpoint to get a paginated list of all crypto deposits for a certain asset.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
assetCode
string

Asset code

limit
integer <int32>

A limit on the number of objects to be returned, between 1 and 100. Default is 10.

startingAfter
string

A cursor for use in pagination. startingAfter is an object ID that defines your place in the list.

endingBefore
string

A cursor for use in pagination. endingBefore is an object ID that defines your place in the list.

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get crypto withdrawals

Use this endpoint to get a paginated list of all crypto withdrawals for a certain asset.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
assetCode
string

Asset code

limit
integer <int32>

A limit on the number of objects to be returned, between 1 and 100. Default is 10.

startingAfter
string

A cursor for use in pagination. startingAfter is an object ID that defines your place in the list.

endingBefore
string

A cursor for use in pagination. endingBefore is an object ID that defines your place in the list.

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Create a crypto withdrawal

Use this endpoint to create a new withdrawal for a given asset.

While executing this request some specific errors can occur:

Status code Error code Description
400 RoundingError Error indicates that input amount is not rounded properly. Please check valid decimal places for requested asset
403 ActionNotAllowed Withdrawals are disabled for this user
404 NotFound Error indicates that the given user has been blocked or deleted and the withdrawal cannot be processed
422 NotEnoughAsset Error indicates that sell order can not be executed due not enough assets on users portfolio
422 InvalidWalletAddress Error indicates that the crypto wallet address could not be validated
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
assetCode
required
string non-empty

Asset code

amount
required
number <decimal>

The amount or quantity of crypto asset to withdraw from the address given

address
required
string non-empty

The destination address for this withdraw

addressTag
string or null

Tag of the blockchain address the withdrawal is made to A Tag/Memo is an additional address feature necessary for identifying a transaction recipient or sender beyond a wallet address.

Responses

Request samples

Content type
application/json
{
  • "assetCode": "string",
  • "amount": 0,
  • "address": "string",
  • "addressTag": "string"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get crypto withdrawal

This allows you to get a withdrawal by using either the default Withdrawal Id or the Transaction Hash.

It can be used to check whether the transaction belonging to your account originated from BSD Broker.

To use a different identifier, modify the WithdrawalIdType parameter.

The available options for WithdrawalIdType are:

  • WithdrawalId (default)
  • TransactionHash
Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

withdrawalId
required
string

The identifier of the withdrawal to retrieve. "WithdrawalId"(default) or "TransactionHash".

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
withdrawalIdType
string

The type of the identifier. The given identifier can either be the default "WithdrawalId" or "TransactionHash".

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get whitelisted withdrawal addresses

Use this endpoint to get whitelisted withdrawal addresses for a given asset.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

assetCode
required
string

Asset code

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Responses

Response samples

Content type
application/json
{
  • "result": [
    ]
}

Portfolio

Get a portfolio

User portfolio will include all the instruments the user currently owns. It will also include the current Euro value, invested value and the current profit or loss.

For B2B partners this will return the aggregated portfolio of the partner.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get portfolio performance data points

Use this endpoint to get portfolio performance chart.

Authorizations:
Bearer
path Parameters
userId
required
string

Boerse Stuttgart Digital user identifier

timePeriod
required
string

Time period for data points. Accepted values are:

  • ThreeHours,
  • OneDay,
  • SevenDays,
  • OneMonth,
  • OneYear,
  • AllTime
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Settlement

Get collateral balance

Returns the collateral balance of the given partner account.

Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
userId
string

Boerse Stuttgart Digital user identifier

Responses

Response samples

Content type
application/json
{
  • "result": {
    }
}

Webhooks

Introduction

Webhooks are a form of server-to-server communication which send notifications as soon as specific events occur. By subscribing to webhooks, you can reduce the number of API calls that your solution makes and build your solution to react to important events in real time.

This guide explains how to subscribe to the BSD Partner-Webhooks and contains an explanation and sample payload for each webhook event.

How to subscribe to a webhook

First, your solution must expose a URL (HTTPS) where BSD can send webhook notifications to.

Then, for each event type you wish to subscribe to, you must call the POST Create a webhook subscription method. Supply the following in the request:

  • event_type: The type of webhook event to subscribe to.
  • url: The URL to which BSD will send the webhook notification.

When you register a new webhook subscription, the BSD API will check the availability of the provided URL by sending a single POST notification. The notification does not include a body, but it includes the BSD-WEBHOOK-EVENT-TYPE header with a value of WEBHOOK-SUBSCRIPTION.

If your URL returns a 2XX HTTP response code, then the BSD API will create the webhook subscription and return you a 201 Created response. In the response body, you will find the secret property. You must use the value of this property to verify the authenticity of BSD webhook notifications. The API only exposes this secret once, so if you misplace it, then you must register a new webhook subscription.

How to update a webhook subscription

Once a webhook subscription has been created, it cannot be modified. You must delete the webhook subscription and register a new one with the desired updated properties.

Webhook notification delivery

Implement the following HTTP response codes for the URL where your solution will receive webhook notifications:

Response Code Reaction
2XX Success BSD will consider the notification delivered and will not retry.
410 Gone BSD will mark the notification delivery as rejected and cancels the subscription on this particular URL.
422 Unprocessable Entity The delivery is marked as rejected, and BSD webhook service will not re-attempt to deliver the notification.

Any response code not listed above will place the webhook notification into a retry loop. The retry will happen up to 3 times with a delay of 2 to 8 seconds between each attempt. If the notification is still not delivered, then the webhook service will stop retrying.

Notification content

A webhook notification consists of two parts:

  • Metadata: Information stored in the HTTP header. This could be information related to the webhook subscription itself.
  • Payload: Information stored in the HTTP body. This usually contains all of the properties of the resource related to the webhook event that caused the notification.

Full list of webhook headers

Each webhook notification will contain the following headers:

  • Content-Type: The media type of the webhook notification content.
  • BSD-Webhook-Subscription-Id: ID of the subscription you created for the webhook event.
  • BSD-Webhook-Event-Type: The event type of the webhook notification. See the section below for a full list.
  • BSD-Webhook-Signature: SHA256 signature that you must use to verify the authenticity of the webhook. See the next section for more information.
  • User-Agent: Indicates the user agent that generated the webhook notification on BSD side.

Content verification

BSD provides a signature hash in each webhook notification as the value of the BSD-Webhook-Signature header. This allows you to verify that the notification really came from BSD and protect against misuse of your webhook URL.

The webhook service generates the signature using the HMAC algorithm. It uses the secret from the webhook subscription as the HMAC key to encrypt the payload, and it encodes the digest used for the signature generation in the header. The BSD-Webhook-Subscription-Id header references the relevant secret for calculating the signature.

We recommend that you use the raw message payload to generate a signature hash to verify the one received in the header. This ensures your implementation will not break in case additional fields are introduced. Moreover, calculating on the raw message will ensure that parsing errors do not compromise your ability to verify the authenticity of your webhook traffic.

In order to explain how to verify the signature, we will use the following example, written in C#, where the secret is the one you received with the initial POST upon subscribing and the payload is the actual payload of the current request. The return value of the example method ComputeSignature is the value you have to compare against the BSD-Webhook-Signature header.

string ComputeSignature(string secret, string payload)
{
    byte[] bytesSecret = Encoding.UTF8.GetBytes(secret);
    using var hmac = new HMACSHA256(bytesSecret);
    byte[] hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
    return Hashing.HexStringFromBytes(hashBytes); // this is an internal method which is described below as well
}

string HexStringFromBytes(byte[] bytes)
{
    var sb = new StringBuilder();
    foreach (byte b in bytes)
    {
        var hex = b.ToString("x2");
        sb.Append(hex);
    }
    return sb.ToString();
}

Webhook events

  • user_updated
    {
      "UserId": "Boerse Stuttgart Digital user identifier. This User Id is the id that you get as a response for the create user endpoint",
      "KycStatus": "Confirmed"
    }
    

Create a webhook

Creates a new webhook subscription for a specific event. When you create a webhook subscription, we check the validity of the provided url by sending a single POST notification. The response from this endpoint contains a unique id for the subscription and a secret. Use this secret to verify the authenticity of the notifications. Webhook URLs cannot be changed after creating a webhook subscription. You must delete the existing webhook and register a new one with the new URL. Note that you will receive a new id and secret.

Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Request Body schema: application/json
url
required
string non-empty

Norification URL address

eventType
required
string non-empty

Event type

Responses

Request samples

Content type
application/json
{
  • "url": "string",
  • "eventType": "string"
}

Response samples

Content type
application/json
{
  • "result": {
    }
}

Get webhooks

Returns current webhook subscriptions.

Authorizations:
Bearer
path Parameters
partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

query Parameters
eventType
string

Event type

Responses

Response samples

Content type
application/json
{}

Delete a webhook

Deletes the webhook subscription specified in the request URL. Please ensure that you have a replacement for a webhook before deleting it. All stored and unsent notifications will be lost.

Authorizations:
Bearer
path Parameters
webhookId
required
string

Webhook identifier

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Responses

Response samples

Content type
application/json
{
  • "result": { }
}

Files

This section covers endpoints related to report and file downloads.

Get file as a download

Use this endpoint to download partner specific files and reports.

Authorizations:
Bearer
path Parameters
fileName
required
string

file name to download

partnerId
required
string

Partner identifier provided by Boerse Stuttgart Digital

Responses

Response samples

Content type
application/problem+json
{
  • "code": "string",
  • "message": "string",
  • "errors": [
    ],
  • "type": "string",
  • "title": "string",
  • "status": 0,
  • "detail": "string",
  • "instance": "string",
  • "trace": "string",
  • "property1": null,
  • "property2": null
}

Monitoring

Ping

Use this endpoint to check if connection is working. Response code of 200 means everything is fine.

Responses

Response samples

Content type
application/problem+json
{
  • "code": "string",
  • "message": "string",
  • "errors": [
    ],
  • "type": "string",
  • "title": "string",
  • "status": 0,
  • "detail": "string",
  • "instance": "string",
  • "trace": "string",
  • "property1": null,
  • "property2": null
}

FIX

FIX api is offered as a complementary to the REST API. It is not meant as a complete substitute. Some of the processes, for example the on-boarding of B2B2C customers can only be done through the REST API.

It is important to review this document in line with the published FIX specification, of which this forms the part that is relevant and implemented for BSD Broker. This specification is publicly available and free, and can be obtained from www.fixprotocol.org.

Connectivity

Channel Endpoint
Quotes Please contact us for connection details.
RfQ Please contact us for connection details.
Trading Please contact us for connection details.
TradeReport Please contact us for connection details.

Session particulars

BSD Broker FIX Session runs as a server. Therefore, the incoming institutions session will normally be deemed to be the client, firewalls and connectivity should be arranged accordingly.

FIX specific technologies

FIX version – BSD Broker facilitates quote driven and trading and has been built around the FIX 4.4 specification, which implemented Quotes, therefore the interface does not attempt to be backwardly compatible with any previous version of the FIX specification. FIX attempts to maintain backward compatibility and therefore this specification should be compatible with 4.4 or previous versions, it is however the onus of the institutions to determine the specific compatibility.

Encryption

Currently encryption is realized only on transport protocol level. On message level no encryption or signing is supported.

Message queuing / Recovery

In case of lost messages - for example due to an unexpected connection failure - for all channels, except Quotes channel, the standard FIX-protocol synchronization is used. On Logon the client has to determine from the MsgSeqNo of the acceptor that messages are missing and send a ResendRequest(2).

For Quotes channel the initiator must reset the FIX session on every connect (restarting with message sequence number 1). To recover just resend the last Quote Request.

Session reset

A FIX session in all channels except Quotes channel should not be active for longer than one week. There are two ways to archieve a frequently session reset. The first option is the default and recommended way:

1. The initiator resets the FIX session upon logon

An initiator should reset the session once a week in the following way:

  • send Test Request(1) message (this is optional, but ensures that both sides have synchronous message sequence numbers)
  • send Logout(5) message
  • terminate the TCP/IP connection
  • establish new TCP/IP connection
  • send Logon(A) message with tags ResetSeqNumFlag(141)=Y and MsgSeqNum(34)=1
  • acceptor will acknowledge with Logon(A) message and MsgSeqNum(34)=1
  • the session reset is done on both sides

Note: to ensure that no Execution Report message is lost on TradeReport channel, the client must ensure that during the session reset process no trade is done, neither over REST API nor over FIX API. This applies only when the TradeReport channel is used.

2. Weekly session with defined start and end time

Both sides agree on a period of time during the week in which the session will end. Within this period both sides do the session reset independently so that after the next connect the first two (Logon) messages have sequence number one. All parameters (time and duration) are negotiable. For example: session reset should be done every saturday at 4am. The session will end at saturday 3:55am and will start at 4:05am.


Note: in both options, when a session is more than two weeks old, the acceptor may force a disconnect by sending a Logout(5) message and will reject any Logon(A) message without ResetSeqNumFlag(141)=Y with the text "FIX session has expired. Please send LOGON with ResetSeqNumFlag(141) = Y and MsgSeqNum(34) = 1." In this exceptional case, messages maybe lost if trades are done between forced logout and successful logon. These lost messages can be requested manually at our support.

General guidelines on error handling

Specific errors to request messages are described under the appropriate message.

If the client gets an error message (for example in the field Text(58)) "Internal server error with id ..." please provide this id when contacting the BSD support.

In general every field that expects a defined number of values is sent with an invalid value, a Reject message will be sent as response. In particular:

Tag Field Name Comments
115 OnBehalfOfCompID Trading partner ID, required in all messages from the client in the RfQ channel.
55 Symbol Must be a valid trading pair.
146 NoRelatedSym In the Quote Request for RfQ must be 1 as only single quote requests are supported.
54 Side Only 1 = Buy or 2 = Sell are allowed.
40 OrdType On RfQ channel always D = Previously quoted, on Trading channel only 1 = Market is supported.
569 TradeRequestType 0 = All trades, 1 = Matched trades matching criteria provided on request.
263 SubscriptionRequestType Always 0 = Snaphot.

Example:

  • Invalid OnBehalfOfCompID:
    8=FIX.4.4 | 9=179 | 35=3 | 34=35 | 49=BSD_RFQ | 52=20240126-15:57:31.366 | 56=RFQ_CLIENT1 | 128=fb2a616d-2ec5-4144-8f09-f5883a5f677e | 45=35 | 58=Value is incorrect (out of range) for this tag | 371=115 | 372=R | 373=5 | 10=163 |

FIX messages

Content

  1. Typographic Conventions
  2. Common restrictions
  3. Extensions to FIX standard
  4. Header and trailer
  5. Session messages
  6. Quotes workflow
  7. RfQ workflow
  8. Trading workflow
  9. Trade Report workflow

Typographic Conventions

Italic tags are values of tags indicates custom extensions in the FIX.4.4 protocol.

Common restrictions

  • All fields having names ending with "ID" have a maximum length of 36 and must match the following regular expression: ^[A-Za-z0-9_-]{1,36}$. Example: A056ADEE-AEBB-4670-AB24-AB1D82E9E3D7

Extensions to FIX standard

These are the new fields defined by this API:

Tag Field Name Description
20020 ExternalTraderID Defines the external dashboard trader identifier
20021 RevokedOrderID Revoked order identifier points from storno to original order
20022 StornoOrderID Storno order identifier points from original order to storno order
20023 PriceImprovementOrderID Price improvement order identifier points from original to new price improved order
20024 RevokedOrderTransactTime Revoked order transaction time in UTC

Header and trailer

Standard FIX message header

FIX stipulates that a certain amount of information must be passed with every message in the header, these fields are flagged as Req’d (Required / Mandatory) in the FIX specification. Also, BSD Broker requires a certain amount of information in order to correctly route the message back to the institution node. The mandatory header fields for FIX and BSDBroker are listed below:

Tag Field Name Mandatory Comments
8 BeginString Y FIX.4.4 (Always unencrypted, must be first field in message)
9 BodyLength Y (Always unencrypted, must be second field in message)
35 MsgType Y (Always unencrypted, must be third field in message)
34 MsgSeqNum Y Integer message sequence number.
49 SenderCompID Y (Always unencrypted)
52 SendingTime Y Time of message transmission (always expressed in UTC)
56 TargetCompID Y BSD_QUOTING, BSD_TRADING, BSD_TRADEREPORT or BSD_RFQ (Always unencrypted)
115 OnBehalfOfCompID N Trading partner ID, required in all messages from the client in the Trading and RfQ channel. This is basically the userId provided during the onboarding (B2B) or the userId of the user the trade is intended for (B2B2C)
128 DeliverToCompID N Trading partner ID, required in all business messages from the server in the "Trading" and "Trade Report" channel.

Note: The SenderCompID(49) is specified by the BSD for each institution.

Note: Please make sure to only send tags specified in this documentation and per message. All messages having other tags, will be rejected.

Standard message trailer

Tag Field Name Mandatory Comments
10 CheckSum Y (Always unencrypted, always last field in message)

Session messages

The following diagram shows the initiation of a FIX connection.

sequenceDiagram
    Note over Initiator,Acceptor: Disconnected
    Initiator-->>Acceptor: TCP connection
    Note over Initiator,Acceptor: TCP connection is established
    Initiator->>Acceptor: Logon (MsgType=A)
    Acceptor->>Initiator: Logon (MsgType=A)
    Note over Initiator,Acceptor: FIX connection is established
    Initiator->>Acceptor: Heartbeat (MsgType=0)
    Acceptor->>Initiator: Heartbeat (MsgType=0)

Logon (A)

Sent by the client to initiate a session and by the server as an acknowledgement. Only one session may exist per connection; sending a Logon message within an established session is an error.

Tag Field Name Mandatory Comments
35 MsgType Y A
34 MsgSeqNum Y Must be 1 in Quotes and RfQ channel. In TradeReport channel the next sequence number of the session.
98 EncryptMethod Y Always 0 (unencrypted)
108 HeartBtInt Y Must be ≤ 30 (secs). Values greater are capped at 30. Server sends Test Request if client messages are not received in approximately (HeartBtInt x 1.5) seconds. Server terminates session if client messages are not received in approximately (HeartBtInt x 2 seconds). Note same value used by both sides.
141 ResetSeqNumFlag N 'Y' for Quote and RfQ channel, 'N' for TradeReport channel, except session reset. Required from client.
553 Username N The provided clientId, you have been given during onboarding. This is the same as used for authenticate in REST API. Required from client.
554 Password N The provided clientSecret, you have been given during onboarding. This is the same as used for authenticate in REST API. Required from client.

Examples

Success
  • Request:
    8=FIX.4.4 | 9=97 | 35=A | 34=1 | 49=RFQ_CLIENT1 | 52=20240126-14:24:37.319 | 56=BSD_RFQ | 98=0 | 108=30 | 141=Y | 553=test | 554=test | 10=198 |
  • Response:
    8=FIX.4.4 | 9=73 | 35=A | 34=1 | 49=BSD_RFQ | 52=20240126-14:24:37.367 | 56=RFQ_CLIENT1 | 98=0 | 108=30 | 10=095 |
Errors
  • 8=FIX.4.4 | 9=128 | 35=5 | 34=1 | 49=BSD_RFQ | 52=20240126-14:15:19.112 | 56=RFQ_CLIENT1 | 58=Rejected Logon Attempt: Authentication failed for user "test2". | 10=183 |

Every reject of a logon request is followed by a disconnect of the underlying TCP/IP connection. Note that if tag Username(553) is missing, the connection will be closed immediatly without sending any response.

Heartbeat (0)

No changes to the FIX.4.4 specification.

Test Request (1)

No changes to the FIX.4.4 specification.

Resend Request (2)

No changes to the FIX.4.4 specification.

Reject (3)

No changes to the FIX.4.4 specification.

BusinessMessageReject (j)

No changes to the FIX.4.4 specification.

Logout (5)

Both sides can initiate the end of the connection. Every connection close without the Logout handshake will be treated as abnormal closure of the session.

In case of a planned system shutdown, the service will send a News message with Urgency = Flash (1) and the constant headline "SYSTEM SHUTDOWN IN 10 MINUTES. PLEASE LOGOUT."

If a client does not logout within 10 minutes, the server will send the Logout message and close the connection even the Logout response from the client is missing.

Within these 10 minutes, a logon is not possible. Any logon request will be rejected with one of the messages "System will shutdown in XXXs." or "System is shut down.".

sequenceDiagram
    Note over Initiator,Acceptor: FIX connection is established
    Initiator->>Acceptor: Logout (MsgType=A)
    Acceptor->>Initiator: Logout (MsgType=A)
    Initiator--xAcceptor: TCP disconnect
    Note over Initiator,Acceptor: FIX connection is terminated

News (B)

All text is always ASCII encoded.

Tag Field Name Mandatory Comments
35 MsgType Y B
61 Urgency Y 0 = Normal, 1 = Flash, 2 = Background
148 Headline Y Subject.
33 NoLinesOfText Y Number of lines in the message, maybe 0.
>58 Text Y One line of the message.

Example

8=FIX.4.4 | 9=129 | 35=B | 34=2 | 49=BSD_TRADING | 52=20230823-09:55:59.786 | 56=TRADING_CLIENT1 | 33=0 | 61=1 | 148=SYSTEM SHUTDOWN IN 10 MINUTES. PLEASE LOGOUT. | 10=077 |

Quotes workflow

The quotes workflow allows to subscribe to a quote stream for all valid trading pairs.

sequenceDiagram
    Initiator->>Acceptor: Quote Request (MsgType=R)
    Acceptor->>Initiator: Mass Quote (MsgType=i)
    Acceptor->>Initiator: Mass Quote (MsgType=i)
    Acceptor->>Initiator: Mass Quote (MsgType=i)

Supported Message Types

The following FIX message types are supported in the RfQ workflow:

MsgType Message Name Direction*
R QuoteRequest O
S Mass Quote I

* I = Inbound to Client, O = Outbound from Client

Quote Request (R)

Subscribe/Unsubscribe of quotes for trading pairs. Each request replaces the subscription list at the server. That means if the client wants to add a new trading pair to the subscriptions all already subscribed trading pairs must be resend in the request.

After sending the request the server will respond with one Mass Quote message containing the last known quotes from each trading pair (if available).

These prices are calculated for an order size of 100 euro and are for informational purposes only.

Tag Field Name Mandatory Comments
35 MsgType Y R
131 QuoteReqID Y Unique identifier for this request, created by the client.
146 NoRelatedSym Y Number of related symbols (trading pairs) in request. If set to zero (0), all quotes will be unsubscribed.
>55 Symbol N Required if NoRelatedSym greater than zero. One or more valid trading pair.

Example

  • Subscribe quotes for 17 different crypto currencies
    8=FIX.4.4 | 9=313 | 35=R | 34=2 | 49=QUOTING_CLIENT1 | 52=20230823-10:01:19.411 | 56=BSD_QUOTING | 131=3ebb9d31-9980-4501-bbe1-8fdcc8b0003e | 146=17 | 55=BTC/EUR | 55=LTC/EUR | 55=ETH/EUR | 55=XRP/EUR | 55=BCH/EUR | 55=LINK/EUR | 55=UNI/EUR | 55=SOL/EUR | 55=ADA/EUR | 55=DOT/EUR | 55=DOGE/EUR | 55=SHIB/EUR | 55=POL/EUR | 55=ALGO/EUR | 55=SAND/EUR | 55=MANA/EUR | 55=AAVE/EUR | 10=177 |

Mass Quote (i)

This message will be sent on any quote change as long a subscription exists.

Tag Field Name Mandatory Comments
35 MsgType Y i
131 QuoteReqID Y Unique identifier for this request, created by the client.
117 QuoteID Y Unique identifier of this quote message created by the server.
296 NoQuoteSets Y The number of sets of quotes in the message.
>302 QuoteSetID Y Sequential number for the Quote Set, starting with 1.
>295 NoQuoteEntries Y The number of quotes for this Symbol (55) that follow in this message. Nested Repeating Group follow
>>299 QuoteEntryID Y Uniquely identifies the quote as part of a QuoteSet.
>>55 Symbol Y A valid trading pair.
>>132 BidPx N Bid price.
>>133 OfferPx N Ask price.

Example

  • response to the example above
    8=FIX.4.4 | 9=816 | 35=i | 34=2 | 49=BSD_QUOTING | 52=20230823-10:04:57.798 | 56=QUOTING_CLIENT1 | 117=0f746bc0-d24d-456a-992d-ed0bb853aaab | 131=3ebb9d31-9980-4501-bbe1-8fdcc8b0003e | 296=1 | 302=1 | 295=17 | 299=1 | 55=BTC/EUR | 132=20000 | 133=21000 | 299=2 | 55=LTC/EUR | 132=20000 | 133=21000 | 299=3 | 55=ETH/EUR | 132=20000 | 133=21000 | 299=4 | 55=XRP/EUR | 132=20000 | 133=21000 | 299=5 | 55=BCH/EUR | 132=20000 | 133=21000 | 299=6 | 55=LINK/EUR | 132=20000 | 133=21000 | 299=7 | 55=UNI/EUR | 132=20000 | 133=21000 | 299=8 | 55=SOL/EUR | 132=20000 | 133=21000 | 299=9 | 55=ADA/EUR | 132=20000 | 133=21000 | 299=10 | 55=DOT/EUR | 132=20000 | 133=21000 | 299=11 | 55=DOGE/EUR | 132=20000 | 133=21000 | 299=12 | 55=SHIB/EUR | 132=20000 | 133=21000 | 299=13 | 55=POL/EUR | 132=20000 | 133=21000 | 299=14 | 55=ALGO/EUR | 132=20000 | 133=21000 | 299=15 | 55=SAND/EUR | 132=20000 | 133=21000 | 299=16 | 55=MANA/EUR | 132=20000 | 133=21000 | 299=17 | 55=AAVE/EUR | 132=20000 | 133=21000 | 10=056 |

RfQ workflow

The RfQ workflow allows you to request a tradeable quote. The server responds with a quote that is valid for a defined timespan. The customer can trade on this quote sending a new order single with the quote reference.

sequenceDiagram
    Initiator->>Acceptor: Quote Request (MsgType=R)
    alt Quote Ok
      Acceptor->>Initiator: Quote (MsgType=S)
      opt
        Initiator->>Acceptor: New Order Single (MsgType=D)
        Acceptor->>Initiator: Execution Report (MsgType=8)
      end
    else Quote not available
      Acceptor->>Initiator: QuoteRequestReject (MsgType=AG)
    end

Supported Message Types

The following FIX message types are supported in the RfQ workflow:

MsgType Message Name Direction*
R QuoteRequest O
S Quote I
AG Quote Request Reject I
G New Order Single O
8 Execution Report I

* I = Inbound to Client, O = Outbound from Client

Order Status Transitions (RfQ)

stateDiagram-v2
    [*] --> Filled : Trade
    [*] --> Rejected : Reject
    Filled --> Canceled
    Filled --> [*]
    Rejected --> [*]
    Canceled --> [*]
    

Valid Status Values (RfQ)

These are the valid values for the field OrdStatus (39) in case of OrdTyp (40) is Limit or Stop order:

Value Name Description
2 Filled The order has been completely filled.
4 Canceled The order has been canceled by backoffice.
8 Rejected The server failed to confirm the validity of the order and the order submission has failed.

Quote Request for RfQ (R)

This request returns a buy or sell Quote (in Euro) for either a chosen amount of crypto or a chosen Euro amount. The quote price returned is the price for which cryptos will bought or sold.

Tag Field Name Mandatory Comments
35 MsgType Y R
131 QuoteReqID Y Unique identifier for this request, created by the client.
146 NoRelatedSym Y Must be 1 as only single quote requests are supported.
55 Symbol Y A valid trading pair.
54 Side Y Only 1 = Buy or 2 = Sell are allowed.
38 OrderQty N The amount of the crypto asset to request a quote for. Required unless you specified CashOrderQty(152) (fiat amount).
152 CashOrderQty N The fiat amount to request a quote to buy or sell. Required unless you specified OrderQty(38) (crypto amount).

Note: Only one of the fields OrderQty(38) and CashOrderQty(152) must be set. If none or both are set in a message the service will respond with a Quote Request Reject message.

Examples

  • Buy 1.5 BTC:
    8=FIX.4.4 | 9=171 | 35=R | 34=2 | 49=RFQ_CLIENT1 | 52=20240125-08:56:32.799 | 56=BSD_RFQ | 115=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 131=31a16668-f919-456d-bdab-4b83af3d7339 | 146=1 | 55=BTC/EUR | 54=1 | 38=15 | 10=106 |
  • Buy BTC for 40.000 euro:
    8=FIX.4.4 | 9=175 | 35=R | 34=5 | 49=RFQ_CLIENT1 | 52=20240125-08:57:39.610 | 56=BSD_RFQ | 115=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 131=9ac60578-1298-4dc3-95c4-b9fb5ca6ae8d | 146=1 | 55=BTC/EUR | 54=1 | 152=40000 | 10=138 |
  • Sell 0.5 BTC:
    8=FIX.4.4 | 9=172 | 35=R | 34=7 | 49=RFQ_CLIENT1 | 52=20240125-08:58:28.736 | 56=BSD_RFQ | 115=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 131=2d0883d7-dda1-489d-bc35-0d5f0c601b16 | 146=1 | 55=BTC/EUR | 54=2 | 38=0.5 | 10=184 |
  • Sell BTC for 5000 euro:
    8=FIX.4.4 | 9=174 | 35=R | 34=9 | 49=RFQ_CLIENT1 | 52=20240125-08:59:25.041 | 56=BSD_RFQ | 115=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 131=2961084e-fee0-4829-abc8-7826269cbfcc | 146=1 | 55=BTC/EUR | 54=2 | 152=5000 | 10=041 |

Quote for RfQ (S)

Tag Field Name Mandatory Comments
35 MsgType Y S
131 QuoteReqID Y Unique identifier of the corresponding request.
117 QuoteID Y Unique identifier of this quote created by the server. Musst be passed in the New Order Single.
537 QuoteType Y Always 1 = Tradeable.
55 Symbol Y A valid trading pair.
38 OrderQty Y The value that was sent in the Quote Request.
152 CashOrderQty Y The value that was sent in the Quote Request.
192 OrderQty2 Y The corrected (rounded) quantity of the backend. This is the value for the OrderQty(38) that must be passed in the New Order Single.
132 BidPx N The bid price. Required if Side = Buy in the request.
133 OfferPx N The offer price. Required if Side = Sell in the request.
134 BidSize N The corrected fiat amount of the backend. This is the value for the CashOrderQty(152) that must be passed in the New Order Single. Required if Side = Buy in the request.
135 OfferSize N The corrected fiat amount of the backend. This is the value for the CashOrderQty(152) that must be passed in the New Order Single. Required if Side = Sell in the request.
62 ValidUntilTime Y UTCTimestamp until this quote is valid.

Examples

  • Buy 1.5 BTC:
    8=FIX.4.4 | 9=242 | 35=S | 34=2 | 49=BSD_RFQ | 52=20240125-08:56:35.368 | 56=RFQ_CLIENT1 | 38=15 | 55=BTC/EUR | 62=20240125-08:56:49.681 | 117=78131079-ee8a-4eb1-90d9-3aec60f2aa5f | 131=31a16668-f919-456d-bdab-4b83af3d7339 | 132=37263.776961754344 | 134=49916.58 | 192=1.33954698 | 537=1 | 10=178 |
  • Buy BTC for 40.000 euro:
    8=FIX.4.4 | 9=245 | 35=S | 34=5 | 49=BSD_RFQ | 52=20240125-08:57:39.792 | 56=RFQ_CLIENT1 | 55=BTC/EUR | 62=20240125-08:57:54.778 | 117=0f0daac5-9f4b-407c-8452-db300294f713 | 131=9ac60578-1298-4dc3-95c4-b9fb5ca6ae8d | 132=37261.354031262168 | 134=40000.0 | 152=40000 | 192=1.07349829 | 537=1 | 10=005 |
  • Sell 0.5 BTC:
    8=FIX.4.4 | 9=236 | 35=S | 34=7 | 49=BSD_RFQ | 52=20240125-08:58:28.917 | 56=RFQ_CLIENT1 | 38=0.5 | 55=BTC/EUR | 62=20240125-08:58:43.903 | 117=660c34d3-1539-4804-bff3-d273cd44f4c6 | 131=2d0883d7-dda1-489d-bc35-0d5f0c601b16 | 133=36318.544038243091 | 135=18159.27 | 192=0.5 | 537=1 | 10=220 |
  • Sell BTC for 5.000 euro:
    8=FIX.4.4 | 9=243 | 35=S | 34=9 | 49=BSD_RFQ | 52=20240125-08:59:25.575 | 56=RFQ_CLIENT1 | 55=BTC/EUR | 62=20240125-08:59:40.560 | 117=099b665d-8d2b-4377-ac19-9add5f5ab7b5 | 131=2961084e-fee0-4829-abc8-7826269cbfcc | 133=36332.512436951857 | 135=5000.0 | 152=5000 | 192=0.13761779 | 537=1 | 10=239 |

Quote Request Reject (AG)

This message is sent in case of a quote is not available.

Tag Field Name Mandatory Comments
35 MsgType Y AG
131 QuoteReqID Y Unique identifier of the corresponding request.
658 QuoteRequestRejectReason Y 99 = Other
146 NoRelatedSym Y Always 1.
55 Symbol Y The valid trading pair of the request.
54 Side Y The value of the request.
38 OrderQty N The value of the request, if available.
152 CashOrderQty N The value of the request, if available.
58 Text N A human readable error description.

Examples

  • Invalid OrderQty (-1):
    8=FIX.4.4 | 9=196 | 35=AG | 34=3 | 49=BSD_RFQ | 52=20240126-12:44:29.876 | 56=RFQ_CLIENT1 | 58=Value -1 for OrderQty(38) is invalid. It must be positive. | 131=734194d7-0901-4bdb-8d16-703616941fc6 | 658=99 | 146=1 | 55=AAVE/EUR | 38=-1 | 10=172 |
  • OrderQty and CashOrderQty set:
    8=FIX.4.4 | 9=208 | 35=AG | 34=5 | 49=BSD_RFQ | 52=20240126-12:45:23.493 | 56=RFQ_CLIENT1 | 58=Either field OrderQty(38) or field CashOrderQty(152) must be set. | 131=7f66b54d-923e-4f39-8013-1d037c5f681f | 658=99 | 146=1 | 55=AAVE/EUR | 38=1 | 152=2 | 10=057 |
  • Rounding error:
    8=FIX.4.4 | 9=195 | 35=AG | 34=5 | 49=BSD_RFQ | 52=20240126-15:42:23.264 | 56=RFQ_CLIENT1 | 58=Exchange order amount not rounded correctly | 131=553145bd-efe3-4c5d-b2dd-dd96cc69dde3 | 658=99 | 146=1 | 55=AAVE/EUR | 152=0.1234567890123 | 10=072 |

New Order Single for RfQ (D)

Tag Field Name Mandatory Comments
35 MsgType Y D
11 ClOrdID Y ID passed by the client and returned in the response Execution Report. Not processed by the server. Values defined on partner level. Maximum length is 35 character. May consist of alphanumerical characters (a-z, A-Z, 0-9) and underscores (_) only.
526 SecondaryClOrdID N Additional ID passed by the client and returned in the response Execution Report. Not processed by the server. Maximum length is 35 character. May consist of alphanumerical characters (a-z, A-Z, 0-9) and underscores (_) only.
55 Symbol Y A valid trading pair. Must match the symbol of the referenced Quote request.
54 Side Y The side of the order, must be the same value as in the Quote Request.
60 TransactTime Y Time this order request was initiated/released by the institution. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)
38 OrderQty Y Crypto amount of the order, must be the value of OrderQty2(192) in the Quote.
152 CashOrderQty Y Fiat amount of the order, must be the value of BidSize(134) or OfferSize(135) in the Quote.
40 OrdType Y Always D = Previously quoted.
117 QuoteID Y The QuoteID of the Quote.

Example

  • Buy 0,35 BTC:
    8=FIX.4.4 | 9=251 | 35=D | 34=27 | 49=RFQ_CLIENT1 | 52=20240125-09:07:49.984 | 56=BSD_RFQ | 115=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 11=f85c73f5-e534-4666-bbbf-311fcceddc59 | 38=0.35 | 40=D | 54=1 | 55=BTC/EUR | 60=20240125-09:07:49.984 | 117=cb1e4280-aa16-4f5b-8086-6e15672e540b | 152=13046.11 | 10=140 |

Execution Report for RfQ (8)

Tag Field Name Mandatory Comments
35 MsgType Y 8
37 OrderID Y Unique ID created by the server. (Always equals the QuoteID(117) of the [Quote](#quote-for-rfq-s] message).
11 ClOrdID N Unique ID created by the client in the New Order Single message. Not set in case of storno or price improvement orders. See Order revoke and price improvement process for more details.
41 OrigClOrdID N Used in storno or price improvement orders to point to the correspondending client order. See Order revoke and price improvement process for more details.
526 SecondaryClOrdID N Additional ID from the New Order Single.
17 ExecID Y Unique identifier of execution message.
150 ExecType Y One of the Valid values for ExecType(150).
39 OrdStatus Y One of the Valid values for OrdStatus(39).
103 OrdRejReason N Only available in case of OrdStatus = Rejected. One of the Order Reject Reason values for RfQ.
55 Symbol Y Valid trading pair.
54 Side Y Only 1 = Buy or 2 = Sell are allowed.
152 CashOrderQty N Required if the OrdStatus(39) is Filled. The total volume in fiat currency (EUR) of the trade.
151 LeavesQty Y Always 0.
14 CumQty Y If OrdStatus = Filled then the OrderQty of the New Order Single otherwise 0.
6 AvgPx Y If OrdStatus = Filled then the BidPx or OfferPx of the Quote otherwise 0.
60 TransactTime Y Trade execution time as recorded on server side. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)
58 Text N A human readable error description in case of OrdRejReason(103) = Other(99).
20021 RevokedOrderID N Revoked order identifier points from storno to original order
20022 StornoOrderID N Storno order identifier points from original order to storno order
20023 PriceImprovementOrderID N Price improvement order identifier points from original to new price improved order
20024 RevokedOrderTransactTime N Revoked order transaction time as recorded on server side. Present on storno orders. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)

Example

  • Buy 0,35 BTC:
    8=FIX.4.4 | 9=294 | 35=8 | 34=27 | 49=BSD_RFQ | 52=20240125-09:07:51.843 | 56=RFQ_CLIENT1 | 6=37274.595716898540 | 11=f85c73f5-e534-4666-bbbf-311fcceddc59 | 14=0.35 | 17=c3abf36b-661f-41dd-a671-eb679a67dfa8 | 37=cb1e4280-aa16-4f5b-8086-6e15672e540b | 39=2 | 54=1 | 55=BTC/EUR | 60=20240125-09:07:51.838 | 150=F | 151=0 | 152=13046.10850091448900 | 10=115 |

Order Reject Reason values for RfQ

Value Name Description
1 Unknown Symbol Wrong value for Symbol (55) (The symbol differs from the Quote Request, an invalid symbol will result in a reject) message.
4 Too late to enter The order arrived too late at the exchange due to the ValidUntilTime (62) of the Quote.
5 Unknown Order The QuoteID (37) is not known.
6 Duplicate Order A order for the QuoteID (37) was already sent.
13 Incorrect quantity The OrderQty (38) of the New Order Single differs from the value in Quote Request.
99 Other Unexpected error occurred.
100 NotEnoughAsset Error indicates that sell order can not be executed due not enough assets on users portfolio.
101 UnstableMarket Error indicates that order can not be executed due unstable market, so price changes to much from quoting time. Please request new quote.

Examples

  • Unknown Symbol
    8=FIX.4.4 | 9=223 | 35=8 | 34=3 | 49=BSD_RFQ | 52=20240125-09:26:49.447 | 56=RFQ_CLIENT1 | 6=0 | 11=dd2c4302-13f1-44db-90ab-14b1cf4fc171 | 14=0 | 17=2bc81866-7c13-4324-8f15-a1d0f47abbd5 | 37=NONE | 39=8 | 54=1 | 55=AAVE/EUR | 60=20240125-09:26:49.447 | 103=1 | 150=8 | 151=0 | 10=088 |
  • Too late to enter:
    8=FIX.4.4 | 9=223 | 35=8 | 34=45 | 49=BSD_RFQ | 52=20240125-09:15:44.536 | 56=RFQ_CLIENT1 | 6=0 | 11=05b0bf15-366a-4d20-b838-f53d7b54eb59 | 14=0 | 17=44c5ab61-6cc1-4cc7-a83a-1971a4cf2087 | 37=NONE | 39=8 | 54=1 | 55=BTC/EUR | 60=20240125-09:15:44.535 | 103=4 | 150=8 | 151=0 | 10=037 |
  • Unknown order
    8=FIX.4.4 | 9=223 | 35=8 | 34=47 | 49=BSD_RFQ | 52=20240125-09:16:26.315 | 56=RFQ_CLIENT1 | 6=0 | 11=ca2883b6-a482-4bec-a381-95534883bf92 | 14=0 | 17=7257d9cb-5d41-48cc-b3bb-3b379786471c | 37=NONE | 39=8 | 54=1 | 55=BTC/EUR | 60=20240125-09:16:26.315 | 103=5 | 150=8 | 151=0 | 10=229 |
  • Duplicate Order:
    8=FIX.4.4 | 9=223 | 35=8 | 34=35 | 49=BSD_RFQ | 52=20240125-09:11:34.567 | 56=RFQ_CLIENT1 | 6=0 | 11=80b3e0d8-bee2-40ea-ad44-0adddcac361c | 14=0 | 17=709db614-add0-451d-86a8-c395f4e98515 | 37=NONE | 39=8 | 54=1 | 55=BTC/EUR | 60=20240125-09:11:34.567 | 103=6 | 150=8 | 151=0 | 10=020 |
  • Incorrect quantity:
    8=FIX.4.4 | 9=224 | 35=8 | 34=41 | 49=BSD_RFQ | 52=20240125-09:13:58.411 | 56=RFQ_CLIENT1 | 6=0 | 11=1d0f8bcd-5162-4e4e-930e-3360df593b08 | 14=0 | 17=7456c551-6319-4bdf-b16c-bdb07a77c4f4 | 37=NONE | 39=8 | 54=1 | 55=BTC/EUR | 60=20240125-09:13:58.411 | 103=13 | 150=8 | 151=0 | 10=086 |

Trading workflow

Supported Message Types

The following FIX message types are supported in the trading workflow:

MsgType Message Name Direction*
D New Order Single O
8 Execution Report I

* I = Inbound to Client, O = Outbound from Client

Successful Workflow

The following sequence diagram shows a short message flow for a successfully executed order that was filled.

sequenceDiagram
    Initiator->>Acceptor: New Order Single (D)
    Acceptor->>Initiator: Execution Report (8) OrdStatus=PendingNew
    Acceptor->>Initiator: Execution Report (8) OrdStatus=New
    Acceptor->>Initiator: Execution Report (8) OrdStatus=Filled

Order Status Transitions

stateDiagram-v2
    [*] --> PendingNew
    [*] --> Rejected
    PendingNew --> Filled : Trade
    PendingNew --> New
    PendingNew --> Rejected
    New --> Filled : Trade
    Filled --> [*]
    Rejected --> [*]

New Order Single for Trading (D)

A New Order Single message is used by the client to place a market order.

Tag Field Name Mandatory Comments
35 MsgType Y D
11 ClOrdID Y Unique identifier created by the client. Maximum length is 35 character. May consist of alphanumerical characters (a-z, A-Z, 0-9) and underscores (_) only.
55 Symbol Y A valid trading pair.
54 Side Y Only 1 = Buy or 2 = Sell are allowed.
60 TransactTime Y Time this order request was initiated/released by the institution. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)
38 OrderQty N Quantity for the quote. Exact one of the tags OrderQty(38) or CashOrderQty(152) must be specified.
152 CashOrderQty N Fiat amount of the order. Exact one of the tags OrderQty(38) or CashOrderQty(152) must be specified.
40 OrdType Y Currently only 1 = Market is supported.

Please make sure to also include the necessary header fields. Specifically the OnBehalfOfCompID needs to be taken into consideration. The response to this message will be an execution report with the appropriate status (normally PendingNew).

Example

  • Buy 0,0001 BTC:
    8=FIX.4.4 | 9=209 | 35=D | 34=2 | 49=TRADING_CLIENT1 | 52=20240829-09:29:52.103437 | 56=BSD_TRADING | 115=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 11=3d8cab81-d571-41a3-afdb-ecf02a85dec1 | 38=0.0001 | 40=1 | 54=1 | 55=BTC/EUR | 60=20240829-09:29:52.101 | 10=101 |

Execution Report for Trading (8)

The Execution Report (8) message is used to:

  1. confirm the receipt of an order (status = PendingNew)
  2. confirm that an order has become active (status = New)
  3. confirm changes to an existing order
  4. information about execution of an order
Tag Field Name Mandatory Comments
35 MsgType Y 8
37 OrderID Y Required to be unique for each chain of orders. If OrdStatus(39) = Pending New(A) OrderID has value 'NONE'.
11 ClOrdID N Unique ID created by the client in the New Order Single message. Not set in case of storno or price improvement orders. See Order revoke and price improvement process for more details.
41 OrigClOrdID N Used in storno or price improvement orders to point to the correspondending client order. See Order revoke and price improvement process for more details.
17 ExecID Y Unique identifier for this message, created by the server (trade identifier).
150 ExecType Y One of the Valid values for ExecType(150).
39 OrdStatus Y One of the Valid values for OrdStatus(39).
103 OrdRejReason N Only available in case of OrdStatus = Rejected. One of the Order Reject Reason values for Trading.
55 Symbol Y Valid trading pair.
54 Side Y Only 1 = Buy or 2 = Sell are allowed.
152 CashOrderQty N Required if the OrdStatus(39) is Filled. The total volume in Fiat currency (EUR) of the trade.
40 OrdType N Currently only 1 = Market is supported.
151 LeavesQty Y Always 0.
14 CumQty Y If OrdStatus = Filled then the OrderQty of the New Order Single otherwise 0.
6 AvgPx Y Calculated average price of all fills on this order.
60 TransactTime N Trade execution time as recorded on server side. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000). Required if OrdStatus(39) is Filled(2)
58 Text N May contain additional information about the reason for rejected orders in case of OrdRejReason(103) = Other(99).
20021 RevokedOrderID N Revoked order identifier points from storno to original order
20022 StornoOrderID N Storno order identifier points from original order to storno order
20023 PriceImprovementOrderID N Price improvement order identifier points from original to new price improved order
20024 RevokedOrderTransactTime N Revoked order transaction time as recorded on server side. Present on storno orders. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)

Examples

  • OrdStatus = Pending New
    8=FIX.4.4 | 9=248 | 35=8 | 34=2 | 49=BSD_TRADING | 52=20240829-09:29:55.518387 | 56=TRADING_CLIENT1 | 128=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 6=0 | 11=3d8cab81-d571-41a3-afdb-ecf02a85dec1 | 14=0 | 17=4bc107d3-e5b2-4faa-8e39-e54a7b8ce1c2 | 37=NONE | 39=A | 40=1 | 54=1 | 55=BTC/EUR | 150=A | 151=0 | 10=197 |
  • OrdStatus = Filled:
    8=FIX.4.4 | 9=335 | 35=8 | 34=3 | 49=BSD_TRADING | 52=20240829-09:29:58.781166 | 56=TRADING_CLIENT1 | 128=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 6=54558.574670600000 | 11=3d8cab81-d571-41a3-afdb-ecf02a85dec1 | 14=0.0001 | 17=f3aff439-302b-4789-8be9-60e9bb7cef19 | 37=f7871e63c2004ad28c0279298a580c11ord | 39=2 | 40=1 | 54=1 | 55=BTC/EUR | 60=20240829-09:29:57.309 | 150=F | 151=0 | 152=5.46 | 10=115 |

Order Reject Reason values for Trading

Value Name Description
99 Other Unexpected error occurred.
100 NotEnoughAsset Error indicates that sell order can not be executed due not enough assets on users portfolio.

Example

  • OrdStatus = Rejected, Reason = NotEnoughAsset
    8=FIX.4.4 | 9=282 | 35=8 | 34=17 | 49=BSD_TRADING | 52=20240829-09:36:09.617152 | 56=TRADING_CLIENT1 | 128=fb2a616d-2ec5-4144-8f09-f5883a5f677d | 6=0 | 11=3d8cab81-d571-41a3-afdb-ecf02a85dec1 | 14=0 | 17=80bee0d6-1f53-4ef0-afb7-40b380173cb5 | 37=NONE | 39=8 | 40=1 | 54=2 | 55=SOL/EUR | 60=20240829-09:36:09.615 | 103=100 | 150=8 | 151=0 | 10=209 |

Trade Report workflow

The TradeReport channel offers a stream of Execution Report(8) messages regardless whether the trades are done with the REST or the FIX API. In this channel FIX message synchronization and recovery are supported. This will ensure that the client will receive messages for all trades regardless whether the client is connected or not.

This channel is only available on explicit request by a customer.

sequenceDiagram
    Initiator->>Acceptor: Logon (MsgType=A)
    Acceptor->>Initiator: Logon (MsgType=A)
    Acceptor->>Initiator: Execution Report (MsgType=8)
    Acceptor->>Initiator: Execution Report (MsgType=8)
    Acceptor->>Initiator: Execution Report (MsgType=8)

Supported Message Types

The following FIX message types are supported in the RfQ workflow:

MsgType Message Name Direction*
8 Execution Report(8) I

* I = Inbound to Client, O = Outbound from Client

Execution Report for TradeReport (8)

Tag Field Name Mandatory Comments
35 MsgType Y 8
37 OrderID Y Unique ID created by the server. (Always equals the QuoteID(117) of the [Quote](#quote-for-rfq-s] message).
11 ClOrdID N ID from the New Order Single. If the trade was done by REST API this field will be omitted.
526 SecondaryClOrdID N Additional ID from the New Order Single or REST API. Values defined on partner level.
17 ExecID Y Unique identifier of execution message.
150 ExecType Y One of the Valid values for ExecType(150).
39 OrdStatus Y One of the Valid values for OrdStatus(39).
55 Symbol Y Valid trading pair.
54 Side Y Only 1 = Buy or 2 = Sell are allowed.
152 CashOrderQty Y The total volume in fiat currency (EUR) of the trade.
151 LeavesQty Y Always 0.
14 CumQty Y The OrderQty of the New Order Single or the amount of the "Request a quote" REST request.
6 AvgPx Y The BidPx or OfferPx of the Quote or the price of the "Request a quote" response.
60 TransactTime Y Trade execution time as recorded on server side. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)
20020 ExternalTraderID N External trader identifier - present when entered field OnBehalfOf on REST API
20021 RevokedOrderID N Revoked order identifier points from storno to original order
20022 StornoOrderID N Storno order identifier points from original order to storno order
20023 PriceImprovementOrderID N Price improvement order identifier points from original to new price improved order
20024 RevokedOrderTransactTime N Revoked order transaction time as recorded on server side. Present on storno orders. The resolution should be 1 microsecond. The expected field format is YYYYMMDD-HH:MM:SS.ssssss (e.g., 20221124-20:59:47.480000)

Note if the trade was done over the FIX API and the client uses both channels (RfQ and TradeReport) the Execution Report is sent twice. The two messages differs only in the fields BodyLength(9), MsgSeqNum(34), SenderCompID(49), SendingTime(52), TargetCompID(56), ExecID(17), DeliverToCompID(128) and CheckSum(10). The field DeliverToCompID is only available in the Trade Report channel.

Examples

  • Buy 0.75 ADA over REST
    8=FIX.4.4 | 9=290 | 35=8 | 34=3 | 49=BSD_TRADEREPORT | 52=20240301-09:50:33.139 | 56=TRADEREPORT_CLIENT1 | 128=d60e79cc-00a1-4037-a53b-60d047ea0c60 | 6=0.635301353186 | 14=0.75 | 17=31d0fd03-7eb5-468a-b826-47ee7448d3b0 | 37=1287fed2-c530-4e32-9a14-bf668dafddc0 | 39=2 | 54=1 | 55=ADA/EUR | 60=20240301-09:50:33.134 | 150=F | 151=0 | 152=0.48 | 20020=trader1 | 10=005 |
  • Sell 1.7 DOT over REST
    8=FIX.4.4 | 9=291 | 35=8 | 34=10 | 49=BSD_TRADEREPORT | 52=20240301-09:52:12.906 | 56=TRADEREPORT_CLIENT1 | 128=111e543e-0be7-4a72-ac24-26ecb6bf9260 | 6=7.699824667800 | 14=1.7 | 17=2667979e-3154-47bb-af82-1c282ed28785 | 37=a481558e-7344-4a81-baa6-a1d319acc909 | 39=2 | 54=2 | 55=DOT/EUR | 60=20240301-09:52:12.906 | 150=F | 151=0 | 152=13.08 | 20020=trader1 | 10=164 |

Order revoke and price improvement process

Revoke process

Revoke is initiated manually from back office dashboard. New storno order with same amounts but reverse side is created and then two execution reports are sent to the client, one for original order, and one for new storno order.

Workflow for customers that use only FIX API for trading

sequenceDiagram
    box Client
        participant I_RfQ as Initiator (RfQ|Trading)
    end
    box BS Digital Broker
        participant A_RfQ as Acceptor (RfQ|Trading)
        participant Backend
        actor Backoffice as Back office
    end
    I_RfQ->>A_RfQ: New Order Single (MsgType=D)
    A_RfQ->>Backend: Process
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=F|OrdStatus=2)
    Backoffice->>Backend: Revoke order process
    Backend->>A_RfQ: Revoke message
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=H|OrdStatus=4) - original order
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=H|OrdStatus=2) - storno order

Workflow for customers that use REST API and FIX TradeReport channel

sequenceDiagram
    box Client
        participant I_RfQ as REST-Client
        participant I_TR as Initiator (Trade Report)
    end
    box BS Digital Broker
        participant A_RfQ as REST-Service
        participant A_TR as Acceptor (Trade Report)
        participant Backend
        actor Backoffice as Back office
    end
    I_RfQ->>A_RfQ: PlaceOrder Request
    A_RfQ->>Backend: Process
    Backend->>A_TR: Trade message
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=F|OrdStatus=2)
    A_RfQ->>I_RfQ: PlaceOrder Response
    Backoffice->>Backend: Revoke order process
    Backend->>A_TR: Revoke message
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=H|OrdStatus=4) - original order
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=H|OrdStatus=2) - storno order

Note: Revoke messages over webhooks are ommitted, because here is the focus on FIX messages.

Example Buy trade with OrderID=123 was revoked. Then these two execution reports are sent (in table are represented only the most important fields for this case)

OrderID ExecType OrdStatus Side RevokedOrderID StornoOrderID RevokedOrderTransactTime ClOrdID OrigClOrdID Comments
123 H (Trade Cancel) 4 (Canceled) Buy 124 From New Order Single Field not available Trade report for original order
124 H (Trade Cancel) 2 (Filled) Sell 123 20240624-20:59:47.480000 Field not available From New Order Single Trade report for storno order

Price improvement process

Price improvement is initiated manually from back office dashboard. Two new orders are created. First one is storno order with same amounts and second is same side as original order with changed price. Then three execution reports are sent to the client, one for original order, one for storno order and one for new price improvement order.

Workflow for customers that use only FIX API for trading

sequenceDiagram
    box Client
        participant I_RfQ as Initiator (RfQ|Trading)
    end
    box BS Digital Broker
        participant A_RfQ as Acceptor (RfQ|Trading)
        participant Backend
        actor Backoffice as Back office
    end
    I_RfQ->>A_RfQ: New Order Single (MsgType=D)
    A_RfQ->>Backend: Process
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=F|OrdStatus=2)
    Backoffice->>Backend: Price improvement order process
    Backend->>A_RfQ: Price improvement message
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=G|OrdStatus=4) - original order
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=G|OrdStatus=2) - new storno order
    A_RfQ->>I_RfQ: Execution Report (MsgType=8|ExecType=G|OrdStatus=2) - new order with new price

Workflow for customers that use REST API and FIX TradeReport channel

sequenceDiagram
    box Client
        participant I_RfQ as REST-Client
        participant I_TR as Initiator (Trade Report)
    end
    box BS Digital Broker
        participant A_RfQ as REST-Service
        participant A_TR as Acceptor (Trade Report)
        participant Backend
        actor Backoffice as Back office
    end
    I_RfQ->>A_RfQ: PlaceOrder-Request
    A_RfQ->>Backend: Process
    Backend->>A_TR: Trade message
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=F|OrdStatus=2)
    A_RfQ->>I_RfQ: PlaceOrder-Response
    Backoffice->>Backend: Price improvement order process
    Backend->>A_TR: Price improvement message
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=G|OrdStatus=4) - original order
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=G|OrdStatus=2) - new storno order
    A_TR->>I_TR: Execution Report (MsgType=8|ExecType=G|OrdStatus=2) - new order with new price

Note: Price-improvement messages over webhooks are ommitted, because here is the focus on FIX messages.

Example Buy trade for OrderID=123 will have an improved price. Then these three execution reports are sent (in table are represented only the most important fields for this case)

OrderID ExecType OrdStatus Side RevokedOrderID StornoOrderID PriceImprovementOrderID RevokedOrderTransactTime ClOrdID OrigClOrdID Comments
123 G (Trade Correct) 4 (Canceled) Buy 124 125 From New Order Single Field not available Trade report for original order
124 G (Trade Correct) 2 (Filled) Sell 123 125 20240624-20:59:47.480000 Field not available From New Order Single Trade report for storno order
125 G (Trade Correct) 2 (Filled) Buy 123 124 20240624-20:59:47.480000 Field not available From New Order Single Trade report for price improved order

Appendix

Session/Administrative Messages

Type Message Originator
A Logon Both
0 Heartbeat Both
1 Test Request Both
3 Reject Both
5 Logout Both
B News Server
j Business Message Reject Server

Note: These messages are used on all channels.

Client-Originated Messages

Type Message Possible Response Messages Quote RfQ TradeReport Trading
R Quote Request/
for RfQ
Mass Quote (i)
Quote (S)
Quote Request Reject
X X - -
D New Order Single for RfQ Execution Report for RfQ - X - X

Note: The Reject (3) or Business Message Reject (j) messages are possible responses for all messages.

Server-Originated Messages

Type Message In Response To Quote RfQ TradeReport Trading
8 Execution Report for RfQ/
for TradeReport
New Order Single for RfQ/
Logon
- X X X
i Mass Quote Quote Request X - - -
S Quote Quote Request for RfQ - X - -
Z Quote Request Reject Quote Request for RfQ - X - -
B News X X X X

Valid trading pairs

Valid trading pairs are (field Symbol (55)). Trading pairs are case sensitive!

  1. AAVE/EUR
  2. ADA/EUR
  3. ALGO/EUR
  4. AXS/EUR
  5. BAT/EUR
  6. BCH/EUR
  7. BTC/EUR
  8. CHZ/EUR
  9. CRV/EUR
  10. DOGE/EUR
  11. DOT/EUR
  12. ETC/EUR
  13. ETH/EUR
  14. GRT/EUR
  15. LINK/EUR
  16. LTC/EUR
  17. MANA/EUR
  18. POL/EUR
  19. QNT/EUR
  20. SAND/EUR
  21. SHIB/EUR
  22. SOL/EUR
  23. UNI/EUR
  24. XLM/EUR
  25. XRP/EUR
  26. XTZ/EUR

Valid values for OrdStatus(39)

Value Name Description
0 New The server has confirmed that the order is valid. The order has been successfully entered into the server's order management system. This order status may be skipped. This status applies to stop orders when they have been triggered and are working.
The server may not send a message for the "New" order state. If the order can be filled immediately, the server may skip the "New" message and send only a "Trade"/"Rejected" Execution Report message to indicate a fill.
2 Filled The order has been completely filled.
4 Canceled Only used in Revoke and Price improvement process.
8 Rejected The server failed to confirm the validity of the order and the order submission has failed.
A Pending New An order has been received by server and is being processed. This is the acknowledgement to a New Order Single request.

Valid values for ExecType(150)

Value Name Description
0 New The server has confirmed that the order is valid. The order has been successfully entered into the server's order management system. This order status may be skipped. This status applies to stop orders when they have been triggered and are working.
The server may not send a message for the "New" order state. If the order can be filled immediately, the server may skip the "New" message and send only a "Trade"/"Rejected" Execution Report message to indicate a fill.
8 Rejected Response to a New Order Single(D) request that could not be fullfilled.
A Pending New An order has been received by server and is being processed. This is the acknowledgement to a New Order Single request.
F Trade Response to a New Order Single(D) request that was successfully executed and fully filled.
G Trade Correct Only used in Price Improvement Process.
H Trade Cancel Only used in Revoke Process.

Sample client configuration for quickfixn

When using Quickfix as client library, the following configuration can be used to connect to prelive (assuming the clientId is <myclientId>):

[DEFAULT]
ConnectionType=initiator
ReconnectInterval=20
FileStorePath=store
FileLogPath=log
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
LogoutTimeout=5
TimeStampPrecision=Microsecond

[SESSION]
BeginString=FIX.4.4
DataDictionary=FIX44_Quoting.xml
SocketConnectHost=<quoting-url> (please contact us)
SocketConnectPort=7200
SenderCompID=QUOTING_<myclientId>	
TargetCompID=BSD_QUOTING
HeartBtInt=30
SSLEnable=Y
SSLValidateCertificates=N
ResetOnLogon=Y
ResetOnDisconnect=Y

[SESSION]
BeginString=FIX.4.4
DataDictionary=FIX44_RfQ.xml
SocketConnectHost=<rfq-url> (please contact us)
SocketConnectPort=7201
SenderCompID=RFQ_<myclientId>
TargetCompID=BSD_RFQ
HeartBtInt=30
SSLEnable=Y
SSLValidateCertificates=N
ResetOnLogon=N
ResetOnDisconnect=N

[SESSION]
BeginString=FIX.4.4
DataDictionary=FIX44_Trading.xml
SocketConnectHost=<trading-url> (please contact us)
SocketConnectPort=7203
SenderCompID=TRADING_<myclientId>
TargetCompID=BSD_TRADING
HeartBtInt=30
SSLEnable=Y
SSLValidateCertificates=N
ResetOnLogon=N
ResetOnDisconnect=N

[SESSION]
BeginString=FIX.4.4
DataDictionary=FIX44_TradeReport.xml
SocketConnectHost=<tradereport-url> (please contact us)
SocketConnectPort=7202
SenderCompID=TRADEREPORT_<myclientId>
TargetCompID=BSD_TRADEREPORT
HeartBtInt=30
SSLEnable=Y
SSLValidateCertificates=N
ResetOnLogon=N
ResetOnDisconnect=N

Note: the referred data dictionaries "FIX44_RfQ.xml", "FIX44_Quoting.xml", "FIX44_TradeReport.xml", "FIX44_Trading.xml" are adapted versions of the original FIX44.xml shipped with the quickfixn libraries containing the exact message definitions defined in this API. Please contact us, if you want to use these files. Otherwise you can also disable validation by setting "UseDataDictionary=N".

Changelog

2025/05/13

  • Document missing 403 and 404 status codes.

2025/05/05

  • Add UserId to GetCollateralBalance endpoint

2025/04/08

  • Enhance change kyc data endpoint.

2025/04/02

  • Add GetWhitelistedWithdrawalAddresses endpoint
  • Add ping endpoint.

2025/04/01

  • Add support for POL

2025/03/31

  • Add Revocation reason to GetOrder response.

2025/02/18

  • Add DeletedBy Delete user request
  • Add "Rejected" KYC status

2025/02/14

  • Fix-Api
    • Add new tag 58 (Text) to message Execution Report(8) in trading channel.

2025/02/10

  • Add aggregate portfolio values to Get portfolio endpoint.

2024/12/18

  • ClOrdID not longer mandatory in Execution Report of RfQ/Trading workflows (Fix Api).
  • New field OrigClOrdID in Execution Report of RfQ/Trading workflows (Fix Api).

2024/11/15

  • Edge case testing is possible by giving the API 'special' values.

2024/10/23

  • Query user by external reference or Id.

2024/10/23

  • Add SetOrderCommission endpoint.

2024/10/04

  • Add GetCryptoAssets endpoint.

2024/09/23

  • Update Get Order to accept ClientOrderId and update Get Withdrawal to use id type for input.

2024/09/09

  • Add GetCryptoWithdrawal endpoint.

2024/09/04

  • Add support for market orders

2024/08/26

  • Add UnavailableCollateral error code to PlaceOrder endpoint

2024/08/08

  • Add endpoint for scheduled user deletion.

2024/08/07

  • Fix-Api
    • New channel Trading added for market orders.
    • Revoke and Price-Improvement workflow added to RfQ channel.
    • RfQ channel supports session recovery like TradeReport channel.
    • TradeCaptureReport messages removed from RfQ workflow.
    • Maximum ID length reduced to 36.

2024/07/10

  • Added endpoint for downloading files, such as reports

2024/07/08

  • Added endpoint for creating a new crypto withdrawal

2024/07/04

  • Add ChangeUser and ChangeUserKycData endpoints.

2024/06/12

  • Document "Order revoke and price improvement process".
  • Change sorting of 'GetRevokedOrders' endpoint to ascending.

2024/05/30

  • Add GetCryptoDeposits and GetCryptoWithdrawals endpoints.

2024/05/22

  • Add transfer section and GetCryptoWalletAddress endpoint.

2024/05/08

  • Add status Failed to GetOrder and GetOrders endpoints response.

2024/04/23

  • Add StornoOrderId, RevokedOrderId fields to GetOrder endpoint response.

2024/04/17

  • Add an endpoint for retrieving revoked orders (GetRevokedOrders).
  • Add priceImprovementOrderId field to GetOrder endpoint response.

2024/04/15

  • Change GetPrices endpoint, make userId parameter optional.

2024/04/08

  • Added Settlement section and a collateral balance endpoint within this section.

2024/04/04

  • Obsolete 'Get transactions' endpoint. This endpoint is not used by any partner and is not needed. Use GetOrders endpoint instead.