API Documentation

Introduction

MorphToken provides a HTTP API for starting trades and recommends using its Websocket API for tracking the latest rates and trade updates.

Base URL for the HTTP API: https://api.morphtoken.com
Websocket (with SockJS) URL: https://api.morphtoken.com/streaming

If you're using MorphToken commercially, or planning to, it's recommended to enter in contact so we can lift limits and better serve your product.

POST /morph

Start a new trade request.

Parameters

inputInput object
outputList of Output objects
Input object
KeyTypeDescription
assetstringAsset to be used for deposit, one of: "BTC", "ETH", "BCH", "LTC", "DASH", "XMR"
refundstringRefund address to be used in case of issues
Output object
KeyTypeDescription
assetstringAsset to be used for this output, one of: "BTC", "ETH", "BCH", "LTC", "DASH", "XMR"
weightintegerA number between 1 (0.01%) and 10000 (100.00%) representing how much of the input deposit should be used for this output
addressstringOutput address to be used during withdraw

For Monero addresses it's recommended to always use integrated addresses, but if you want to specify a payment id then the address can be formatted as address_paymentid.

Example

$ curl https://api.morphtoken.com/morph \
  -X POST -H "Content-Type: application/json" \
  -d '{
    "input": {
      "asset": "ETH",
      "refund": "0x4d2022abbda11a510ee109ea8a1446ed5fd8210d"
    },
    "output": [{
      "asset": "BTC",
      "weight": 10000,
      "address": "3CuWxAYh8niCuhMfb5fXN5NjasiY54E8cc"
    }]
  }'
{
  "created_at": "2017-11-26T11:32:44.718697+00:00", 
  "id": "2MGK3GXP2JN",
  "state": "PENDING", 
  "input": {
    "asset": "ETH", 
    "received": null, 
    "confirmed_at_height": null, 
    "deposit_address": "0x82817105e9bd380f81f4492644100c90ee8ee523",
    "legacy_deposit_address": null, 
    "refund_address": "0x4d2022abbda11a510ee109ea8a1446ed5fd8210d", 
    "limits": {
      "max": 106665000000000000000, 
      "min": 20000000000000000
    }
  }, 
  "output": [
    {
      "asset": "BTC", 
      "weight": 10000, 
      "address": "3CuWxAYh8niCuhMfb5fXN5NjasiY54E8cc", 
      "seen_rate": "0.05115837", 
      "final_rate": null, 
      "network_fee": {
        "flat": true, 
        "fee": 60000
      }, 
      "converted_amount": null, 
      "txid": null
    }
  ], 
  "refund": null, 
  "remaining_weight": 0
}

Response data

Successful responses always return with http status 200 and json data.

KeyTypeDescription
created_atstringUTC date in ISO 8601 format
idstringID for this morph trade
statestringCurrent state for this trade. See below for further state information.
input.
asset
stringOne of the assets accepted
input.
received
null or integerAmount received as an integer. ETH uses 18 decimal places, XMR uses 12, others 8
input.
confirmed_at_height
null or integerBlock height that contains the deposit transaction.
input.
deposit_address
stringDeposit address returned from MorphToken to be used for this trade
input.
legacy_deposit_address
null or stringUsed by Litecoin for displaying an address in an older format, other assets do not use this field
input.
refund_address
stringRefund address specified by the user
input.
limits.max
integerThe maximum deposit amount accepted for this trade
input.
limits.min
integerThe minimum deposit amount accepted for this trade
outputlistA list of objects describing each output
output.i.
asset
stringOne of the assets accepted
output.i.
weight
integerA number between 1 (0.01%) and 10000 (100.00%)
output.i.
address
stringOutput address owned by the user
output.i.
seen_rate
stringRate that was seen when this trade started
output.i.
final_rate
stringRate obtained when trading the assets
output.i.
network_fee.flat
boolAlways true for now, indicates whether this output will be deducted a flat amount (MorphToken covers for the actual fee) or a dynamic amount (MorphToken charges the exact amount used for the network fee).
output.i.
network_fee.fee
numberNetwork fee to be used for this output
output.i.
converted_amount
null or integerAfter the assets are traded this field shows the converted amount
output.i.
txid
null or stringAfter the assets are traded a withdraw will be created, when the withdraw completes this field shows the transaction id used for it
refundnull or objectThis field remains null unless a refund is required
remaining_weightinteger10000 - sum of weights specified
Morph trade states

All trades start as "PENDING" (meaning: Waiting deposit). The most common flow from there, in the following order, is:

  • "CONFIRMING" (Waiting confirmations),
  • "PROCESSING" (Deposit confirmed, preparing trades),
  • "TRADING",
  • "TRADED" (Finished trading),
  • "COMPLETE".

If a refund is required the flow will be:

  • "PROCESSING_REFUND" (Deposit outside limits), and then
  • "COMPLETE_WITH_REFUND" (Refund completed), or
  • "COMPLETE_WITHOUT_REFUND" (Deposit below network fee, too small to refund).

If no deposit is received within 2 days the trade moves to "EXPIRED". Unexpected issues will move it to "CANCELED".

These are all the possible states.

Refund object

This object will only be seen in the result if MorphToken had to refund, i.e. reject, the deposit. The typical case for this is for deposits outside the limits specified.

KeyTypeDescription
assetstringSame as the input asset specified
network_feeintegerFee used for the refund
final_amountintegerAmount refunded
txidnull or stringThis is null while the refund is being processed
reasonnull or stringIf this refund involved some special error, its reason is described here

Errors

If the request contains invalid data then a http error 400 is returned. If some unexpected error occurs server side, either an http error 502 or 503 is returned.

Error: input/output missing

{
    "code": 1000,
    "description": "input/output must be specified",
    "success": false
}

Error: asset missing

{
    "code": 1010,
    "description": "input asset missing",
    "success": false
}

Error: unknown input asset

{
    "code": 1011,
    "description": "input asset not recognized",
    "success": false
}

Error: invalid refund address

{
    "code": 1012,
    "description": "input refund address <addr> for <asset> is invalid",
    "success": false
}

Error: empty output list

{
    "code": 1020,
    "description": "output must be a non-empty list of entries",
    "success": false
}

Error: invalid output entry

{
    "code": 1021,
    "description": "every output must contain an address, asset, and weight",
    "success": false
}

Error: invalid output weight

{
    "code": 1022,
    "description": "output weight must be an integer between 1 and 10000",
    "success": false
}

Error: overweight outputs

This happens if you specify output weights that sum up to more than 100%. Specifying less than 100% as total weight is accepted and considered a donation.

{
    "code": 1023,
    "description": "output total weight is greater than 10000",
    "success": false
}

Error: unknown output asset

{
    "code": 1024,
    "description": "output asset not recognized",
    "success": false
}

Error: no rates for the input/output asset pair

This is returned only for pairs that are not yet active but a request tries to use it anyway.

{
    "code": 1025,
    "description": "output asset <asset> not available for input asset",
    "success": false
}

Error: invalid output address

{
    "code": 1026,
    "description": "output address <addr> for <asset> is invalid",
    "success": false
}

Error: too many outputs

{
    "code": 1027,
    "description": "too many outputs, maximum supported is 32",
    "success": false
}

GET /morph/:mid

Fetch an existing trade request either by its morph id or by the deposit address received.

Example

curl https://api.morphtoken.com/morph/2MGK3GXP2JN

Both
  GET /morph/2MGK3GXP2JN and
  GET /morph/0x82817105e9bd380f81f4492644100c90ee8ee523
return the same data:

{
  "created_at": "2017-11-26T11:32:44.718697+00:00", 
  "id": "2MGK3GXP2JN",
  "state": "PENDING", 
  "input": {
    "asset": "ETH", 
    "received": null, 
    "confirmed_at_height": null, 
    "deposit_address": "0x82817105e9bd380f81f4492644100c90ee8ee523",
    "legacy_deposit_address": null, 
    "refund_address": "0x4d2022abbda11a510ee109ea8a1446ed5fd8210d", 
    "limits": {
      "max": 106665000000000000000, 
      "min": 20000000000000000
    }
  }, 
  "output": [
    {
      "asset": "BTC", 
      "weight": 10000, 
      "address": "3CuWxAYh8niCuhMfb5fXN5NjasiY54E8cc", 
      "seen_rate": "0.05115837", 
      "final_rate": null, 
      "network_fee": {
        "flat": true, 
        "fee": 60000
      }, 
      "converted_amount": null, 
      "txid": null
    }
  ], 
  "refund": null, 
  "remaining_weight": 0
}

Error

The only possible error for this route is http error 404 for a trade not found.

{
  "code": 1100,
  "description": "Trade not found",
  "success": false
}

GET /rates

Fetch the latest rates.

{
  "timestamp": 1507935821.05505,
  "type": "ticker",
  "LTC": {
    "ETH": "0.17334385",
    "XMR": "0.61394616",
    "BTC": "0.01041068"
  },
  "BTC": {
    "LTC": "95.05158579",
    "ETH": "16.56731826",
    "XMR": "58.67783216"
  },
  "ETH": {
    "LTC": "5.70547144",
    "XMR": "3.52213688",
    "BTC": "0.05972488"
  },
  "XMR": {
    "LTC": "1.60342520",
    "ETH": "0.27947409",
    "BTC": "0.01678466"
  }
}

POST /limits

Query the limits that would be used for a trade if it happened now. The parameters for this endpoint are the same as those for POST /morph except that addresses are not specified.

Example

$ curl https://api.morphtoken.com/limits \
  -X POST -H "Content-Type: application/json" \
  -d '{
    "input": {
      "asset": "ETH"
    },
    "output": [{
      "asset": "BTC",
      "weight": 10000
    }]
  }'
{
  "input": {
    "asset": "ETH", 
    "limits": {
      "max": 39322000000000000000, 
      "min": 18000000000000000
    }
  }, 
  "output": [
    {
      "asset": "BTC", 
      "final_rate": null, 
      "network_fee": 90000, 
      "seen_rate": "0.05814412", 
      "weight": 10000
    }
  ]
}

Websocket

MorphToken runs a sockjs server at https://api.morphtoken.com/streaming.

Ticker updates

After connecting to it, ticker messages will be received as one or more rates have changed. Ticker messages are formatted exactly as shown at GET /rates.

Trade request updates

In order to receive updates regarding a trade request, send a message formatted as

{
  "type": "join",
  "channel": <morph id>
}

Messages of type "tx" will be received, those are formatted exactly as shown by GET /morph/:mid.

Example code

$ npm install sockjs-client
const SockJS = require("sockjs-client")
const socket = new SockJS("https://api.morphtoken.com/streaming")

socket.onopen = () => {
  // Join some channel to get tx updates.
  // NOTE: no error is returned if the transaction does not exist.
  const data = { type: "join", channel: "2MGK3GXP2JN" }
  socket.send(JSON.stringify(data))
}

socket.onmessage = msg => {
  // Handle messages.
  const data = JSON.parse(msg.data)
  if (data.type === "ticker") {
    console.log("received ticker", data)
  } else if (data.type === "tx") {
    console.log("received tx update", data)
  }
}

Example output

received ticker { timestamp: 1507938461.311158,
  LTC: { ETH: '0.17395163', XMR: '0.61759435', BTC: '0.01040770' },
  BTC: { LTC: '95.11518975', ETH: '16.63017499', XMR: '59.04343698' },
  ETH: { LTC: '5.68237167', XMR: '3.52737301', BTC: '0.05944329' },
  type: 'ticker',
  XMR: { LTC: '1.59774496', ETH: '0.27935368', BTC: '0.01671401' } }