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
# ...