Overview

For v3 and going forward Silvergate APIs use a combination of Subscription Key and Client Secret as unique material for sending secure requests. Both secrets are available via the Silvergate Portal accessible by a customer Profile Admin. See Intro for getting started with this process. Once Silvergate’s back office completes initial setup, the customer Profile Admin will need to retrieve the Subscription Key and generate the Client Secret, which is only available to be copied one time. Both “secrets” must be used to generate a secure request header, as specified in following sections.

Client Required Headers

All clients will need to send in the following headers to be validated properly.

  • X-Auth-Signature - This is the client generated signature based on the data sent to the API and signed in an HMAC512 crypto as a base64 string. See next section “Generating a Signature” for more details.
  • Ocp-Apim-Subscription-Key – Each Subscription is assigned a unique key for which specific permissions may be applied
  • X-Auth-Nonce – A unique random number which cannot be reused within 150 seconds. It is required to aid against cases of replay attacks.
  • X-Auth-Timestamp – The UTC time when the request is generated. It is used to validate the request is not stale when it is received.
  • X-Auth-Version – The authentication version which should be defaulted to “v1”. It may be used in the future if the authentication is modified.

Generating a Signature

For the API to validate any calls, the client must generate a signature using the Secret and set the value in the X-Auth-Signature header. The signature is a combination of header values, calling URL, and the body of the request if it exists. The following steps can be used to generate the signature for any of the Silvergate Bank v3+ API endpoints. The examples listed for reference are in C#.

  1. Create a string that contains the URL path that is being called, including any query parameters, i.e. https://example.com/api/account/{accountnumber}/balance . Call this absoluteUri.

    Ex. For a Balance call for account # 1234567890:
string absoluteUri = "https://example.com/api/account/1234567890/balance";
  1. Create another string that combines the above with all the information set in the headers. These are listed in the string as [ ] and should be replaced with the actual value that is set in the header of the same name. Call this stringToSign.
    "Silvergate {Ocp-Apim-Subscription-Key}{absoluteUri}{X-Auth-Nonce}{X-Auth-Timestamp}{X-Auth-Version}{RequestBody}"
    NOTE: If the endpoint being called is a GET http verb or does not contain a request body, then the request body should be omitted. The request body should be in the form of a json string.

  2. Compute the Hash of the above string using an HMAC512 crypto object. This object should be created using your client secret as your key.
    NOTE: If your language requires the string to be a byte array to compute the HMAC512 hash, we recommend using UTF8 encoding.

  3. Compute the hash to generate a new base64 encoded string object, which is used as the X-Auth-Signature header.

Sample Code (Python)

import requests
import datetime
import uuid
from datetime import timezone
import hmac
import base64
import json

subscription_key = ""
subscription_secret = ""

url = "https://api-sandbox.silvergate.com/v3/api/account/list" # url of request
nonce = uuid.uuid4().hex
timestamp = datetime.datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
version = "v1"
body = """""" # body of request

pre_encrypted_signature = f"Silvergate {subscription_key}{url}{nonce}{timestamp}{version}{body}".encode()
sha = hmac.new(subscription_secret.encode(), pre_encrypted_signature, "sha512")
signature = base64.b64encode(sha.digest()).decode()

headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": subscription_key,
    "X-Auth-Nonce": nonce,
    "X-Auth-Timestamp": timestamp,
    "X-Auth-Version": version,
    "X-Auth-Signature": signature
}

response = requests.get(url, headers=headers)
# response = requests.post(url, headers=headers, json=json.loads(body))
print(response)
print(response.content.decode())