NAV
cURL ruby php

Introduction

Welcome to the Magnr Trading API. Technical details on how to implement and connect to our API is provided below.

Environments

Magnr provides 2 separate environments for development and production. API pub/priv keys differ between the 2 environments so you will have to request one set from each environment separately.

All responses are of content type application/json

PRODUCTION ENVIRONMENT

The Magnr production environment API is live and used by our own website https://magnr.com .

TEST ENVIRONMENT

All the examples of code in this documentation use the sandbox API in URLs. It is recommended that attempts to use the API are performed against sandbox before live.

The sandbox environment is connected to bitcoins testnet, consequently you can fund your account from one of many testnet faucets

Error Handling

Example JSON Error

{
  "errors": ["some error string", "another error string"]
}

All errors follow general REST principles. Included in the body of any error response (e.g. non-2xx status code) will be an error object of the form:

Parameter Value
errors List of error strings

Authentication

<?php
$privkey = "your private key";
$pubkey = "your public key";

// @note SET THIS DATA CORRECTLY ON EACH REQUEST AND BEFORE SIG AND AUTH GENERATION
$data = "empty string or json string";
$tonce = intval(microtime(true)*1000);

$sig = base64_encode(hash_hmac("sha512", $tonce.$pubkey.$data, $privkey, true));
$auth = base64_encode($pubkey.":".$sig);
# With shell, you can pass a signed header with each request
TONCE=$(($(date +%s)*1000))
PRIVKEY=`echo -e "your private key here"`
PUBKEY=`echo -e "your public key here"`
DATA="some json or empty string"
SIG=`echo -en "$TONCE$PUBKEY$DATA" | openssl dgst -sha512 -hmac "$PRIVKEY" -binary | base64`
AUTH=`echo -en "$PUBKEY:$SIG" | base64`

curl "https://sandbox.magnr.com/api/v1/<some end point>/" \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic $AUTH" \
  -H "Tonce: $TONCE" \
  -d $DATA

Note: The rest of the shell examples assume the shell variables TONCE and AUTH are regenerated per request.
require 'uri'
require 'net/http'
require 'time'
require 'securerandom'
require 'base64'

uri = URI.parse("https://sandbox.magnr.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

pubkey = "YOUR PUBLIC KEY"
privkey = "YOUR PRIVATE KEY"

# milliseconds time
tonce = Time.now.to_i * 1000

data = ""
signature = Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), privkey, tonce.to_s+pubkey+data))

request = Net::HTTP::Get.new("/api/v1/<some end point>/")
request.add_field('Content-Type', 'application/json')
request.add_field('Tonce', tonce)
request.basic_auth(pubkey,signature)

response = http.request(request)
print response.body

We use pairs of long-lived application keys to authenticate requests. To request an API key log in to Magnr, click on Account Settings (In the Account menu drop-down) and select the API tab.

Every request should include the following header values

Header Required Description
Tonce yes It should be a non-repeating number, and be around a 5 minutes window around the current timestamp. THIS TONCE NEEDS TO BE IN MILLISECONDS
Authorization yes The string “Basic ”, appended with the signature resulting of calculating the HMAC SHA-512 value of the tonce, the public key that you were assigned, and the body of the request.

Trading

Create Trade

DATA="{\"leverage\":10, \"side\":\"BUY\", \"exchange\":\"Bitfinex\", \"pair\":\"BTCUSD\", \"stop_margin\":5, \"size\":0.2, \"take\":10}"
curl "https://sandbox.magnr.com/api/v1/trades/" \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Basic $AUTH" \
  -H "Tonce: $TONCE" \
  -d $DATA

Returns 201 CREATED when the trade is correctly placed. See error list for other response codes.

<?php
$data = json_encode(["leverage"=>10, "side"=>"buy", "exchange"=>"Bitfinex", "pair"=>"BTCUSD", "stop_margin"=>5, "size"=>0.2, "take"=>10]);

/**
 * DO AUTH STUFF HERE TO GENERATE $auth AND $tonce
 */

$curl = curl_init("https://sandbox.magnr.com/api/v1/trades/");
// Set to a POST request
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

// apply headers
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: Basic $auth", "Tonce: $tonce", "Content-Type: application/json", "Accept: application/json"]);

// define how we want our response.
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // curl_exec returns the result
curl_setopt($curl, CURLOPT_HEADER, 0); // don't include headers in the response from curl_exec

// gimme gimme!
$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

$json = json_decode($body,true); // the json as an array
echo "STATUS: $status\nBODY:\n$body";
require 'uri'
require 'net/http'
require 'time'
require 'securerandom'
require 'base64'
require 'json'

uri = URI.parse("https://sandbox.magnr.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

#TRADE DATA
data = {:leverage =>10, :side =>"buy", :exchange =>"LOCAL", :pair =>"BTCUSD", :stop_margin =>5, :size =>0.3, :take =>10}.to_json

#BEGIN AUTH (see authentication section)
pubkey = "YOUR PRIVATE KEY"
privkey = "YOUR PUBLIC KEY"
tonce = Time.now.to_i * 1000
signature = Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), privkey, tonce.to_s+pubkey+data))
#END AUTH

request = Net::HTTP::Post.new("/api/v1/trades/")
request.add_field('Content-Type', 'application/json')
request.add_field('Tonce', tonce)
request.basic_auth(pubkey,signature)
request.body = data

response = http.request(request)
json = JSON.parse(response.body)
print json

HTTP Request

POST /api/v1/trades/

BODY Parameters

Parameter Type Required Default Description
side string YES none buy or sell (case sensitive)
size float YES none Size of the position to market.
exchange string YES none Bitstamp,ItBit,Bitfinex (Exchange to be used for the trade)
pair string YES none BTCUSD, XBTUSD (exchange dependent)
leverage number NO 10 10,5,2 (Leverage to apply on this trade)
stop_margin float NO max stop for deposit An amount in $USD the price can move against you before being automatically closed out.
type string NO market market is the only option at present
take float NO none The amount in $USD you wish the price to move in your favour before closing out.

Example response - 201 CREATED

{
  "id":1234
}

RESPONSE

Parameter Type Description
id string Trade identifier

ERRORS

Response Description
400 Bad Request The request parameters were missing or incorrect
409 Conflict The request could be completed due to a state conflict with the account
500 Internal Server Error The system encountered an error, or the exchange failed to accept the trade

List Trades

curl "https://sandbox.magnr.com/api/v1/trades/"
  -H "Content-Type: application/json"
  -H "Accept: application/json"
  -H "Authorization: Basic $AUTH"
  -H "Tonce: <tonce>"
<?php

$data = "";

/**
 * DO AUTH STUFF HERE TO SET $auth AND $tonce
 */

$curl = curl_init("https://sandbox.magnr.com/api/v1/trades/");
// apply headers
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: Basic $auth", "Tonce: $tonce"]);

// define how we want our response.
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // curl_exec returns the result
curl_setopt($curl, CURLOPT_HEADER, 0); // don't include headers in the response from curl_exec

// gimme gimme!
$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

echo "STATUS: $status\nBODY:\n$body";
require 'uri'
require 'net/http'
require 'time'
require 'securerandom'
require 'base64'
require 'json'

uri = URI.parse("https://sandbox.magnr.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

data = ""
#BEGIN AUTH (see authentication section)
pubkey = "YOUR PRIVATE KEY"
privkey = "YOUR PUBLIC KEY"
tonce = Time.now.to_i * 1000
signature = Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), privkey, tonce.to_s+pubkey+data))
#END AUTH

request = Net::HTTP::Get.new("/api/v1/trades/")
request.add_field('Content-Type', 'application/json')
request.add_field('Tonce', tonce)
request.basic_auth(pubkey,signature)

response = http.request(request)
json = JSON.parse(response.body)
print json

Response - 200 OK

{
  "trades": [
    {
        "id"  : 1234,
        "side": "buy",
        "leverage": 10,
        "size": 0.2,
        "deposit": 0.002,
        "exchange":"LOCAL",
        "created_at":1444251389,
        "closed_at": null,
        "open_price": null,
        "close_price": null,
        "closed_reason":null,
        "trade_rate": 0.48,
        "daily_rate": 0.2,
        "trade_fees": 0.004,
        "daily_fees": 0.00,
        "stop_margin": 20,
        "trail_margin": 20,
        "sell_limit": 10,
        "status": "pending",
        "profit": null
    },
    {
        "id"  : 1233,
        "side": "sell",
        "leverage": 5,
        "size": 0.3,
        "deposit": 0.008,
        "exchange":"LOCAL",
        "created_at":1444230624,
        "closed_at":1444612316,
        "open_price": 234.45,
        "close_price": 235.56,
        "closed_reason":"stop",
        "trade_rate": 0.48,
        "daily_rate": 0.2,
        "trade_fees": 0.002,
        "daily_fees": 0.0009,
        "stop_margin": 20,
        "trail_margin": 20,
        "sell_limit": 10,
        "status": "settled",
        "profit": -0.00000667
      }
  ]
}

HTTP Request

GET /api/v1/trades/

URL Parameters

NONE

RESPONSE

Parameter Type Description
trades array An array of trade objects (see Get Trade call)

Get Trade

ID=1234
// regenerate TONCE and AUTH
curl "https://sandbox.magnr.com/api/v1/trades/$ID/"
  -H "Content-Type: application/json"
  -H "Accept: application/json"
  -H "Authorization: Basic $AUTH"
  -H "Tonce: $TONCE"
<?php

$id = 1234;
$data = "";

/**
 * DO AUTH STUFF HERE TO SET $auth AND $tonce
 */

$curl = curl_init("https://sandbox.magnr.com/api/v1/trades/$id/");
// apply headers
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: Basic $auth", "Tonce: $tonce"]);

// define how we want our response.
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // curl_exec returns the result
curl_setopt($curl, CURLOPT_HEADER, 0); // don't include headers in the response from curl_exec

// gimme gimme!
$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

echo "STATUS: $status\nBODY:\n$body";
require 'uri'
require 'net/http'
require 'time'
require 'securerandom'
require 'base64'
require 'json'

uri = URI.parse("https://sandbox.magnr.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

#DATA
id = "TRADE ID"
data = ""

#BEGIN AUTH (see authentication section)
pubkey = "YOUR PRIVATE KEY"
privkey = "YOUR PUBLIC KEY"
tonce = Time.now.to_i * 1000
signature = Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), privkey, tonce.to_s+pubkey+data))
#END AUTH

# BEGIN REQUEST
request = Net::HTTP::Get.new("/api/v1/trades/#{id}/")
request.add_field('Content-Type', 'application/json')
request.add_field('Tonce', tonce)
request.basic_auth(pubkey,signature)

response = http.request(request)
json = JSON.parse(response.body)
print json

Example response

{
  "trade": {
    "id"  : 1234,
    "side": "buy",
    "leverage": 10,
    "size": 0.2,
    "deposit": 0.002,
    "exchange":"LOCAL",
    "created_at":1444230624,
    "closed_at":1444612316,
    "open_price": 234.45,
    "close_price": 235.56,
    "closed_reason":"user",
    "trade_rate": 0.48,
    "daily_rate": 0.2,
    "trade_fees": 0.004,
    "daily_fees": 0.00,
    "stop_margin": 20,
    "trail_margin": 20,
    "sell_limit": 10,    
    "status": "settled",
    "profit": 0.00019382
  }
}

This endpoint retrieves a specific trade.

HTTP REQUEST

GET /api/v1/trades/:id/

URL PARAMETERS

Parameter Type Required Description
id string YES The ID of the trade to retrieve

RESPONSE

Returns a Trade object

Field Type Description
id string id of the trade
side string “buy” or “sell”
leverage int the leverage applied on the trade
size float size of the trade at market
deposit float size of the deposit taken for the trade
exchange string the name of the exchange that the trade was opened on
created_at int timestamp of trade creation (in seconds since epoch)
closed_at int timestamp of the trade close (in seconds since epoch)
open_price float price the trade was opened at
close_price float price the trade closed at
closed_reason string the reason the trade closed (user,stop,limit,insufficient funds)
trade_rate float trade charge PERCENTAGE (e.g. 0.48%)
daily_rate float daily charge PERCENTAGE (e.g. 0.2%)
trade_fees float bitcoin trade fees (absolute) applied to the trade (note: this includes BOTH open AND close fees)
daily_fees float bitcoin daily fees (absolute) applied to the trade since it was opened
status string the state of the trade (pending -> open -> closed -> settled), see status info.
profit float the profit on the trade if it has settled, otherwise NULL
stop_margin float size in currency (e.g. USD) of the stop margin
trail_margin float size in currency (e.g. USD) of the trailing stop, otherwise NULL if not set
sell_limit float size in currency (e.g. USD) of the sell limit, otherwise NULL if not set

STATUS

Field Description
pending The trade has been placed at the exchange but is awaiting fill (i.e. open price is NULL).
open The trade has been filled and now has an open price
closed The trade has been closed either by user or system but it awaiting a closing price (i.e. close price is NULL).
settled The trade has been filled at a close price and now has a profit, all deposits should have been refunded.

CLOSED REASON

Field Description
user You (the user) have requested the trade be closed.
stop The trade has reached the stop margin specified, and it has been automatically closed.
trail The trade has reached the trail margin specified, and it has been automatically closed.
limit The trade has reached the target sell limit, and has been automatically closed.
insufficient funds A healthly balance was NOT maintained and a daily charge would not be applied, as a result the trade has been automatically closed.

ERRORS

Response Description
400 Bad Request The request parameters were missing or incorrect
404 Not Found The trade you requested does not exist
500 Internal Server Error The system encountered an error

Liquidate (Close) Trade

ID=1234
// regenerate TONCE and AUTH
curl "https://sandbox.magnr.com/api/v1/trades/$ID/"
  -H "Content-Type: application/json"
  -H "Accept: application/json"
  -H "Authorization: Basic $AUTH"
  -H "Tonce: $TONCE"
<?php
$id = 1234;
$data = "";

/**
 * DO AUTH STUFF HERE TO SET $auth AND $tonce
 */

$curl = curl_init("https://sandbox.magnr.com/api/v1/trades/$id/");

// DELETE REQUEST TYPE
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");

// apply headers
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Authorization: Basic $auth", "Tonce: $tonce"]);

// define how we want our response.
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);

// gimme gimme!
$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

echo "STATUS: $status\nBODY:\n$body";

Example Response - 200 OK

{
  "id":1234
}

HTTP REQUEST

DELETE /api/v1/trades/:id/

URL PARAMETERS

Parameter Type Required Description
id string yes The ID of the trade to liquidate/close

RESPONSE

Returns a identity object indicating the ID of the liquidated position.

ERRORS

Response Description
404 Not Found The trade you requested to delete does not exist.
409 Conflict The trade is in an invalid state (possibly still pending)
500 Internal Server Error The system encountered an error
504 Gateway Timeout The exchange encountered an issue and could not complete the request.

Price Data

Exchange Pricing

For the lowest latency, we recommend using price data direct from the exchanges we connect with. This will allow for better pricing data to be fed directly into your trading scripts. Magnr’s position execution policy is at-best market price. Frequent price updates will result in execution prices closer to market prices.

Bitfinex

Bitfinex Documentation

Bitstamp

Bitstamp Documentation

ItBit

ItBit Documentation