Firi Trading API (1.0.0)

This is the Trading API that enables our Market Makers.

Authorization

Some endpoints are public and do not require any form for authentication and authorization, and some are private which means that they require authentication and authorization. The private endpoints require an access key (See section about authentication for more information about access keys). The user can define the security levels of their access key(s)

Errors and problems

Error messages: Access control (Authorization/Authentication)

Error Error description
ApiKeyNotFound The request contains an access key that was not found in our systems
Expired Signature The request contains an expired hmac encrypted secretKey. Make sure the timestamp was not made in the past and that the validity is sufficient
Invalid Signature The hmac encrypted secretKey did not match with our hmac encryption of APIkey. PS! Timestamp and validity has to be strings
SecurityLevelTooLow Try changing the security level of your access key, to the required security level.

Authentication

API-key

Beware that this type of API key can be intercepted and stolen by Man-in-the-Middle attacks due to the static nature of the security related to this type of authentication. In every request to private endpoints, miraiex-access-key has to be added to the header with the correct API-key.

Security Scheme Type API Key
Header parameter name: miraiex-access-key

HMAC_encrypted_secretKey

This type of security is preventing Man-in-the-Middle attacks. But it increases complexity by keeping track of nonce and the secret key used to encrypt every signature. If someone gets ahold of your secret key, contact us immediately. Every request on a private endpoint needs to have this header added as specified at the bottom security scheme table:

miraiex-user-signature

In order to generate the miraiex-user-signature, the client has to generate a signature for every request based on the current time in epoch.

Kotlin snippet (run it at https://pl.kotl.in/X6okS4-xC) for generating the signature based on timestamp in epoch (string) and validity (string):

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.util.Date


fun main() {
    val secretKey = "RTk2eNs67Vpan3345pmrwYEBYsWXRXtGF3BKTFq8WMLLOLOL"
    val time = Date().time / 1000
    val validity = 2000
    val body = "{\"timestamp\":\"$time\",\"validity\":\"$validity\"}"
    val signature = createHmac(
        body,
        secretKey
    )
    println(signature)
}


fun createHmac(data: String, key: String): String {
        val sha256Hmac = Mac.getInstance("HmacSHA256")
        val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256")
        sha256Hmac.init(secretKey)
        return sha256Hmac.doFinal(data.toByteArray()).toHex()
}

fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) }

Node.js snippet (run it at https://runkit.com/embed/2xf1vceb3edz) for generating the signature based on timestamp in epoch and validity:

const crypto = require('crypto'),
secretKey = 'RTk2eNs67Vpan3345pmrwYEBYsWXRXtGF3BKTFq8WMLLOLOL',
 timestamp = Math.round(new Date().getTime() / 1000).toString(),
body = {
   timestamp: timestamp ,
   validity: '2000'
};
const signature = crypto.createHmac('sha256', secretKey).update(JSON.stringify(body)).digest('hex')

Validity is used for keeping tabs on how long this request is valid (1000 = 1 second) from the creation of signature to the API receiving it. When using the HMAC encypted APIkey for authentication the following also applies:

miraiex-user-clientid added as a header

timestamp used for generating the signature added as a query

validity used for generating the signature added as a query

PS! Notice how timestamp and validity are strings in the body for HMAC signature generation

POST requests and HMAC authentication

For POST endpoints which require a requestbody (e.g POST to /v2/orders), the request values must also be included when you generate the HMAC signature from timestamp and validity. For example, given that you want to create an order where market = BTCNOK, price = 1000, amount = 1, type = ask, the above examples would look like this:

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import java.util.Date


fun main() {
    val secretKey = "RTk2eNs67Vpan3345pmrwYEBYsWXRXtGF3BKTFq8WMLLOLOL"
    val time = Date().time / 1000
    val validity = 2000
    val body = "{\"timestamp\":\"$time\",\"validity\":\"$validity\", \"market\":\"BTCNOK\", \"price\":\"1000\", \"amount\":\"1\", \"type\":\"ask\"}"
    val signature = createHmac(
        body,
        secretKey
    )
    println(signature)
}


fun createHmac(data: String, key: String): String {
        val sha256Hmac = Mac.getInstance("HmacSHA256")
        val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256")
        sha256Hmac.init(secretKey)
        return sha256Hmac.doFinal(data.toByteArray()).toHex()
}

fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) }
const crypto = require('crypto'),
secretKey = 'RTk2eNs67Vpan3345pmrwYEBYsWXRXtGF3BKTFq8WMLLOLOL',
 timestamp = Math.round(new Date().getTime() / 1000).toString(),
body = {
    timestamp: timestamp ,
    validity: '2000',
    market: 'BTCNOK',
    price: '1000',
    type: 'ask',
    amount: '1'
};
const signature = crypto.createHmac('sha256', secretKey).update(JSON.stringify(body)).digest('hex')
Security Scheme Type API Key
Header parameter name: miraiex-user-signature

validity

Must be supplied when authenticating with HMAC encrypted secretKey

Security Scheme Type API Key
Query parameter name: validity

timestamp

Must be supplied when authenticating with HMAC encrypted secretKey

Security Scheme Type API Key
Query parameter name: timestamp

clientID

Must be supplied when authenticating with HMAC encrypted secretKey

Security Scheme Type API Key
Header parameter name: miraiex-user-clientid

Time

Provides current time as epoch. Recommended to use for the timestamp required for HMAC encryption of your secretKey

Get current timestamp in epoch

Responses

Response samples

Content type
application/json
{
  • "time": 0
}

History

Get history over all transactions

Direction is either end or start

query Parameters
direction
string
count
integer <int32>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over transactions by year

Direction is either end or start.

year > 2017

path Parameters
year
required
string
query Parameters
direction
string

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over transactions by month and year

Direction is either end or start.

12 >= month >= 1

year > 2017

path Parameters
month
required
string
year
required
string
query Parameters
direction
string

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over all trades

Direction is either end or start

query Parameters
direction
string
count
integer <int32>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over trades by year

Direction is either end or start.

year > 2017

path Parameters
year
required
string
query Parameters
direction
string

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over trades by month and year

Direction is either end or start.

12 >= month >= 1

year > 2017

path Parameters
month
required
string
year
required
string
query Parameters
direction
string

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over all orders

query Parameters
type
string
count
integer <int32>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over orders defined by market

path Parameters
market
required
string
query Parameters
type
string
count
integer <int32>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Market

Get history over a specific market

path Parameters
market
required
string
query Parameters
count
integer <int32>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get history over a specific market

path Parameters
market
required
string
query Parameters
count
integer <int32>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get orderbooks for a market

path Parameters
market
required
string
query Parameters
bids
integer <int32>
asks
integer <int32>

Responses

Response samples

Content type
application/json
{
  • "bids": [
    ],
  • "asks": [
    ]
}

Get orderbooks for a market

path Parameters
market
required
string
query Parameters
bids
integer <int32>
asks
integer <int32>

Responses

Response samples

Content type
application/json
{
  • "bids": [
    ],
  • "asks": [
    ]
}

Get info about specific market

path Parameters
market
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "last": "string",
  • "high": "string",
  • "change": "string",
  • "low": "string",
  • "volume": "string"
}

Get info about specific market

path Parameters
market
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "last": "string",
  • "high": "string",
  • "change": "string",
  • "low": "string",
  • "volume": "string"
}

Get available markets

Responses

Response samples

Content type
application/json
[
  • {