A series of tutorials to make it easy for non-coders to trade on LN Markets via our API with several programming languages, starting here with Python.

Reference Docs

Our API reference provides information on available endpoints and how to interact with it: https://lnmarkets.github.io/docs/

The API endpoint for mainnet is: https://api.lnmarkets.com

The API endpoint for testnet is: https://api.testnet.lnmarkets.com

Get your JSON Web Token

In order to use LN Markets API, you first need to create your authentication token. We are currently using JSON Web Token (JWT).

Go to your Profile (click on the menu in the upper right corner) and select API Tokens. You can now generate your token for various scopes: user, positions, deposit, withdraw. It can be valid for a given period of time or indefinitely.

Here we created a token for all the scopes, without expiry. We copy it for later usage (button copy):

Setup your Python environment

There is a ton of online resources to help you. To get started and download the latest version of Python: https://www.python.org/

Enter your API Token

Copy your token in JWT = '...' and run this code.

#Mainnet Token
import requests
import json

JWT = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MThlNGZlZi1lM2M1LTQ4ZmItODFlOC0yMzc1Yj[...]cDA2bjc5MHdxMzdtcSIsImlhdCI6MTYwNTcyMTIxNX0.D1ifOH1NvIQx0FsbU__Y_vv_Grl-h6ZBgjHexHNY-6M'

We also import two libraries we will use throughout the rest of the tutorial, requests and json.

Get your positions' history

#Get your positions' history

#For testnet, url = "https://api.testnet.lnmarkets.com/positions"

url = "https://api.lnmarkets.com/positions"

headers = {
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

#Change ht = 'all', ht = 'open', ht = 'closed' to get the history of all your position, open positions, and closed positions

ht = 'all'
params = '?type=' + ht

response = requests.request("GET", url + params, headers=headers)

print(response.text)

Here is a sample of the JSON file we get for all positions of a particular account with no positions open at the moment and two previously closed positions:

{"open":[],"closed":[{"pid":"0c367782-88c1-42f5-89d9-c70c3f3b57d6","side":"b","type":"m","quantity":1,"price":9149,"margin":218,"liquidation":8970,"stoploss":null,"takeprofit":null,"market_wi":"filled","margin_wi":"closed","stoploss_wi":null,"takeprofit_wi":null,"pl":-29,"closed":true,"canceled":false,"exit_price":9124.5,"leverage":50,"creation_ts":"2020-06-26T15:16:51.153Z","closed_ts":"2020-06-26T15:17:03.073Z","market_filled_ts":"2020-06-26T15:16:51.153Z"},{"pid":"789a8a35-fa4b-4787-b6be-7089884e3e46","side":"b","type":"l","quantity":1,"price":9136,"margin":218,"liquidation":8957.5,"stoploss":null,"takeprofit":null,"market_wi":"filled","margin_wi":"closed","stoploss_wi":null,"takeprofit_wi":null,"pl":12,"closed":true,"canceled":false,"exit_price":9146,"leverage":50,"creation_ts":"2020-06-26T15:22:45.177Z","closed_ts":"2020-06-26T17:21:16.266Z","market_filled_ts":"2020-06-26T15:22:52.608Z"}]}

Create a position

In order to create a position, we must enter in the payload its type ('m' for market order, 'l' for limit order), its side ('b' for buy, 's' for sell) and the required parameters. Which are either quantity and leverage (quantity of 1 means 1 contract, each contract is worth 1 USD, leverage must be between 1 and 50) or margin and leverage (max margin is currently limited to 0.01 BTC = 100,000,000 satoshis):

#Create a market order

url = "https://api.lnmarkets.com/positions"

payload = {'type':'m', 'side': 'b', 'quantity': 1, 'leverage': 50}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)

We run this code to create a position, which we can now see in my Positions History with parameter ht = 'all' or ht = 'open' :

{"position":{"pid":"4fbb25dd-ea1a-4a92-bd15-485dadfd018a","side":"b","type":"m","price":"32232.0","quantity":"1","margin":"62","takeprofit":null,"liquidation":"31600.5","stoploss":null,"pl":"-6","leverage":"50.0000","market_wi":"filled","margin_wi":"running","takeprofit_wi":null,"stoploss_wi":null,"creation_ts":"2021-01-11T17:23:02.986Z","market_filled_ts":"2021-01-11T17:23:02.920Z"}}

We can also see the position open in our LN Markets account:

Update a position

We can add a take profit and/or stop loss to this position. We just need to enter in payload the position id 'pid', the type of update ('takeprofit' or 'stoploss') and its value:

#Update a position

url = "https://api.lnmarkets.com/positions"

payload = {"pid":"97baa050-62f1-456c-be8a-ed854f2f51d2","type":"takeprofit","value":12000}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

response = requests.request("PUT", url, data=payload, headers=headers)

print(response.text)

We get the following output:

{"pid":"4fbb25dd-ea1a-4a92-bd15-485dadfd018a"}

And we can check the update for confirmation in our LN Markets account:

Close a position

We can then close this position with our pid in the querystring:

#Close a position

url = "https://api.lnmarkets.com/positions"

querystring = {"pid":"4fbb25dd-ea1a-4a92-bd15-485dadfd018a"}

headers = {
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

response = requests.request("DELETE", url, params=querystring, headers=headers)

print(response.text)

We get the following output:

{"pid":"4fbb25dd-ea1a-4a92-bd15-485dadfd018a","closed":true,"exit_price":"33288.5","pl":"98","closed_ts":"2021-01-11T17:40:42.753Z"}

And we can check that the position was closed in our LN Markets account:

Cancel a position

Only limit orders that have not yet been filled can be canceled. First, let's create a limit buy order at Price 30,000$ for a Quantity of 1 contract and Leverage of 1:

#Create a Limit Order

url = "https://api.lnmarkets.com/positions"

payload = {'type':'l', 'side': 'b', 'price': 30000, 'quantity': 1, 'leverage': 1}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)

The limit order is now open:

{"position":{"pid":"8edd66c0-cc72-48d7-a5e3-ed85aae5c135","side":"b","type":"l","price":"30000.0","quantity":"1","margin":"3333","takeprofit":null,"liquidation":"15001.0","stoploss":null,"pl":null,"leverage":"1.0000","market_wi":"running","margin_wi":null,"takeprofit_wi":null,"stoploss_wi":null,"creation_ts":"2021-01-12T13:35:16.057Z","market_filled_ts":null}}

As long as the order has not been filled, we can cancel it using its pid:

#Positions Cancel

url = "https://api.lnmarkets.com/positions/cancel"

payload = {"pid":"8edd66c0-cc72-48d7-a5e3-ed85aae5c135"}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)

The position is now cancelled:

{"pid":"8edd66c0-cc72-48d7-a5e3-ed85aae5c135","closed_ts":"2021-01-12T13:38:34.153Z","canceled":true}

We can verify that in our closed positions blotter:

Deposit funds to your account

In order to generate a Lightning Network invoice to fund your account on LN Markets, enter the desired amount (between 1,000 and 1 million sats) and unit ('sat' or 'btc') in payload:

#Deposit

url = "https://api.lnmarkets.com/user/deposit"

payload = {"amount":1000,"unit":"sat"}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json",
    'authorization': "Bearer " + JWT
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)

And you get the invoice, that you need to pay within 45 seconds for your deposit to be successful:

{"paymentRequest":"lnbc10u1p0lm28app55pzcd3cncd64len9t4yxna395k3huvrshme769wrjd9vqyw2lh3sdzcf3hy6ctjddjhgueqg3jhqmmnd96zqge5xqcr2d3cxvmj6cmzxenz6dp4v3jz6wf3vgmj6epsvyursdnxxg6xzcejcqzpgxqzpdsp5slegun3nvs24kk9ggmfq6znjlcx5423zs93dyj0d0s50xzs5wf2s9qy9qsqm4t2njyjaxfnp0v5vezazlc6j8pnav3lsy7n7thtdwrvp2h9j0z8w2j2tx4r7e2pcgsvj38dff8hwd9jzf2dp3e9696slu49elzr90gpka9zh5","expiry":45}

Withdraw funds from your account

You can either withdraw funds via an invoice or via lnurl-withdraw (here is the list of wallets that support it). In order to withdraw via an invoice you enter in the payload the amount, the unit, and your invoice:

#Withdraw via Invoice

import requests
import json

url = "https://api.lnmarkets.com/user/withdraw"

payload = {"amount":1000,"unit":"sat","invoice":"lnbc10u1p0lm2cmpp53c7yh36wq9r38dwf0ytte42clf7qx8lrvtz3tjn65jek8fzxtgzqdqqxqyjw5q9qtzqqqqqq9qsqsp50pctql2pgrjsg6vasmty4yrj5uhc6f7zkqnmvckteldzk7zwe5lwegtrwegrep9lh50kkranzgcdnn2fgvx390wgj5jd07rwr3vxeje0glclluye5e2a70hyqqqqqlgqqqqqeqqjqdxpr2lj7eusj8rp4x2udhm2cr5n3ykyt6zmenrd6ppl9cdrf5qnsls3jkt35ex7fmx2q5gqfzldx8m3h44vg8g8tclgp7tvfad4rc5cpt2mfmc"}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json",
    'authorization': "Bearer " +  JWT
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(response.text)

And you get the instant withdrawal confirmation:

{"amount":1000,"paymentsecret":"4e789efcbba7807ceb09886cefa5ec7b544ef8343ef105ea7c48dc017d4d36a1","wid":"0c78f631-a742-467c-ade5-12373f3aded4","paymenthash":"8e3csdf74e014713b5c97916bcd558fa7c031fe362c515ca7aa4b363a4465a04"}

Get the Leaderboard

Now it is time for you to check if you made it to the Leaderboard!

#Get current leaderboard

url = "https://api.lnmarkets.com/state/leaderboard"

headers = {'accept': 'application/json'}

response = requests.request("GET", url, headers=headers)

print(response.text)

By default, you do not appear in the leaderboard. It's only if you authorize it your profile section that you may appear under your desired pseudonymous. Here is the Top 10:

[{"username":"SirLongboi","pl":23009623,"direction":10},{"username":"Anonymous","pl":14615062,"direction":0},{"username":"Anonymous","pl":13145709,"direction":0},{"username":"CrownCrypto LN Node","pl":10637826,"direction":0},{"username":"50xalwayslong","pl":10028805,"direction":0},{"username":"Anonymous","pl":8610132,"direction":0},{"username":"LNmarketsme","pl":8207344,"direction":1},{"username":"bigworm118","pl":8103826,"direction":1},{"username":"TheBigCohooNah","pl":8049535,"direction":-1},{"username":"MrWade","pl":6463578,"direction":0}]

Create an account

You can either create an account using credentials or with lnurl-auth. Here we show how do it via credentials.

First, you need to request new credentals:

#Request new credentials

url = "https://api.lnmarkets.com/login/credentials"

headers = {'accept': 'application/json'}

response = requests.request("GET", url, headers=headers)

print(response.text)

And you get the 100 sats invoice you need to pay within 90 seconds to create new credentials:

{"invoice":"lnbc1u1p0lmvv6pp5dfz865a3gurv5ex756560sjlfl6r2w6ryasr08f58pdh0nnghussdz42pshjgr5dp5hxgrfdemx76trv5s8gmeqvdex2ct5v5s8jmm4wgsxzcmrda6kuapqdahzqnzwypxkzuntv468xcqzpgxqzz6sp54henkny2tlt8d3she2qt3fyxqekjvkup4a9nualuskz6w9mur7nq9qy9qsq4kvrylwsfl00rrmrmhcc7vqmpyc8ehwvn8uzym2rjq0s77vt27urqjzm3q9mwf3juf4jewrn4wk2whyq5q7pueh8skg40khg25x6mzsq90xekr","expiry":90}

After paying the invoice, we enter in the payload the payment hash of the invoice and the login and password we want to use:

#Register new credentials

url = "https://api.lnmarkets.com/login/credentials"

payload = {'login':'python_tuto',
           'password':'mYUNwrffso0r48L3P422w0rd',
           'paymentHash':'01040402f55679843f3a4bac19fa90534a7822ed4214fae2aaf4e1463d6e8b21'}

payload = json.dumps(payload)

headers = {
    'content-type': "application/json",
    'accept': "application/json"
    }

response = requests.request("PUT", url, data=payload, headers=headers)

print(response.text)

Our account is now created:

{"username":"python_tuto","balance":0,"account_type":"credentials"}

There is much more

There are plenty of other actions that we did not cover in this tutorial (account creation and withdraw via lnurl, API tokens revocation, state of LN Markets node and our API, announcements, etc.), but that you will be able to run easily using the previous lines of codes.

Should you have any questions about using the API, feel free to join LN Markets Telegram support group: https://www.t.me/lnmarkets