Skip to main content

Introduction

Welcome to the CoinRPC documentation.

API​

Each wallet can be configured to enable API access. See each individual network's API documention for the endpoint URL and the specific methods available.

The API uses the JSON-RPC 2.0 specification.

Authentication​

The following headers must be sent with each API request to properly authenticate:

  • x-api-key: Your API key
  • x-signature: A locally generated signature (see below).
  • x-timestamp: The unix timestamp of when the request was sent.

Generating the signature:

  • Join a dumped string of the JSON request data and the request unix timestamp with a semicolon (:).
  • Create an HMAC digest string (hex), using the joined string as the message, your API secret as the key, and SHA256 as the digest method.
def create_signature(payload, secret, timestamp):
import hashlib
import hmac
import json
message = ":".join([json.dumps(payload, separators=(',',':')), str(timestamp)])
return hmac.new(secret.encode('utf-8'), msg=message.encode('utf-8'), digestmod=hashlib.sha256).hexdigest()

Request​

Requests must be sent using the POST method with the content-type header set to application/json.

The request JSON should be in the following format. The params member can be omitted if the method does not require any.

{
"id": 1,
"jsonrpc": "2.0",
"method": "get_balance",
"params": {
"currency": "BTC",
}
}

Response​

The response will be in JSON format. If an error member is present, there was an error with the invocation.

{
"id": 1,
"jsonrpc": "2.0",
"result": "0.135", // can be any JSON literal, object or list.
}

Client Library​

import hashlib
import hmac
import json
import time
import requests

class ApiClient():
def __init__(self, endpoint, api_key, secret):
self.endpoint = endpoint
self.api_key = api_key
self.secret = secret
self.session = requests.Session()

@staticmethod
def create_signature(payload, secret, timestamp):
message = ":".join([json.dumps(payload, separators=(',',':')), str(timestamp)])
return hmac.new(secret.encode('utf-8'), msg=message.encode('utf-8'), digestmod=hashlib.sha256).hexdigest()

def send(self, method, params=None):
payload = {
'id': '1',
'jsonrpc': '2.0',
'method': method,
}
if params:
payload['params'] = params
timestamp = str(int(time.time()))
signature = self.create_signature(payload, self.secret, timestamp)
headers = {
'x-api-key': self.api_key,
'x-signature': signature,
'x-timestamp': timestamp,
}
r = self.session.post(self.endpoint, json=payload, headers=headers)
r.raise_for_status()
res = r.json()
if 'error' in res:
raise Exception(res['error'].get('message'))
return res.get('result')

# configuration
endpoint = 'http://api.coinrpc.com/bitcoin'
api_key = 'YOUR_API_KEY'
api_secret = 'YOUR API SECRET'

# create an instance
client = ApiClient(endpoint, api_key, api_secret)

# make a call to get the wallet balance
try:
result = client.send('get_balance', {'currency': 'BTC'})
print(result)
except Exception as e:
print("error: " + str(e))

Webhook​

Each wallet can be configured to support webhook notifications. See each individual network's webhook documentation for the specific notification events and name/value pairs sent. Webhook notifcations are sent to your configured URL via POST method with name/value pairs in standard application/x-www-form-urlencoded format.

Verification​

Every webhook notification contains a verify_hash name/value pair. This value can be used to validate the authenticity of a webhook notification.

Creating the local verification hash:

  • Sort all name/value pairs by name, alphabetically.
  • Iterate each sorted pair and add the value to a list. (excluding verify_hash name/value pair)
  • Add the wallet secret as the last item in the list.
  • Join the list of values by a semicolon (:).
  • Create an SHA256 hash (hex) with the result of the join.

Compare the local hash with the value of the verify_hash pair. If they are the same, then the webhook notification is authentic.

Example

The webhook secret is:

  • WALLET_WEBHOOK_SECRET

Assume we have the following name/value pairs:

  • guid=ABCD12349876
  • recipient=1Lbcfr7sAHTD9CgdQo3HTMTkV8LK4ZnX71
  • amount=0.1
  • currency=BTC
  • verify_hash=fbd985e0ddfc6fb63cf8fc3091b06bd992bf64ba9ea6b468f13f27fd372f0913

The alphabetically sorted name/value pair values (excluding verify_hash) with the webhook secret joined by semicolon would be:

0.1:BTC:ABCD12349876:1Lbcfr7sAHTD9CgdQo3HTMTkV8LK4ZnX71:WALLET_WEBHOOK_SECRET

The SHA256 hex of this string would be:

fbd985e0ddfc6fb63cf8fc3091b06bd992bf64ba9ea6b468f13f27fd372f0913

def create_verify_hash(params, secret):
import hashlib
parts = []
for key in sorted(params.keys()):
if key != 'verify_hash':
parts.append(params[key])
parts.append(secret)
raw = ':'.join(parts)
return hashlib.sha256(raw.encode('utf-8')).hexdigest()

# endpoint handler (assumes flask)
@app.route("/endpoint", methods=["POST"])
def endpoint():
from flask import request
secret = 'WALLET_WEBHOOK_SECRET'
local_hash = create_verify_hash(request.form, secret)
if local_hash != request.form.get('verify_hash'):
raise RuntimeError("verification failed")

# do work with request.form
# ...