NAV

Introduction

Copper platform offers a powerful API to provide integration with your applications. This documentation describes composition and usage of all API endpoints.

To stay informed on new methods as well as changes in actual endpoints, please check this documentation regularly.

Contents

Contents of this API documentation are stated on the left panel.

API methods

To learn more about specific endpoints of Copper API, refer to following sections:

Copper Unlimited Online

Copper also provides an alternative to Copper Unlimited desktop app: a dockerised application which can be deployed independently and provide swift signing of transactions.

Follow the guide stated in the Copper Unlimited Online section to configure and deploy Copper Unlimited Online for your application.

Updates

To keep track of all changes related to the Copper platform API, refer to the changelog of this documentation.

Getting started

+ PATCH /platform/orders/{orderId}

+ Header
  Content-Type: application/vnd.cancel-order+json

Copper API is based on the REST API interface provided for data exchange between a client and a server with the use of HTTPS requests and responses.

Copper API utilises three types of requests: GET, POST and PATCH. All data is sent and received as JSON. Examples in this documentation will reflect the actual method endpoint.

By default, the request should include a Content-Type header set as application/json. Some requests require different header fields, as well as other Content-Type values. In this case, a proper header will be stated in an example (see the right panel).

You can try our API using Postman.

To do this, use our Postman API collection.

Authorisation

#!bash

API_KEY='ksgJrNOT1...i02V1hLfZs1I'
SECRET='W02cN5UDsF...SJtTyjDtq5SN'

TIMESTAMP="$(($(date +%s) * 1000))"
METHOD="GET"
URL_PATH="/platform/accounts"
BODY=""

SIGNATURE="$(echo -n "${TIMESTAMP}${METHOD}${URL_PATH}${BODY}" | openssl dgst -sha256 -hmac ${SECRET})"

curl -v "https://api.copper.co${URL_PATH}" \
  -H "Authorization: ApiKey ${API_KEY}" \
  -H "Content-Type: application/json" \
  -H "X-Signature: ${SIGNATURE}" \
  -H "X-Timestamp: ${TIMESTAMP}"
#!python

import hashlib
import hmac
import requests
import time

ApiKey = 'ksgJrNOT1X...i02V1hLfZs1I'
Secret = 'W02cN5UDsF...SJtTyjDtq5SN'

timestamp = str(round(time.time() * 1000))
method = "GET"
path = "/platform/accounts"
body = ""

signature = hmac.new(
    key=bytes(Secret, 'utf-8'),
    msg=bytes(timestamp + method + path + body, 'utf-8'),
    digestmod=hashlib.sha256
).hexdigest()

print(signature)  # example: 1b6064ca0d052d1a08d831c915ead54e6c5ff17237c845dab8b8c1cb8439a9c1

url = 'https://api.copper.co' + path

resp = requests.get(url, headers={
    'Authorization': 'ApiKey ' + ApiKey,
    'X-Signature': signature,
    'X-Timestamp': timestamp
})

print(resp.json())

All Copper API methods require authorisation via Copper API key. The API key can be obtained at the Copper platform. As a result, you will receive two strings required for authentication: API key and API key secret.

Headers

To provide access to the API, all requests must contain the following headers:

Authorization: ApiKey 6a7eef41b0e160b27eb***********6af970fa77e45a8e20581e4ffd8

Signature

To sign your request, generate the X-Signature header as follows:

  1. Concantenate and pre-hash following strings:

    • X-Timestamp (value of the corresponding header);
    • HTTP request method in capitals: GET, POST or PATCH;
    • Path of a requested endpoint including additional parameters (e.g. /platform/orders?limit=1000);
    • All fields of the request body (set an empty string if a request does not include a body). For example:

    {"externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494", "orderType": "buy", "baseCurrency": "BTC", "quoteCurrency": "USD", "amount": "5"}

  2. Sign the pre-hashed strings with your API Secret using HMAC SHA256 method.

  3. Encode the generated signature in the hexadecimal format.

After this, you can use the resulting string as the request X-Signature header.

Complete examples are provided on the right panel of this page.

Important note: To run the Bash script, make it executable and run in the current shell with the use of chmod 777 ; script_name.sh.

API responses

+ Response 200 (application/json)
  {
    "orderId": "14697072",
    "externalOrderId": "ck2m90bpq000i3i5qwinf48ap",
    "status": "waiting-counterparty-approve",
    "orderType": "sell",
    "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
    "portfolioType": "trading",
    "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
    "amount": "10",
    "baseCurrency": "XRP",
    "quoteCurrency": "USD",
    "limitType": "otc",
    "priceLimit": "0.02",
    "extra": {
      "reportingCurrencyRate": "0.31",
      "counterpartyPortfolioId": "666",
      "counterpartyOrderId": "14697073",
      "daysToSettle": "0",
      "feesPercent": "0.05"
    },
    "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa",
    "organizationId": "TESTORG",
    "createdAt": "1572982234471",
    "updatedAt": "1572982234585"
  }

Successful responses are indicated with 2xx HTTP status codes.

Some responses may include a body containing data returned by Copper platform. Examples of returned fields are described in this documentation under a definite request.

+ Response 401 (application/json)
{
  "error":"incorrect-api-key",
  "message":"Incorrect API key"
}

Unless otherwise stated, invalid requests will return HTTP 4xx status codes. The returned body will also contain information about the error.

If you use an HTTP library to automate your API calls, it should be configured to provide message bodies for non-2xx requests so that you are able to read the message field from the body.

Common Error Codes

Status code Brief description Details
400 Bad Request Validation errors: empty required fields, unsupported values
401 Unauthorized Invalid API Key
403 Forbidden Access to the requested resource is denied
404 Not Found The requested endpoint has not been found
409 Conflict Validation error or the request cannot be completed due to an internal issue
500 Internal Server Error Problems with the Copper platform server

All errors have standard response format:

NB: Not all errors of the Copper API have the error field. In this case, only the message field will be returned.

Account API

Get account data

+ GET /platform/accounts

This method allows to retrieve the full volume of information on your accounts, including related portfolios and wallets. The method does not require any request fields.

Required API Key permissions: View

Make sure you have granted access to definite portfolios: you will not be able to retrieve any account information of your API key is not assigned to this account while created.

Properties

+ Response 200 OK (application/json)
  {
    "accounts": [
      {
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
        "reportingCurrency": "USD",
        "accountName": "Default Account",
        "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
        "createdAt": "1566300620914",
        "_embedded": {
          "wallets": [
            {
              "walletId": "cjzjuf9ok000b3j5hv8eu73ya",
              "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
              "currency": "BTC",
              "balance": "0",
              "reserve": "0",
              "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
              "createdAt": "1566306458090",
              "updatedAt": "1566306458090",
              "extra": {},
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "organizationId": "TESTORG",
              "_embedded": {
                "depositTargets": [
                  {
                    "targetType": "crypto",
                    "mainCurrency": "BTC",
                    "address": "1AkwMcn1akvxBPEKJixKnhKKaBoQxDPcy9"
                  }
                ]
              }
            },
            {
              "walletId": "08f49895-34ea-4804-9cfe-0644c2e68e19",
              "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
              "currency": "XRP",
              "balance": "0",
              "reserve": "0",
              "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
              "createdAt": "1567009192348",
              "updatedAt": "1567009192348",
              "extra": {},
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "organizationId": "TESTORG",
              "_embedded": {
                "depositTargets": [
                  {
                    "targetType": "crypto",
                    "mainCurrency": "XRP",
                    "address": "rQUmVCVzbN9X91UzoiUKVs3sNRtpE5xWxi",
                    "destinationTag": "1339786120"
                  }
                ]
              }
            },
            {
              "walletId": "cjzjt2cxv000d3j5hh6asqx7v",
              "portfolioId": "3de435b4-e03c-48ab-a40c-cc2571bd9955",
              "currency": "BTC",
              "balance": "0",
              "reserve": "0",
              "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
              "createdAt": "1566304176754",
              "updatedAt": "1572979747481",
              "extra": {},
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "organizationId": "TESTORG",
              "_embedded": {
                "depositTargets": [
                  {
                    "targetType": "crypto",
                    "mainCurrency": "BTC",
                    "address": "1K853Hd32yiSJcZc1KQoXVpcxAk21KwLPt"
                  }
                ]
              }
            },
            {
              "walletId": "ck0h1dan6000b3j5nfekpgi6x",
              "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
              "currency": "USD",
              "balance": "0",
              "reserve": "0",
              "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
              "createdAt": "1568313507384",
              "updatedAt": "1568313507384",
              "extra": {},
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "organizationId": "TESTORG",
              "_embedded": {
                "depositTargets": [
                  {
                    "targetType": "bank-account",
                    "accountName": "Copper Technologies (UK) Limited",
                    "recipientAddress": "1-4 Argyll Street, London W1F 7LD United Kingdom",
                    "iban": "-",
                    "swiftCode": "SIGNUS33XXX",
                    "aba": "026013576",
                    "bankName": "Signature Bank",
                    "bankAddress": "565 Fifth Avenue New York NY 10017",
                    "accountNumber": "1503750496",
                    "referenceNumber": "TESTORGQWJ89N"
                  },
                  {
                    "targetType": "bank-account",
                    "accountName": "Dolfin Financial Client Money Account",
                    "recipientAddress": "50 Berkeley Street, London W1J 8HA",
                    "iban": "GB77MYMB23058019927587",
                    "swiftCode": "MYMBGB2L",
                    "aba": "-",
                    "bankName": "Metro Bank plc",
                    "bankAddress": "1 Southampton Row, London WC1B 5HA",
                    "accountNumber": "19927587",
                    "referenceNumber": "Credit to CLN1988 TESTORGQWJ89N"
                  },
                  {
                    "targetType": "bank-account",
                    "accountName": "Signet",
                    "recipientAddress": "-",
                    "iban": "-",
                    "swiftCode": "-",
                    "aba": "-",
                    "bankName": "-",
                    "bankAddress": "-",
                    "accountNumber": "0x207f012ce4882f9bcd56d5907a3cf411f402437f",
                    "referenceNumber": "TESTORGQWJ89N"
                  },
                  {
                    "targetType": "bank-account",
                    "accountName": "Silvergate",
                    "recipientAddress": "Coming soon!",
                    "iban": "-",
                    "swiftCode": "-",
                    "aba": "-",
                    "bankName": "-",
                    "bankAddress": "-",
                    "accountNumber": "-",
                    "referenceNumber": ""
                  },
                  {
                    "targetType": "bank-account",
                    "accountName": "SEN",
                    "recipientAddress": "Coming soon!",
                    "iban": "-",
                    "swiftCode": "-",
                    "aba": "-",
                    "bankName": "-",
                    "bankAddress": "-",
                    "accountNumber": "-",
                    "referenceNumber": ""
                  }
                ]
              }
            },
            {
              "walletId": "ck0m6345z000d3j5n4v0dmfuj",
              "portfolioId": "c98af32b-c3e9-4bfb-972e-7e413bb5ce7e",
              "currency": "BNB",
              "mainCurrency": "BNB",
              "balance": "0.0000000",
              "reserve": "0.00000000",
              "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
              "createdAt": "1568623763772",
              "updatedAt": "1568623763772",
              "extra": {
              },
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "organizationId": "TESTORG",
              "_embedded": {
                "depositTargets": [
                  {
                    "targetType": "crypto",
                    "mainCurrency": "BNB",
                    "address": "bnb1evas9qm5xj38xek2klmq2u49qf5cg8g0u82s4c"
                  }
                ]
              }
            }
          ],
          "portfolios": [
            {
              "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "portfolioName": "Default Trading",
              "portfolioType": "trading",
              "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
              "createdAt": "1566300620921",
              "updatedAt": "1566300620921",
              "isActive": true,
              "organizationId": "TESTORG",
              "extra": {}
            },
            {
              "portfolioId": "c98af32b-c3e9-4bfb-972e-7e413bb5ce7e",
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "portfolioName": "Default Vault",
              "portfolioType": "custody",
              "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
              "createdAt": "1566300620925",
              "updatedAt": "1566300620925",
              "isActive": true,
              "organizationId": "TESTORG",
              "extra": {}
            },
            {
              "portfolioId": "3de435b4-e03c-48ab-a40c-cc2571bd9955",
              "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
              "portfolioName": "Bittrex",
              "portfolioType": "external",
              "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
              "createdAt": "1566300770963",
              "updatedAt": "1566300770963",
              "isActive": true,
              "organizationId": "TESTORG",
              "extra": {
                "exchange": "bittrex"
              }
            }
          ]
        }
      }
    ]
  }

Request

The method request can include following parameters:

Parameter Data type Description
organizationId Optional<String> Unique identifier of an organisation including this account
isArchived Optional<Boolean> false (default value) - the requested account is active, true - the requested account is archived
portfolioType Optional<PortfolioType> Filter the accounts by portfolio type (see the variants below)

Response

The main field of the method response is "accounts" including following model:

Field Data type Description
accountId String Unique account identifier
organizationId Optional<String> Unique identifier of an organisation including this account
reportingCurrency Currency Currency code used for reports
accountName String Name of the account
createdBy String User ID of account creator
createdAt Long Time of account creation
updatedAt Optional<Long> Time of last account update
updatedBy Optional<String> User ID of last account updater

Each account field includes an "_embedded" section which contains information on account's "wallets" and "portfolios":

Field Data type Description
walletId String Unique wallet identifier
portfolioId String Unique portfolio identifier that includes this wallet
currency Currency Wallet currency
mainCurrency Optional<Currency> Currency of main blockchain of the vault (e.g. For USDT, it could be either ETH or BTC)
balance String Current total balance
reserve String Reserved balance
createdBy String User ID of wallet creator
updatedBy Optional<String> User ID of the last wallet updater
createdAt String Time of wallet creation
updatedAt Optional<String> Time of the latest wallet update
extra WalletExtra Additional wallet data (includes the WalletExtra model below)
accountId String unique account identifier that includes this wallet
organizationId Optional<String> Unique identifier of an organisation including this wallet
_embedded Optional<WalletEmbedded> Additional information on the wallet (includes the WalletEmbedded model below)

WalletExtra

Field Data type Description
externalAccountId Optional<String> Third-party identifier (ID of an external account)

WalletEmbedded

Field Data type Description
depositTargets List<DepositTarget> List of deposit targets attached to the wallet (includes the DepositTarget model below)

DepositTarget

Field Data type Description
targetType String Type of the deposit target: may be crypto or bank-account

For crypto targetType:

Field Data type Description
mainCurrency Optional<Currency> Currency of the main blockchain (e.g. BTC or ETH for USDT currency)
address Optional<String> Blockchain address
destinationTag Optional<Long> Destination tag (for XRP addresses)
memo Optional<String> Address memo (if any)

For bank-account targetType, the fields contain information according to the bank account details:

Field Data type Description
accountName Optional<String> Bank account name
recipientAddress Optional<String> Recipient address
iban Optional<String> Bank IBAN
swiftCode Optional<String> Bank SWIFT
aba Optional<String> Bank ABA number (for U.S. banks)
bankName Optional<String> Bank name
bankAddress Optional<String> Bank address
accountNumber Optional<String> Bank account number
referenceNumber Optional<String> Bank account reference number
billingAddress Optional<String> Bank billing address
sortCode Optional<String> Bank sort code

Portfolio

Field Data type Description
portfolioId String Unique portfolio identifier
accountId String Unique identifier of the account including this portfolio
portfolioName String Portfolio name
portfolioType Enum<PortfolioType> Type of the portfolio (see the PortfolioType list below)
createdBy String User ID of the portfolio creator
updatedBy Optional<String> User ID of the last portfolio updater
createdAt Long Time of portfolio creation
updatedAt Optional<String> Time of the last portfolio update
isActive Boolean Boolean flag showing is portfolio active (true) or archived (false)
organizationId Optional<String> Unique identifier of the organisation including this portfolio
extra PortfolioExtra Additional portfolio data (see the PortfolioExtra model below)

PortfolioType Enum with following values (may be changed in future):

PortfolioExtra

Field Data type Description
exchange Optional<Exchange> External portfolio exchange (see the Exchange list below)
exchangeWalletType Optional<ExchangeWalletType> External portfolio exchange type (see the ExchangeWalletType list below)
tradingKeys Optional<Map<String, ExternalTradingKey>> Trading keys for the external portfolio (see the ExternalTradingKey model below)
viewKeys Optional<Map<String, ExternalViewKey>> View keys of the external portfolio (see the ExternalViewKey model below)
parentPortfolioId Optional<String> Identifier of a parent portfolio, if any
usdWithdrawalLimit Optional<BigDecimal> Withdrawal limit of the portfolio in USD
baseCurrency Optional<Currency> Base currency for external accounts that use margin pair
quoteCurrency Optional<Currency> Quote currency for external account that use margin pair
showWalletBalance Optional<BalanceType> Type of balance demonstrated for the external account (see the BalanceType list below)
externalAccountId Optional<String> Identifier of an external third-party account related to the portfolio

Exchange

String with following possible values (may be changed in future):

ExchangeWalletType

Enum with following values (may be changed in future):

ExternalTradingKey

Field Data type Description
tradingKey String Public part of trading key

ExternalViewKey

Field Data type Description
viewKey String public part of view only key

BalanceType Enum with following values (may be changed in future):

Get portfolio with its wallets

+ GET /platform/portfolios/{portfolioId}

This method allows to retrieve information about a definite portfolio according to the portfolio identifier. Information about each portfolio includes data of all wallets related to the portfolio. The method does not require any request fields.

Required API Key permissions: View

Make sure you have granted access to definite portfolios: you will not be able to retrieve any account information of your API key is not assigned to this account while created.

Properties

+ Response 200 (application/json)
  {
    "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
    "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
    "portfolioName": "Default Trading",
    "portfolioType": "trading",
    "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
    "createdAt": "1566300620921",
    "updatedAt": "1566300620921",
    "isActive": true,
    "organizationId": "TESTORG",
    "extra": {},
    "_embedded": {
      "wallets": [
        {
          "walletId": "cjzjuf9ok000b3j5hv8eu73ya",
          "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
          "currency": "BTC",
          "balance": "130.45",
          "reserve": "10.45",
          "available": "120",
          "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
          "createdAt": "1566306458090",
          "updatedAt": "1566306458090",
          "extra": {},
          "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
          "organizationId": "TESTORG",
          "_embedded": {
            "depositTargets": [
              {
                "targetType": "crypto",
                "mainCurrency": "BTC",
                "address": "1AkwMcn1akvxBPEKJixKnhKKaBoQxDPcy9"
              }
            ]
          }
        },
        {
          "walletId": "08f49895-34ea-4804-9cfe-0644c2e68e19",
          "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
          "currency": "XRP",
          "balance": "12",
          "reserve": "0",
          "available": "12",
          "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
          "createdAt": "1567009192348",
          "updatedAt": "1567009192348",
          "extra": {},
          "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
          "organizationId": "TESTORG",
          "_embedded": {
            "depositTargets": [
              {
                "targetType": "crypto",
                "mainCurrency": "XRP",
                "address": "rQUmVCVzbN9X91UzoiUKVs3sNRtpE5xWxi",
                "destinationTag": "1339786120"
              }
            ]
          }
        }
      ]
    }
  }

Request

The portfolioId parameter is mandatory.

The method request can also include following optional parameters:

Parameter Data type Description
organizationId Optional<String> Unique identifier of an organisation including the requested portfolio
isArchived Optional<Boolean> false (default value) - the requested account is active, true - the requested account is archived

Response

The main field of the method is "portfolio" including following model:

Field Data type Description
portfolioId String Unique portfolio identifier
accountId String Unique identifier of the account including this portfolio
portfolioName String Portfolio name
portfolioType Enum<PortfolioType> Type of the portfolio (see the PortfolioType list below)
createdBy String User ID of the portfolio creator
updatedBy Optional<String> User ID of the last portfolio updater
createdAt Long Time of portfolio creation
updatedAt Optional<Long> Time of the last portfolio update
isActive Boolean Boolean flag showing is portfolio active (true) or archived (false)
organizationId Optional<String> Unique identifier of the organisation including this portfolio
extra PortfolioExtra Additional portfolio data (see the PortfolioExtra model below)

PortfolioType Enum with following values (may be changed in future):

PortfolioExtra

Field Data type Description
exchange Optional<Exchange> External portfolio exchange (see the Exchange list below)
exchangeWalletType Optional<ExchangeWalletType> External portfolio exchange type (see the ExchangeWalletType list below)
tradingKeys Optional<Map<String, ExternalTradingKey>> Trading keys for the external portfolio (see the ExternalTradingKey model below)
viewKeys Optional<Map<String, ExternalViewKey>> View keys of the external portfolio (see the ExternalViewKey model below)
bitstampId Optional<String> Identifier of the external Bitstamp account (for Bitstamp accounts)
parentPortfolioId Optional<String> Identifier of a parent portfolio, if any
deribitAccountId Optional<String> Identifier of the external Deribit account (for Deribit accounts)
huobiAccountId Optional<String> Identifier of the external Huobi account (for Huobi accounts)
usdWithdrawalLimit Optional<BigDecimal> Withdrawal limit of the portfolio in USD
baseCurrency Optional<Currency> Base currency for external accounts that use margin pair
quoteCurrency Optional<Currency> Quote currency for external account that use margin pair
showWalletBalance Optional<BalanceType> Type of balance demonstrated for the external account (see the BalanceType list below)
externalAccountId Optional<String> Identifier of an external third-party account related to the portfolio

Exchange

String with following values (may be changed in future):

ExchangeWalletType

String with following values (may be changed in future):

ExternalTradingKey

Field Data type Description
tradingKey String Public part of trading key

ExternalViewKey

Field Data type Description
viewKey String public part of view only key

BalanceType Enum with following values (may be changed in future):

Each account field includes an "_embedded" section which contains information on account's "wallets":

Field Data type Description
walletId String Unique wallet identifier
portfolioId String Unique portfolio identifier that includes this wallet
currency Currency Wallet currency
mainCurrency Optional<Currency> Currency of main blockchain of the vault (e.g. For USDT, it could be either ETH or BTC)
balance BigDecimal Current total balance
reserve BigDecimal Reserved balance
createdBy String User ID of wallet creator
updatedBy Optional<String> User ID of the last wallet updater
createdAt Long Time of wallet creation
updatedAt Optional<Long> Time of the latest wallet update
extra WalletExtra Additional wallet data (includes the WalletExtra model below)
accountId String unique account identifier that includes this wallet
organizationId Optional<String> Unique identifier of an organisation including this wallet
_embedded Optional<WalletEmbedded> Additional information on the wallet (includes the WalletEmbedded model below)

WalletExtra

Field Data type Description
externalAccountId Optional<String> Third-party identifier (ID of an external account)

WalletEmbedded

Field Data type Description
depositTargets List<DepositTarget> List of deposit targets attached to the wallet (includes the DepositTarget model below)

DepositTarget

Field Data type Description
targetType String Type of the deposit target: may be crypto or bank-account

For crypto targetType:

Field Data type Description
mainCurrency Optional<Currency> Currency of the main blockchain (e.g. BTC or ETH for USDT currency)
address Optional<String> Blockchain address
destinationTag Optional<Long> Address destination tag
memo Optional<String> Address memo

For bank-account targetType, the fields contain information according to the bank account details:

Field Data type Description
accountName Optional<String> Bank account name
recipientAddress Optional<String> Recipient address
iban Optional<String> Bank IBAN
swiftCode Optional<String> Bank SWIFT
aba Optional<String> Bank ABA number (for U.S. banks)
bankName Optional<String> Bank name
bankAddress Optional<String> Bank address
accountNumber Optional<String> Bank account number
referenceNumber Optional<String> Bank account reference number
billingAddress Optional<String> Bank billing address
sortCode Optional<String> Bank sort code

Get wallets

+ GET /platform/wallets

This method allows to retrieve information about all wallets related to the account. It does not require any request fields.

Required API Key permissions: View

Properties

+ Response 200 (application/json)
  {
    "wallets": [
      {
        "walletId": "cjzjuf9ok000b3j5hv8eu73ya",
        "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
        "currency": "BTC",
        "balance": "0",
        "reserve": "0",
        "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
        "createdAt": "1566306458090",
        "updatedAt": "1566306458090",
        "extra": {},
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
         "_embedded": {
           "depositTargets": [
             {
               "targetType": "crypto",
               "mainCurrency": "BTC",
               "address": "1AkwMcn1akvxBPEKJixKnhKKaBoQxDPcy9"
             }
           ]
         }
      },
      {
        "walletId": "08f49895-34ea-4804-9cfe-0644c2e68e19",
        "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
        "currency": "XRP",
        "balance": "0",
        "reserve": "0",
        "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
        "createdAt": "1567009192348",
        "updatedAt": "1567009192348",
        "extra": {},
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
        "_embedded": {
          "depositTargets": [
            {
              "targetType": "crypto",
              "mainCurrency": "XRP",
              "address": "rQUmVCVzbN9X91UzoiUKVs3sNRtpE5xWxi",
              "destinationTag": "1339786120"
            }
          ]
        }
      },
      {
        "walletId": "cjzjt2cxv000d3j5hh6asqx7v",
        "portfolioId": "3de435b4-e03c-48ab-a40c-cc2571bd9955",
        "currency": "BTC",
        "balance": "0",
        "reserve": "0",
        "createdBy": "dc188f74-7f50-46e9-8925-d134f72209a8",
        "createdAt": "1566304176754",
        "updatedAt": "1572980507472",
        "extra": {},
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
        "_embedded": {
          "depositTargets": [
            {
              "targetType": "crypto",
              "mainCurrency": "BTC",
              "address": "1K853Hd32yiSJcZc1KQoXVpcxAk21KwLPt"
            }
          ]
        }
      },
      {
        "walletId": "ck0h1dan6000b3j5nfekpgi6x",
        "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
        "currency": "USD",
        "balance": "0",
        "reserve": "0",
        "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
        "createdAt": "1568313507384",
        "updatedAt": "1568313507384",
        "extra": {},
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
        "_embedded": {
          "depositTargets": [
            {
              "targetType": "bank-account",
              "accountName": "Copper Technologies (UK) Limited",
              "recipientAddress": "1-4 Argyll Street, London W1F 7LD United Kingdom",
              "iban": "-",
              "swiftCode": "SIGNUS33XXX",
              "aba": "026013576",
              "bankName": "Signature Bank",
              "bankAddress": "565 Fifth Avenue New York NY 10017",
              "accountNumber": "1503750496",
              "referenceNumber": "TESTORGQWJ89N"
            },
            {
              "targetType": "bank-account",
              "accountName": "Dolfin Financial Client Money Account",
              "recipientAddress": "50 Berkeley Street, London W1J 8HA",
              "iban": "GB77MYMB23058019927587",
              "swiftCode": "MYMBGB2L",
              "aba": "-",
              "bankName": "Metro Bank plc",
              "bankAddress": "1 Southampton Row, London WC1B 5HA",
              "accountNumber": "19927587",
              "referenceNumber": "Credit to CLN1988 TESTORGQWJ89N"
            },
            {
              "targetType": "bank-account",
              "accountName": "Signet",
              "recipientAddress": "-",
              "iban": "-",
              "swiftCode": "-",
              "aba": "-",
              "bankName": "-",
              "bankAddress": "-",
              "accountNumber": "0x207f012ce4882f9bcd56d5907a3cf411f402437f",
              "referenceNumber": "TESTORGQWJ89N"
            },
            {
              "targetType": "bank-account",
              "accountName": "Silvergate",
              "recipientAddress": "Coming soon!",
              "iban": "-",
              "swiftCode": "-",
              "aba": "-",
              "bankName": "-",
              "bankAddress": "-",
              "accountNumber": "-",
              "referenceNumber": ""
            },
            {
              "targetType": "bank-account",
              "accountName": "SEN",
              "recipientAddress": "Coming soon!",
              "iban": "-",
              "swiftCode": "-",
              "aba": "-",
              "bankName": "-",
              "bankAddress": "-",
              "accountNumber": "-",
              "referenceNumber": ""
            }
          ]
        }
      },
      {
        "walletId": "ck0m6345z000d3j5n4v0dmfuj",
        "portfolioId": "c98af32b-c3e9-4bfb-972e-7e413bb5ce7e",
        "currency": "BNB",
        "mainCurrency": "BNB",
        "balance": "0.0000000",
        "reserve": "0.00000000",
        "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921ff",
        "createdAt": "1568623763772",
        "updatedAt": "1568623763772",
        "extra": {
        },
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
        "_embedded": {
          "depositTargets": [
            {
              "targetType": "crypto",
              "mainCurrency": "BNB",
              "address": "bnb1evas9qm5xj38xek2klmq2u49qf5cg8g0u82s4c"
            }
          ]
        }
      }
    ]
  }

Request

The method request can include following optional parameters:

Parameter Data type Description
portfolioId Optional<String> Unique identifier of a portfolio
organizationId Optional<String> Unique identifier of an organisation including the requested portfolio
includeOutstandingBalance Optional<Boolean> Show outstanding balances of a wallet

Response

The main field of the method response is "wallets" including following model:

Field Data type Description
walletId String Unique wallet identifier
portfolioId String Unique portfolio identifier that includes this wallet
currency Currency Wallet currency
mainCurrency Optional<Currency> Currency of main blockchain of the vault (e.g. For USDT, it could be either ETH or BTC)
balance BigDecimal Current total balance
reserve BigDecimal Reserved balance
createdBy String User ID of wallet creator
updatedBy Optional<String> User ID of the last wallet updater
createdAt Long Time of wallet creation
updatedAt Optional<Long> Time of the latest wallet update
extra WalletExtra Additional wallet data (includes the WalletExtra model below)
accountId String unique account identifier that includes this wallet
organizationId Optional<String> Unique identifier of an organisation including this wallet
_embedded Optional<WalletEmbedded> Additional information on the wallet (includes the WalletEmbedded model below)

WalletExtra

Field Data type Description
externalAccountId Optional<String> Third-party identifier (ID of an external account)

WalletEmbedded

Field Data type Description
depositTargets List<DepositTarget> List of deposit targets attached to the wallet (includes the DepositTarget model below)
outstandingBalance BigDecimal Amount of outstanding balances, if any

DepositTarget

Field Data type Description
targetType String Type of the deposit target: may be crypto or bank-account

For crypto targetType:

Field Data type Description
mainCurrency Optional<Currency> Currency of the main blockchain (e.g. BTC or ETH for USDT currency)
address Optional<String> Blockchain address
destinationTag Optional<Long> Address destination tag
memo Optional<String> Address memo

For bank-account targetType, the fields contain information according to the bank account details:

Field Data type Description
accountName Optional<String> Bank account name
recipientAddress Optional<String> Recipient address
iban Optional<String> Bank IBAN
swiftCode Optional<String> Bank SWIFT
aba Optional<String> Bank ABA number (for U.S. banks)
bankName Optional<String> Bank name
bankAddress Optional<String> Bank address
accountNumber Optional<String> Bank account number
referenceNumber Optional<String> Bank account reference number
billingAddress Optional<String> Bank billing address
sortCode Optional<String> Bank sort code

Get whitelisted bank accounts

+ GET /platform/bank-accounts

This method allows to retrieve information about all bank accounts for fiat withdraw, whitelisted in your organisation on the Copper platform. The fields of the method response include full bank account details.

The method does not require any request fields.

Required API Key permissions: View

Make sure you have granted access to definite portfolios: you will not be able to retrieve any account information of your API key is not assigned to this account while created.

Properties

+ Response 200 (application/json)
  {
    "bankAccounts": [
      {
        "bankAccountId": "cjzjqt53c00063j5hgp7c6rya",
        "bankAccountType": "international",
        "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
        "organizationId": "TESTORG",
        "bankAccountName": "TSK",
        "beneficiaryAccountName": "AccName",
        "beneficiaryAccountAddress": "AccAdress",
        "beneficiaryAccountPostalCode": "AccPostalCode",
        "beneficiaryAccountCity": "AccPostalCity",
        "beneficiaryAccountCountry": "BD",
        "iban": "ibannumber",
        "swift": "swiftnumber",
        "bankName": "BankName",
        "bankAddress": "BankAdress",
        "bankPostalCode": "BankPostalCode",
        "bankCity": "PostalCity",
        "bankCountry": "AL",
        "createdBy": "0802703c-11d4-4e49-8b9b-d0c909301709",
        "updatedBy": "0802703c-11d4-4e49-8b9b-d0c909301709",
        "createdAt": "1566300620934",
        "updatedAt": "1569402415337",
        "coinbasePaymentReference": "coinbaseRef",
        "senId": "senNum",
        "senDescription": "senDesc",
        "comment": "test"
      }
    ]
  }

Request

The method request does not have any optional parameters.

Response

The main field of the method response is "bank-account" including following model:

Field Data type Description
bankAccountId String Unique bank account identifier
bankAccountType BankAccountType Type of the bank account (see the BankAccountType below)
accountId String Unique account identifier
organizationId Optional<String> Unique identifier of the organisation including the related account
bankAccountName Optional<String> Bank account name
beneficiaryAccountName Optional<String> Beneficiary account name
beneficiaryAccountAddress Optional<String> Beneficiary account address
beneficiaryAccountPostalCode Optional<String> Beneficiary account postal code
beneficiaryAccountCity Optional<String> Beneficiary account city
beneficiaryAccountCountry Optional<String> Beneficiary account country
iban Optional<String> Bank IBAN
swift Optional<String> Bank SWIFT
bankName Optional<String> Bank name
bankAddress Optional<String> Bank address
bankPostalCode Optional<String> Bank postal code
bankCity Optional<String> Bank city
bankCountry Optional<String> Bank country
lastUsedAt Optional<Long> Time of last account usage
createdBy String User ID of the bank account creator
updatedBy Optional<String> User ID of the bank account updater
createdAt Long Time of bank account creation
updatedAt Optional<Long> Time of last bank account update
coinbasePaymentReference Optional<String> Coinbase bank account ID for this bank account
senId Optional<String> Silvergate Network ID for this bank account
senDescription Optional<String> Silvergate Network description for this bank account
comment Optional<String> Additional comments for this bank account

BankAccountType Enum with following values (may be changed in future):

CryptoAddresses

Field Data type Description
cryptoAddresses List<CryptoAddress>

CryptoAddress

Field Data type Description
cryptoAddressId String Unique crypto address identifier
accountId String Unique account identifier
organizationId Optional<String> Unique identifier of the organisation including the related account
currency Currency Crypto address currency
mainCurrency Optional<Currency Currency of main blockchain (e.g. may be BTC or ETH for USDT currency)
name String Crypto address name
address String
destinationTag Optional<Long> Destination tag (for XRP addresses)
memo Optional<String> Address memo (if any)
lastUsedAt Optional<Long> Time of last usage of the crypto address
createdBy String User ID of the crypto address creator
updatedBy Optional<String> User ID of the last crypto address updater
createdAt Long Time of crypto address creation
updatedAt Optional<Long> Time of last crypto address update

Get whitelisted crypto addresses

+ GET /platform/crypto-addresses

This method allows to retrieve information about all whitelisted crypto addresses related to the account. The method does not require any request fields.

Required permissions: View Make sure you have granted access to definite portfolios: you will not be able to retrieve any account information of your API key is not assigned to this account while created.

Properties

+ Response 200 (application/json)
{
  'cryptoAddresses': [
    {
      'accountId': 'c0576ce4-00aa-4bdc-82fb-c4101fbe491b',
      'address': 'SomeBTCwalletAddress',
      'createdAt': '1567522689656',
      'createdBy': 'd4248500-5f57-4199-8f5e-6512ff075a52',
      'cryptoAddressId': 'ck03yjay5000a215urupkajfa',
      'currency': 'BTC',
      'isWhitelist': True,
      'lastUsedAt': '1606237167221',
      'mainCurrency': 'BTC',
      'name': 'SomeBTCwallet',
      'organizationId': '123456'
    }
  ]
}

Request

The method request does not have any optional parameters.

Response

The main field of the method response is "CryptoAddresses" including following model:

Field Data type Description
cryptoAddressId String Unique crypto address identifier
accountId String Unique account identifier
organizationId Optional<String> Unique organization identifier
currency Currency Crypto address currency
mainCurrency Optional<Currency Currency of main blockchain (e.g. may be BTC or ETH for USDT currency)
name String Name of the crypto address
address String Address string
destinationTag Optional<Long> Destination tag (for XRP addresses)
memo Optional<String> Address memo (if any)
lastUsedAt Optional<Long> Time of last usage of the crypto address
createdBy String User ID of the crypto address creator
updatedBy Optional<String> User ID of the crypto address creator
createdAt Long Time of crypto address creation
updatedAt Optional<Long> Time of the last crypto address update

Download account reports

+ POST /platform/reports/wallets/{report-type}

This method is designed for generation of an account report. The method required the report-type string in the endpoint:

Request

The request body of this method includes following fields:

Field Data type Description
dateFrom String Date of the report initial entry (in the DDMMYYYY format). Mandatory field
dateTo String Date of the report last entry (in the DDMMYYYY format). Mandatory field
organizationId Optional<String> Filter entries by a definite organisation identifier
organizationId Optional<String> Filter entries by a definite portfolio identifier
portfolioIds Optional<Set<String>> Filter entries by a number of portfolio identifiers
portfolioTypes Optional<Set<PortfolioType>> Filter entries by a number of portfolioTypes (see below)

PortfolioType Enum with following values (may be changed in future):

Response

The return field of the method is "fileID" string containing the relative path to the generated report.

+ Response 201 Created
  {
    "fileId": "wallets-snapshots/30c1464a6774d85b1a5802d15826c7ad.xlsx"
  }

To download the generated report, use the subsequent method GET /platform/files/{fileId}. In response, you will receive the binary content of the file.

Note: You may receive a 404 (Not Found Error), even if the relative path is correct. This occurs while the report is not fully generated. Carry on pulling this route until you receive the 200 OK response.

Trading API

Get token pairs for trading

+ GET /platform/pairs?eotc=true

+ Response 200 OK
  {
    "currenciesPairs": [
      {
        "baseCurrency": "AAVE",
        "quoteCurrency": "BTC",
        "tags": [
          "stream",
          "rfq"
        ]
      },
      {
        "baseCurrency": "AAVE",
        "quoteCurrency": "USD",
        "tags": [
          "rfq"
        ]
      }
    ]
  }

This method allows to obtain the token pairs available for trading operations.

Required API Key permissions: View

Request

The method request can include the boolean eotc parameter for filtering. It specifies if a definite token pair is available for EOTC orders.

Response

The method response includes the currenciesPairs with following fields:

Field Data type Description
baseCurrency Currency Base currency
quoteCurrency Currency Quote currency
tags Array<String> Tags reflecting availability of the token pair for eotc and rfq orders

tags

The tags field can include following:

Place a trading offer


# Placing an offer

+ POST /platform/offers

+ Request
  {
    "portfolioId": "oishiphoosaipho9ooTikohk5foo4Wah",   # The portfolioId you want to trade with
    "limitType": "rfq",
    "orderType": "buy",     # "buy" or "sell"
    "baseCurrency": "BTC",
    "quoteCurrency": "USD",
    "amount": "0.01"
  } 

+ Response 201 Created
{
    "offerId": "284775",
    "status": "new",
    "orderType": "sell",
    "limitType": "rfq",
    "portfolioId": "182be0c5cdcd5072bb1864cdee4d3d6e",
    "amount": "0.01",
    "baseCurrency": "BTC",
    "quoteCurrency": "USD",
    "feesPercent": "0.05",
    "createdBy": "f68fd5f7-d740-47fe-8673-80e6111112eb",
    "createdAt": "1634819150709",
    "expiredAt": "1634819750709"
}

This method allows to place a trading offer to buy or sell currency.

Required API Key permissions: Trading

Request

To place a trading offer, the method should include following fields:

Field Data type Description
portfolioId String Identifier of the portfolio to trade from
limitType LimitType Limit type (see below)
orderType OrderType buy or sell
baseCurrency Currency Base currency
quoteCurrency Currency Quote currency
amount BigDecimal Amount of tokens for the trading offer
quoteAmount BigDecimal Quote amount for the trading offer. Can be used to request a token price instead of the amount field.

limitType

The limitType field can include following limit types:

To get the price of the placed offer, this method does not require any additional fields, but requires the offerId parameter of the placed offer.

Response

In the response, the method returns following fields:

Field Data type Description
offer String Identifier of the placed offer
limitType LimitType Limit type (see below)
orderType OrderType buy or sell
baseCurrency String Base currency
quoteCurrency String Quote currency
amount BigDecimal Amount of tokens for the trading offer
quoteAmount BigDecimal Quote amount for the trading offer. Can be used to request a token price instead of the amount field.

Get the price of the placed offer

+ GET /platform/offers/{offerId}

+ Response 200 OK

  {
      "offerId": "284775",
      "status": "canceled",    # May be "new", "waiting", "working" and "canceled"
      "orderType": "sell",
      "limitType": "rfq",
      "portfolioId": "182be0c5cdcd5072bb1864cdee4d3d6e",
      "amount": "0.01",
      "quoteAmount": "647.81990000",
      "baseCurrency": "BTC",
      "quoteCurrency": "USD",
      "price": "64781.99",
      "feesPercent": "0.05",
      "createdBy": "f68fd5f7-d740-47fe-8673-80e6111112eb",
      "createdAt": "1634819150709",   # Creation time, timestamp in milliseconds
      "expiredAt": "1634819157222"    # Expiration time, timestamp in milliseconds
  }

This method allows to get the price and additional data of the placed offer.

Required permissions: View

Create buy/sell order

+ POST /platform/orders

+ Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
    "offerId": "8822",
    "orderType": "buy",
    "baseCurrency": "BTC",
    "quoteCurrency": "USD",
    "amount": "5",
    "portfolioId": "oishiphoosaipho9ooTikohk5foo4Wah",
    "limitType": "rfq",
    "description": "Some description"
  }
+ Response 201 (application/json)
  {
    "orderId": "28",
    "externalOrderId": "B9185DA7-EBC4-467B-B515-0B8D95B5D624",
    "baseCurrency": "BTC",
    "quoteCurrency": "USD",
    "orderType": "buy",
    "amount": "5",
    "status": "executed",
    "portfolioId": "oishiphoosaipho9ooTikohk5foo4Wah",
    "organizationId": "1234567890",
    "limitType": "rfq",
    "priceLimit": "64045.67",
    "createdAt": "1536854681576",
    "createdBy": "test-user1",
    "extra": {}
  }

This method allows to create an order to buy or sell cryptocurrency.

Required API Key permissions: Trading

Properties

Request

This request should include the CreateOrder model specific for trading:

Field Data type Description
externalOrderId String Unique order identifier from client (should be unique for the portfolio)
orderType OrderType Order type: buy or sell
portfolioId String Unique identifier of the portfolio, for which the order will be created
baseCurrency Currency Base currency
quoteCurrency Currency Quote currency
limitType LimitType Limit type
amount BigDecimal Amount of tokens for the order
quoteAmount BigDecimal Quote amount for the order. Can be used to request a token price instead of the amount field
offerId String Offer Id
description String Arbitrary description allowing to identify an order.

limitType

The limitType field can include following limit types:

Response

The response of the method includes the Order model:

Field Data type Description
orderId String Unique order identifier generated upon its creation
externalOrderId String Unique order identifier passed in the request
status OrderStatus Operating status of the order
orderType OrderType Order type: buy or sell
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
quoteCurrency Currency Trading quote currency
limitType LimitType Limit type (see above)
priceLimit BigDecimal Limit value for order with the corresponding limitType
extra OrderExtra Additional order data
createdBy String User ID of the order creator
organizationId String Unique ID of the organisation of the creator
createdAt Long Time of order creation

status The status field can include following order statuses:

Status Description
error something went wrong, see the errorDescription field
new order has been created.
reserved required amount of funds has been reserved on the balance (for withdraw, buy and sell orders only)
working order processing
waiting-approve awaiting administrator approval (for deposit and withdrawal orders)
co-sign-require order still needs to be co-signed by an authorised organisation member
approved deposit or withdraw order has been approved by Copper’s admin, and will be processed shortly
processing waiting for the minimum required number of network confirmations from the blockchain (for withdraw orders)
executed order is completed
canceled order has been cancelled
part-signed-tx-added partly-signed transaction has been added for a Vault order
full-signed-tx-added fully-signed transaction has been added for a Vault order
rejected-part-signed-tx-added after rejected: a rejected part-signed transaction has been added for a Vault order
rejected-full-signed-tx-added after rejected: a rejected fully-signed transaction has been added for a Vault order
awaiting-settlement a Vault order is waiting for settlement (as a rule, requires a user action: press the Start settlement button in the UI)

master-password-required - a Vault order requires a master password from the user to proceed rejected | a request has been rejected by Copper’s admin, now waiting for rejection transaction signature waiting-counterparty-approve | awaiting counterparty to approve OTC order require-initializer-approve | an OTC requires approval of its initializer require-counterparty-approve | new OTC order requires counterparty approval settled | an OTC order has been settled

Cancel order

+ PATCH /platform/orders/{orderId}

+ Header
  Content-Type: application/vnd.cancel-order+json

This method allows to cancel an issued order. The method does not require any additional fields.

Required permissions: Trading

Properties

Request

Response

This method does not return any fields in response.

Get latest orders

+ GET /platform/orders?baseCurrency=BTC&limit=1000&offset=0

This method allows to obtain the latest placed orders.

Required permissions: View

Properties

+ Response 200 (application/json)
  {
    "orders": [
      {
        "orderId": "412341",
        "externalOrderId": "F7FCCFD3-B61B-4467-B456-XXXX",
        "portfolioId": "330354E8-53F2-4FC9-826C-8CA4D74FC509", 
        "orderType": "buy",
        "limitType": "market",
        "priceLimit": "0",
        "baseCurrency": "BTC",
        "mainCurrency": "BTC",
        "status": "executed", 
        "amount": "0.00078656",
        "createdAt": "1551426613000",
        "updatedAt": "1551426613000",
        "createdBy": "uid",
        "extra": {
          "trades": [
            {
              "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
              "tradeId": "B61B-4467-B456"
              "orderId": "B0FC27CE4494",
              "baseCurrency": "BTC",
              "quoteCurrency": "USD",
              "amount": "1000",
              "price": "8700",
              "createdAt": "1562257877000"
            }
          ]
        }
      }
    ]
  }

Request

The request of the method can have following optional parameters in its endpoint:

Parameter Data type Description
externalOrderId optional <String> Filter by external order ID: in this case, the list will be returned with one item or empty if nothing is found
organizationId optional <String> Filter by organization ID: in this case, the list will be returned with one item or empty if nothing is found
portfolioId optional <String> Return orders that are related to this portfolio
currency optional <String> Filter by the order currency
orderType optional <String> Filter by order type: buy, sell, deposit, withdraw
limitType optional <String> Filter by limit type (see below)
limit optional <Integer> Limit output of the orders: 1000 by default, max. 2000
offset optional <Integer> an offset between the beginning of the deposit target list and a first displayed element; 0 by default
isArchived Optional<Boolean> false (default value) - the requested account is active, true - the requested account is archived
updatedSince optional <String> Timestamp in milliseconds returning all orders updated since a requested timetamp and sorted in ASC (oldest first)
createdSince optional <String> Timestamp in milliseconds returning all orders created since a requested timetamp and sorted in ASC (oldest first)
terminatedAtFrom optional <Long> Timestamp in milliseconds returning all orders terminated since a requested timetamp and sorted in ASC (oldest first)
terminatedAtTo optional <Long> Timestamp in milliseconds returning all orders terminated before a requested timetamp and sorted in ASC (oldest first)
portfolioType Optional<String> Filter the accounts by portfolio type (see the variants below)
baseCurrency optional <String> Filter by the order base currency
quoteCurrency optional <String> Filter by the order quote currency
transferChainId optional <String> Filter by the identifier of the transfer blockchain
transactionId optional <String> Filter by the identifier of a certain transaction

If no parameters are set in the request, the response will contain the latest 1000 orders.

PortfolioType Enum with following values (may be changed in future):

limitType The limitType field can include following limit types:

Response

The response of the method contains the orders list, each order includes the fields according to the order model:

Field Data type Description
orderId String Unique order identifier generated upon its creation
externalOrderId String Unique order identifier passed in the request
status OrderStatus Operating status of the order
orderType OrderType Order type: buy or sell
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
quoteCurrency Optional<Currency> Trading quote currency
limitType LimitType Limit type (see above)
priceLimit Optional<BigDecimal> Limit value for order with the corresponding limitType
extra OrderExtra Additional order data
createdBy String User ID of the order creator
organizationId String Unique ID of the organisation of the creator
createdAt Long Time of order creation
updatedAt Optional<Long> Time of the latest order update

Settle API

Get currencies and tokens supported for trading

+ GET /platform/currencies?tags=show-trading

+ Response 200 OK:
 {
   "currencies": [
     {
       "currency": "AKRO",
       "mainCurrency": "ETH",
       "name": "Akropolis",
       "priority": "0",
       "confirmations": "30",
       "decimal": "18",
       "tags": [
         "show-trading"
       ]
     },
     {
       "currency": "ETC",
       "mainCurrency": "ETC",
       "name": "Ethereum Classic",
       "priority": "0",
       "confirmations": "120",
       "decimal": "18",
       "tags": [
         "show-trading"
       ]
     }
   ]
 }

The GET /platform/currencies method allows to obtain the list of currencies supported by the Copper platform. In order to get a list of currencies supported for trading, use the show-trading tag. The complete example is provided on the right panel.

Required permissions: View

Create settle order

+ POST /platform/orders

+ Request
 {
   "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
   "orderType": "buy", # "buy" or "sell"
   "baseCurrency": "BTC",
   "quoteCurrency": "USD",
   "amount": "5",
   "portfolioId": "46",
   "limitType": "otc",
   "priceLimit": "3300.57",
   "counterpartyPortfolioId": "53453", # Recieved counterparty portfolio ID
   "description": "Some description"
 }  
+ Response 201 (application/json)
  {
     "orderId": "35981617",
     "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
     "status": "waiting-counterparty-approve",
     "orderType": "buy",
     "portfolioId": "46",
     ...
     "extra": {
       ...
       "counterpartyOrderId": "35981618",   # A counterparty has to approve this order manually or via the API
       ...
     },
   }

Required API Key permissions: Trading

Properties

Request

This request should include the CreateOrder model specific for trading:

Field Data type Description
externalOrderId String Unique order identifier from client (should be unique for the portfolio)
orderType OrderType Order type: buy or sell
portfolioId String Unique identifier of the portfolio, for which the order will be created
counterpartyPortfolioId String Unique identifier of the portfolio, which will receive the opposite order
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
quoteCurrency Currency Trading quote currency
limitType LimitType Limit type
priceLimit BigDecimal Limit value for order with the corresponding limitType
description String Arbitrary description allowing to identify an order.

limitType

The limitType field can include following limit types:

Response

The response of the method includes the Order model:

Field Data type Description
orderId String Unique order identifier generated upon its creation
externalOrderId String Unique order identifier passed in the request
status OrderStatus Operating status of the order
orderType OrderType Order type: buy or sell
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
quoteCurrency Currency Trading quote currency
limitType LimitType Limit type (see above)
priceLimit BigDecimal Limit value for order with the corresponding limitType
extra OrderExtra Additional order data
createdBy String User ID of the order creator
organizationId String Unique ID of the organisation of the creator
createdAt Long Time of order creation
updatedAt Optional<Long> Time of the latest order update

status The status field can include following order statuses:

Status Description
error something went wrong, see the errorDescription field
new order has been created.
reserved required amount of funds has been reserved on the balance (for withdraw, buy and sell orders only)
working order processing
waiting-approve awaiting administrator approval (for deposit and withdrawal orders)
co-sign-require order still needs to be co-signed by an authorised organisation member
approved deposit or withdraw order has been approved by Copper’s admin, and will be processed shortly
processing waiting for the minimum required number of network confirmations from the blockchain (for withdraw orders)
executed order is completed
canceled order has been cancelled
part-signed-tx-added partly-signed transaction has been added for a Vault order
full-signed-tx-added fully-signed transaction has been added for a Vault order
rejected-part-signed-tx-added after rejected: a rejected part-signed transaction has been added for a Vault order
rejected-full-signed-tx-added after rejected: a rejected fully-signed transaction has been added for a Vault order
awaiting-settlement a Vault order is waiting for settlement (as a rule, requires a user action: press the Start settlement button in the UI)

master-password-required - a Vault order requires a master password from the user to proceed rejected | a request has been rejected by Copper’s admin, now waiting for rejection transaction signature waiting-counterparty-approve | awaiting counterparty to approve OTC order require-initializer-approve | an OTC requires approval of its initializer require-counterparty-approve | new OTC order requires counterparty approval settled | an OTC order has been settled

Accept an OTC order

+ PATCH /platform/orders/{counterpartyOrderId}

+ Header
  Content-Type: application/vnd.approve-counterparty-otc+json
+ Response 200 OK (application/json)

This method allows to accept an OTC order by its identifier specified in the endpoint. The method does not require any additional fields, as well as it returns only the standard success or error codes.

Required API Key permissions: Trading

Cancel an OTC order

+ PATCH /platform/orders/{orderId}

+ Header
  Content-Type: application/vnd.cancel-order+json
+ Response 200 OK (application/json)

Required API Key permissions: Trading

Transfer API

The /platform/orders endpoint of the Copper API is used not only for trading, but also for deposit and withdraw purposes. The orderType field defines the purpose of a definite order: the values for transferring assets are deposit and withdraw correspondingly.

Get latest orders

+ GET /platform/orders?baseCurrency=BTC&limit=1000&offset=0

This method allows to obtain the latest placed orders.

Required API Key permissions: View

Properties

+ Response 200 (application/json)
  {
    "orders": [
      {
        "orderId": "412341",
        "externalOrderId": "F7FCCFD3-B61B-4467-B456-XXXX",
        "portfolioId": "330354E8-53F2-4FC9-826C-8CA4D74FC509", 
        "orderType": "buy",
        "limitType": "market",
        "priceLimit": "0",
        "baseCurrency": "BTC",
        "mainCurrency": "BTC",
        "status": "executed", 
        "amount": "0.00078656",
        "createdAt": "1551426613000",
        "updatedAt": "1551426613000",
        "createdBy": "uid",
        "extra": {
          "trades": [
            {
              "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
              "tradeId": "B61B-4467-B456"
              "orderId": "B0FC27CE4494",
              "baseCurrency": "BTC",
              "quoteCurrency": "USD",
              "amount": "1000",
              "price": "8700",
              "createdAt": "1562257877000"
            }
          ]
        }
      }
    ]
  }

Request

The request of the method can have following optional parameters in its endpoint:

Parameter Data type Description
externalOrderId optional <String> Filter by external order ID: in this case, the list will be returned with one item or empty if nothing is found
organizationId optional <String> Filter by organization ID: in this case, the list will be returned with one item or empty if nothing is found
portfolioId optional <String> Return orders that are related to this portfolio
currency optional <String> Filter by the order currency
orderType optional <String> Filter by order type: deposit, withdraw
limitType optional <String> Filter by limit type (see below)
limit optional <Integer> Limit output of the orders: 1000 by default, max. 2000
offset optional <Integer> an offset between the beginning of the deposit target list and a first displayed element; 0 by default
isArchived Optional<Boolean> false (default value) - the requested account is active, true - the requested account is archived
updatedSince optional <String> Timestamp in milliseconds returning all orders updated since a requested timetamp and sorted in ASC (oldest first)
createdSince optional <String> Timestamp in milliseconds returning all orders created since a requested timetamp and sorted in ASC (oldest first)
terminatedAtFrom optional <Long> Timestamp in milliseconds returning all orders terminated since a requested timetamp and sorted in ASC (oldest first)
terminatedAtTo optional <Long> Timestamp in milliseconds returning all orders terminated before a requested timetamp and sorted in ASC (oldest first)
portfolioType Optional<String> Filter the accounts by portfolio type (see the variants below)
baseCurrency optional <String> Filter by the order base currency
quoteCurrency optional <String> Filter by the order quote currency
transferChainId optional <String> Filter by the identifier of the transfer blockchain
transactionId optional <String> Filter by the identifier of a certain transaction

If no parameters are set in the request, the response will contain the latest 1000 orders.

PortfolioType Enum with following values (may be changed in future):

limitType The limitType field can include following limit types:

Response

The response of the method contains the orders list, each order includes the fields according to the order model:

Field Data type Description
orderId String Unique order identifier generated upon its creation
externalOrderId String Unique order identifier passed in the request
status OrderStatus Operating status of the order
orderType OrderType Order type: deposit or withdraw
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
quoteCurrency Optional<Currency> Trading quote currency
limitType LimitType Limit type (see above)
priceLimit Optional<BigDecimal> Limit value for order with the corresponding limitType
extra OrderExtra Additional order data
createdBy String User ID of the order creator
organizationId String Unique ID of the organisation of the creator
createdAt Long Time of order creation
updatedAt Optional<Long> Time of the latest order update

status The status field can include following order statuses:

Status Description
error something went wrong, see the errorDescription field
new order has been created.
reserved required amount of funds has been reserved on the balance (for withdraw, buy and sell orders only)
working order processing
waiting-approve awaiting administrator approval (for deposit and withdrawal orders)
co-sign-require order still needs to be co-signed by an authorised organisation member
approved deposit or withdraw order has been approved by Copper’s admin, and will be processed shortly
processing waiting for the minimum required number of network confirmations from the blockchain (for withdraw orders)
executed order is completed
canceled order has been cancelled
rejected a request has been rejected by Copper’s admin, now waiting for rejection transaction signature

Create withdraw order

+ POST /platform/orders

This method allows to create a deposit or withdraw order on the Copper platform.

Required API Key permissions: Withdraw

Properties

+ Request (application/json)
  {
    "externalOrderId": "be70d9a8-2290-4692-9592-0fd572f6e864",
    "orderType": "withdraw",
    "baseCurrency": "XRP",
    "mainCurrency": "XRP",
    "amount": "10",
    "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
    "toAddress": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
    "description": "Some description"
  }

+ Response 201 (application/json)
  {
    "orderId": "14703607",
    "externalOrderId": "be70d9a8-2290-4692-9592-0fd572f6e864",
    "status": "co-sign-require",
    "orderType": "withdraw",
    "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
    "portfolioType": "trading",
    "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
    "amount": "10",
    "baseCurrency": "XRP",
    "mainCurrency": "XRP",
    "extra": {
      "description": "Some description",
      "toAddress": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
      "coSignersNumber": "2",
      "coSigners": [
        "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa"
      ],
      "feesPercent": "0"
    },
    "createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa",
    "organizationId": "PSHENKIN",
    "createdAt": "1572984084262",
    "updatedAt": "1572984084447"
  }

Request

This request should include the CreateOrder model specific for withdrawals:

Field Data type Description
externalOrderId String Unique order identifier from client (should be unique for the portfolio)
orderType OrderType Order type: withdraw
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency for the amount
mainCurrency Optional<Currency> Currency of main blockchain (e.g. for USDT, it could be either ETH or BTC currency)
toAddress Optional<String> Withdraw address
toCryptoAddressId Optional<String> Withdraw crypto address identifier
toBankAccountId Optional<String> Withdraw bank account identifier
toPortfolioId Optional<String> Withdraw portfolioId identifier
destinationTag Optional<Long> Withdraw destination tag
memo Optional<String> Withdraw memo
withdrawalPassword Optional<String> Withdraw password for External portfolio (sha256 hash string)
description String Arbitrary description allowing to identify an order.

Response

The response of the method includes the Order model:

Field Data type Description
orderId String Unique order identifier generated upon its creation
externalOrderId String Unique order identifier passed in the request
status OrderStatus Operating status of the order
orderType OrderType Order type: deposit or withdraw
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
mainCurrency Optional<Currency> Currency of main blockchain (e.g. for USDT, it could be either ETH or BTC currency)
extra Optional<OrderExtra> Additional order data
createdBy String User ID of the order creator
organizationId String Unique ID of the organisation of the creator
createdAt Long Time of order creation
updatedAt Optional<Long> Time of the latest order update

Cancel order

+ PATCH /platform/orders/{orderId}

+ Header
  Content-Type: application/vnd.cancel-order+json

This method allows to cancel an issued order.

Required API Key permissions: Withdraw

Properties

Request

Response

This method does not return any fields.

"Dry run" for withdrawal orders

+ POST /platform/dry-run-orders

+ Request 
  {
    "orderType": "withdraw",
    "baseCurrency": "BTC",
    "amount": "0.02",
    "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",    
    "toAddress": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6"
  }

This method allows to perform a test run of a withdraw order and check data you are going to enter. Currently, the method works for ETH itself and ETH tokens, as well as for BTC.

Required API Key permissions: Withdraw

Properties

+ Response 200
{
    "orderType": "withdraw",
    "portfolioId": "ck8owwcvj000f3j5wrjoyip4d",
    "amount": "0.0001",
    "baseCurrency": "ETH",
    "extra": {
        "toAddress": "0x023ac7b2faeb5275e1c2868d107ae38978b34764",
        "estimatedFees": {
            "fee": "0.001344",
            "estimatedTime": "600000",
            "feeCurrency": "ETH",
            "gasPriceGwei": "64",
            "gasLimit": "21000"
        }
    }
}

Request

This request should include theCreateOrder model with following basic parameters:

Field Data type Description
orderType OrderType Order type: withdraw
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency for the amount
mainCurrency Optional<Currency> Currency of main blockchain (e.g. for USDT, it could be either ETH or BTC currency)
toAddress Optional<String> Withdraw address
toCryptoAddressId Optional<String> Withdraw crypto address identifier
toBankAccountId Optional<String> Withdraw bank account identifier
toPortfolioId Optional<String> Withdraw portfolioId identifier
destinationTag Optional<Long> Withdraw destination tag
memo Optional<String> Withdraw memo
withdrawalPassword Optional<String> Withdraw password for External portfolio (sha256 hash string)

Response

The method returns the details of the dry-run order:

Field Data type Description
orderType OrderType Order type
portfolioId String Unique identifier of the portfolio, for which the order will be created
amount BigDecimal Order execution amount
baseCurrency Currency Currency of the amount
mainCurrency Optional<Currency> Currency of main blockchain (e.g. for USDT, it could be either ETH or BTC currency)
extra Optional<OrderExtra> Additional order data

Transfer API webhooks

+ POST {https://your-domain.com/webhook/path}

+ Headers:
  X-Signature: 97dee97560699a639f3cf5...9ea463
  X-Timestamp: 1567165602271

+ Request
  {
    "eventId": "test-b17c862a961fbba3a02af42a7de6e643",
    "event": "deposit-created",
    "subscriptionId": "test",
    "payload": {
      "extra": {
        "transaction": {
          "txId": "89a88991db6bd3c3c550d8d07a275748c074a3fea38eef4372e0b1096b237ab7",
          "inputs": [
            {
              "value": "1898836",
              "address": "2N4KgeDXHCnZP1XnAJsCZLR7XosMmjiQCMF"
            }
          ],
          "outputs": [
            {
              "value": "1888670",
              "address": "2Mt2TrU7nZkRxbciKxstS2egNVV1TgiwEvK",
              "txIndex": "0",
            },
            {
              "value": "10000",
              "address": "2NAdrCdqYGHR93Ft2koBXgdKbnoDmNdiS1n",
              "txIndex": "1",
            }
          ],
          "currency": "BTC",
          "isSuccess": true,
          "timestamp": "1608296004000",
          "blockHeight": "1898224",
          "mainCurrency": "BTC",
          "transactionType": "deposit"
        },
        "confirmations": "1",
        "transactionId": "89a88991db6bd3c3c550d8d07a275748c074a3fea38eef4372e0b1096b237ab7",
        "reportingCurrencyRate": "22886.1"
      },
      "amount": "0.0001",
      "status": "working",
      "orderId": "5842527",
      "accountId": "7814e6b5-ec66-47a3-b566-ed28228eec99",
      "createdAt": "1608296151293",
      "orderType": "deposit",
      "updatedAt": "1608296151308",
      "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",
      "baseCurrency": "BTC",
      "mainCurrency": "BTC",
      "portfolioType": "custody",
      "organizationId": "TEST",
      "externalOrderId": "89a88991db6bd3c3c550d8d07a275748c074a3fea38eef4372e0b1096b237ab7:BTC:1"
    },
    "createdAt": "1608296152012"
  }

Copper Transfer API allows to subscribe on definite types of events on your resource for automation of processes on the Copper platform.

Available events for Order API:

Webhook event Description
deposit-created Deposit order has been created
deposit-completed Deposit order has been completed
withdraw-created Withdraw order has been created
withdraw-completed Withdraw order has been completed
withdraw-transaction-sent Withdraw transaction has sent to the corresponding blockchain

How to set up webhooks

To integrate with your resource, send following information to Copper account managers or support team:

Your resource will be subscribed for the desired events, and you will be able to receive them for further processing.

Webhook body

Request body contains following main fields:

Parameter Data type Description
eventId String Unique event identifier
event String Type of event from the list above
subscriptionId String Unique identifier of a webhook subscription
Payload Order Payload of the webhook corresponding with the model containing data of the specified order

How to check webhook request signature

You can calculate and verify request signature.

X-Signature header is hmac sha256 hash in hex format.

Example:

# Variables:

echo -n "${timestamp}${eventId}${body}" | openssl dgst -sha256 -r -hmac ${secretKey} | awk '{print $1}'

# Values: 
echo -n '1567165602271test-b17c862a961fbba3a02af42a7de6e643{"eventId": "test-b17c862a9......96152012"}' | openssl dgst -sha256 -r -hmac ${secretKey} | awk '{print $1}'

Here, ${timestamp} is a value you can get from the X-Timestamp header.

Wallet Messages API

Wallet Messages API is used for creating blockchain messages and obtaining data on existing ones. Particularly, this API is used in XZC staking.

Get all messages

+ GET /platform/wallet-messages?limit=1&offset=0
+ Response 200 (application/json)
{
    "walletMessages": [
        {
            "externalMessageId": "ckki3n7xj000r3f62ey5rr4r7",
            "messageId": "45",
            "status": "canceled",
            "portfolioId": "ck7bs8wpu000d3h5mt9ja3s8s",
            "mainCurrency": "ETH",
            "extra": {
                "messageRequest": {
                    "publicKeyHash": "d12f3b91e8446b6c49077c1dc16ab921f35f6e7d8bab43fda673f2a2858704ad",
                    "currency": "ETH",
                    "mainCurrency": "ETH",
                    "message": "IDEX_verifyWallet:address=0x1a75344addadcdecce4fbf859caa7ef9d9299f78,nonce=e5debb90-5fde-11eb-a6af-b3c7e31c67be",
                    "nonceNumber": "5"
                }
            },
            "createdBy": "c066a06c-c556-4105-99d9-9e6c8cfec489",
            "organizationId": "65748",
            "accountId": "77bd1eec-7189-48fa-8e66-d3c114ff1e3e",
            "createdAt": "1611913442234"
        }
    ],
    "total": "1"
}

This method allows to retrieve information about all blockchain messages of the organisation.

Required API Key permissions: View

Properties

Request

Thу request of the method can include following optional parameters:

Field Data type Description
limit Optional<Int> Limit output of messages: 1000 by default, max. 2000
offset Optional<Int> An offset between the beginning of the message list and a first displayed element; 0 by default

Response

The response of the method includes the WalletMessage model:

Field Data type Description
messageId String Unique message identifier
externalMessageId String Unique message identifier given by a client (should be unique for a portfolio)
status MessageStatus Message processing status (see below)
portfolioId String Unique identifier of a portfolio containing the message
accountId String Unique account identifier
mainCurrency Optional<Currency> Main currency of the used blockchain
extra WalletMessageExtra Additional wallet message data (see below)
createdBy String User ID of a message creator
organizationId String Unique organization identifier
createdAt Long Timestamp of message creation

MessageStatus Enum with following values (may be changed in the future):

Status Description
working Processing the message: waiting for a client signature
canceled The message has been cancelled
part-signed-tx-added The message has been partly signed
full-signed-tx-added The message has been fully signed

WalletMessageExtra

Field Data type Description
messageRequest MessageRequest Message request data (see below)
partSigned Optional<PartSigned> Partly-signed message data (see below)
signed Optional<FullSigned> Fully-signed message data (see below)

MessageRequest

Field Data type Description
publicKeyHash String Wallet public key hash
currency String Wallet currency
message String Message to be signed

PartSigned

Field Data type Description
uploadBy String User ID of the uploader
partSignedMessage Object Data of the partly-signed message

FullSigned

Field Data type Description
uploadBy String User ID of the uploader
signedMessage Object Data of the fully-signed message

Get message by its ID

+ GET /platform/wallet-messages/{messageId}

+ Response 200 (application/json)
  {
      "externalMessageId": "ckf2lcuv4000g3i5uv3x4xn6f",
      "messageId": "11",
      "status": "full-signed-tx-added",
      "portfolioId": "ck8owwcvj000f3j5wrjoyip4d",
      "mainCurrency": "XZC",
      "extra": {
          "messageRequest": {
              "publicKeyHash": "d9f3c6b1066c188aa039e0f4a67dd8b10caf3de3e9c7862a8d0fb17320d57b14",
              "currency": "XZC",
              "message": "tesssss",
              "nonceNumber": "14"
          },
          "partSigned": {
              "uploadBy": "191b5342-2157-4ede-9458-eb673f324468",
              "partSignedMessage": {
                  "type": "part-signed-message",
                  "value": "eyJjdXJyZW5jeSI6IlhaQyIsIm1lc3NhZ2..."
              }
          },
          "signed": {
              "uploadBy": "d098b47d-5387-4f01-956e-561f15f72f2d",
              "signedMessage": {
                  "signature": "IGqvr8lz78p7ZE1eIYkrRL1znpkcxhzhi1peiqoEnEDNKU3i0F5Bct509/dzjkrVeHKtQIl1S8aa82eh2IRG5jI="
              }
          }
      },
      "createdBy": "191b5342-2157-4ede-9458-eb673f324468",
      "organizationId": "PSHENKIN",
      "accountId": "67126cc0-357d-4642-9596-ac0c0bdf4006",
      "createdAt": "1600091821812"
  }

This method retrieves information about a specific message.

Required API Key permissions: View

Properties

Request

The messageId parameter is mandatory. The method does not require any request fields.

Response

The response of the method includes the WalletMessage model for one message with the specified messageId (see above).

Cancel message

+ PATCH /platform/wallet-messages/{messageId}

+ Header
  Content-Type: application/vnd.cancel-wallet-message+json

+ Request
  {}

+ Response 200 (application/json)
  {}

This method allows to cancel processing an early pushed message. After the successful response, the message with the specified messageId will not be processed further, its status will be changed for canceled.

Required API Key permissions: Trading or Withdraw.

Request

The messageId parameter is mandatory. The method does not require any request fields.

Response

The response of the method includes only the standard status code.

Deposit API

The Deposit API methods include creation and operating deposit accounts.

Create new Deposit target

+ POST /platform/deposit-targets

+ Request
    {
        "externalId": "[[external id]]",  
        "portfolioId": "[[portfolio id]]",
        "currency": "USDT",
        "mainCurrency": "ALGO",
        "name": "Algo Wallet",
        "metadata": {
          "tags": ["test"]
        }
    }

This method creates a new deposit target.

Required API Key permissions: Trading or Withdraw

Properties

+ Response
    {
        "depositTargetId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
        "externalId": "[[external Id]]",
        "portfolioId": "[[portfolio id]]",
        "portfolioType": "trading",
        "organizationId": "TEST",
        "targetType": "proxy",
        "name": "Algo Wallet",
        "address": "BIVPTF7GFBMYA3EUYCUIHRSE5F2IKVX4LDJNZEHDTQZPGFHE6AKGZXMZLY",
        "memo": "123",
        "status": "enabled",
        "mainCurrency": "ALGO",
        "createdBy": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
        "updatedBy": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
        "metadata": {
          "tags": ["test"]
        },
        "acceptAllTokens": true,
        "requireTokensActivation": true,
        "activatedTokens": [
            {
                "currency": "USDT",
                "status": "pending"
            }
        ]
    }

Request

The request body of the method includes the depositTarget model:

Field Data type Description
externalId String Unique external identifier
portfolioId String Identifier of a portfolio where a new deposit target will be created
currency Currency Deposit target currency (standard exchange ticker)
mainCurrency Currency Deposit target blockchain main currency (standard exchange ticker)
name Optional<String> Arbitrary name of a new deposit target
metadata Optional<Object> JSON object with any additional metadata you want to store with a new deposit target

Response

The response of the method includes following fields:

Field Data type Description
depositTargetId UUID Unique deposit target identifier
externalId String Unique external identifier
portfolioId String Identifier of a deposit target portfolio
portfolioType PortfolioType Portfolio type (see below)
organizationId String Unique identifier of an organisation which uses this portfolio
targetType DepositTargetTypeEnum Target type (see below)
address Optional<String> Address of deposit target
memo Optional<String> Memo of deposit target
status DepositTargetStatusEnum Deposit target status
currency Optional<Currency> If an address is same for MainCurrency and all tokens, this field can be left empty
mainCurrency Currency Deposit target main currency (standard exchange ticker)
createdBy String User ID of a deposit target creator
updatedBy String ID of a user who has made last deposit target update
createdAt Long Time of deposit target creation
updatedAt Long Time of the latest target update
name Optional<String> Name of the created deposit target
metadata Object JSON object with any additional metadata that you want to store with deposit target
acceptAllTokens Boolean This parameter defines if this target is able to accept all tokens - for instance, this parameter is true for ETH deposit targets
requireTokensActivation Boolean true If this target can accept all tokens, but each token requires additional activation
activatedTokens Optional<List<ActivatedToken>> If tokens of a blockchain should be activated prior to any operation, this parameter includes a list of currencies to be activated with corresponding status - otherwise, the field is set as null

PortfolioType

Enum with following values (may be changed in future):

DepositTargetTypeEnum

Enum describing type of deposit target:

DepositTargetStatusEnum Enum describing a current status of a particular deposit target with following possible values (the values can be changed in the future):

ActivatedToken The list containing array of activatedToken includes following values for each deposit target token:

Field Data type Description
currency Currency token currency
status DepositTargetStatusEnum activation status (see above)

Get list of Deposit targets

+ GET /platform/deposit-targets?currency=ALGO&mainCurrency=ALGO&limit=1&offset=0

This method retrieves information on all deposit targets of the organisation. Deposit targets are sorted by the createdAt criteria (creation timestamp).

Required API Key permissions: Trading or Withdraw

Properties

+ Response 200 (application/json)
  {
    "depositTargets": [
        {
          "depositTargetId" : "fe8eeea7-f21c-450f-9331-d779eecb5242",
          "externalId" : "hohodiggenapgatofocn-wallet-ALGO-activation",
          "portfolioId" : "hohodiggenapgatofocn",
          "portfolioType" : "custody",
          "organizationId" : "TEST",
          "targetType" : "direct",
          "address" : "J43B6OALMJRNMHLMVURTTEHQ65IOIGI7YMJV26RJF7P6WG5LPBRSBR75LA",
          "status" : "enabled",
          "mainCurrency" : "ALGO",
          "createdBy" : "admin",
          "updatedBy" : "admin",
          "createdAt" : "a3a2ddb4-3e74-4fbf-beeb-a9ea39d9fc4d",
          "updatedAt" : "a3a2ddb4-3e74-4fbf-beeb-a9ea39d9fc4d",
          "metadata" : { },
          "acceptAllTokens" : true,
          "requireTokensActivation" : true,
          "activatedTokens" : [ {
            "currency" : "ARCC",
            "status" : "pending"
          } ],
        }
    ],
  }

Request

The method request can include following parameters:

Field Data type Description
portfolioId Optional<String> Identifier of a portfolio including the requested deposit targets
organizationId Optional<String> Identifier of an organisation including the requested deposit targets
currency Optional<String> Deposit targets containing a specified currency
mainCurrency Optional<String> Deposit target with a specified mainCurrency
targetType Optional<DepositTargetTypeEnum> direct or proxy
status Optional<DepositTargetStatusEnum> new, pending or enabled
sortDirection Optional<SortingDirection> ascending or descending sorting order
limit Optional<Int> 50 units by default, max. 1000 units
offset Optional<Int> an offset between the beginning of the deposit target list and a first displayed element; 0 by default

Response

The response of the method includes fields according to the depositTarget model:

Field Data type Description
depositTargetId UUID Unique deposit target identifier
externalId String Unique external identifier
portfolioId String Identifier of a deposit target portfolio
portfolioType PortfolioType Portfolio type (see below)
organizationId String Unique identifier of an organisation which uses this portfolio
targetType DepositTargetTypeEnum Target type (see below)
address Optional<String> Address of deposit target
memo Optional<String> Memo of deposit target
status DepositTargetStatusEnum Deposit target status
currency Optional<Currency> If an address is same for MainCurrency and all tokens, this field can be left empty
mainCurrency Currency Deposit target main currency (standard exchange ticker)
createdBy String User ID of a deposit target creator
updatedBy String ID of a user who has made last deposit target update
createdAt Long Time of deposit target creation
updatedAt Long Time of the latest target update
name Optional<String> Name of the created deposit target
metadata Object JSON object with any additional metadata that you want to store with deposit target
acceptAllTokens Boolean This parameter defines if this target is able to accept all tokens - for instance, this parameter is true for ETH deposit targets
requireTokensActivation Boolean true If this target can accept all tokens, but each token requires additional activation
activatedTokens Optional<List<ActivatedToken>> If tokens of a blockchain should be activated prior to any operation, this parameter includes a list of currencies to be activated with corresponding status - otherwise, the field is set as null

Activate token for a Deposit target

+ PATCH /platform/deposit-targets/{depositTargetId}

+ Header
  Content-Type: application/vnd.activate-deposit-target-currency+json

+ Request
    {
        "currency": "MCAU"
    }

This method activates a new token for a specified deposit target. It is required only in case when a deposit target accepts all tokens, but each of the accepted tokens requires activation. For instance, in the ALGO blockchain, each token should be activated separately.

Properties

+ Response
    {
        "depositTargetId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
        "externalId": "[[external Id]]",
        "portfolioId": "[[portfolio id]]",
        "portfolioType": "trading",
        "organizationId": "TEST",
        "targetType": "proxy",
        "address": "BIVPTF7GFBMYA3EUYCUIHRSE5F2IKVX4LDJNZEHDTQZPGFHE6AKGZXMZLY",
        "memo": "123",
        "status": "enabled",
        "mainCurrency": "ALGO",
        "createdBy": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
        "updatedBy": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
        "metadata": {
          "tags": ["test"]
        },
        "acceptAllTokens": true,
        "requireTokensActivation": true,
        "activatedTokens": [
            {
                "currency": "USDT",
                "status": "enabled"
            },
            {
                "currency": "MCAU",
                "status": "pending"
            }
        ]
    }

Request

The endpoint of the method should include a valid deposit target identifier. The request body includes a currency field requiring a standard market ticker of a token to be activated.

Response

The response body includes the deposit target data (see above). Under the activatedToken field, you will find the activation status of the tokens.

Deposit processing

+ GET /platform/orders?limit=1&offset=0

+ Response 200 (application/json)
  {
  "orders": [
    {
      "orderId": "14694738",
      "externalOrderId": "BTC:3831041",
      "status": "waiting-approve",
      "orderType": "deposit",
      "portfolioId": "9a7b6398-d4ac-4b26-ab62-f4dd7396aedb",
      "portfolioType": "trading",
      "accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
      "amount": "19.99985645",
      "baseCurrency": "BTC",
      "mainCurrency": "BTC",
      "extra": {
        "confirmations": "2",
        "transactionId": "b408f62cd714a817af4915caf491e4fa9e753f1e2c333cca6d1fdedd511e90f3",
        "fromAddresses": ["1AkD7DkqWuV2UPZUKywM6PkSJUsr4SYuND", "14yZeGLUDrnmAWEBp3BoevYaF6EHi8jnoX"],
        "depositTargetId": "3803a59c-0652-45e9-acd0-825bfc684410",
        "transferFees": "0.00014355",
        "transferFeesCurrency": "BTC",
        "transferTransactionId": "9b7f573bcae690259fcb05bc6feceb4bd34d231d06ee5c4791c852b6815a0f24",
        "transferDepositTargetId": "9ef96061-26d6-4471-9da9-74ea711f0ec2"
      },
      "organizationId": "TESTORG",
      "createdAt": "1572981553305",
      "updatedAt": "1572981771848",
      "terminatedAt": "1572981771582"
    }
  ], 
  }

When any deposit comes to a deposit target, a corresponding order is created for its portfolio. The order contains all information related to the deposit:

Field Data type Description
transactionId String Identifier of a deposit transaction
confirmations Int Required number of transaction confirmations (gathered while an order is in the working status)
fromAddresses String array List of addresses deposits come from
depositTargetId String Identifier of a deposit target deposits come to
transferFees Optional<BigDecimal> Fee amount which has been paid for movement of funds from a proxy target to a corresponding direct target
transferFeesCurrency Currency Currency for payment of transfer fees
transferTransactionId String Identifier of a transfer transaction
transferDepositTargetId String Identifier of a direct deposit target fund have been transferred to

In order to acquire deposit-created and deposit-completed events for all orders, you can use Transfer API webhooks.

Copper Unlimited Online

× Warning!
The POST http://0.0.0.0:3010/signatures method is now deprecated.
You may use it currently, but it is recommended to switch to the new method:
POST http://0.0.0.0:3010/sign-async/

The description of the deprecated method has been removed from the documentation.

Copper Unlimited Online is a dockerised application made by Copper as an alternative to Copper Unlimited Desktop.

CU Online can be deployed in your network and allows to automate the process of transaction signing. To do this, you can easily export shards of your wallet from CU Desktop to CU Online and sign transaction requests via its internal API.

Software requirements

CU Online is as a Docker image based on debian:10.5-slim and using Docker Compose and the NodeJS daemon for its operation.

The image is publicly available in Copper DockerHub.

Network characteristics of the image:

How to launch

  1. Export shards of your key from the CU Desktop application via wallet backup function: click the drop-down menu in the top right corner of the window and choose the Backup option. During the export process, CU Desktop will ask a password to encrypt each shard of the wallet. This will prevent accessing the shard data in case a potential attacker gains access to the filesystem. Choose a preferred folder to save the *.copper file containing the wallet shards.
  2. Start the dockerised CU Online. Before running, specify following fields:
    • a path to your folder with the *.copper file.
    • a port that CU Online endpoints will listen to.
    • the required environment as the APP_ENVIRONMENT environment variable:
      • testnet - https://api.testnet.copper.co/ (if the variable is not specified, this value will be used by default)
      • stage - https://api.stage.copper.co/
      • prod - https://api.copper.co/ The choice depends on a platform you are going to operate on.

To launch the server, use the command below (for any docker run command reference, see the official Docker documentation).

docker run --rm -ti \
  -v ${PWD}/key-backups/:/app/keys/ \
  -e APP_ENVIRONMENT='testnet' \
  -p your_port_for_the_cu_online:3010 \
  copperexchange/copper-unlimited:latest

# ${PWD}/key-backups/ is the folder containing the wallet backup.
# The APP_ENVIRONMENT variable can be 'testnet', 'stage' or 'mainnet' (see details above).

After startung the server, refer to the next section to get acquainted with typical CU Online use cases.

Transaction signing

docker run --rm -ti \
  -v ${PWD}/key-backups/:/app/keys/ \
  -e APP_ENVIRONMENT='testnet' \
  -p your_port_for_the_cu_online:3010 \
  copperexchange/copper-unlimited:latest
+ POST https://api.copper.co/platform/orders          
+ Request
{
  "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
  "orderType": "withdraw",
  "baseCurrency": "ETH",
  "mainCurrency": "ETH",
  "amount": "0.01",
  "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",  # from account
  "toPortfolioId": "28a26c72-4d72-4f97-9b36-6811ab708216", # to account
  "includeFeeInWithdraw": true,
  "feeLevel": "low",
  "description": "Some description"
} 

+ Response 201
{
  "orderId": "5824946",
  "orderType": "withdraw",
  "amount": "0.01",
  "baseCurrency": "ETH",
  "mainCurrency": "ETH",
  "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
  "extra": {
    "feeLevel": "low",
    "includeFeeInWithdraw": true,
    "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
    "toPortfolioId": "28a26c72-4d72-4f97-9b36-6811ab708216"
  },
  "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",
  "portfolioType": "custody",
  "status": "awaiting-settlement"
}
+ PATCH https://api.copper.co/platform/orders/{orderId}

+ Headers
  Content-Type: application/vnd.start-custody-settlement+json

+ Response 200
  {
    "amount": "0.01",
    "baseCurrency": "ETH",
    "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
    "extra": {
      "toPortfolioId": "ck8plg2if000f3j5qnnbw13op",
      "transactionRequest": {
        "transactionRequestId": "a5ba9f1c-c538-46e9-8b25-af21572b8077",
        "publicKeyHash": "765188378c75dd61140d765242a0a3d09cd15680a862769e4000f75204fa86de",
        "currency": "ETH",
        "mainCurrency": "ETH",
        "amount": "10000000000000000",
        "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
        "includeFee": true,
        "transactionRequest": {
          "fee": "231000000000000",
          "outputs": [
            {
              "value": "10000000000000000",
              "address": "0xf71b4a401734a3f1fe9794003a4956ada7753175"
            }
          ],
          "gasLimit": "21000",
          "gasPrice": "11000000000",
          "sequence": "4",
          "includeFee": true,
          "nonceNumber": "15"
        }
      },
      "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
      "reportingCurrencyRate": "338.15",
      "feesPercent": "0",
      "feeLevel": "low",
      "includeFeeInWithdraw": true,
      "withdrawFee": "0.000231000000000000"
    },
    "mainCurrency": "ETH",
    "orderId": "5824946",
    "orderType": "withdraw",
    "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",
    "portfolioType": "custody",
    "status": "working"
  }
+ POST http://0.0.0.0:3010/sign-async/

+ Headers
  Content-Type: application/json

+ Request
  {
    "type": "request",
    "keyPassword": "myTestPaswordFromKeyBackup.1234#",
    "keyFilename": "BTC_My Default Vault_wallet.copper",
    "transactionRequestId": "a5ba9f1c-c538-46e9-8b25-af21572b8077",
    "masterPassword": "PASSWORD",
    "apiKey": "KEY",
    "apiSecret": "SECRET",

    # get all this fields from order.extra.transactionRequest described above
    "signRequest": {
      "transactionRequestId": "a5ba9f1c-c538-46e9-8b25-af21572b8077", # Same transactionRequestId as above
      "publicKeyHash": "765188378c75dd61140d765242a0a3d09cd15680a862769e4000f75204fa86de",
      "currency": "ETH",
      "mainCurrency": "ETH",
      "amount": "10000000000000000",
      "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
      "includeFee": true,
      "transactionRequest": {
        "fee": "231000000000000",
        "outputs": [
          {
            "value": "10000000000000000",
            "address": "0xf71b4a401734a3f1fe9794003a4956ada7753175"
          }
        ],
        "gasLimit": "21000",
        "gasPrice": "11000000000",
        "sequence": "4",
        "includeFee": true,
        "nonceNumber": "15"
      }
    }
  }

+ Response 200 OK
  {
    "transactionRequestId": "a5ba9f1c-c538-46e9-8b25-af21572b8077", # Same transactionRequestId as above
    "sessionKey": "9baa2670-2291-43d4-814f-e04427204925",
    "sessionTimestamp": "1608296004000"
  }

After signing (the transaction is in the completed status), the signed transaction will be uploaded to the Copper platform automatically.

+ GET http://0.0.0.0:3010/sign-async/{transactionRequestId}

+ Headers
  Content-Type: application/json

+ Response 200 OK
  {
    "status": "in-progress",
    "message": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0=",
  }

Possible statuses:

Status Description
starting The request is accepted for processing
session-established The CU session has been established
in-progress The signature is being generated
completed The transaction has been signed
error Something went wrong, see the message field

Transaction signing (deprecated)

You can also use the deprecated POST /signatures endpoint. In this case, the workflow will differ.

docker run --rm -ti \
-v ${PWD}/key-backups/:/app/keys/ \
-p 3010:3010 \
copperexchange/copper-unlimited:latest
+ POST https://api.copper.co/platform/orders          
+ Request
{
  "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
  "orderType": "withdraw",
  "baseCurrency": "ETH",
  "mainCurrency": "ETH",
  "amount": "0.01",
  "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",  # from account
  "toPortfolioId": "28a26c72-4d72-4f97-9b36-6811ab708216", # to account
  "includeFeeInWithdraw": true,
  "feeLevel": "low",
  "description": "Some description"
} 

+ Response 201
{
  "orderId": "5824946",
  "orderType": "withdraw",
  "amount": "0.01",
  "baseCurrency": "ETH",
  "mainCurrency": "ETH",
  "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
  "extra": {
    "feeLevel": "low",
    "includeFeeInWithdraw": true,
    "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
    "toPortfolioId": "28a26c72-4d72-4f97-9b36-6811ab708216"
  },
  "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",
  "portfolioType": "custody",
  "status": "awaiting-settlement"
}
+ PATCH https://api.copper.co/platform/orders/{orderId}

+ Headers
  Content-Type: application/vnd.start-custody-settlement+json

+ Response 200
  {
    "amount": "0.01",
    "baseCurrency": "ETH",
    "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
    "extra": {
      "toPortfolioId": "ck8plg2if000f3j5qnnbw13op",
      "transactionRequest": {
        "publicKeyHash": "765188378c75dd61140d765242a0a3d09cd15680a862769e4000f75204fa86de",
        "currency": "ETH",
        "mainCurrency": "ETH",
        "amount": "10000000000000000",
        "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
        "includeFee": true,
        "transactionRequest": {
          "fee": "231000000000000",
          "outputs": [
            {
              "value": "10000000000000000",
              "address": "0xf71b4a401734a3f1fe9794003a4956ada7753175"
            }
          ],
          "gasLimit": "21000",
          "gasPrice": "11000000000",
          "sequence": "4",
          "includeFee": true,
          "nonceNumber": "15"
        }
      },
      "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
      "reportingCurrencyRate": "338.15",
      "feesPercent": "0",
      "feeLevel": "low",
      "includeFeeInWithdraw": true,
      "withdrawFee": "0.000231000000000000"
    },
    "mainCurrency": "ETH",
    "orderId": "5824946",
    "orderType": "withdraw",
    "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",
    "portfolioType": "custody",
    "status": "working"
  }
+ POST http://0.0.0.0:3010/signatures

+ Headers
  Content-Type: application/json

+ Request
  {
    "type": "request",
    "keyPassword": "myTestPaswordFromKeyBackup.1234#",
    "keyFilename": "BTC_My Default Vault_wallet.copper",

    # get all this fields from order.extra.transactionRequest, described above
    "signRequest": {
      "publicKeyHash": "765188378c75dd61140d765242a0a3d09cd15680a862769e4000f75204fa86de",
      "currency": "ETH",
      "mainCurrency": "ETH",
      "amount": "10000000000000000",
      "toAddress": "0xf71b4a401734a3f1fe9794003a4956ada7753175",
      "includeFee": true,
      "transactionRequest": {
        "fee": "231000000000000",
        "outputs": [
          {
            "value": "10000000000000000",
            "address": "0xf71b4a401734a3f1fe9794003a4956ada7753175"
          }
        ],
        "gasLimit": "21000",
        "gasPrice": "11000000000",
        "sequence": "4",
        "includeFee": true,
        "nonceNumber": "15"
      }
    }
  }

+ Response 200 OK
  {
    "type": "part-signed-tx",
    "value": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0=",
  }

Note: "masterPassword" is an optional field, required only in case you sign a transaction for a Warm Vault. It contains a sha256 hash of the Withdrawal password hexadecimal string.

+ PATCH https://api.copper.co/platform/orders/{orderId}

+ Headers
  Content-Type: application/vnd.upload-part-signed-tx+json

+ Request
  {
    "masterPassword": "97dee97560699a639f3cf55c464855eefe97ae97493b242fe01ecdbab39ea463",
  } 

+ Request
  {
    "transaction": {
      "type": "part-signed-tx",
      "value": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0="
    }
  }

+ Response 200
  {
    "amount": "0.01",
    "baseCurrency": "ETH",
    "externalOrderId": "ckdr8xy1l00303g5neu5iunh4",
    "extra": {
      "transactionId": "0xc5344c295cffc4db0dfe869bd395ced34e0877b0f139b8939cf2c357ea1599e4",
      ...
    },
    "mainCurrency": "ETH",
    "orderId": "5824946",
    "orderType": "withdraw",
    "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",
    "portfolioType": "custody",
    "status": "processing"
  }

Enabling SSL/TLS

To enable SSL/TLS support, add a volume containing with your key and certificate to the CU Online container:

openssl genrsa -out privatekey.key
openssl req -new -key privatekey.key -out csr.pem
openssl x509 -req -days 9999 -in csr.pem -signkey privatekey.key -out certificate.cert
docker run --rm -ti \
  -v ${PWD}/key-backups/:/app/keys/ \
  -e APP_ENVIRONMENT='testnet' \
  -v ${PWD}/ssl/certificate.cert:/app/ssl/certificate.cert \
  -v ${PWD}/ssl/privatekey.key:/app/ssl/privatekey.key \
  -p 3010:3010 \
  copperexchange/copper-unlimited:latest

User flows

This section includes combined use-cases of the Copper platform API.

Move funds between accounts

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",   # Unique identifier
    "orderType": "withdraw",
    "baseCurrency": "ETH", # Currency to move
    "mainCurrency": "ETH", # What blockchain/vault wallet to use when moving
    "amount": "42", # Amount to move
    "portfolioId": "46",   # From this portfolioId
    "toPortfolioId": "7",   # To this portfolioId
    "withdrawalPassword": "97dee97560699a639f3cf55c464855eefe97ae97493b242fe01ecdbab39ea463" # Optional, sha256 has of organization Withdrawal Password 
  }

Withdraw fiat to bank account

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",  # Unique identifier
    "orderType": "withdraw",
    "baseCurrency": "USD", # Fiat currency to withdraw
    "amount": "100", # Amount to withdraw
    "portfolioId": "46", # Chosen portfolioId
    "toBankAccountId": "67"      # Chosen bankAccountId
  }

Withdraw crypto to an unknown or external address

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",     # Unique order identifier (e.g. UUID or timestamp)
    "orderType": "withdraw",
    "baseCurrency": "BTC",
    "mainCurrency": "BTC",
    "amount": "1.00451",
    "portfolioId": "46",
    "toAddress": "15BLpZebnTTTtfuBwmB8x1VRfcGtPJhK3p",      # Destination wallet address
    "destinationTag": 34,       # Optional, used only for XRP (Ripple) withdrawal
    "memo": "testme",       # Optional blockchain memo
    "feeLevel": "low",      # "low", "medium" or "high". Optional, "low" by default
    "includeFeeInWithdraw": true   # Include fee in the transaction amount, optional.
  }

After this, you will have to sign the withdraw from your vault.

Withdraw cryptocurrency to a whitelisted crypto address

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",     # Unique order identifier (e.g. UUID or timestamp)
    "orderType": "withdraw",
    "baseCurrency": "BTC",
    "mainCurrency": "BTC",
    "amount": "1.00451",
    "portfolioId": "46",
    "toCryptoAddressId": "cbc328f5-85de-4c2d-a0b9-65a0c7f81b72"      # Destination cryptoAddressId
  }

After this, you will have to sign the withdraw from your vault.

Withdraw cryptocurrency to an address inside the platform

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",   
    "orderType": "withdraw",
    "baseCurrency": "BTC",
    "amount": "3",
    "portfolioId": "ba8azuNgohfeiphietai9Angeiz2thi8",    # Withdraw from 
    "toPortfolioId": "poo5feesa8ahKai6phoo1iofai3niesh"   # Withdraw to
  }

After this, you will have to sign the withdraw from your vault.

Conditional transfers

The Copper API allows to create a withdrawal chain with the use of only one order.

+ POST /platform/orders

+ Request
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",   
    "orderType": "withdraw",
    "baseCurrency": "BTC",
    "amount": "3",
    "portfolioId": "ba8azuNgohfeiphietai9Angeiz2thi8",     # Withdraw from
    "toPortfolioId": "poo5feesa8ahKai6phoo1iofai3niesh",   # Withdraw to
    "nextTransferTo": [
      { "targetType": "portfolio", "portfolioId": "ckj45ee8f001k3g5vna9bf9vl" },  # Then transfer here
      { "targetType": "portfolio", "portfolioId": "ckj45eu0m001r3g5vbh1k2caf" }   # After this, transfer here
    ]
  }

+ Response:
  {
    "orderId": "234234",
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
    "orderType": "withdraw",
    "extra": { "transferChainId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494" },
    ...
  }

In this workflow, orders in the master-password-required status still require additional processing:

+ PATСH /platform/orders/554433

+ Headers:
  Content-Type: application/vnd.enter-withdrawal-password+json

+ Request
  {
  "withdrawalPassword": "97dee97560699a639f3cf55c464855eefe97ae97493b242fe01ecdbab39ea463" # SHA256 hash of the organization Withdrawal Password
  }

All orders in the withdraw chain will contain the same extra.transferChainId field. That is why, you can request all withdraw chain orders at once:

+ GET /platform/orders?transferChainId=PBTEST-939175d9-4d92-4d86-a8b5-1173554f645c

+ Response
  {
    "orders": [
      {
        "orderId": "1",
        "orderType": "withdraw",
        "extra": { "transferChainId": "PBTEST-939175d9-4d92-4d86-a8b5-1173554f645c" },
        ....
      },
      {
        "orderId": "2",
        "orderType": "deposit",
        "extra": { "transferChainId": "PBTEST-939175d9-4d92-4d86-a8b5-1173554f645c" },
        ....
      },
      {
        "orderId": "3",
        "orderType": "withdraw",
        "extra": { "transferChainId": "PBTEST-939175d9-4d92-4d86-a8b5-1173554f645c" },
        ....
      },
      {
        "orderId": "4",
        "orderType": "deposit",
        "extra": { "transferChainId": "PBTEST-939175d9-4d92-4d86-a8b5-1173554f645c" },
        ....
      }
    ]
  }

Create an ETH withdrawal transaction with a payload: unknown or external address

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",     # Unique order identifier (e.g. UUID or timestamp)
    "orderType": "withdraw",
    "baseCurrency": "ETH",
    "mainCurrency": "ETH",
    "amount": "0",
    "portfolioId": "46",
    "toAddress": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",      # Destination wallet address
    "payload": "0x7ff36ab50000000000000000000000000000000000000000000000011f36d51e6b78ff1100000000000000000000000000000000000000000000000000000000000000800000000000000000000000001a75344addadcdecce4fbf859caa7ef9d9299f78000000000000000000000000000000000000000000000000000000005fb2ad0a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef",       # Optional payload
    "feeLevel": "low",      # "low", "medium", "high". Optional, "low" by default
    "includeFeeInWithdraw": false 
  }

Create an ETH withdraw transaction with a payload: whitelisted crypto address

  + POST /platform/orders

  + Request (application/json)
  {
    "externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",     # Unique order identifier (e.g. UUID or timestamp)
    "orderType": "withdraw",
    "baseCurrency": "ETH",
    "mainCurrency": "ETH",
    "amount": "0",
    "payload": "0x7ff36ab50000000000000000000000000000000000000000000000011f36d51e6b78ff1100000000000000000000000000000000000000000000000000000000000000800000000000000000000000001a75344addadcdecce4fbf859caa7ef9d9299f78000000000000000000000000000000000000000000000000000000005fb2ad0a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef",       # Optional payload
    "feeLevel": "low",      # "low", "medium", "high". Optional, "low" by default
    "includeFeeInWithdraw": false, 
    "toCryptoAddressId": "cbc328f5-85de-4c2d-a0b9-65a0c7f81b72"      # Destination cryptoAddressId
  }

Get supported currencies and tokens

In order to obtain a full list of currencies and tokens supported by Copper, use the GET /platform/currencies method. This method does not require any permissions and will return the currencies model containing the information on each supported currency.

To filter the output, specify following parameters in the request:

Parameter Type Additional information
currency Optional<[String]> Return an asset only with the specified market ticker.
rateFor Optional<String> Return the price of the currency only for an asset with the market ticker specified in this field.
+ GET /platform/currencies?currency=BTC&rateFor=USD

+ Response
  {
    "currencies": [
      {
        "currency": "BTC",
        "mainCurrency": "BTC",
        "name": "Bitcoin",
        "fiat": false,
        "priority": "6",
        "confirmations": "2",
        "decimal": "8",
        "tags": [
          "deposit-custody",
        ],
        "color": "#fa8a34",
        "feesLevels": [
          {
            "feeLevel": "low",
            "value": "0.00029"
          },
          {
            "feeLevel": "medium",
            "value": "0.00031"
          },
          {
            "feeLevel": "high",
            "value": "0.00033"
          }
        ],
        "explorerUrl": "blockchair.com/bitcoin/transaction/",
        "_embedded": {
          "price": {
            "baseCurrency": "BTC",
            "quoteCurrency": "USD",
            "price": "41038.46"
          }
        }
      }
    ]
  }

HNT Staking (Trading API)

Note: Minimum amount of the stake should be equal or more than 10,000 HNT.

To process HNT staking from your Vault, perform following steps:

  docker run --rm -ti \
  -v ${PWD}/key-backups/:/app/keys/ \  # Here, **key-backups** is a directory containing saved shards of your HNT wallet.
  -p 3010:3010 \
  copperexchange/copper-unlimited:latest
Field Type Additional information
externalOrderId String Unique order identifier given by the client (should be unique to portfolio)
orderType OrderType Type of order
baseCurrency Currency Currency used for the order
mainCurrency Currency Main currency of the blockchain
amount BigDecimal Order execution amount
portfolioId String Portfolio used for staking
blockchainTransactionType TransactionType Type of blockchain transaction to perform: stake-delegation
poolId String filter by tags, should be comma-separated string

  + POST /platform/orders

  + Request
  {
    "externalOrderId": "[[external id]]",  
    "orderType": "withdraw",
    "baseCurrency": "HNT",
    "mainCurrency": "HNT",
    "amount": "10000",
    "portfolioId": "[[portfolio id]]",
    "blockchainTransactionType": "stake-delegation",
    "poolId": "[[stake address]]"
  } 

  + Response 201
  {
    "orderId": "5824946",
    "orderType": "withdraw",
    "amount": "10000",
    "baseCurrency": "HNT",
    "mainCurrency": "HNT",
    "externalOrderId": "[[external id]]",
    "portfolioId": "[[portfolio id]]",
    "portfolioType": "custody",
    "status": "awaiting-settlement"
  } 
  + PATCH https://api.copper.co/platform/orders/{orderId}

  + Headers
    Content-Type: application/vnd.start-custody-settlement+json

  + POST http://172.17.0.2:3010/signatures

  + Headers
    Content-Type: application/json

  + Request
  {
    "type": "request",
    "keyPassword": "myTestPaswordFromKeyBackup.1234#",
    "keyFilename": "HNT_staking.copper",

    # Here, insert all the fields included into transactionRequest at the previous step.
  }

  + Response 200 OK
  {
    "type": "part-signed-tx",
    "value": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0=",
  }

+ PATCH https://api.copper.co/platform/orders/{orderId}

+ Headers
  Content-Type: application/vnd.upload-part-signed-tx+json

+ Request
{
  "transaction": {
    "type": "part-signed-tx",
    "value": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0="
  }
}

XZC staking (Wallet Messages API)

For staking operations with the XZC token, the Copper platform uses the Wallet Messages API. To learn more, refer to the corresponding section.

To stake XZC from your Copper account, follow these steps:

  docker run --rm -ti \
  -v ${PWD}/key-backups/:/app/keys/ \  # Here, **key-backups** is a directory containing saved shards of your HNT wallet.
  -p 3010:3010 \
  copperexchange/copper-unlimited:latest
  + POST https://api.copper.co/platform/wallet-messages

  + Request
  {
    "externalMessageId": "ckdr8xy1l00303g5neu5iunh4",
    "mainCurrency": "XZC",
    "message": "test",
    "portfolioId": "edd7e0ea-9d00-4538-b187-c14813d7b0ba",  # From account
  } 

  + Response 201
  {
    "externalMessageId": "ckfgpkesr000d3j5twa61gzl1",
    "messageId": "24",
    "status": "working",
    "portfolioId": "ck8owwcvj000f3j5wrjoyip4d",
    "mainCurrency": "XZC",
    "extra": {
      "messageRequest": {
        "publicKeyHash": "d9f3c6b1066c188aa039e0f4a67dd8b10caf3de3e9c7862a8d0fb17320d57b14",
        "currency": "XZC",
        "mainCurrency": "XZC",
        "message": "test",
        "nonceNumber": "16"
      }
    },
    "createdBy": "191b5342-2157-4ede-9458-eb673f324468",
    "organizationId": "PSHENKIN",
    "accountId": "67126cc0-357d-4642-9596-ac0c0bdf4006",
    "createdAt": "1600945419113"
  }
  + POST http://127.0.0.1:3010/signatures

  + Headers
    Content-Type: application/json

  + Request
  {
    "type": "message-request",
    "keyPassword": "myTestPaswordFromKeyBackup.1234#",
    "keyFilename": "XZC_My Default Vault_wallet.copper",


    # Get all this fields from message.extra.messageRequest, described above
    "signRequest": {
      "publicKeyHash": "d9f3c6b1066c188aa039e0f4a67dd8b10caf3de3e9c7862a8d0fb17320d57b14",
      "currency": "XZC",
      "mainCurrency": "XZC",
      "message": "test",
      "nonceNumber": "16"
    }
  }

  + Response 200 OK
  {
    "type": "part-signed-message",
    "value": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0=",
  }
  + PATCH https://api.copper.co/platform/wallet-messages/{walletMessageId}

  + Headers
    Content-Type: application/vnd.upload-part-signed-wallet-message+json

  + Request
  {
    "partSignedMessage": {
      "type": "part-signed-tx",
      "value": "AQRwL5FqGrbLaPO4w+NoEq9oZ...R5I/wjEQND/4YmIn+rbN9uh5U/0="
    }
  }

The complete examples of each step are specified on the right panel.

ClearLoop: delegating funds to exchange

To delegate funds to an exchange via the ClearLoop, use the POST /platform/orders method: create a new withdraw order for transferring funds from your Trading account to the ClearLoop account.

+ POST /platform/orders

+ Request
  {
    "externalOrderId": "720A55C4-30FB-4418-8B73-F12E4AD99AA5",  # Unique order identifier (e.g. UUID or timestamp)
    "amount": "1",
    "baseCurrency": "BTC",
    "orderType": "withdraw",
    "portfolioId": "Bahng9nai9ieGhaeg8Heasokahshee7A",   # From the parent Trading account
    "toPortfolioId": "oishiphoosaipho9ooTikohk5foo4Wah"  # To the ClearLoop account
  } 

ClearLoop: undelegating funds

To undelegate funds delegated earlier to an exchange, use the POST /platform/orders method: create a new withdraw order for transferring funds from the ClearLoop account to the parent Trading account.

+ POST /platform/orders

+ Request
{
  "externalOrderId": "720A55C4-30FB-4418-8B73-F12E4AD99AA5",  # Unique order identifier (e.g. UUID or timestamp)
  "amount": "1",
  "baseCurrency": "BTC",
  "orderType": "withdraw",
  "portfolioId": "oishiphoosaipho9ooTikohk5foo4Wah",   # From the parent ClearLoop account
  "toPortfolioId": "Bahng9nai9ieGhaeg8Heasokahshee7A"  # To the ClearLoop account
} 

ClearLoop: get data on delegated funds

To retrieve information about funds delegated within the organisation, use the GET /platform/wallets with the portfolioId={clearLoopPortfolioId} parameter to output only wallets related to your specified ClearLoop portfolio.

+ GET /platform/wallets?portfolioId={clearLoopPortfolioId}

+ Response 200 OK
{
  "wallets": [
  {
    "walletId": "ck92vvxyc000a3g5mb74gcdjh",
    "portfolioId": "oishiphoosaipho9ooTikohk5foo4Wah",
    "organizationId": "MYORG1"
    "currency": "BTC",
    "balance": "13",
    "reserve": "0",
    "available": "13"
  },
  {
    "walletId": "oWou4Queir5eevaezeed6",
    "portfolioId": "oishiphoosaipho9ooTikohk5foo4Wah",
    "organizationId": "MYORG1"
    "currency": "ETH",
    "balance": "1348.4562",
    "reserve": "0",
    "available": "1348.4562"
  }
  ]
}

Changelog

November 2021

October 2021