Calculate the API Signature

The following steps describe how to calculate the API signature.
  1. First, concatenate a string based on your request, as shown below: str_to_sign = {METHOD}|{PATH}|{TIMESTAMP}|{PARAMS}|{BODY}
    FieldDescriptionExample
    METHODHTTP method.GET
    PATHAPI endpoint./v2/transactions/transfer
    TIMESTAMPCurrent Unix timestamp in milliseconds. This value must be identical to the nonce in the request header.1718587017026
    PARAMSQuery parameters.chain_id=ETH&limit=10
    BODYThe raw request body as a string.{"wallet_type":"Custodial"}
    The PARAMS and BODY fields are optional. If a corresponding parameter is not present, leave it as an empty string.
  2. Use the hashlib library to apply SHA-256 to the string twice, as shown below:
      import hashlib
      content_hash = hashlib.sha256(hashlib.sha256(str_to_sign.encode()).digest()).digest()
    
  3. Sign the string with your API Secret, as shown below:
      from nacl.signing import SigningKey
    
      # Create an Ed25519 signing key. Replace `api_secret` with your API Secret.
      sk = SigningKey(bytes.fromhex(api_secret))
      # Sign the hashed message
      signature = sk.sign(content_hash).signature.hex()
    
You have now calculated an API signature.

Signature Code Samples

Below are complete signature helper implementations in various languages. You can copy them directly into your project. Signature flow:
  1. Concatenate the string to sign: {METHOD}|{PATH}|{TIMESTAMP}|{PARAMS}|{BODY}
  2. Double SHA256 hash: sha256(sha256(str_to_sign))
  3. Sign with the Ed25519 private key
  4. Place the signature data in the request headers: BIZ-API-KEY, Biz-Api-Nonce, Biz-Api-Signature
import hashlib
import time
import json
import requests
from nacl.signing import SigningKey


class NBTSigner:
    """NBT API signing helper"""

    def __init__(self, api_key: str, api_secret: str, base_url: str = "https://apidev.nusd.me"):
        self.api_key = api_key
        self.api_secret = api_secret
        self.base_url = base_url

    def sign(self, method: str, path: str, params: str = "", body: str = "") -> dict:
        """
        Generate the signature and return request headers.

        Args:
            method: HTTP method (GET/POST)
            path: API path (e.g. /nps/balance)
            params: query string (e.g. wallet_id=xxx)
            body: request body as JSON string
        Returns:
            A dict of headers containing the signature info.
        """
        timestamp = str(int(time.time() * 1000))
        str_to_sign = f"{method}|{path}|{timestamp}|{params}|{body}"

        # Double SHA256
        content_hash = hashlib.sha256(
            hashlib.sha256(str_to_sign.encode()).digest()
        ).digest()

        # Ed25519 signature
        signing_key = SigningKey(bytes.fromhex(self.api_secret))
        signature = signing_key.sign(content_hash).signature.hex()

        return {
            "BIZ-API-KEY": self.api_key,
            "Biz-Api-Nonce": timestamp,
            "Biz-Api-Signature": signature,
            "Content-Type": "application/json",
        }

    def get(self, path: str, params: dict = None) -> dict:
        """Send a signed GET request"""
        from urllib.parse import urlencode
        query_string = urlencode(params) if params else ""
        headers = self.sign("GET", path, params=query_string)
        url = f"{self.base_url}{path}"
        if query_string:
            url += f"?{query_string}"
        return requests.get(url, headers=headers).json()

    def post(self, path: str, data: dict = None) -> dict:
        """Send a signed POST request"""
        body = json.dumps(data, ensure_ascii=False) if data else ""
        headers = self.sign("POST", path, body=body)
        return requests.post(
            f"{self.base_url}{path}", headers=headers, data=body
        ).json()


# Usage example
if __name__ == "__main__":
    signer = NBTSigner(
        api_key="your_api_key",
        api_secret="your_api_secret_hex"
    )

    # GET request example
    result = signer.get("/nps/balance", {"wallet_id": "your_wallet_id"})
    print("Balance:", result)

    # POST request example
    result = signer.post("/nps/address", {
        "wallet_id": "your_wallet_id",
        "chain_id": "BASE_ETH",
        "user_token": "user_123"
    })
    print("Address:", result)