Bit Capital

The Bit Capital Developer Hub

Welcome to the Bit Capital developer hub. You'll find comprehensive guides and documentation to help you start working with Bit Capital as quickly as possible, as well as support if you get stuck. Let's jump right in!

Guides    API Reference

Request Signing

To preventing packet tampering, some of the API endpoints requires Request Signing. The request signature is created with an HMAC using SHA256. The hash should be created using a concatenation of the following strings using the credential secret comma-separated:

  • The uppercase HTTP method being used, e.g. GET or POST.
  • The request path, e.g./consumers.
  • The UNIX timestamp in seconds for the request. This must be within 30 seconds of the time at which the request is received at the server or the request will not be considered valid.
  • If present, the request body as a single line stringified JSON.

Then, pass the signature information as HTTP Headers in the request:

  • X-Request-Timestamp: The timestamp of the request signing.
  • X-Request-Signature: The computed hash for the request.

Troubleshooting

The request signature is needed for account protection, so it is very restrictive with its parameters. Please make sure you have:

  • Set your device clock to automatic date time, synchronized with a trusted NTP (we use Google's Time);
  • A valid set and active of OAuth Client Credentials (the one used as a Basic Authorization header);
  • No paddings added to the signing params around the commas;
  • A "fresh" signature (it will only be accepted within 30s from the server current timestamp).

Sample Codes

You can check the Request Signing Toolbox in the Bitcapital Labs for more information and sample codes.

import * as CryptoJS from 'crypto-js';

export interface RequestSigningHeaders {
  'X-Request-Signature': string;
  'X-Request-Timestamp': string;
}

export interface RequestSigningOptions {
  method: string;
  url: string;
  body?: string;
  timestamp?: string;
}

export class RequestUtil {
  /**
   * Generates headers for request signing.
   */
  public static sign(secret: string, req: RequestSigningOptions): RequestSigningHeaders {
    const now = req.timestamp ? req.timestamp : Date.now();
    const payload = [req.method, req.url, now];

    // Check if should sign body as well
    if (req.body && req.method === 'POST' || req.method === 'PUT') {
      payload.push(req.body);
    }

    // Generate signature using HMAC SHA 256
    const signature = CryptoJS.HmacSHA256(payload.join(','), secret);

    return {
      'X-Request-Signature': signature.toString(),
      'X-Request-Timestamp': now.toString(),
    };
  }
}
package app.btcore.java;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

public class RequestSigning {
    private static final char[] digits = "0123456789ABCDEF".toCharArray();

    public String sign(String secret, String method, String url) throws InvalidKeyException {
        return this.sign(secret, method, url, null, System.currentTimeMillis());
    }

    public String sign(String secret, String method, String url, String body) throws InvalidKeyException {
        return this.sign(secret, method, url, body, System.currentTimeMillis());
    }

    public String sign(String secret, String method, String url, String body, long timestamp) throws InvalidKeyException {
        List<String> segments = new ArrayList<>();

        segments.add(method);
        segments.add(url);
        segments.add(String.valueOf(timestamp));

        if (body != null && body.length() > 0) {
            segments.add(body);
        }

        return this.raw(secret, String.join(",", segments));
    }

    public String raw(String key, String content) throws InvalidKeyException {
        String algorithm = "HmacSHA256";

        try {
            return this.generateSignature(content, key, algorithm);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException exception) {
            // Algorithm or encoding is not available, maybe we should crash
            throw new RuntimeException(exception);
        }
    }

    private static String bytesToHex(final byte[] bytes) {
        final StringBuilder buf = new StringBuilder();
        for (byte aByte : bytes) {
            buf.append(RequestSigning.digits[(aByte >> 4) & 0x0f]);
            buf.append(RequestSigning.digits[aByte & 0x0f]);
        }
        return buf.toString();
    }

    protected String generateSignature(String content, String key, String algorithm)
        throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        // 1. Get an algorithm instance.
        Mac sha256_hmac = Mac.getInstance(algorithm);

        // 2. Create secret key.
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);

        // 3. Assign secret key algorithm.
        sha256_hmac.init(secret_key);

        // You can use any other encoding format to get hash text in that encoding.
        return RequestSigning.bytesToHex(sha256_hmac.doFinal(content.getBytes(StandardCharsets.UTF_8))).toLowerCase();
    }
}

Request Signing


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.