Overview
LN Markets API (2.0.0)
LN Markets opens a REST and a Websocket API to integrate with your program or trading bot.
This API reference provides information on available endpoints and how to interact with it.
You can find a javascript package here ready to use
Signature
LNM-ACCESS-SIGNATURE
header is generated by creating a sha256 HMAC using the secret key on the prehash string timestamp + method + path + params
(where + represents string concatenation) digested in Base 64.
-
method
: MUST be UPPER CASE. -
path
: is the request path of the URL, e.g.: /v2/user -
timestamp
: value is the same as theLNM-ACCESS-TIMESTAMP
header.It MUST be number of millisecond since Unix Epoch in UTC and it should be within 30 seconds of our API time.
-
params
: is the request body as a JSON string (with no space, no line return)or the request query as URL search params
and if there is no data it should be an empty string
Here is some example to create the signature
Javascript
const { createHmac } = require('crypto')
const { URLSearchParams } = require('url')
let params = ''
if (method.match(/^(GET|DELETE)$/)) {
params = new URLSearchParams(data).toString()
} else {
params = JSON.stringify(data)
}
const signature = createHmac('sha256', secret).update(`${timestamp}${method}${path}${params}`).digest('base64')
Python
import hmac
import base64
import json
import urllib
params = ''
if ((method == 'GET') | (method == 'DELETE')):
params = urllib.parse.urlencode(data)
elif ((method == 'POST') | (method == 'PUT')):
params = json.dumps(data, separators=(',', ':'))
signature = base64.b64encode(hmac.new(secret, timestamp + method + path + params, hashlib.sha256).digest())
Bash
signature=$(echo -n "$timestamp$method$path$params" | openssl dgst -sha256 -hmac $SECRET -binary | base64 )
REST API
The API endpoint for mainnet is https://api.lnmarkets.com/v2
If you want to try our API with testnet bitcoin use https://api.testnet.lnmarkets.com/v2
REST Authentication
API key authentication requires each request to be signed (enhanced security measure). You can create and activate new API keys on your profile here. Your API keys should be assigned to access only accounts and permission scopes that are necessary for your app to function.
Making a request
All REST requests must contain the following headers:
Header | Description |
---|---|
LNM-ACCESS-KEY | API key as a string. |
LNM-ACCESS-SIGNATURE | Message signature. |
LNM-ACCESS-PASSPHRASE | API key passphrase. |
LNM-ACCESS-TIMESTAMP | Timestamp for your request. |
Request POST and PUT must have content type Content-Type: application/json
and be valid JSON and in the body.
Request queries with GET and DELETE must not have a body and the header Content-Type: application/json
must be omitted.
curl https://api.lnmarkets.com/v2/futures \
--header "LNM-ACCESS-KEY: <your api key>" \
--header "LNM-ACCESS-PASSPHRASE: <your api key passphrase>" \
--header "LNM-ACCESS-SIGNATURE: <the user generated message signature in base64>" \
--header "LNM-ACCESS-TIMESTAMP: <a timestamp for your request in milliseconds>" \
--header "Content-Type: application/json" \
--request POST \
--data '{"type":"l","side":"b","price":40000,"quantity":1,"leverage":10}'
REST Examples
Here is an example on how to do a request to LN Markets :
const https = require('https')
const { createHmac } = require('crypto')
const { URLSearchParams } = require('url')
const requestAPI = (options) => {
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
res.setEncoding('utf8')
let data = ''
res.on('data', (chunk) => {
data += chunk
})
res.on('error', (error) => {
reject(error)
})
res.on('end', () => {
if (this.debug) {
return resolve({ req, res })
}
try {
const body = JSON.parse(data)
if (res.statusCode === 200) {
resolve(body)
} else {
console.error(body)
reject(new Error(res.statusCode, body))
}
} catch (error) {
error.data = data
reject(error)
}
})
})
req.on('error', (error) => {
reject(error)
})
if (options.method.match(/^(PUT|POST)$/) && options.params) {
req.write(JSON.stringify(options.params))
}
req.end()
})
}
const main = async () => {
const key = 'API_KEY'
const secret = 'API_SECRET'
const passphrase = 'API_PASSPHRASE'
const timestamp = Date.now()
const params = { type: 'm', side: 'b', quantity: 4242 }
const method = `POST`
const path = `/v2/futures`
let data = ''
if (method.match(/^(GET|DELETE)$/)) {
data = new URLSearchParams(params).toString()
} else {
data = JSON.stringify(params)
}
const payload = `${timestamp}${method}${path}${data}`
const signature = createHmac('sha256', secret)
.update(payload)
.digest('base64')
const headers = {
'Content-Type': 'application/json',
'LNM-ACCESS-KEY': key,
'LNM-ACCESS-PASSPHRASE': passphrase,
'LNM-ACCESS-TIMESTAMP': timestamp,
'LNM-ACCESS-SIGNATURE': signature,
}
const options = {
port: 443,
hostname: 'api.lnmarkets.com',
method,
path,
headers,
}
if (method.match(/^(GET|DELETE)$/) && params) {
options.path += `?${new URLSearchParams(params).toString()}`
}
const position = await requestAPI(options)
console.log(position)
}
main()
If you want a full implementation example you can take a look at our npm package @ln-markets/api.
Websockets API
The websocket endpoint for mainnet is wss://api.lnmarkets.com
If you want to try with testnet bitcoin use wss://api.testnet.lnmarkets.com
This API follows the JSON-RPC specification.
Request sent to the API should be a valid JSON like:
{
"jsonrpc": "2.0",
"method": "debug/echo",
"id": "faffssdfsdf432", // Random id
"params": {
"hello": "world"
}
}
And response would look like:
{
"jsonrpc": "2.0",
"id": "faffssdfsdf432", // Same id
"result": {
"hello": "world"
}
}
You need to listen for the id provided in the request to get the response back!
Websocket Authentication
To create an authenticated websocket you need to send a payload once, this payload should be like:
{
"jsonrpc": "2.0",
"method": "auth/api-key",
"params": {
"timestamp": 1636389122390, // The current timestamp
"signature": "SAFiGx46GGqztiHu31Mfm89VT3Cp0kqhap4DEs6Pv/U=", // HMAC SHA256 (method + timestamp concatenation) Base 64
"passphrase": "fd026g0d4i52", // Your passphrase
"key": "DKJLy/OlXQqQgbT0bE18HJgzQOJnuaTW43OQD8EEHuM=" // Your api key
}
}
Websockets Examples
Here is an example on how to do a request to LN Markets :
const Websocket = require('ws')
const ws = new Websocket('wss://api.lnmarkets.com')
const key = 'API_KEY'
const secret = 'API_SECRET'
const passphrase = 'API_PASSPHRASE'
const timestamp = Date.now()
const method = `auth/api-key`
const payload = `${timestamp}${method}`
const signature = createHmac('sha256', secret)
.update(payload)
.digest('base64')
const request = {
jsonrpc: '2.0',
method,
params: {
timestamp,
signature,
passphrase,
key,
},
}
ws.on('message', console.log)
ws.send(JSON.stringify(request))
If you want a full implementation example you can take a look at our npm package @ln-markets/api
Heartbeats
If you are concerned about your connection silently dropping, we recommend implementing the following flow:
After receiving each message, set a timer duration of 5 seconds. If any message is received before that timer fires, restart the timer. When the timer fires (no messages received in 5 seconds), send a raw ping frame. Expect a raw pong frame in response. If this is not received within 5 seconds, throw an error or reconnect.
Subscription
You can subscribe to differents events using the subscribe
method. If you wish to unsubscribe, call the unsubscribe
and the event you want to be unsubscribed from. Here is the full list of available subscriptions.
[
"futures/market/bid-offer",
"futures/market/index",
"options/data/forwards",
"options/data/volcurve",
"options/data/ordermap"
]
Limits
We established some limitation across th API to ensure our services integrity.
Futures
There is a maximum of 50 open positions per account.
Options
There is a maximum of 50 open trades per account.
Rate
Requests to our REST API are rate limited to 1 request per second, endpoints which do not require authentication are limited to 30 requests per minute.
Here are Headers related to rate limitation:
Header | Description |
---|---|
Retry-After | Will tell you how many seconds you need to wait to call this endpoint if your limit is down to 0. |
X-Ratelimit-Remaining | This is how many request do you have left before blocking. |
X-Ratelimit-Reset | This is the timestamp in ms when limitation will be reset. |
Requests
If you throw too much error such as 4XX or 5XX, your IP could be banned for a certain period of time.
Errors
Code | Meaning |
---|---|
400 | Bad request. Your request is invalid. |
401 | Unauthorized. Your API key is wrong or you don’t have access to the requested resource. |
403 | Forbidden. Your API key has the wrong scope. |
404 | Not found. |
405 | Method Not Allowed. You tried to access a resource with an invalid method. |
418 | I’m a teapot. |
429 | Too many requests. Your connection is being rate limited. |
500 | Internal server error. Something went wrong, please try again or contact us. |
503 | Service unavailable. We’re temporarily offline for maintenance. Please try again later. |
- OpenAPI version: 3.0.2