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.
- Getting Started - follow this guide to begin building applications using Copper API.
API methods
To learn more about specific endpoints of Copper API, refer to following sections:
- Account API - API methods provided for working with platform accounts.
- Trading API - API methods to perform eOTC trading operations.
- Settle API - API methods to perform OTC trading operations.
- Transfer API - API methods for transferring cryptocurrency.
- Deposit API - API methods provided for operations with deposit targets.
Webhooks
The Copper platform provides the webhooks on deposit and withdrawal events. To learn more, refer to the Webhooks.
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 - here, specify your API key in the following format:
Authorization: ApiKey 6a7eef41b0e160b27eb***********6af970fa77e45a8e20581e4ffd8
X-Timestamp - specify the timestamp of your request in UNIX Timestamp format (in milliseconds).
X-Signature - signature of your request (see the next subsection for details).
Signature
To sign your request, generate the X-Signature
header as follows:
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"}
Sign the pre-hashed strings with your API Secret using HMAC SHA256 method.
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, use the bash mode: bash script.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:
error
- error code, string constant. This value can be used to parse for specific errors.message
- error description in plain text.
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 (Switzerland) AG",
"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 | 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 - displayed if an account has been updated |
updatedBy | Optional <String> |
User ID of last account updater - displayed if an account has been updated |
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 - displayed if account has been updated |
createdAt | String |
Time of wallet creation |
updatedAt | Optional<String> |
Time of the latest wallet update - displayed if account has been updated |
extra | WalletExtra |
Additional wallet data (includes the WalletExtra model below) |
accountId | String |
unique account identifier that includes this wallet |
organizationId | 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) |
stakeInfos | Optional List<StakeInfo> |
Information about staked assets of the wallet (see the StakeInfo model below ) |
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 |
StakeInfo
Field | Data type | Description |
---|---|---|
poolId | Optional<String> |
Staking pool identifier (can be returned as a list) |
poolName | Optional<String> |
Staking pool name |
rewardAmount | Optional<BigDecimal> |
Reward amount of the wallet |
stakedAmount | Optional<BigDecimal> |
Staked amount of the wallet |
stakedFrozen | Optional<Boolean> |
true - the staked amount is blocked, false - the staked amount is available |
readyToWithdrawal | Optional<Boolean> |
true - the reward is ready to withdrawal, false - the reward is not ready to withdrawal |
stakePublicKey | Optional<String> |
For Solana staking: public key of the stake |
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 |
accountDescription | Optional<String> |
Bank account description |
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):
custody
trading-vault
trading
external
clearloop
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) |
exchangeAccountType | Optional<ExchangeAccountType> |
External portfolio exchange account type (see the ExchangeAccountType 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) |
customerId | Optional<String> |
External customer identifier from an exchange |
parentPortfolioId | Optional<String> |
Identifier of a parent portfolio, if any |
clearLoopPortfolioId | Optional<String> |
Identifier of a ClearLoop portfolio |
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):
binance
bitfinex
bitmex
bitstamp
kraken
okex
huobi
bittrex
coinbase
coinbase-prime
deribit
hitbtc
ExchangeWalletType
Enum with following values (may be changed in future):
exchange
margin
funding
spot
futures
account
subaccount
trading
swap
contract
subcontract
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):
real
margin
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
endpoint 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):
custody
trading-vault
trading
external
clearloop
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) |
exchangeAccountType | Optional<ExchangeAccountType> |
External portfolio exchange account type (see the ExchangeAccountType 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) |
customerId | Optional<String> |
External customer identifier from an exchange |
parentPortfolioId | Optional<String> |
Identifier of a parent portfolio, if any |
clearLoopPortfolioId | Optional<String> |
Identifier of a ClearLoop portfolio |
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):
binance
bitfinex
bitmex
bitstamp
kraken
okex
huobi
bittrex
coinbase
coinbase-prime
deribit
hitbtc
ExchangeWalletType
String with following values (may be changed in future):
exchange
margin
funding
spot
futures
account
subaccount
trading
swap
contract
subcontract
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):
real
margin
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 - displayed if account has been updated |
createdAt | String |
Time of wallet creation |
updatedAt | Optional<String> |
Time of the latest wallet update - displayed if account has been updated |
extra | WalletExtra |
Additional wallet data (includes the WalletExtra model below) |
accountId | String |
unique account identifier that includes this wallet |
organizationId | 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) |
stakeInfos | Optional List<StakeInfo> |
Information about staked assets of the wallet (see the StakeInfo model below ) |
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 |
StakeInfo
Field | Data type | Description |
---|---|---|
poolId | Optional<String> |
Staking pool identifier (can be returned as a list) |
poolName | Optional<String> |
Staking pool name |
rewardAmount | Optional<BigDecimal> |
Reward amount of the wallet |
stakedAmount | Optional<BigDecimal> |
Staked amount of the wallet |
stakedFrozen | Optional<Boolean> |
true - the staked amount is blocked, false - the staked amount is available |
readyToWithdrawal | Optional<Boolean> |
true - the reward is ready to withdrawal, false - the reward is not ready to withdrawal |
stakePublicKey | Optional<String> |
For Solana staking: public key of the stake |
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 (Switzerland) AG",
"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 | Optional<BigDecimal> |
Current total balance |
reserve | Optional<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) |
stakeInfos | Optional List<StakeInfo> |
Information about staked assets of the wallet (see the StakeInfo model below ) |
WalletEmbedded
Field | Data type | Description |
---|---|---|
depositTargets | List<DepositTarget> |
List of deposit targets attached to the wallet (includes the DepositTarget model below) |
outstandingBalance | Optional<BigDecimal> |
Amount of outstanding balances, if any |
StakeInfo
Field | Data type | Description |
---|---|---|
poolId | Optional<String> |
Staking pool identifier (can be returned as a list) |
poolName | Optional<String> |
Staking pool name |
rewardAmount | Optional<BigDecimal> |
Reward amount of the wallet |
stakedAmount | Optional<BigDecimal> |
Staked amount of the wallet |
stakedFrozen | Optional<Boolean> |
true - the staked amount is blocked, false - the staked amount is available |
readyToWithdrawal | Optional<Boolean> |
true - the reward is ready to withdrawal, false - the reward is not ready to withdrawal |
stakePublicKey | Optional<String> |
For Solana staking: public key of the stake |
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):
sepa
international
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:
"wallets-snapshots"
- reports on each wallet related to the account;"net-asset-values"
- net values for all assets of the account.
Request
The request body of this method includes following fields:
Field | Data type | Description |
---|---|---|
dateFrom | Mandatory <String> |
Date of the report initial entry (in the DDMMYYYY format). |
dateTo | Mandatory <String> |
Date of the report last entry (in the DDMMYYYY format). |
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 portfolioType s (see below) |
PortfolioType Enum with following values (may be changed in future):
custody
trading-vault
trading
external
clearloop
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.
Address validation
+ POST /platform/reports/address-validations
This method allows to check if an entered blockchain address is valid (exists in an entered blockchain).
The method is functional for all blockchains supported by Copper.
Required API Key permissions: View
Properties
+ POST /platform/address-validations
+ Request
{
"address": "1CN8YbBhamkB62fq2BbR8BAq1HQ5cL4af4",
"mainCurrency": "BTC",
"currency": "BTC"
}
+ Response 200 OK (application/json)
{
"valid": "true"
"address": "1CN8YbBhamkB62fq2BbR8BAq1HQ5cL4af4",
"mainCurrency": "BTC",
"currency": "BTC"
}
Request
The request body of this method includes following fields:
Field | Data type | Description |
---|---|---|
mainCurrency | Mandatory <String> |
Blockchain main currency. |
currency | Mandatory <String> |
Blockchain address currency. |
address | Mandatory <String> |
Blockchain address to validate. |
Response
The response body of this method includes following fields:
Field | Data type | Description |
---|---|---|
valid | Boolean |
Address validation result. |
mainCurrency | Optional<String> |
Blockchain main currency. |
currency | Optional<String> |
Blockchain address main currency. |
address | Optional<String> |
Blockchain address that has been validated. |
Trading API
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": "36116086",
"externalOrderId": "7b5516f77410a35d92a086c85aebe500",
"status": "awaiting-settlement",
"orderType": "sell",
"portfolioId": "349",
"portfolioType": "trading",
"accountId": "c0576ce4-00aa-4bdc-82fb-c4101fbe491b",
"amount": "0.1",
"baseCurrency": "LTC",
"mainCurrency": "LTC",
"quoteCurrency": "KSM",
"quoteMainCurrency": "KSM",
"limitType": "otc",
"priceLimit": "0.1",
"extra": {
"toAddress": "LQZbDWLxdMrtgi73zBmAjuA6D7WZPWzbTH",
"reportingCurrencyRate": "205.23198961802248",
"totalQuoteAmount": "0.01",
"daysToSettle": "0",
"initializerPortfolioId": "ulCJwlxHCV0VOZoZGrLJkYTC",
"initializerOrderId": "36116085",
"feesPercent": "0.05",
"includeFeeInWithdraw": false
},
"organizationId": "123456",
"createdAt": "1634819546513",
"updatedAt": "1634819554963",
"_embedded": {
"debitingAmount": "0.1",
"debitingCurrency": "LTC"
}
}
]
}
Request
If no parameters are set in the request, the response will contain the latest 1000 orders.
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 |
PortfolioType Enum with following values (may be changed in future):
custody
- an individual address managed by a client.trading
- an address providing access to the treasury (custody part managed by Copper).external
- an address connected to Walled Garden exchanges.trading-vault
- an individual address allowed to take part in OTC trading on the Copper platform.clearloop
- an address connected to the ClearLoop.
limitType
The limitType
field can include following limit types:
stream
- token prices are transferred continuously: a deal price changes in real time.rfq
- 10-second price freeze for a deal.off-exchange
- ClearLoop settlement.otc
- OTC trade with a corresponding settlement.eotc
- trade order with the use of Copper's liquidity provider engine.
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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
quoteCurrency | Optional<Currency> |
Trading quote currency |
limitType | Optional<LimitType> |
Limit type (see above) |
priceLimit | Optional<BigDecimal> |
Limit value for order with the corresponding limitType |
extra | OrderExtra |
Additional order data |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
PortfolioType
custody
- an individual address managed by a client.trading
- an address providing access to the treasury (custody part managed by Copper).external
- an address connected to Walled Garden exchanges.trading-vault
- an individual address allowed to take part in OTC trading on the Copper platform.clearloop
- an address connected to the ClearLoop.
Get data of an order according to its ID
+ GET /platform/orders/{orderId}
This method allows to obtain data of an exact order according to its unique orderId
.
Required permissions: View
Properties
+ Response 200 (application/json)
{
"orders": [
{
"orderId": "36116086",
"externalOrderId": "7b5516f77410a35d92a086c85aebe500",
"status": "awaiting-settlement",
"orderType": "sell",
"portfolioId": "349",
"portfolioType": "trading",
"accountId": "c0576ce4-00aa-4bdc-82fb-c4101fbe491b",
"amount": "0.1",
"baseCurrency": "LTC",
"mainCurrency": "LTC",
"quoteCurrency": "KSM",
"quoteMainCurrency": "KSM",
"limitType": "otc",
"priceLimit": "0.1",
"extra": {
"toAddress": "LQZbDWLxdMrtgi73zBmAjuA6D7WZPWzbTH",
"reportingCurrencyRate": "205.23198961802248",
"totalQuoteAmount": "0.01",
"daysToSettle": "0",
"initializerPortfolioId": "ulCJwlxHCV0VOZoZGrLJkYTC",
"initializerOrderId": "36116085",
"feesPercent": "0.05",
"includeFeeInWithdraw": false
},
"organizationId": "123456",
"createdAt": "1634819546513",
"updatedAt": "1634819554963",
"_embedded": {
"debitingAmount": "0.1",
"debitingCurrency": "LTC"
}
}
]
}
Request
The request of the method does not have any additional parameters.
Response
The response of the method contains one instance of the orders
with the requested order data:
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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
quoteCurrency | Optional<Currency> |
Trading quote currency |
limitType | Optional<LimitType> |
Limit type (see above) |
priceLimit | Optional<BigDecimal> |
Limit value for order with the corresponding limitType |
extra | OrderExtra |
Additional order data |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
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:
stream
rfq
Place a trading offer
# Placing an offer
+ POST /platform/offers
+ Request
{
"portfolioId": "182be0c5cdcd5072bb1864cdee4d3d6e", # 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": "buy",
"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:
stream
rfq
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, cannot be blank) |
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 | Optional <Currency> |
Quote currency |
limitType | Optional<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 | Optional<String> |
Offer identifier |
description | Optional<String> |
Arbitrary description allowing to identify an order. |
limitType
The limitType
field can include following limit types:
stream
rfq
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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
quoteCurrency | Optional<Currency> |
Trading quote currency |
limitType | Optional<LimitType> |
Limit type (see above) |
priceLimit | Optional<BigDecimal> |
Limit value for order with the corresponding limitType |
extra | OrderExtra |
Additional order data |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
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
orderId
- Unique order identifier generated upon its creation (see theOrder
model).
Response
This method does not return any fields in response.
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 | Optional<Currency> |
Trading quote currency |
limitType | Optional<LimitType> |
Limit type |
priceLimit | Optional<BigDecimal> |
Limit value for order with the corresponding limitType |
description | Optional<String> |
Arbitrary description allowing to identify an order. |
limitType
The limitType
field can include following limit types:
stream
- token prices are transferred continuously: a deal price changes in real time.rfq
- 10-second price freeze for a deal.off-exchange
- ClearLoop settlement.otc
- OTC trade with a corresponding settlement.eotc
- trade order with the use of Copper's liquidity provider engine.
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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
quoteCurrency | Optional<Currency> |
Trading quote currency |
limitType | Optional<LimitType> |
Limit type (see above) |
priceLimit | Optional<BigDecimal> |
Limit value for order with the corresponding limitType |
extra | OrderExtra |
Additional order data |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
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": "36097872",
"externalOrderId": "ckr4t9gfp00113b5z94j02dlo",
"status": "executed",
"orderType": "withdraw",
"portfolioId": "ckmx8iv1s001o3g5zenbx1ku3",
"portfolioType": "custody",
"accountId": "29af7ea0-5878-4a6a-93de-6647e0d287fa",
"amount": "0.031685614938804011",
"baseCurrency": "ETH",
"mainCurrency": "ETH",
"extra": {
"toPortfolioId": "ckr4sbit000153f5zz3frjta8",
"transactionRequest": {
"publicKeyHash": "f7486bca5ccacacc88b72460448da45b5da1e35bbf00a9fbf7b8866591e06b79",
"currency": "ETH",
"mainCurrency": "ETH",
"amount": "31685614938804011",
"toAddress": "0xcf76cc2abf1f4c09543d75213f5614ceae1e5ad6",
"includeFee": true,
"transactionRequest": {
"fee": "672000000000000",
"outputs": [
{
"value": "31685614938804011",
"address": "0xcf76cc2abf1f4c09543d75213f5614ceae1e5ad6"
}
],
"gasLimit": "21000",
"gasPrice": "32000000000",
"sequence": "7",
"includeFee": true,
"nonceNumber": "26"
}
},
"toAddress": "0xcf76cc2abf1f4c09543d75213f5614ceae1e5ad6",
"reportingCurrencyRate": "1972.3",
"terminatedReportingCurrencyRate": "1972.3",
"feesPercent": "0",
"transactionId": "0x4c360211513c43681e8bb94e4d6bf01b32d35408b4a73d10f01a8257975fdfe7",
"partSigned": {
"uploadBy": "6bc831ef-277b-4299-8c7e-0b1364a1e853",
"transaction": {
"type": "part-signed-tx",
"value": "12woxmfrcjsk3Msdf8w="
},
"orderId": "36097872",
"partSignNumber": "1"
},
"signed": {
"uploadBy": "system",
"transaction": {
"txId": "0x4c360211513c43681e8bb94e4d6bf01b32d35408b4a73d10f01a8257975fdfe7",
"txRaw": "0xf86b0785077359400082520894cf76cc2abf1f4c09543d75213f5614ceae1e5ad6876e2eb7eda0cf2b8026a0ebf8e073ed2a379cde913f3f3e4e124710e9ba5fa18c6918526921203d5c051aa030906cc6408fb52c48d27668b56722ee90b3e5aaeffd1e4481093d3dfd8e37eb"
},
"orderId": "36097872"
},
"feeLevel": "low",
"includeFeeInWithdraw": true,
"withdrawFee": "0.000672",
"blockchainTransactionType": "send",
"estimatedFees": {
"fee": "0.000672",
"feeCurrency": "ETH",
"estimatedTime": "600000",
"reportingCurrencyRate": "1972.3",
"gasPriceGwei": "32",
"gasLimit": "21000"
}
},
"createdBy": "6bc831ef-277b-4299-8c7e-0b1364a1e853",
"organizationId": "1234567",
"createdAt": "1626347420199",
"updatedAt": "1636559739474",
"terminatedAt": "1626347556431"
},
]
}
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 |
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 |
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):
custody
- an individual address managed by a client.trading
- an address providing access to the treasury (custody part managed by Copper).external
- an address connected to Walled Garden exchanges.trading-vault
- an individual address allowed to take part in OTC trading on the Copper platform.clearloop
- an address connected to the ClearLoop.
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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
extra | OrderExtra |
Additional order data including information about the corresponding blockchain transaction |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
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 |
Get data of an order according to its ID
+ GET /platform/orders/{orderId}
This method allows to obtain data of an exact order according to its unique orderId
.
Required permissions: View
Properties
+ Response 200 (application/json)
{
"orders": [
"orderId": "36097318",
"externalOrderId": "414a024bfeb2c86c417d25cc2d1966c57bc7fb93067b17ee13801065d828dce6",
"status": "executed",
"orderType": "deposit",
"portfolioId": "ckm2cskb3000u3b5zpwoe4vzg",
"portfolioType": "external",
"accountId": "29af7ea0-5878-4a6a-93de-6647e0d287fa",
"amount": "0.099",
"baseCurrency": "LTC",
"mainCurrency": "LTC",
"extra": {
"fromPortfolioId": "ckomztrj3003h3a60dcqkk8eu",
"reportingCurrencyRate": "132.12",
"terminatedReportingCurrencyRate": "132.12",
"withdrawOrderId": "36096313",
"transactionId": "414a024bfeb2c86c417d25cc2d1966c57bc7fb93067b17ee13801065d828dce6"
},
"organizationId": "1234567",
"createdAt": "1626193444000",
"updatedAt": "1636559739474",
"terminatedAt": "1626193708344"
},
{
"orderId": "36097275",
"externalOrderId": "ckr21hjhn00003b5xy0myxqqt",
"status": "error",
"orderType": "withdraw",
"portfolioId": "ckmx8iv1s001o3g5zenbx1ku3",
"portfolioType": "custody",
"accountId": "29af7ea0-5878-4a6a-93de-6647e0d287fa",
"amount": "0.01104817",
"baseCurrency": "ETH",
"mainCurrency": "ETH",
"statusDescription": "Transaction was sent, but it failed in blockchain",
"extra": {
"transactionRequest": {
"publicKeyHash": "f7486bca5ccacacc88b72460448da45b5da1e35bbf00a9fbf7b8866591e06b79",
"currency": "ETH",
"mainCurrency": "ETH",
"amount": "1000000000000000",
"toAddress": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"includeFee": false,
"transactionRequest": {
"fee": "10048170000000000",
"outputs": [
{
"value": "1000000000000000",
"address": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"payload": "0x7ff36ab500000000000000000000000000000000000000000000000001591117364c3d95000000000000000000000000000000000000000000000000000000000000008000000000000000000000000096f8e8a885164ff725cd2d90597ab65883d6f4570000000000000000000000000000000000000000000000000000000060ed8d630000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d"
}
],
"gasLimit": "456735",
"gasPrice": "22000000000",
"sequence": "6",
"includeFee": false,
"nonceNumber": "23"
}
},
"toAddress": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"payload": "0x7ff36ab500000000000000000000000000000000000000000000000001591117364c3d95000000000000000000000000000000000000000000000000000000000000008000000000000000000000000096f8e8a885164ff725cd2d90597ab65883d6f4570000000000000000000000000000000000000000000000000000000060ed8d630000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d",
"reportingCurrencyRate": "2014.8035755605238",
"terminatedReportingCurrencyRate": "1977.93",
"feesPercent": "0",
"transactionId": "0x9c98b9e3fe02e24f482528f33b753710364b7560ff3da4af83eb917819f4f970",
"partSigned": {
"uploadBy": "6bc831ef-277b-4299-8c7e-0b1364a1e853",
"transaction": {
"type": "part-signed-tx",
"value": "q3wefijwe4s="
},
"orderId": "36097275",
"partSignNumber": "1"
},
"signed": {
"uploadBy": "system",
"transaction": {
"txId": "0x9c98b9e3fe02e24f482528f33b753710364b7560ff3da4af83eb917819f4f970",
"txRaw": "0xf901510685051f4d5c008306f81f947a250d5630b4cf539739df2c5dacb4c659f2488d87038d7ea4c68000b8e47ff36ab500000000000000000000000000000000000000000000000001591117364c3d95000000000000000000000000000000000000000000000000000000000000008000000000000000000000000096f8e8a885164ff725cd2d90597ab65883d6f4570000000000000000000000000000000000000000000000000000000060ed8d630000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d26a0cdc90d82430ac6ea3fb556b7a39dc4b9f7dd73c44b4c823f3a4ea1efdcd0cf55a024169eb95826eee73cd357cc6a1b361ff1fcb648f0ae66596c9be3e757660e9e"
},
"orderId": "36097275"
},
"feeLevel": "low",
"includeFeeInWithdraw": false,
"withdrawFee": "0.01004817",
"errorWithdrawFee": "0.000514514",
"blockchainTransactionType": "send",
"estimatedFees": {
"fee": "0.01004817",
"feeCurrency": "ETH",
"estimatedTime": "600000",
"reportingCurrencyRate": "2014.8035755605238",
"gasPriceGwei": "22",
"gasLimit": "456735"
},
},
"createdBy": "6bc831ef-277b-4299-8c7e-0b1364a1e853",
"organizationId": "1234567",
"createdAt": "1626179835497",
"updatedAt": "1636559739474",
"terminatedAt": "1626188136294"
},
]
}
Request
The request of the method does not have any additional parameters.
Response
The response of the method contains one instance of the orders
with the requested order data:
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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
extra | OrderExtra |
Additional order data including information about the corresponding blockchain transaction |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
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",
"feeLevel": "low",
"includeFeeInWithdraw": false,
"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",
"feeLevel": "low",
"includeFeeInWithdraw": false
},
"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, should not be blank) |
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 | Optional<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 |
portfolioType | Enum<PortfolioType> |
Type of the portfolio (see the PortfolioType model below) |
accountId | String |
Account idenifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Main currency of the blockchain |
quoteCurrency | Optional<Currency> |
Trading quote currency |
limitType | Optional<LimitType> |
Limit type (see above) |
priceLimit | Optional<BigDecimal> |
Limit value for order with the corresponding limitType |
extra | OrderExtra |
Additional order data |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | Optional<String> |
Unique ID of the organisation of the creator |
createdAt | Long |
Time of order creation |
updatedAt | Optional<Long> |
Time of the latest order update |
terminatedAt | Optional<Long> |
Time of the order termination |
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
orderId
- Unique order identifier generated upon its creation (see theOrder
model).
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 |
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 (enter manually) |
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 | 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):
custody
trading-vault
trading
DepositTargetTypeEnum
Enum describing type of deposit target:
direct
- funds sent to this target will be directly allocated in the portfolio. Direct deposit targets can include one direct mainCurrency for one vault and multiple currencies for trading.proxy
- proxy wallet: funds come to this deposit target first, and then are redirected to the direct address (in case of using proxy wallets, do not forget about transfer fees). This deposit target type is available only for Vault accounts.
DepositTargetStatusEnum Enum describing a current status of a particular deposit target with following possible values (the values can be changed in the future):
new
- a customer has requested a new deposit target.pending
- a new deposit target is being created (a new deposit target cannot be used with this status).enabled
- a deposit target is ready and can accept funds.
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 | 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 the platform webhooks.
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"
}
The Copper platform has a built-in webhook system to subscribe your service on definite events connected with deposit and withdrawal of funds.
The events will be automatically sent to your resource in JSON format as a POST method payload. Webhook events are not sent for internal transfers on the platform.
Available webhook events:
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-transaction-sent |
Withdraw transaction has been sent to the corresponding blockchain |
withdraw-completed |
Withdraw order has been completed |
Contents of a webhook message
Each webhook message sent by the Copper platform to your service has the following structure:
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 (see example of orders in the Transfer API section for details) |
On the right panel, you will find a corresponding example of the webhook message. The actual payload can differ depending on a corresponding order.
Webhook backend on your side
import hashlib
import hmac
from flask import Flask, request
app = Flask(__name__)
WebhookSecret = '<YOUR_SECRET_FROM_UI>'
@app.route('/', methods=['POST'])
def handle():
timestamp = request.headers.get('X-Timestamp')
event_id = request.get_json().get('eventId')
signature = hmac.new(
key=bytes(WebhookSecret, 'utf-8'),
msg=bytes(timestamp + event_id + request.get_data().decode("utf-8"), 'utf-8'),
digestmod=hashlib.sha256
).hexdigest()
if hmac.compare_digest(request.headers.get('X-Signature'), signature):
return 'OK', 200
else:
return 'Bad signature', 400
if __name__ == '__main__':
app.run(debug=True)
To accept webhook messages, you have to add a web application with a route to accept POST calls from the Copper platform.
The platform calls do not require authorisation, that is why you have to implement verification of a signature provided with each webhook message. To compare signatures:
- sign the entire message with the secret key obtained from the platform UI (see the guidance below) with the use of the
X-Timestamp
value from the message header; - compare the obtained signature with the
X-Signature
value obtained from the header of the same webhook message.
The X-Signature
header is hmac sha256 hash in hex format.
On the right panel, you will find an example of the backend code on Python developed with the use of the Flask library.
To run it on your side, create the __init__.py
file and run it. The service will be exposed to your localhost on the port 5000. Then, expose it to an external domain name - for instance, with the use of the ngrok package.
For debug purposes, you can calculate and verify a request signature of a webhook message with the use of following Bash commands:
# 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}'
In this example:
${timestamp}
is a value you can get from theX-Timestamp
header;${eventId}
is provided within the webhook message;${body}
is the entire webhook message;${secretKey}
is your key obtained within the platform UI (see the guidance below).
How to set up webhooks on the Copper platform
To set up webhooks on the Copper platform, navigate to the Webhooks sub-menu situated in the menu of your account in the bottom-left corner.
In the Webhooks menu, click the Add new button and enter following information:
- Choose portfolios to subscribe on from the dropdown list;
- Enter the URL of your webhook endpoint, e.g.
https://your-domain.com/webhook/path
- only HTTPS addresses are acceptable; - Select the event types to subscribe on.
Click the Generate button to obtain your secret key in order to verify incoming webhook messages. The secret key will be shown only while creating the webhook.
Then, click the Save button to add your webhook address. After this, your service will start to obtain webhook messages occuring within your organisation for specified portfolios.
In the Webhooks menu, you will see webhook endpoints that are currently in operation. You can suspend sending webhook messages to a definite URL by clicking the Pause button, as well as Edit the webhook setup or Delete it.
By clicking upon a definite webhook URL, you will see latest webhook messages transferred to your service and their content, as well as portfolios specified for a definite endpoint.
Copper Unlimited Online
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/
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:
- listens to port 3010 for incoming data and 443 for outgoing calls;
- connects with the Copper API, depending on a chosen
APP_ENVIRONMENT
; - supports SSL/TLS. To enable encryption, see Enabling SSL/TLS section below.
How to launch
- 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. - 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/mainnet
- https://api.copper.co/ The choice depends on a platform you are going to operate on.
- a path to your folder with the
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
- Start CU Online:
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
- Create a withdraw order (e.g., to move funds from a Vault to a Walled Garden exchange):
+ 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"
}
- Start the transaction settlement flow:
+ 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"
}
- Sign the transaction asynchronously with the use of the Copper Unlimited Online:
+ 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.
- Optionally, get the status of your request using your
transactionRequestId
:
+ 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.
- Start CU Online:
docker run --rm -ti \
-v ${PWD}/key-backups/:/app/keys/ \
-p 3010:3010 \
copperexchange/copper-unlimited:latest
- Create a withdraw order (e.g., to move funds from a Vault to a Walled Garden exchange):
+ 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"
}
- Start the transaction settlement flow:
+ 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"
}
- Sign the transaction in the local deployment of the CU online:
+ 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. Here, enter your Withdrawal password.
- Upload the partly-signed transaction to Copper:
+ 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:
- Generate custom certificates:
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
- Add the path to the folder containing certificates as volumes:
-v ${PWD}/ssl/certificate.cert:/app/ssl/certificate.cert
, as well as-v ${PWD}/ssl/privatekey.key:/app/ssl/privatekey.key
:
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
Example of the service
In order to familiarise you with operation of Copper Unlimited Online, the Copper Team have the ready-made containerised example of the service to deploy on your side.
It looks like one more image to deploy together with the Copper Unlimited Online and is available in Copper DockerHub.
The application works as follows:
- The application pulls orders in the
working
andawaiting-settlement
status using Copper public API. If there are no orders available, application enters the sleeping mode for 10 seconds. - Then, the application takes the first order, and if it is in the
awaiting-settlement
status, moves it to theworking
status. - After this, it triggers the order signing request to the Copper Unlimited Server.
- The application waits until the request will be either in the
completed
or in theerror
status. - If request is in
error
status - fires an error, if is incomplete
repeat the whole process starting from the first point.
To deploy and test the service, perform following steps:
1. Configure your docker-compose.yml
file. Below, you will find a complete example with comments:
version: "3.7"
services:
cu-server: # Copper Unlimited Online service
container_name: cu-server
image: copperexchange/copper-unlimited:latest
ports:
- "3010:3010"
volumes:
- ${PWD}/key-backups/:/app/keys/ # Specify the correct path to your shards before the colon
environment:
APP_ENVIRONMENT: "testnet" # Specify the environment where you are going to use the service. Possible variants: "testnet", "stage" or "mainnet"
APP_NETWORK: "testnet"
networks:
- cu-network
hot-wallet:
image: copperexchange/hot-wallet:latest
depends_on:
- cu-server
volumes:
- ${PWD}/wallets-config.js:/app/wallets-config.js # Specify the correct path to your wallet-config.js file before the colon.
environment:
APP_ENVIRONMENT: "testnet" # Specify the environment (see above)
APP_CUSTODY_DOCKER_URL: "http://cu-server:3010" # Link to the CU Online container
APP_API_KEY: "" # Your API key from a desired environment
APP_API_SECRET: "" # API secret associated with the API key
APP_WITHDRAWAL_PASSWORD: "" # Withdrawal password from your organisation in a desired environment
networks:
- cu-network
networks:
cu-network:
driver: bridge
2. Backup your wallet shards and place them in the directory specified as an external volume for the cu-server
container (in the example: ${PWD}/key-backups/
). Do not forget to activate the created wallets in the desired platform environment and request to switch corresponding vaults to hot if it is has not been done before.
3. Configure your wallets-config.js
file containing details of the shards. Below, you will find the example with the comments:
module.exports = [
{
portfolioId: 'ckuwfho1y000p3e626z2zmmoy', // Identifier of the portfolio containing the wallet
currency: 'SOL', // Wallet currency
walletFilename: 'sol-wallet.copper', // Name of the file containing the wallet shard
walletPassword: process.env.SOL_WALLET_PASSWORD, // Password
},
{
portfolioId: 'cd213vvo1y000p3e62dd21dhy', // You may specify as many shards as needed separating details with commas
currency: 'ALGO',
walletFilename: 'algo-wallet.copper',
walletPassword: process.env.ALGO_WALLET_PASSWORD,
},
];
Place this file in the directory specified as an extrnal volume for the hot-wallet
container (in the example: ${PWD}/wallets-config.js
).
As per the example, the resulting file composition on this step looks as follows:
/${PWD}
├── key-backups
│ ├── sol-wallet.copper
│ └── algo-wallet.copper
├── docker-compose.yml
└── wallets-config.js
4. Start your service with the use of the docker-compose up --build
command.
5. Use the specified environment of the Copper platform to create withdrawal orders. They will be signed and pushed forward automatically.
User flows
This section includes combined use-cases of the Copper platform API.
Create a deposit target
Choose the portfolio (vault) you want to create a deposit target for. Remember the
portfolioId
.Create the deposit target via the
POST /platform/deposit-targets
method:
+ POST /platform/deposit-targets
+ Request
{
"externalId": "[[external id]]", # Enter the external ID manually
"portfolioId": "[[portfolio id]]", # Paste the portfolio ID here
"currency": "USDT", # Portfolio currency
"mainCurrency": "ALGO", # Portfolio main currencny
"name": "Algo Wallet", # Arbitrary name
"metadata": {
"tags": ["test"] # Arbitrary tag
}
}
Move funds between accounts
Choose the portfolios from/to where you want to move funds using the
GET /platform/accounts
method. RememberportfolioId
s for chosen accounts.Create a withdraw order using the
POST /platform/orders
method with the parameters of your portfolios:
+ 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
Choose a bank account to withdraw to with the use of the
GET /platform/bank-accounts
method.Remember the bankAccountId of the chosen bank account.
Choose the portfolio wallet you want to withdraw from using the
GET /platform/accounts
method. RememberportfolioId
for the chosen account.Create a withdraw order order using the
POST /platform/orders
with the parameters from the previous steps.
+ 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
Choose the portfolio wallet you want to withdraw from using the
GET /platform/accounts
method. RememberportfolioId
for the chosen account.Choose a withdraw target: fill the
toAddress
,destinationTag
andmemo
fields: this option will be acceptable for unknown or external addresses.Create a withdraw order using the
POST /platform/orders
method with the parameters of the specified withdraw target.
+ 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
Choose the portfolio wallet you want to withdraw from using the
GET /platform/accounts
method. RememberportfolioId
for the chosen account.Choose a withdraw target: use an already saved (whitelisted)
cryptoAddress
from theGET /platform/crypto-addresses
method.Create a withdraw order using the
POST /platform/orders
method with the parameters of the specified withdraw target.
+ 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
Choose the portfolio wallet you want to withdraw from using the
GET /platform/accounts
method. RememberportfolioId
for the chosen account.Choose a withdraw target: fill the
toPortfolioId
field to transfer crypto to other account within the platform (including custody, Walled Garden or other types of accounts).Create a withdraw order using the
POST /platform/orders
method with the parameters of the specified withdraw target.
+ 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
Choose the portfolio wallet you want to withdraw from using the
GET /platform/accounts
method. Remember theportfolioId
for a chosen account.Choose a withdraw target: fill the
toAddress
field: this option can be used for unknown or external addresses.Create a withdraw order using the
POST /platform/orders
method with the parameters of the specified withdraw target.
+ 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
Choose the portfolio wallet you want to withdraw from using the
GET /platform/accounts
method. Remember theportfolioId
for a chosen account.Choose a withdraw target% use an already saved (whitelisted)
cryptoAddress
from theGET /platform/crypto-addresses
method.Create a withdraw order using the
POST /platform/orders
method with the parameters of the specified withdraw target.
+ 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:
Backup the shards of your HNT wallet from the Copper Unlimited app. To do this, choose the Backup option for your wallet in Copper Unlimited. Save the .copper file in a preferred directory.
Start the Copper Unlimited Online with the saved shards of the HNT wallet. When started, the IP address and the corresponding port of the service will be displayed in the terminal.
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
- Create a Copper platform withdraw order with a
stake-delegation
blockchain transaction type. The request should include following fields:
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 |
- In response, obtain the set of fields describing the transaction to be sent.
+ 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"
}
- Use the
orderId
field from the method response to start settlement. Save thetransactionRequest
fields of the method response for the next step.
+ PATCH https://api.copper.co/platform/orders/{orderId}
+ Headers
Content-Type: application/vnd.start-custody-settlement+json
- Sign the transaction with the use of your dockerised Copper Unlimited Online. In the request, specify your CU master password in the
keyPassword
field, as well as the name or path to the .copper file containing shards of your wallet in thekeyFilename
field. In response, obtain the status of the transaction and the hashed transaction itself. These fields are used in the next step.
+ 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=",
}
- Upload the partly-signed transaction to Copper.
+ 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:
Backup the shards of your XZC wallet from the Copper Unlimited app. To do this, choose the Backup option for your wallet in Copper Unlimited. Save the .copper file in a preferred directory.
Start Copper Unlimited Online:
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
- Create the wallet message with the use of the
POST platform/wallet-messages
method:
+ 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"
}
- Sign message in Copper Unlimited Online:
+ 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=",
}
- Upload the partly-signed message to Copper.
+ 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="
}
}
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"
}
]
}
Binance Smart Chain: sending unjail transaction
The unjail transaction is designed for releasing validator nodes that were jailed (blocked) for suspiciously malicious or negative behaviour.
This transaction can be sent from an address of a validator operator that is within the Copper ecosystem.
Official reference about the unjail transaction can be found here.
The unjail transaction can be sent from the address within the Copper ecosystem with the use of the POST /platform/orders
method with the payload described below.
+ POST /platform/orders
+ Request
{
"externalOrderId": "{{externalId}}",
"orderType": "withdraw",
"baseCurrency": "BNB",
"mainCurrency": "BNB",
"amount": "0",
"blockchainTransactionType": "unjail",
"portfolioId": "{{portfolioId}}"
}
+ Response 200 OK
Changelog
February 2022
- Address validation endpoint has been implemented.
December 2021
- The workflows for creating a deposit target and sending an unjail transaction into the Binance Smart Chain has been added to the User Flows section.
- The
GET /orders/{orderId}
endpoint has been described for Trading and Transfer API.
November 2021
- The
includeOutstandingBalance
parameter has been included into theGET /platform/wallets
method of the Account API. - Copper Unlimited Server has been renamed to Copper Unlimited Online.
- The description of the deprecated
POST http://0.0.0.0:3010/signatures
method of the Copper Unlimited Online has been changed for the newPOST http://0.0.0.0:3010/sign-async/
method with a corresponding warning.
October 2021
- Completely new API documentation engine.
Methods of the Orders API have been divided into three sets of methods:
- Trading API - methods for operating eOTC trading orders;
- Settle API - methods for operating OTC trading orders;
- Transfer API - methods for operating deposit and withdraw orders. This section also includes the corresponding webhooks.
The Wallet Messages API previously stated only in the User Flows, has been moved to a separate section.
Description of the Proxy Wallet API has been expunged and substituted with the new Deposit API.
The present Changelog article has been created.