Introduction
The Copper platform is equipped with a powerful API to provide integration with your applications. This documentation describes composition and usage of available API endpoints.
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.
- Common API operations - API methods that are related to platform orders and unified for subsequent APIs
- Transfer API - API methods for transferring cryptocurrency.
- Copper Network API - API methods to perform operations available via Copper Network.
- Deposit API - API methods provided for operations with deposit targets.
Webhooks
The Copper platform provides the webhook service which can send information about platform events to your resource for further handling. This way of data exchange is recommended for usage together with a conventional API polling.
To learn more, refer to the Webhooks section.
Copper Unlimited Online
Copper Unlimited Online is an alternative to the Copper Unlimited desktop application: a Docker image deployed independently on the client side and providing swift signing of transactions from Hot Vaults.
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
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.
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.
When interacting with the API, please note that all numerical values, such as order amounts or timestamps, should be transmitted as strings. This ensures consistent data representation and prevents potential issues with floating-point precision.
You can try our API using Postman.
To do this, use our Postman API collection.
Platform REST API URL: https://api.copper.co.
For Demo environment (demo.copper.co), you can use https://api.stage.copper.co
Authorisation
The majority of 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.
The only method available without an API key:
Below, you will find request authorisation examples for Bash and Python.
#!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())
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
.
Request limitations
Copper API limits the number of API requests. The rate limit depends on request type. If the limit is exceeded, the request processing for the IP address or UserID is blocked for the specified lockup period.
Request type | Limit | Lockup period |
---|---|---|
HTTP request | 30000 requests per last 5 minutes for a single IP address | Until the number of requests in last 5 minutes is less than 30000 |
Authorization errors (wrong API key or signature) | 200 failed requests per 1 hour for a single IP address | 1 hour |
Erroneous API requests (any business logic errors - bad request, missed required parameters, wrong amounts, currencies, etc) | 60 requests per 1 minute for a single UserID | 3 minutes |
If either of the limits is exceeded, the Copper API returns Error 429.
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 |
429 | Request Limit Exceeded | The request rate limit is exceeded. Request processing is temporarily blocked |
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.
Accounts API
Retrieve portfolios
+ GET /platform/portfolios
This method allows to retrieve your portfolios (in UI terms - accounts).
Required API Key permissions: View
Properties
+ Response 200 OK (application/json)
{
"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": "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 |
---|---|---|
isArchive | Optional<Boolean> |
false (default value) - the requested account is active, true - the requested account is archived |
portfolioTypes | Optional<String> |
Filter the portfolios by type (see the PortfolioType variants below), may include multiple comma-separated types |
Response
Field | Data type | Description |
---|---|---|
portfolios | List<Portfolio> |
List of portfolios |
Retrieve a portfolio by id
+ GET /platform/portfolios/{portfolioId}
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.
+ 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": {}
}
Response
On success, the Portfolio
is returned.
Retrieve wallets
+ GET /platform/wallets
When you perform request without specifying any additional filters like portfolioId
or currency
, the method returns all wallets which has non-zero balances only.
Required API Key permissions: View
+ Response 200 OK (application/json)
{
"wallets": [
{
"walletId": "cleoe9air000u3b5o7m9f8npb",
"portfolioId": "302fcb96-ec2b-4fff-88a5-2773cd77d112",
"currency": "BTC",
"mainCurrency": "BTC",
"balance": "1.01480155",
"stakeBalance": "0",
"totalBalance": "1.01480155",
"rebateBalance": "0",
"reserve": "0.00014972",
"locked": "0",
"available": "1.01465183",
"pledged": "0",
"createdAt": "1677597540441",
"createdBy": "75ed05af-ac02-4809-8891-e19ab395f59a",
"updatedAt": "1677601972985",
"accountId": "e23d0427-e312-4cd5-a1b3-cc32b7843ba8",
"organizationId": "TESTORG",
"portfolioType": "custody",
"isActive": true
},
{
"walletId": "7dd60ed7-eba0-4330-9249-15b14b8d9652",
"portfolioId": "592d8ae70ecb39139",
"currency": "USD",
"balance": "885",
"stakeBalance": "0",
"totalBalance": "885",
"rebateBalance": "0",
"reserve": "14.00",
"locked": "0",
"available": "871.00",
"physical": "885",
"pledged": "0",
"createdAt": "1658833481574",
"createdBy": "4a2a3625-12ca-4cfc-9732-8c4951de73f9",
"updatedAt": "1671201428375",
"extra": {},
"accountId": "e23d0427-e312-4cd5-a1b3-cc32b7843ba8",
"organizationId": "SIDORENKOINC",
"portfolioType": "trading-vault",
"isActive": true
}
]
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
portfolioId | Optional<String> |
Unique identifier of a portfolio |
currency | Optional<Currency> |
Filter wallets for a particular currency, may include multiple comma-separated currencies codes |
mainCurrency | Optional<Currency> |
Filter wallets for a particular main currency (chain), may include multiple comma-separated main currencies codes |
nonEmpty | Optional<Boolean> |
Filter only non zero wallets |
Response
Field | Data type | Description |
---|---|---|
wallets | List<Wallet> |
List of wallets |
Retrieve a wallet by id
+ GET /platform/wallets/{walletId}
Required API Key permissions: View
Properties
+ Response 200 OK (application/json)
{
"walletId": "cleoe9air000u3b5o7m9f8npb",
"portfolioId": "302fcb96-ec2b-4fff-88a5-2773cd77d112",
"currency": "BTC",
"mainCurrency": "BTC",
"balance": "1.01480155",
"stakeBalance": "0",
"totalBalance": "1.01480155",
"rebateBalance": "0",
"reserve": "0.00014972",
"locked": "0",
"available": "1.01465183",
"pledged": "0",
"createdAt": "1677597540441",
"createdBy": "75ed05af-ac02-4809-8891-e19ab395f59a",
"updatedAt": "1677601972985",
"accountId": "e23d0427-e312-4cd5-a1b3-cc32b7843ba8",
"organizationId": "SIDORENKOINC",
"portfolioType": "custody",
"isActive": true
}
Response
On success, the Wallet
is returned.
Retrieve crypto addresses
+ GET /platform/crypto-addresses?currency=BTC&address=SomeBTCwalletAddress&limit=1000
This method allows to retrieve information about all crypto addresses in an organization's address book.
Required permissions: View
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 can include following parameters:
Parameter | Data type | Description |
---|---|---|
organizationId | Optional<String> |
Unique organization identifier, user must be allowed to access the organization |
address | Optional<String> |
Blockchain address |
memo | Optional<String> |
Memo of Deposit Target |
currency | Optional<Currency> |
Filter wallets for a particular currency, may include multiple comma-separated currencies codes |
mainCurrency | Optional<Currency> |
Filter wallets for a particular main currency (chain), may include multiple comma-separated main currencies codes |
isWhitelist | Optional<Boolean> |
Filter for isWhitelist being true or false, defaults to no filter |
limit | Optional<Integer> |
Number of records to return, defaults to 500 if parameter is absent |
offset | Optional<Integer> |
Number of records to skip over, defaults as 0 if parameter is absent |
Response
Field | Data type | Description |
---|---|---|
cryptoAddresses | List<CryptoAddresses> |
Retrieve bank accounts
+ GET /platform/bank-accounts
This method allows to retrieve information about all fiat addresses in an organization's address book.
Required API Key permissions: View
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"
}
]
}
Response
Field | Data type | Description |
---|---|---|
bankAccounts | List<BankAccount> |
Download account reports
+ POST /platform/reports/{report-category}/{report-type}
This method is designed for generation of an account report.
The method requires both the report-category
and report-type
string in the endpoint:
The request header of this method may include following field:
Field | Data type | Description |
---|---|---|
Accept | Optional <String> |
Set to application/zip and the generated binary report file is contained within a .zip file format. This is now the recommend approach when downloading account reports. |
Report Category & Report Type options are:
Wallets
"/wallets/wallets-snapshots"
- displayed asBalances
on the UI"/wallets/net-asset-values"
- displayed asPosition Statement
on the UI
The request body of this method includes following fields:
Field | Data type | Description |
---|---|---|
dateFrom | Long |
Timestamp in milliseconds for the initial report entry |
dateTo | Long |
Timestamp in milliseconds for the last report entry |
organizationId | Optional <String> |
Filter entries by a definite organisation identifier |
portfolioId | 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 |
Example
URL - https://{env}/platform/reports/wallets/wallets-snapshots
Payload - {dateFrom: "1726704000639", dateTo: "1727395199639", organizationId: "TEST_ORG"}
Orders
"/orders/net"
The request body of this method includes following fields:
Field | Data type | Description |
---|---|---|
terminatedAtFrom | Long |
Timestamp in milliseconds for the initial report entry |
terminatedAtTo | Long |
Timestamp in milliseconds for the last report entry |
reportType | String |
orders , trading , transfers |
organizationId | Optional <String> |
Filter entries by a definite organisation identifier |
portfolioId | 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 |
orderTypes | Optional Set< OrderType > |
Filter entries by a number of orderType |
Example
URL - https://{env}/platform/reports/orders/net
Payload - {"terminatedAtFrom": "1726704000639", "terminatedAtTo": "1727395199639", "reportType": "orders", "organizationId": "TEST_ORG"}
Stake
"/stake/orders"
"/stake/rewards"
The request body of this method includes following fields:
Field | Data type | Description |
---|---|---|
terminatedAtFrom | Long |
Timestamp in milliseconds for the initial report entry |
terminatedAtTo | Long |
Timestamp in milliseconds for the last report entry |
reportType | String |
rewards , staking-order |
organizationId | Optional <String> |
Filter entries by a definite organisation identifier |
portfolioId | 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 |
orderTypes | Optional Set< OrderType > |
Filter entries by a number of orderType |
Example
URL - https://{env}/platform/reports/stake/rewards
Payload - {"terminatedAtFrom": "1726704000639", "terminatedAtTo": "1727395199639", "organizationId": "TEST_ORG", "reportType": "rewards"}
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"
}
Alternatively, when Accept
header is set to application/zip
shell
+ Response 201 Created
{
"fileId": "wallets-snapshots/30c1464a6774d85b1a5802d15826c7ad.zip"
}
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.
Shared Order API
This section includes the most common operations with the Copper platform API unified for the subsequent sections:
Operations with orders (create, cancel) are described in the corresponding sections above as well but include links to the models in this section and operation-specific examples.
Also, each subsequent section includes specific order statuses.
Retrieve orders
+ GET /platform/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:
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 |
portfolioType | Optional Set< PortfolioType > |
Return orders that are related to specified portfolio types. If multiple types set, they should be comma-separated.E.g. trading,custody |
currency | Optional <String> |
Filter by the order currency |
orderType | Optional Set< OrderType > |
Filter by order type. If multiple types set, they should be comma-separated.E.g. buy,sell |
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 timestamp and sorted in ASC (oldest first) |
createdSince | Optional <String> |
Timestamp in milliseconds returning all orders created since a requested timestamp |
terminatedAtFrom | Optional <Long> |
Timestamp in milliseconds returning all orders terminated since a requested timestamp |
terminatedAtTo | Optional <Long> |
Timestamp in milliseconds returning all orders terminated before a requested timestamp |
baseCurrency | Optional <Currency> |
Filter by the order base currency |
mainCurrency | Optional <Currency> |
Filter by blockchain main currency |
quoteCurrency | Optional <Currency> |
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 |
status | Optional Set< OrderStatus > |
Filter by status |
Please note that orders in the response are sorted by the createdAt
timestamp in DESC (newest first) order. This is the case unless an updatedSince
search parameter is provided, which changes the sorting order to ASC (oldest first) by the updatedAt
timestamp.
If no parameters are set in the request, the response will contain the latest 1000 orders.
Response
The response of the method contains the orders
list, each order includes the fields according to the order
model: See Order
Retrieve an order by id
+ GET /platform/orders/{orderId}
This method allows to retrieve an order by its id
Properties
+ Response 200 (application/json)
{
"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",
"toAddress": "0xcf76cc2abf1f4c09543d75213f5614ceae1e5ad6",
"reportingCurrencyRate": "1972.3",
"terminatedReportingCurrencyRate": "1972.3",
"feesPercent": "0",
"transactionId": "0x4c360211513c43681e8bb94e4d6bf01b32d35408b4a73d10f01a8257975fdfe7",
"feeLevel": "low",
"includeFeeInWithdraw": true,
"withdrawFee": "0.000672",
"blockchainTransactionType": "send"
},
"createdBy": "6bc831ef-277b-4299-8c7e-0b1364a1e853",
"organizationId": "1234567",
"createdAt": "1626347420199",
"updatedAt": "1636559739474",
"terminatedAt": "1626347556431"
}
Response
See Order
Approve an order
+ PATCH /platform/orders/{orderId}
+ Header
Content-Type: application/vnd.co-sign-order+json
+ Response 200 OK (application/json)
This method allows to approve an order in co-sign-require status
Properties
Response
This method returns an empty JSON object.
Cancel an order
+ PATCH /platform/orders/{orderId}
+ Header
Content-Type: application/vnd.cancel-order+json
+ Request
{}
This method allows to cancel an issued withdrawal or buy/sell order.
Withdraw
for a withdrawal orderTrading
for buy/sell orders for eOTC and OTC trading operations
Properties
Response
This method returns an empty JSON object.
Validate a blockchain address
+ POST /platform/address-validations
This method allows to check if an entered blockchain address is valid (exists in a specified 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 | String |
Blockchain main currency. |
currency | String |
Blockchain address currency. |
address | 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<Currency> |
Blockchain main currency. |
currency | Optional<Currency> |
Blockchain address main currency. |
address | Optional<String> |
Blockchain address that has been validated. |
Copper Network API
The Copper Network is a settlement network that enables counterparties to create and execute bilateral settlements while minimizing counterparty risk on the Copper Platform. Copper Network supports both crypto-to-crypto settlements and Fiat-linked settlements.
In addition to settlements between Copper Clients, the Copper Network also allows custodian-agnostic settlements through Copper Lite. This means that users can access the Copper Settlement network even if they are not registered as a Copper Custody Client.
The following settlement order types are currently supported by the Copper Network:
- Payment vs Payment (PvP): PvP settlement orders require both counterparties to complete their opening legs before triggering the closing settlement legs. This ensures that a delivery occurs only if another delivery has occurred (and vice versa).
- Free of Payment (FoP): in FoP settlement orders, the settlement legs are transferred independently of each other.
The status of active Copper Network Settlements and Transfers can be monitored and actioned for approval or cancellation from the order
response.
Retrieve Copper Network participants
+ GET /platform/organizations/{organizationId}/counterparties
+ Response 200 OK:
{
"counterparties": [
{
"counterpartyId": "7296511f-5940-4a91-a99d-79caaa48907f",
"counterpartyName": "Copper Network",
"networkTag": "copper",
"counterpartyType": "standard",
"tags": [
"featured"
],
"counterpartyDescription": "Copper Network Card",
"_embedded": {
"counterpartyDetails": {
"counterpartyId": "92d06217-4daa-4c13-8484-af0173c60d5d",
"counterpartyAddress": "Counterparty Address",
"counterpartyPhoneNumber": "Counterparty Phone Number",
"counterpartyEmail": "Counterparty Email"
}
}
},
{
"counterpartyId": "92d06217-4daa-4c13-8484-af0173c60d5d",
"counterpartyName": "Copper Network Connected Counterparty",
"networkTag": "copper-connected",
"counterpartyType": "standard",
"tags": [
"featured"
],
"_embedded": {
"counterpartyConnection": {
"connectionId": "cde182baff1d3fe1e54f6e35baacc741",
"requestorCounterpartyId": "bdbd7818-0b19-4e47-998d-0e268e9723d6",
"receiverCounterpartyId": "92d06217-4daa-4c13-8484-af0173c60d5d",
"requestStatus": "accepted"
}
}
}
]
Retrieve the list of Copper Network Participants available for your organisation.
Required API Key permissions: Trading
Request
The request may include following filtering options:
Field | Data | Description |
---|---|---|
organizationId | String |
Unique identifier of a counterparty on the Copper Platform |
search | String |
String used to find one or more counterparties according to their counterpartyName , networkTag or counterpartyDescription . This string can include minimum three characters. |
isConnected | Boolean |
Boolean value used to find only counterparties which accepted a network connection request |
Response
Field | Data type | Description |
---|---|---|
counterparties | Counterparties |
Settle via Copper Network
Use the following methods to settle an order via Copper Network.
Get currencies and tokens supported for trading
+ GET /platform/currencies?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
+ Response 200 OK:
{
"currencies": [
{
"currency": "ETC",
"mainCurrency": "ETC",
"name": "Ethereum Classic",
"priority": "0",
"confirmations": "120",
"decimal": "18",
"tags": [
"show-trading"
]
}
]
}
Create a settlement order via Copper Network
+ POST /platform/orders
Required API Key permissions: Trading
Request
+ Request
{
"externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
"orderType": "buy",
"baseCurrency": "BTC",
"quoteCurrency": "USD",
"amount": "5",
"portfolioId": "46",
"limitType": "otc",
"priceLimit": "3300.57",
"toCounterpartyId": "e9caae7f-2b69-4513-b909-31531e07ad98",
"description": "Some description"
}
This request should include the following:
+ Response 201 (application/json)
{
"orderId": "35981617",
"externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
"status": "waiting-counterparty-approve",
"orderType": "buy",
"portfolioId": "46",
...
}
Field | Data type | Description |
---|---|---|
externalOrderId | String |
Unique order identifier from client (should be unique for the portfolio) |
orderType | OrderType |
The type of the order. Acceptable buy or sell |
portfolioId | String |
Unique identifier of the portfolio, for which the order will be created |
toCounterpartyId | String |
Unique identifier of the counterparty |
amount | BigDecimal |
Trading amount |
quoteAmount | Optional<BigDecimal> |
Trading quote amount. Must be provided if priceLimit is missing |
baseCurrency | Currency |
Currency of the amount |
quoteCurrency | Currency |
Trading quote currency |
mainCurrency | Currency |
Currency defining a blockchain network for baseCurrency |
quoteMainCurrency | Currency |
Currency defining a blockchain network for quoteCurrency |
limitType | LimitType |
The limit type of the order. Acceptable otc |
priceLimit | Optional<BigDecimal> |
Price of a settle order. Must be provided if quoteAmount is missing |
description | Optional<String> |
Arbitrary description allowing to identify an order |
deliveryType | Optional<DeliveryType> |
Settlement order type. Use free-of-payment or payment-vs-payment (default) |
Response
On success, the Order
is returned. Includes deliveryType
: free-of-payment
or payment-vs-payment
.
Accept an OTC order
+ PATCH /platform/orders/{counterpartyOrderId}
Required API Key permissions: Trading
+ Header
Content-Type: application/vnd.approve-counterparty-otc+json
+ Response 200 OK (application/json)
Use this method to accept an OTC order (from the counterparty side) 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.
Transfer via Copper Network
Use the following methods to transfer funds between Copper Network participants.
Create a one way transfer order via Copper Network
Transfers are one-way movements of funds between Copper Network participants.
+ POST /platform/orders
Required API Key permissions: Withdraw
Request
+ Request
{
"externalOrderId": "484e89d6-0124-4193-b4f8-59ba2dc91008",
"orderType": "withdraw",
"baseCurrency": "BTC",
"amount": "5",
"portfolioId": "46",
"toCounterpartyId": "e9caae7f-2b69-4513-b909-31531e07ad98",
"description": "Some description"
}
This request should include the CreateOrder
model specific for trading:
+ Response 201 (application/json)
{
"orderId": "35981617",
"externalOrderId": "F7FCCFD3-B61B-4467-B456-B0FC27CE4494",
"status": "co-sign-require",
"orderType": "withdraw",
"portfolioId": "46",
...
}
Field | Data type | Description |
---|---|---|
externalOrderId | String |
Unique order identifier from client (should be unique for the portfolio) |
orderType | OrderType |
The type of the term of the order. Acceptable withdraw |
portfolioId | String |
Unique identifier of the portfolio, for which the order will be created |
toCounterpartyId | String |
Unique identifier of the counterparty |
amount | BigDecimal |
Amount of assets to be transferred |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Currency |
Currency defining a blockchain network for baseCurrency |
description | Optional<String> |
Arbitrary description allowing to identify an order. |
Response
On success, the Order
is returned.
Approve a transfer order
+ PATCH /platform/orders/{orderId}
+ Header
Content-Type: application/vnd.co-sign-order+json
+ Response 200 OK (application/json)
Required API Key permissions: Withdraw
This method allows to approve a Transfer order by required approves specified in withdraw limits of an organization and of a team member, by whom the transfer order has been created.
Transfer API
Create withdraw order
This method creates a deposit or withdraw order on the Copper platform.
Note: from 24 January 2024, all outgoing withdrawal orders will need to include beneficiary information. Financial regulations require us to collect this information under the Travel Rule. To provide this information use cryptoAddressId from the address book.
To use Transfer API the address must be created in the address book and linked to an address Owner. Owner can only be created via Copper Platform UI and requires filling in the owner information: address, name etc. In order to link the address to the Owner properly, it is recommended to create the addresses with the owners via the Copper Platform UI first.
Example of withdraw order to external address (with travel rule data)
+ POST /platform/orders
+ 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",
"toCryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv"
}
+ 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,
"toCryptoAddress": {
"cryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv",
"accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
"organizationId": "NTESTORG",
"currency": "BTC",
"mainCurrency": "BTC",
"name": "Autogenerated NTESTORG BTC",
"address": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
"createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa",
"createdAt": "1658312909707",
"isWhitelist": false,
"travelRuleInfo": {
"beneficiaryVerificationMethod": "vasp",
"beneficiaryVerificationStatus": "verified",
"beneficiaryName": "Some name",
"beneficiaryType": "legal-person",
"beneficiaryVaspId": "did:ethr:123456789",
"beneficiaryVaspName": "VASP Name"
}
}
},
"createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa",
"organizationId": "NTESTORG",
"createdAt": "1572984084262",
"updatedAt": "1572984084447"
}
Request parameters
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 |
The type of the order. Use 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). This value is mandatory for Custody, Trading or Settlement Lite portfolios. |
toAddress | Optional<String> |
Withdraw address. |
toCryptoAddressId | Optional<String> |
Withdraw crypto address identifier. To retrieve travel rule data from address book use cryptoAddressId value returned by Create address in address book method |
toBankAccountId | Optional<String> |
Withdraw bank account identifier |
toPortfolioId | Optional<String> |
Withdraw portfolioId identifier |
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
See Order
.
Response inludes travelRuleInfo
with the following travel rule fields:
Parameter | Description |
---|---|
beneficiaryVerificationMethod | Verification method: manual , signature or VASP |
beneficiaryVerificationStatus | Verification status: verified , unverified , unknown |
beneficiaryType | Type of beneficiary: legal-person (default) or natural-person |
beneficiaryName | Name of beneficiary receiving funds. |
beneficiaryVaspId | The VASP ID associated with beneficiary address. |
beneficiaryVaspName | The VASP name associated with beneficiary address. |
Example: Create bulk Bitcoin-like transfer order
+ POST /platform/orders
This method creates a single withdraw order that moves the funds from a wallet to multiple wallets. This order should be signed once and requires paying one fee.
Note: This method supports only bitcoin-like currencies: Litecoin, Dogecoin, Bitcoin. Use Get supported currencies
method to retrieve the list of currencies. Supported currencies have multi-withdraw
tag.
Required API Key permissions: Withdraw
Properties
+ Request (application/json)
{
"externalOrderId": "4e9dd69c-efd5-11ed-a05b-0242ac120010",
"orderType": "multi-withdraw",
"baseCurrency": "BTC",
"mainCurrency": "BTC",
"feeLevel": "low",
"includeFees": false,
"includeFeeInWithdraw": false,
"portfolioId": "ckx0ddhzu000g3e64xlzh4522",
"toReceivers": [
{
"toAddress": "mqJTMqUDRKM7ZjfzBX1oCXWerXNVsb8rx0",
"amount": "0.001"
},
{
"toPortfolioId": "cktwyhom0003c3a60wpx31a12",
"amount": "0.002"
},
{
"toCryptoAddressId": "cl4h3ogpo000u3b5nm78ecl11",
"amount": "0.003"
}
]
}
+ Response 201 (application/json)
{
"orderId": "1891",
"externalOrderId": "4e9dd69c-efd5-11ed-a05b-0242ac120010",
"status": "awaiting-settlement",
"orderType": "multi-withdraw",
"portfolioId": "ckx0ddhzu000g3e64xlzh4522",
"portfolioType": "custody",
"accountId": "34b1f836-2b0c-45ca-af6a-50e33c0f3100",
"amount": "0.003",
"baseCurrency": "BTC",
"mainCurrency": "BTC",
"extra": {
"reportingCurrencyRate": "27422.965281279696",
"includeFeeInWithdraw": false,
"blockchainTransactionType": "multi-withdraw",
"estimatedFees": {
"fee": "0.0000026",
"feeCurrency": "BTC",
"estimatedTime": "7200000",
"reportingCurrencyRate": "27422.965281279696",
"transactionBytes": "260",
"feePerByte": "1"
},
"includeFees": false,
"toReceivers": [
{
"toAddress": "mqJTMqUDRKM7ZjfzBX1oCXWerXNVsb8rx0",
"amount": "0.001"
},
{
"toPortfolioId": "cktwyhom0003c3a60wpx31a12",
"toAddress": "mzpZ5m6fm4dFyDknWMkVH6Mm5yGDoXr400",
"amount": "0.002"
},
{
"toAddress": "mv7vPkkHTSQmvog6tUWWuTZBy4Aher6123",
"amount": "0.003"
}
]
},
"createdBy": "b2270629-5917-433a-93dc-aae28e190b00",
"organizationId": "CRP",
"createdAt": "1683797101156",
"updatedAt": "1683797101522"
}
Request
This request should include the CreateOrder
model specific for bulk bitcoin withdrawals:
Field | Data type | Description |
---|---|---|
externalOrderId | String |
Unique order identifier from client (should be unique for the portfolio, should not be blank) |
orderType | OrderType |
The type of the order. Use multi-withdraw |
portfolioId | String |
Unique identifier of the portfolio, for which the order will be created |
baseCurrency | Currency |
Currency for the amount. Use BTC , LTC or DOGE |
mainCurrency | Optional<Currency> |
Currency of main blockchain. Use BTC , LTC or DOGE |
toReceivers | toReceivers |
Array of JSON objects (see the variants below) |
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. |
toReceivers
array contains the JSON objects. Each JSON object contains two fields: one address field and the amount field:
Field | Data type | Description |
---|---|---|
amount | BigDecimal |
The amount of funds to transfer |
To specify the address use one of the following address fields:
Field | Data type | Description |
---|---|---|
toAddress | Optional<String> |
Withdraw address |
toCryptoAddressId | Optional<String> |
Withdraw crypto address identifier |
toPortfolioId | Optional<String> |
Withdraw portfolioId identifier |
Response
See Order
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 performs a test run of a withdraw order and checks data you are going to enter. Currently, the method works for ETH itself, ETH tokens and 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 the following:
Field | Data type | Description |
---|---|---|
orderType | OrderType |
The type of the order. Acceptable 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) |
feeLevel | <String> |
Note: required for specific currencies. Use if the response indicates a missing feeLevel field. Transaction processing fee: low , medium or high |
Response
The method returns the details of the dry-run order:
Field | Data type | Description |
---|---|---|
orderType | OrderType |
The type of the order. Acceptable withdraw |
portfolioId | String |
Unique identifier of the portfolio, for which the order will be created |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Currency of main blockchain (e.g. for USDT , it could be either ETH or BTC currency) |
extra | Optional<OrderExtra> |
Additional order data |
Deposit API
The Deposit API includes methods for creation and operations with Deposit Targets.
Create a 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 (will be shown in the UI) |
metadata | Optional<Object> |
JSON object with any additional metadata you want to store with a new Deposit Target (will be shown in the API only) |
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 |
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 |
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 or requires an activation (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 organisation 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: View
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 |
---|---|---|
depositTargetId | UUID |
Unique Deposit Target identifier |
externalId | Optional<String> |
Deposit target with specified externalId |
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"
}
],
}
Staking API
The /platform/orders
endpoint of the Copper API is used also for staking purposes.
The orderType
field defines the order purpose: earn-reward
type for the rewards received for staking the assets.
Get staking reward orders
+ GET /platform/orders?orderType=earn-reward
This method returns the list of staking reward orders, including the orders with errors. Orders without the rewards are not included in the list.
Method: GET
Required API Key permissions: View
Properties
+ Response 200 OK (application/json)
{
"orders": [
{
"orderId": "36705489",
"externalOrderId": "NEAR:f5fd82fc-199e-43d6-a2fa-2e907adb3ca6",
"status": "executed",
"orderType": "earn-reward",
"portfolioId": "2CmdQOfcSx0ocqMxJGr23Bvl",
"portfolioType": "trading-vault",
"accountId": "52ed19ee-c4d6-40c6-be0f-c9496e06a694",
"amount": "0.000015546001130188963516",
"baseCurrency": "NEAR",
"mainCurrency": "NEAR",
"extra": {
"reportingCurrencyRate": "1.5108232029644666",
"terminatedReportingCurrencyRate": "1.5108232029644666",
"balanceSnapshot": "1.8487099292701487",
"availableSnapshot": "1.8487099292701487",
"depositTargetId": "79379ad0-3680-4795-88f2-0d52e8d26429"
},
"organizationId": "SCTC",
"createdAt": "1669118874888",
"updatedAt": "1669119536964",
"terminatedAt": "1669119536931"
}
]
}
Request
The request can have the following optional parameters:
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<Currency> |
Filter by the order currency |
orderType | Optional<OrderType> |
Filter by order type: use earn-reward to view orders of earn-reward type |
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 timestamp and sorted in ASC (oldest first) |
createdSince | Optional<String> |
Timestamp in milliseconds returning all orders created since a requested timestamp and sorted in DESC (newest first) |
terminatedAtFrom | Optional<Long> |
Timestamp in milliseconds returning all orders terminated since a requested timestamp (not sorted) |
terminatedAtTo | Optional<Long> |
Timestamp in milliseconds returning all orders terminated before a requested timestamp (not sorted) |
portfolioType | Optional<PortfolioType> |
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.
Response
Field | Data type | Description |
---|---|---|
orders | List<Order> |
List of orders |
Create staking order
+ POST /platform/orders
This method creates a staking order on the Copper platform.
Method: POST
Required API Key permissions: Withdraw
Properties
Stake delegation order example (currency: NEAR)
+ POST /platform/orders
+ Request (application/json)
{
"externalOrderId": "clbam4hss000e3b6flvqb26gc",
"baseCurrency": "NEAR",
"mainCurrency": "NEAR",
"orderType": "withdraw",
"portfolioId": "JsFMjYC3FCRnAWv2Ud9MUNBm",
"amount": "0.1",
"blockchainTransactionType": "stake-delegation",
"poolId": "cryptogarik.pool.f863973.m0"
}
+ Response 201 (application/json)
{
"orderId": "6054886",
"externalOrderId": "clbam4hss000e3b6flvqb26gc",
"status": "awaiting-settlement",
"orderType": "withdraw",
"portfolioId": "JsFMjYC3FCRnAWv2Ud9MUNBm",
"portfolioType": "trading-vault",
"accountId": "ab161f57-bec1-45b7-9a77-0dd33f741ef3",
"amount": "0.1",
"baseCurrency": "NEAR",
"mainCurrency": "NEAR",
"extra": {
"reportingCurrencyRate": "1.753557057801753",
"includeFeeInWithdraw": false,
"blockchainTransactionType": "stake-delegation",
"poolId": "cryptogarik.pool.f863973.m0",
"poolName": "cryptogarik.pool.f863973.m0"
},
"createdBy": "a2a06805-db21-427f-94f3-67f3a779af8e",
"organizationId": "QACS",
"createdAt": "1670234358987",
"updatedAt": "1670234366476"
}
Request
This request should include the CreateOrder
specific for staking:
Field | Data type | Description |
---|---|---|
externalOrderId | String |
Unique order identifier from client (should be unique for the portfolio, should not be blank) |
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) |
orderType | OrderType |
Order type: withdraw |
portfolioId | String |
Unique identifier of the portfolio, for which the order will be created. The portfolioId matches the Account ID on the Copper Platform |
amount | BigDecimal |
Order execution amount |
blockchainTransactionType | Optional<BlockchainTransactionType> |
Blockchain transaction type (see the description below). send is used by default |
The BlockchainTransactionType
sets up the type of performed blockchain operation. Each currency has a set of available staking operations, which is shown in the table below.
Currency | Staking operations |
---|---|
ADA | pool-creation, stake-delegation, take-reward |
ALGO | register-offline, register-online |
ATOM | stake-delegation, stake-undelegation, take-reward |
AVAX | complete-withdrawal, stake-nomination, pool-creation, stake-complete-deposit, stake-delegation, stake-undelegation |
AXL | stake-delegation, stake-undelegation, take-reward |
BLD | stake-delegation, stake-undelegation, take-reward |
BNB | pool-creation, stake-delegation, stake-undelegation, unjail |
CCD | pool-creation, stake-delegation, stake-undelegation |
DIVI | stake-delegation |
DOT | chill, complete-withdrawal, stake-nomination, rebond-stake, stake-delegation, stake-undelegation |
ETH | pool-creation, stake-delegation |
HNT | pool-creation, stake-undelegation, transfer-stake |
INJ | stake-delegation, stake-undelegation, take-reward, transfer-stake |
KSM | chill, complete-withdrawal, stake-nomination, rebond-stake, stake-delegation, stake-undelegation |
NEAR | complete-withdrawal, stake-delegation, stake-undelegation |
POKT | stake-delegation, stake-undelegation |
ROSE | stake-delegation, stake-undelegation |
SOL | complete-withdrawal, stake-delegation, stake-undelegation |
ZIL | complete-withdrawal, stake-delegation, stake-undelegation, take-reward |
Response
The response of the method includes the Order
Get active stakes
+ GET /platform/staking/active-stakes
This method returns the list of the active stakes.
Method: GET
Required API Key permissions: View
Properties
+ Response 200 OK (application/json)
{
"activeStakes": [
{
"activeStakeId": "c563b5f83af3f6ba5f738c639c7a960e8dda9e6532f6208bd6ec628640d845c4",
"portfolioId": "clk1bumcw000h3b6d7bzm16tg",
"organizationId": "COMPANY",
"depositTargetId": "3d070184-ce9c-404b-bb01-04a1c7c1d226",
"currency": "ADA",
"mainCurrency": "ADA",
"activeStake": {
"pool": {
"poolId": "pool1k4nqdlvd9y3l4rfgj8fm80mcrrgcvgkx732x0n04jqfakxy2dvd",
"poolName": "Cardano Pool"
},
"activeStakedAmount": "20038.58836",
"claimableRewardsAmount": "46.947901",
"rewardsRequireClaim": true,
"readyToUnstake": false,
"readyToRedelegate": true
},
"createdAt": "1692921790216",
"updatedAt": "1694165767345",
"isFromCopperPool": true
}
],
"_embedded": {
"pendingCount": "0",
"outstandingCount": "1"
}
}
Request
The request can have the following optional parameters:
Parameter | Data type | Description |
---|---|---|
currency | Optional<Currency> |
Filter by the staked currency |
mainCurrency | Optional<Currency> |
Filter by the main currency for staking |
portfolioId | Optional<String> |
Return stakes only for specific portfolio |
limit | Optional<Integer> |
Limit output of the stake: 100 by default, max. 100 |
offset | Optional<Integer> |
An offset between the beginning of the list and a first displayed element; 0 by default |
Response
The response contains the list of active stakes. Each active stake includes the following fields:
Field | Data type | Description |
---|---|---|
activeStakeId | String |
Unique identifier of the active stake |
depositTargetId | String |
Unique identifier of the Deposit Target |
portfolioId | String |
Unique identifier of the portfolio, for which the stake was created |
organizationId | Optional<String> |
Unique ID of the organisation |
currency | Currency |
Staked currency |
mainCurrency | Currency |
Main currency of the blockchain |
createdAt | Long |
Time of the stake creation |
updatedAt | Long |
Time of the latest stake update |
activeStake | ActiveStake |
Active stake data (see the description below) |
ActiveStake
Field | Data type | Description |
---|---|---|
pool | Optional<Pool> |
A pool that this stake is connected to (see the description below). Returned if the stake is connected to one pool |
pools | Optional<List<Pool>> > |
A list of pools that this stake is connected to. Returned if the stake is connected to two or more pools |
claimableRewardsAmount | Optional<BigDecimal> |
Amount of rewards, that can still be claimed from this active stake using TAKE_REWARD transaction |
activeStakedAmount | BigDecimal |
Amount which used to calculate rewards in the current epoch/period of stake |
readyToUnstake | Boolean |
true - the funds are ready to unstake, false - unstaking is currently impossible |
readyToRedelegate | Optional<Boolean> |
true - the active stake is ready to be redelegated, false - redelegating is currently impossible |
rewardsRequireClaim | Optional<Boolean> |
true - to claim rewards TAKE_REWARD transaction is required, false - TAKE_REWARD transaction is not required |
rewardsAutoRestake | Optional<Boolean> |
true - if rewards will be automatically restaked after payment false - rewards will not be restaked |
requireChillToUnstake | Optional<Boolean> |
Used for Substrate-based currencies: true - chill is required before unstaking BONDING stake, false - chill is not required |
warning | Optional<Warning> |
Warning message that notifies about a problem with this stake |
stakeAddress | Optional<String> |
Solana only: the address of a dedicated staking account |
activeStakedAmount | BigDecimal |
The amount of active stake |
Pool
Field | Data type | Description |
---|---|---|
poolId | String |
Pool identifier |
poolName | Optional<String> |
Pool name |
totalBonded | Optional<BigDecimal> |
Amount of all current stakes for the pool |
Get pending stakes
+ GET /platform/staking/pending-stakes
This method returns the list of the pending stakes.
Method: GET
Required API Key permissions: View
Properties
+ Response 200 OK (application/json)
{
"pendingStakes": [
{
"pendingStakeId": "6e48b40e0ee61df2214569e4ac4f0b5d6682e8f0ffb4f3a56e9d0fd4d627bf23",
"portfolioId": "clgeyi3vt000o3b6fap2dzjzy",
"organizationId": "COMPANY",
"depositTargetId": "11f39b64-c43e-4972-afe1-10070552110a",
"currency": "ADA",
"mainCurrency": "ADA",
"pendingStake": {
"pool": {
"poolId": "pool1m8crhnqj5k2kyszf5j2scshupystyxc887zdfrpzh6ty6eun4fx",
"poolName": "Cardano Pool"
},
"originPool": {
"poolId": "pool1k4nqdlvd9y3l4rfgj8fm80mcrrgcvgkx732x0n04jqfakxy2dvd",
"poolName": "Cardano Pool"
},
"pendingAmount": "1000",
"pendingStakeStatus": "changing-validator",
"pendingEndsAt": "1694217600000"
},
"createdAt": "1693469088208",
"updatedAt": "1694185621606",
"isFromCopperPool": false
}
]
}
Request
The request can have the following optional parameters:
Parameter | Data type | Description |
---|---|---|
currency | Optional<Currency> |
Filter by the staked currency |
mainCurrency | Optional<Currency> |
Filter by the main currency for staking |
portfolioId | Optional<String> |
Return stakes only for specific portfolio |
limit | Optional<Integer> |
Limit output of the stakes: 100 by default, max. 100 |
offset | Optional<Integer> |
An offset between the beginning of the list and a first displayed element; 0 by default |
Response
The response contains the list of pending stakes. Each pending stake includes the following fields:
Field | Data type | Description |
---|---|---|
pendingStakeId | String |
Unique identifier of the pending stake |
depositTargetId | String |
Unique identifier of the Deposit Target |
portfolioId | String |
Unique identifier of the portfolio, for which the stake was created |
organizationId | Optional<String> |
Unique ID of the organisation |
currency | Currency |
Staked currency |
mainCurrency | Currency |
Main currency of the blockchain |
createdAt | Long |
Time of stake creation |
updatedAt | Long |
Time of the latest stake update |
pendingStake | PendingStake |
Pending stake data (see the description below) |
PendingStake
Field | Data type | Description |
---|---|---|
pool | Optional<Pool> |
A pool that this stake is connected to (see the description below). Returned if the stake is connected to one pool |
pools | Optional<List<Pool>> |
A list of pools that this stake is connected to. Returned if the stake is connected to two or more pools |
originPool | Optional<Pool> |
If pendingStakeStatus is changing-validator : lists pools from which the stake was moved |
pendingStakeStatus | String |
The status of a pending stake (see description below) |
pendingAmount | BigDecimal |
Pending stake amount |
canBeRebonded | Optional<Boolean> |
Used for Substrate-based currencies:true - to rebond stake use REBOND_STAKE transaction during UNBONDING status, false - REBOND_STAKE transaction cannot be used |
canBeUnstaked | Optional<Boolean> |
Used for Substrate-based currencies: true - stake can be unbonded during BONDING status, false - rewards will not be restaked |
requireChillToUnstake | Optional<Boolean> |
Used for Substrate-based currencies: true - chill is required before unstaking BONDING stake, false - chill is not required |
warning | Optional<Warning> |
Warning message that notifies about a problem with this stake |
stakeAddress | Optional<String> |
Solana only: the address of a dedicated staking account |
The pendingStakeStatus
contains the following stake statuses:
Value | Description |
---|---|
unbonding | The stake is in waiting period before assets become available after unstaking |
bonding | The stake is in waiting period before it becomes active after initial staking |
changing-validator | The stake is in waiting period before it becomes active after changing validator |
The pool
is a JSON object that contains the following pool data:
Field | Data type | Description |
---|---|---|
poolId | String |
Pool identifier |
poolName | Optional<String> |
Pool name |
totalBonded | Optional<BigDecimal> |
Amount of all current stakes for the pool |
Get outstanding stakes
+ GET /platform/staking/outstanding-stakes
This method returns the list of the outstanding stakes.
Method: GET
Required API Key permissions: View
Properties
+ Response 200 OK (application/json)
{
"outstandingStakes": [
{
"outstandingStakeId": "1ea1be9ce75ca8e7c6fe0ebccc3940a74c55e7451fbc66e1af992ed9adcfe0e9",
"portfolioId": "clk1bumcw000h3b6d7bzm16tg",
"organizationId": "COMPANY",
"depositTargetId": "3d070184-ce9c-404b-bb01-04a1c7c1d226",
"currency": "ADA",
"mainCurrency": "ADA",
"outstandingOperation": {
"outstandingAmount": "46.947901",
"outstandingOperationType": "claim-reward"
},
"createdAt": "1691625675218",
"updatedAt": "1694166801291",
"isFromCopperPool": false
}
]
}
Request
The request can have the following optional parameters:
Parameter | Data type | Description |
---|---|---|
currency | Optional<Currency> |
Filter by the staked currency |
mainCurrency | Optional<Currency> |
Filter by the main currency for staking |
portfolioId | Optional<String> |
Return stakes only for specific portfolio |
limit | Optional<Integer> |
Limit output of the stakes: 100 by default, max. 100 |
offset | Optional<Integer> |
An offset between the beginning of the list and a first displayed element; 0 by default |
Response
The response contains the list of outstanding stakes. Each outstanding stake includes the following fields:
Field | Data type | Description |
---|---|---|
outstandingStakeId | String |
Unique identifier of the outstanding stake |
depositTargetId | String |
Unique identifier of the Deposit Target |
portfolioId | String |
Unique identifier of the portfolio, for which the stake was created |
organizationId | Optional<String> |
Unique ID of the organisation |
currency | Currency |
Staked currency |
mainCurrency | Currency |
Main currency of the blockchain |
createdAt | Long |
Time of stake creation |
updatedAt | Long |
Time of the latest stake update |
outstandingOperation | outstandingOperation |
Outstanding stake data (see description below) |
The outstandingOperation
is a JSON object that contains the following stake data:
Field | Data type | Description |
---|---|---|
pool | Optional<pool> |
A pool that this stake is connected to (see description below). Returned if the stake is connected to one pool |
pools | Optional <List<pool>> |
A list of pools that this stake is connected to. Returned if the stake is connected to two or more pools |
outstandingOperationType | String |
The type of the outstanding operation (see description below) |
outstandingAmount | BigDecimal |
Outstanding stake amount |
stakeAddress | Optional<String> |
Solana only: the address of a dedicated staking account. Can be used for unstaking operations |
canCreatePool | Optional<boolean> |
AVAX only: true - if outstandingOperationType is set to allocate-stake , false - outstandingOperationType is not set to allocate-stake |
The outstandingOperationType
contains the following outstanding operation types:
Value | Description |
---|---|
claim-reward | Outstanding reward, that should be claimed as separate blockchain transaction |
complete-withdrawal | Outstanding stake that was unstaked and requires separate blockchain transaction to make it available for regular operations |
allocate-stake | Outstanding stake that was staked and now requires allocation to a pool |
complete-deposit | Outstanding stake that was staked and requires separate blockchain transaction to make it active |
The pool
is a JSON object that contains the following pool data:
Field | Data type | Description |
---|---|---|
poolId | String |
Pool identifier |
poolName | Optional<String> |
Pool name |
totalBonded | Optional<BigDecimal> |
Amount of all current stakes for the pool |
ClearLoop API
The ClearLoop api contains information about ClearLoop: settlements, delegations/undelegations, exchanges information and any other relevant information related ClearLoop.
Fetch ClearLoop balances
+ GET /platform/clearloop/balances
Fetch all the ClearLoop balances, that could be add-funds (delegation) or remove-funds (undelegation) associated to your account.
Properties
+ Response 200 OK (application/json)
{
"balances": [
{
"currency": "ETH",
"balance": "9.85773100",
"amount": "9.85773100",
"available": "2.25",
"reserve": "0.00000000",
"organizationId": "KLI1",
"delegatedOrganizationId": "DRBT",
"clientAccountId": "mNjMonVF",
"portfolioId": "ckmnkyust000f3f5wpjk7rya4",
"onChainSettlement": false,
"_embedded": {
"organizationName": "David"
}
}
]
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
portfolioId | Optional<String> |
ClearLoop Copper portfolioId |
organizationId | Optional<String> |
Organization id to filter the results with. |
includeEmptyWallets | Boolean |
include or not empty wallets. Default value false |
Response
The main field of the method response is "balances"
including a list of Balances. The definition of balances can be find below.
Field | Data type | Description |
---|---|---|
balances | List<ClearLoopBalance> |
List of ClearLoop Balances |
ClearLoop Balance
Field | Data type | Description |
---|---|---|
organizationId | String |
Unique Copper organization identifier |
delegatedOrganizationId | String |
Unique Copper exchange organization identifier |
clientAccountId | String |
Unique client exchange account identifier |
portfolioId | String |
Unique Copper client account identifier |
currency | String |
Currency that the balance is associated to |
mainCurrency | String |
Network |
balance | BigDecimal |
Total Balance value |
amount | BigDecimal |
Delegated Available Balance. Full amount delegated minus the reserved balance |
available | BigDecimal |
Available balance to undelegate. Minimum between funds on the exchange and delegated balance |
reserve | BigDecimal |
Reserved balance for open orders |
Fetch ClearLoop actions
+ GET /platform/clearloop/actions
Fetch all the ClearLoop actions, that could be add-funds (delegation) or remove-funds (undelegation) associated to your account.
Properties
+ Response 200 OK (application/json)
{
"actions": [
{
"delegatedOrganizationId": "GATE",
"organizationId": "WGTEST",
"orderId": "37952764",
"clientAccountId": "110281676",
"action": "add-funds",
"currency": "BTC",
"amount": "0.2",
"createdAt": "1682367644707",
"completedAt": "1682367727913",
"usdAmount": "5473.973562629252",
"status": "executed"
},
{
"delegatedOrganizationId": "GATE",
"organizationId": "WGTEST",
"orderId": "36774083",
"clientAccountId": "110281702",
"action": "add-funds",
"currency": "USDT",
"amount": "1000",
"createdAt": "1671627736258",
"completedAt": "1671628377350",
"usdAmount": "1000.0882673373988000",
"status": "executed"
}
],
"pagination": {
"pageSize": 100,
"page": 1,
"pages": 6,
"totalItems": 550
}
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
fromTimestamp | Optional<String> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records from this time |
toTimestamp | Optional<String> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records until this time |
clientAccountId | Optional<String> |
Exchange account unique identifier for which records can be retrieved |
portfolioId | Optional<Int> |
Copper portfolio unique identifier for which records can be retrieved |
actionType | Optional<Long> |
'add-funds' or 'remove-funds' |
limit | Optional<Integer> |
Number of records to return, maximum is 1000, default as 100 if parameter is absent |
offset | Optional<Integer> |
Number of records to skip over, default as 0 if parameter is absent |
sortDirection | Optional<String> |
Parameter to sort data in "asc" ascending or "desc" descending order according to "created_at", default as ascending if parameter is absent |
Response
The main field of the method response is "actions"
including a list of ClearLoopAction. The definition of actions can be find below.
Field | Data type | Description |
---|---|---|
actions | List<ClearLoopAction> |
List of actions - Delegation and Undelegations |
pagination | Pagination |
Pagination object starting from page 1 until the last page N |
ClearLoop Action
Field | Data type | Description |
---|---|---|
organizationId | String |
Unique Copper organization identifier |
delegatedOrganizationId | String |
Unique Copper exchange organization identifier |
clientAccountId | String |
Unique client exchange account identifier |
orderId | Optional<String> |
Order identifier associated with this action. |
action | String |
'add-funds' or 'remove-funds' |
amount | BigDecimal |
Decimal value amount. |
currency | String |
Currency |
createdAt | Long |
Unix timestamp at millisecond precision specific to the action creation time |
completedAt | Optional<Long> |
Unix timestamp at millisecond precision specific to the action completion time |
usdAmount | Optional<BigDecimal> |
USD amount value at the moment of the action |
status | String |
Order status: new, processing, executed and error |
+ GET /platform/clearloop/actions/{actionId}
Fetch all the ClearLoop actions, that could be add-funds (delegation) or remove-funds (undelegation) associated to your account.
Properties
+ Response 200 OK (application/json)
{
"delegatedOrganizationId": "GATE",
"organizationId": "WGTEST",
"orderId": "37952764",
"clientAccountId": "110281676",
"action": "add-funds",
"currency": "BTC",
"amount": "0.2",
"createdAt": "1682367644707",
"completedAt": "1682367727913",
"usdAmount": "5473.973562629252",
"status": "executed"
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
fromTimestamp | Optional<String> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records from this time |
toTimestamp | Optional<String> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records until this time |
clientAccountId | Optional<String> |
Exchange account unique identifier for which records can be retrieved |
portfolioId | Optional<Int> |
Copper portfolio unique identifier for which records can be retrieved |
actionType | Optional<Long> |
'add-funds' or 'remove-funds' |
Response
The main field of the method response is "actions"
including a list of ClearLoopAction. The definition of actions can be find below.
Field | Data type | Description |
---|---|---|
actions | List<ClearLoopAction> |
List of actions - Delegation and Undelegations |
pagination | Pagination |
Pagination object starting from page 1 until the last page N |
ClearLoop Action
Field | Data type | Description |
---|---|---|
organizationId | String |
Unique Copper organization identifier |
delegatedOrganizationId | String |
Unique Copper exchange organization identifier |
clientAccountId | String |
Unique client exchange account identifier |
orderId | Optional<String> |
Order identifier associated with this action. |
action | String |
'add-funds' or 'remove-funds' |
amount | BigDecimal |
Decimal value amount. |
currency | String |
Currency |
createdAt | Long |
Unix timestamp at millisecond precision specific to the action creation time |
completedAt | Optional<Long> |
Unix timestamp at millisecond precision specific to the action completion time |
usdAmount | Optional<BigDecimal> |
USD amount value at the moment of the action |
status | String |
Order status: new, processing, executed and error |
Fetch ClearLoop settlements
+ GET /platform/clearloop/settlements
Fetch all the settlements between an organization and the different ClearLoop exchanges that the client has bound in their account.
Settlement is the process in which the balances between the exchange and Copper delegated balances are updated with the PnL over the last settlement cycle.
Required API Key permissions: ClearLoop Omni RiskOps Viewer
Make sure you have granted access to view ClearLoop Risk Analytics section: you will not be able to retrieve any information if your API key does not have this role assigned.
Properties
+ Response 200 OK (application/json)
{
"settlements": [
{
"settlementId": "0752d9ac-79ca-4f95-9648-bbec101cd9ec",
"settlementStatus": "failed",
"cycleStartTimestamp": "1690257600000",
"cycleEndTimestamp": "1690261200000",
"deadline": "845129880000",
"exchange": "Bitget",
"exchangeId": "bitget",
"createdAt": "1690257605149",
"completedAt": "1690257605608",
"failureReason": "An error happened.",
"settlementDetails": [
{
"portfolioId": "cljyg0c6s000t3t6k7oqnyazc",
"exchangeSettlementId": "db35b015-b530-402f-bf3e-32f8ca09d428",
"clientAccountId": "51171",
"settlementInstructions": []
}
]
},
{
"settlementId": "f261191e-0b6f-4b90-8d8c-82583f59fc94",
"settlementStatus": "completed",
"cycleStartTimestamp": "1690459403000",
"cycleEndTimestamp": "1690545803000",
"deadline": "1690718600000",
"exchange": "Deribit",
"exchangeId": "deribit",
"createdAt": "1690462752465",
"completedAt": "1690462752975",
"settlementDetails": [
{
"portfolioId": "cljyg0c6s000t3t6k7oqnyazc",
"exchangeSettlementId": "db35b015-b530-402f-bf3e-32f8ca09d428",
"clientAccountId": "51171",
"settlementInstructions": [
{
"currency": "USDC",
"settlementAmount": "-29.48",
"settlementAmountUSD": "29.483855459466098064",
"orderId": "6325552",
"orderStatus": "executed"
},
{
"currency": "BTC",
"settlementAmount": "0.001",
"settlementAmountUSD": "29.47568121354447",
"orderId": "6325550",
"orderStatus": "executed"
},
{
"currency": "ETH",
"settlementAmount": "-0.006978",
"settlementAmountUSD": "13.0897411038406200624",
"orderId": "6325551",
"orderStatus": "executed"
}
]
}
]
}
],
"pagination": {
"pageSize": 100,
"page": 1,
"pages": 6,
"totalItems": 550
}
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
portfolioId | Optional<String> |
Copper portfolio unique identifier for which records can be retrieved |
clientAccountId | Optional<String> |
Exchange account unique identifier for which records can be retrieved |
exchange | Optional<String> |
Exchange to query settlements associated with |
cycles | Optional<Int> |
Last number of cycles that you want to retrieve for every exchange. For example for 1 cycle, it would mean to bring back the last settlement for every exchange |
cycleStartTimestamp | Optional<Long> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records for this cycle timestamp |
fromMillis | Optional<Long> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records from this time |
toMillis | Optional<Long> |
Unix timestamp down to the millisecond granularity that can be used to retrieve records until this time |
settlementStatusesNotIn | Optional<String> |
Comma separated list with statuses not to be included: failed, pending-exchange-confirmation, new, completed |
limit | Optional<Integer> |
Number of records to return, maximum is 1000, default as 100 if parameter is absent |
offset | Optional<Integer> |
Number of records to skip over, default as 0 if parameter is absent |
sortDirection | Optional<String> |
Parameter to sort data in "asc" ascending or "desc" descending order according to "created_at", default as ascending if parameter is absent |
Response
Field | Data type | Description |
---|---|---|
settlements | List<ClearLoopSettlement> |
List of settlements |
pagination | Pagination |
Pagination object starting from page 1 until the last page N |
The main field of the method response is "settlements"
including a list of settlement. The definition of settlements can be find below.
+ GET /platform/clearloop/settlements/${settlementId}
Fetch one client settlement with a particular exchange account.
Required API Key permissions: ClearLoop Omni RiskOps Viewer
Make sure you have granted access to view ClearLoop Risk Analytics section: you will not be able to retrieve any information if your API key does not have this role assigned.
Properties
+ Response 200 OK (application/json)
{
"settlementId": "f261191e-0b6f-4b90-8d8c-82583f59fc94",
"settlementStatus": "completed",
"cycleStartTimestamp": "1690459403000",
"cycleEndTimestamp": "1690545803000",
"deadline": "1690718600000",
"exchange": "Deribit",
"exchangeId": "deribit",
"createdAt": "1690462752465",
"completedAt": "1690462752975",
"settlementDetails": [
{
"portfolioId": "cljyg0c6s000t3t6k7oqnyazc",
"exchangeSettlementId": "db35b015-b530-402f-bf3e-32f8ca09d428",
"clientAccountId": "51171",
"settlementInstructions": [
{
"currency": "USDC",
"settlementAmount": "-29.48",
"settlementAmountUSD": "29.483855459466098064",
"orderId": "6325552",
"orderStatus": "executed"
},
{
"currency": "BTC",
"settlementAmount": "0.001",
"settlementAmountUSD": "29.47568121354447",
"orderId": "6325550",
"orderStatus": "executed"
},
{
"currency": "ETH",
"settlementAmount": "-0.006978",
"settlementAmountUSD": "13.0897411038406200624",
"orderId": "6325551",
"orderStatus": "executed"
}
]
}
]
}
Request
The method request needs a settlementId at the end of the URL endpoint.
Response
The 200 response contains all the field of a settlement defined below.
Common Settlement schemes
Settlement
Field | Data type | Description |
---|---|---|
settlementId | String |
Unique Copper settlement identifier |
exchangeId | String |
Exchange id |
cycleStartTimestamp | Long |
Unix timestamp at millisecond precision specific to when the settlement cycle has started |
cycleEndTimestamp | Long |
Unix timestamp at millisecond precision specific to when the settlement cycle ends |
deadline | Long |
Unix timestamp at millisecond precision specific to the settlement deadline |
settlementStatus | SettlementStatus |
Status describing the settlement |
createdAt | Long |
Unix timestamp at millisecond precision specific to when the settlement started |
completedAt | Optional <Long> |
Unix timestamp at millisecond precision specific to when the settlement was fully completed |
failureReason | Optional <String> |
Reason why the settlement has not been completed successfully |
Settlement Details
Field | Data type | Description |
---|---|---|
portfolioId | String |
Unique Copper account identifier |
clientAccountId | String |
Unique exchange account identifier |
exchangeSettlementId | Optional <String> |
Exchange unique identifier of settlement |
settlementInstructions | List <SettlementInstruction> |
List of all settlement instructions |
Settlement Instruction
Field | Data type | Description |
---|---|---|
currency | String |
Settlement currency |
settlementAmount | BigDecimal |
PnL of the client in the settlement period. This amount is the aggregation between mainAccount and subaccounts in the exchange |
settlementAmountUSD | BigDecimal |
Same as the settlementAmount but calculated in USD |
balance | BigDecimal |
Client Delegated Balance in Copper fetched at the moment of the settlement |
orderId | Optional <String> |
Order id associated to the settlement |
OrderStatus | Optional<OrderStatus> |
Describes the order status |
Settlement Status
Status | Description |
---|---|
new | newly created settlement with only metadata information |
in-progress | settlement is ready to be started or has already started. We have received succcessfully settlement instructions from exchange |
completed | settlement completed successfully |
failed | settlement failed after having retried it until the end of the cycle. This is due to errors in the api call to exchange that after many retries during the cycle couldn't be recovered |
partially-completed | some settlement instructions has been completed and other are still in progress. This is due to client trading vault orders missing signatures |
pending-exchange-confirmation | pending exchange to send the settlement instructions. This is due to some api/network error connecting to the exchange |
pending-previous-settlement | waiting for a previous settlement to be completed |
Fetch ClearLoop exchanges
+ GET /platform/clearloop/exchanges
Fetch all ClearLoop exchanges information related collateral health and settlements configuration
Required API Key permissions: ClearLoop Omni RiskOps Viewer
Make sure you have granted access to view ClearLoop Risk Analytics section: you will not be able to retrieve any information if your API key does not have this role assigned.
Properties
+ Response 200 OK (application/json)
{
"clearLoopExchanges": [
{
"exchangeId": "okex",
"name": "OKX",
"settlementDetails": {
"frequency": "14400000",
"nextSettlementTimestamp": "1694419200000"
},
"collateralDetails": {
"currencies": []
}
},
{
"exchangeId": "deribit",
"name": "Deribit",
"settlementDetails": {
"frequency": "86400000",
"nextSettlementTimestamp": "1694421000000"
},
"collateralDetails": {
"currencies": []
}
}
]
}
Request
The method request does not need any parameter.
Response
The main field of the method response is "exchanges"
including a list of ClearLoop exchanges. The definition of exchanges could be find below.
+ GET /platform/clearloop/exchanges/${exchangeId}
Fetch one ClearLoop exchange.
Required API Key permissions: ClearLoop Omni RiskOps Viewer
Make sure you have granted access to view ClearLoop Risk Analytics section: you will not be able to retrieve any information if your API key does not have this role assigned.
Properties
+ Response 200 OK (application/json)
{
"exchangeId": "deribit",
"name": "Deribit",
"settlementDetails": {
"frequency": "86400000",
"nextSettlementTimestamp": "1694421000000"
},
"collateralDetails": {
"currencies": []
}
}
Request
The method request needs a exchangeId at the end of the URL endpoint.
Response
The 200 response contains all the fields of a ClearLoop exchange defined below.
Common ClearLoop Exchange schemes
Exchange
Field | Data type | Description |
---|---|---|
exchangeId | String |
Unique Copper exchange identifier |
name | String |
Exchange name |
settlementDetails | ExchangeSettlementDetails |
Settlements configuration details |
collateralDetails | ExchangeCollateralDetails |
Collateral details |
ExchangeSettlementDetails
Field | Data type | Description |
---|---|---|
frequency | Integer |
Frequency of the settlement in milliseconds |
nextSettlementTimestamp | Integer |
Unix timestamp at millisecond precision specific when the next settlement cycle will start |
ExchangeCollateralDetails
Field | Data type | Description |
---|---|---|
currencies | Array<ClearLoopCurrencyCollateralDetails> |
Collateral details per currency |
ClearLoopCurrencyCollateralDetails
Field | Data type | Description |
---|---|---|
settlementCurrency | String |
Settlement currency |
uPnL | BigDecimal |
Unrealised PnL, sourced for open positions on Derivative |
currentCollateralBalance | BigDecimal |
Current Exchange collateral balance in their ClearLoop accou |
uPnLExcessDeficit | BigDecimal |
Difference between the current collateral balance and unrealised PnL |
buffer | BigDecimal |
Ratio of current collateral excess/deficit over the current collateral balance. Displayed as % |
updatedAt | ExchangeCollateralDetails |
Timestamp in milliseconds, reflecting the latest time that data was computed/fetched |
Fetch ClearLoop Treasury Holdings
+ GET /platform/clearloop/holdings
Fetch ClearLoop treasury holdings information. Returns the Copper ClearLoop treasury details per currency vs Copper ClearLoop client aggregated balances.
Required API Key permissions: ClearLoop Omni RiskOps Viewer
Make sure you have granted access to view ClearLoop Risk Analytics section: you will not be able to retrieve any information if your API key does not have this role assigned.
Properties
+ Response 200 OK (application/json)
{
"holdings": [
{
"asset": "USDC",
"variance": "-7165.59345678",
"clearLoopOnChainReserve": "1",
"clearLoopVirtualBalance": "7166.59345678",
"clientBalance": "982.52654322",
"depositAddresses": [
{
"network": "TRX",
"depositAddresses": [
"TEzh31h7xk1Xu7TNzQGG7kKLmsii"
]
},
{
"network": "BSC",
"depositAddresses": [
"0xa10a1af58c99a8sssssssssssssss"
]
},
{
"network": "ETH",
"depositAddresses": [
"0x761c0d34193c23ad01a738aa1b",
"0x3d134293effa3623fb96fc8827ff0ef"
]
}
]
}
]
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
asset | Optional<String> |
Currency or asset |
Response
The main field of the method response is "holdings"
including a list of ClearLoop treasury holdings.
ClearLoop Treasury Holding
Field | Data type | Description |
---|---|---|
asset | String |
Currency or asset |
variance | String |
Difference between treasury blockchain balance and clients aggregated balance |
clearLoopOnChainReserve | String |
Treasury blockchain amount |
clearLoopVirtualBalance | String |
Aggregated clients balance |
clientBalance | Long |
Balance associated with the client that made the request |
depositAddresses | List<DepositAddress> |
List of deposit addresses per network |
ClearLoop Treasury Deposit Address
Field | Data type | Description |
---|---|---|
network | String |
Currency Network |
depositAddresses | List<String> |
List of deposit addresses |
DeFi API
This section describes the usage of /platform/orders
endpoint for DeFi interactions.
Create send order with payload
+ POST /platform/orders
This method creates a send order containing a data payload field for a smart contract. The transaction can be signed using Copper Unlimited.
Required API Key permissions: Withdraw
+ Request (application/json)
{
"amount": "0",
"baseCurrency": "ETH",
"externalOrderId": "464e66da-6183-44c5-a3c6-1a8655c44a95",
"mainCurrency": "ETH",
"orderType": "withdraw",
"payload": "0x379607f50000000000000000000000000000000000000000000000000000000000000001",
"portfolioId": "J4MZ46Jq27B3N74RI8tsYB5o",
"toAddress": "0xd6cef1bce2810ca92ab2fa865283761d5bdec9e0",
"origin": {
"url": "https://etherscan.io",
"icon": "https://etherscan.io/images/favicon3.ico"
},
"feeLevel": "low",
"blockchainTransactionType": "send"
}
+ Response 201 (application/json)
{
"orderId": "918",
"externalOrderId": "164e66da-6183-44c5-a3c6-1a8655c44a95",
"status": "awaiting-settlement",
"orderType": "withdraw",
"portfolioId": "J4MZ46Jq27B3N74RI8tsYB51",
"portfolioType": "custody",
"accountId": "34b1f836-2b0c-45ca-af6a-50e33c0f31a0",
"amount": "0",
"baseCurrency": "ETH",
"mainCurrency": "ETH",
"extra": {
"toAddress": "0xd6cef1bce2810ca92ab2fa865283761d5bdec9e2",
"payload": "0x379607f50000000000000000000000000000000000000000000000000000000000000001",
"reportingCurrencyRate": "1212.8295821568893",
"feesPercent": "0",
"feeLevel": "low",
"includeFeeInWithdraw": false,
"blockchainTransactionType": "send",
"estimatedFees": {
"fee": "0.00000009157095183",
"feeCurrency": "ETH",
"estimatedTime": "600000",
"reportingCurrencyRate": "1212.8295821568893",
"gasPriceGwei": "0.001474905",
"gasLimit": "62086"
},
"origin": {
"url": "https://goerli.etherscan.io",
"icon": "https://goerli.etherscan.io/images/favicon3.ico"
}
},
"createdBy": "b2270629-5917-433a-93dc-aae28e190b5e",
"organizationId": "TEST",
"createdAt": "1670002739347",
"updatedAt": "1670002739395"
}
Request
The request should include the specific CreateOrder
model:
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 |
payload | String |
Serialised data payload for a smart contract |
portfolioId | String |
Unique identifier of the DeFi portfolio, for which the order will be created |
blockchainTransactionType | Optional<String> |
DeFi blockchain transaction type: send (default). A transaction request, which can include a smart contract payload |
amount | BigDecimal |
Order execution amount. It is recommended to set the amount to 0, unless the request is used to ether to a smart contract |
baseCurrency | Currency |
Currency for the amount (e.g. for USDT , it could be ETH ) |
mainCurrency | Currency |
Currency of main blockchain (e.g. for USDT , it could be ETH ) |
feeLevel | Optional<feeLevel> |
The fee level: low , medium or high |
toAddress | Optional<String> |
Withdrawal or smart contract address |
toCryptoAddressId | Optional<String> |
Withdraw crypto address identifier |
toPortfolioId | Optional<String> |
Withdraw portfolioId identifier |
Note: this method broadcasts the transaction automatically.
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 | Currency |
Main currency of the blockchain |
extra | OrderExtra |
Additional order data, including payload value and blockchainTransactionType |
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 |
Create smart-call order
+ POST /platform/orders
This method creates a smart-call
order containing an unsigned transaction. The transaction can be signed using Copper Unlimited.
Required API Key permissions: Withdraw
Properties
+ Request (application/json)
{
"baseCurrency": "ETH",
"externalOrderId": "464e66da-6183-44c5-a3c6-1a8655c44a95",
"mainCurrency": "ETH",
"orderType": "withdraw",
"payload": "0xf8890884883190a28302064694bc1f23aba4f942559e090c637b36acef0c58e7f280b8643d7403a30000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b3132204f63742032303232000000000000000000000000000000000000000000808080",
"portfolioId": "J4MZ46Jq27B3N74RI8tsYB5o",
"blockchainTransactionType": "smart-call",
"externalBroadcast": "true",
"origin": {
"url": "https://goerli.etherscan.io",
"icon": "https://goerli.etherscan.io/images/favicon3.ico"
},
"amount": "0"
}
+ Response 201 (application/json)
{
"orderId": "988",
"externalOrderId": "464e66da-6183-44c5-a3c6-1a8655c44a95",
"status": "awaiting-settlement",
"orderType": "withdraw",
"portfolioId": "J4MZ46Jq27B3N74RI8tsYB5o",
"portfolioType": "custody",
"accountId": "34b1f836-2b0c-45ca-af6a-50e33c0f31a9",
"amount": "0",
"baseCurrency": "ETH",
"mainCurrency": "ETH",
"extra": {
"payload": "0xf8890884883190a28302064694bc1f23aba4f942559e090c637b36acef0c58e7f280b8643d7403a30000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b3132204f63742032303232000000000000000000000000000000000000000000808080",
"reportingCurrencyRate": "1281.71",
"includeFeeInWithdraw": false,
"blockchainTransactionType": "smart-call",
"origin": {
"url": "https://goerli.etherscan.io",
"icon": "https://goerli.etherscan.io/images/favicon3.ico"
},
"externalBroadcast": true
},
"createdBy": "b2270629-5917-433a-93dc-aae28e190b5e",
"organizationId": "TEW",
"createdAt": "1670002739347",
"updatedAt": "1670002739395"
}
Request
The request should include the CreateOrder
model specific for smart-call orders:
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 |
payload | String |
Serialised unsigned transaction. For Ethereum only type 0 (legacy) transactions are supported |
portfolioId | String |
Unique identifier of the portfolio (vault), for which the order will be created. The vault must be configured in the Copper Platform interface as the DeFi vault |
blockchainTransactionType | String |
DeFi blockchain transaction type: smart-call |
externalBroadcast | Boolean |
Sets broadcast mode. If true : manual broadcast. Use Retrieve order by id to get the fully signed trasactions, and then broadcast them manually. If false (default): automatic broadcast. Copper automatically broadcasts transactions to the network after fully signing |
amount | BigDecimal |
Order execution amount. To interact with a smart-contract or make a Layer 2 transfer (i.e. transfer USDC or USDT), the amount must be 0 |
baseCurrency | Currency |
Currency of main blockchain (e.g. for USDT , it could be ETH ) |
mainCurrency | Currency |
Currency of main blockchain (e.g. for USDT , it could be ETH ) |
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: 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 | Currency |
Main currency of the blockchain |
extra | OrderExtra |
Additional order data, including payload value and blockchainTransactionType |
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 |
Create multi-smart-call order with multiple transactions in payload
+ POST /platform/orders
This method creates a multi-smart-call
order containing a a list of unsigned transactions. The transactions can be signed using Copper Unlimited.
Required API Key permissions: Withdraw
Properties
+ Request (application/json)
{
"baseCurrency": "ETH",
"externalOrderId": "ef2a1db4-baa3-4f11-80ee-eddeb2e1cf70",
"mainCurrency": "ETH",
"orderType": "withdraw",
"payloads": [
"0xeb1c85037545f602825208940c19377f8b628698dcaf6028b43a0b16d1c4401787038d7ea4c6800080808080",
"0xf8691d85037545f60282fde89407865c6e87b9f70255377e024ace6630c1eaa37f80b844a9059cbb0000000000000000000000000c19377f8b628698dcaf6028b43a0b16d1c4401700000000000000000000000000000000000000000000000000000000000186a0808080"
],
"portfolioId": "7yzQLWtDeZEYYsVYb028h3OM",
"blockchainTransactionType": "multi-smart-call",
"externalBroadcast": true
}
+ Response 201 (application/json)
{
"orderId": "37242081",
"externalOrderId": "ef2a1db4-baa3-4f11-80ee-eddeb2e1cf70",
"status": "awaiting-settlement",
"orderType": "withdraw",
"portfolioId": "7yzQLWtDeZEYYsVYb028h3OM",
"portfolioType": "custody",
"accountId": "52ed19ee-c4d6-40c6-be0f-c9496e06a694",
"amount": "0.001",
"baseCurrency": "ETH",
"mainCurrency": "ETH",
"extra": {
"payloads": [
"0xeb1c85037545f602825208940c19377f8b628698dcaf6028b43a0b16d1c4401787038d7ea4c6800080808080",
"0xf8691d85037545f60282fde89407865c6e87b9f70255377e024ace6630c1eaa37f80b844a9059cbb0000000000000000000000000c19377f8b628698dcaf6028b43a0b16d1c4401700000000000000000000000000000000000000000000000000000000000186a0808080"
],
"reportingCurrencyRate": "1654.9549806311848",
"includeFeeInWithdraw": false,
"blockchainTransactionType": "multi-smart-call",
"externalBroadcast": true
},
"createdBy": "d73ce276-4716-410a-a1a0-9fa9b7336798",
"organizationId": "TEST",
"createdAt": "1675882449886",
"updatedAt": "1675882449943"
}
Request
The request should include the specific CreateOrder
model:
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 |
payloads | List<String> |
Serialised list of unsigned transactions. For Ethereum only type 0 (legacy) transactions are supported |
portfolioId | String |
Unique identifier of the DeFi portfolio, for which the order will be created. The vault must be configured in the Copper Platform interface as the DeFi vault |
blockchainTransactionType | String |
DeFi blockchain transaction type: multi-smart-call . Creates multi-smart-call order with multiple transactions in payload |
externalBroadcast | Boolean |
Sets broadcast mode. If true : manual broadcast. Use Retrieve order by id to get the fully signed trasactions, and then broadcast them manually. If false (default): automatic broadcast. Copper automatically broadcasts transactions to the network after fully signing |
baseCurrency | Currency |
Currency of main blockchain (e.g. for USDT , it could be ETH ) |
mainCurrency | Currency |
Currency of main blockchain (e.g. for USDT , it could be ETH ) |
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: 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 | Currency |
Main currency of the blockchain |
extra | OrderExtra |
Additional order data, including payloads value and blockchainTransactionType |
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 |
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.
Create a message
This method signs a blockchain message.
+ POST /platform/wallet-messages
Properties
+ Request (application/json)
{
"externalMessageId": "8879aaa4-309a-4999-831d-109c10ddda56",
"portfolioId": "07gX5HVJHhPTYifYwF8gTapm",
"mainCurrency": "ETH",
"message": "Test"
}
+ Response 201 (application/json)
{
"externalMessageId": "8879aaa4-309a-4999-832d-109c10ddda56",
"messageId": "207",
"status": "working",
"portfolioId": "07gX5HVJHhPTYifYwF8gTap1",
"mainCurrency": "ETH",
"extra": {
"messageRequest": {
"publicKeyHash": "4de54dca3c103ff970bf8d3951fe12d5fbea6db0db1f2ad14228e41a3f6c11aa",
"currency": "ETH",
"mainCurrency": "ETH",
"message": "Test",
"nonceNumber": "29"
}
},
"createdBy": "c785c80a-e46c-4493-a8ed-c701fd5c5cc5",
"organizationId": "6887239497",
"accountId": "43cdead5-f14e-406b-871b-2878dda12f64",
"createdAt": "1675780091940"
}
Request
The request can include the following parameters:
Field | Data type | Description |
---|---|---|
externalMessageId |
String |
Unique message identifier provided by a client (should be unique for a portfolio) |
portfolioId |
String |
Unique identifier of a portfolio containing the message |
mainCurrency |
Currency |
Main currency of the blockchain |
message |
String |
Message to be signed |
version |
Optional<MessageVersion> |
Version of the message |
MessageVersion
MessageVersion
is an enum with following values:
Status | Description |
---|---|
empty | Personal message |
v3 |
message is a signTypedData message based on EIP-712. The message does not support arrays and recursive data structures |
v4 |
message is a signTypedData message based on EIP-712. The message fully supports of arrays and recursive data structures |
hash |
message is a message hash, e.g. for a personal message or an EIP-712 based message. A hash preserves the privacy of the actual message. This version is supported only on DeFi vaults |
eip155-hash |
message is a replay protected EIP-155 hash, e.g. for a mainnet chain transaction. A hash preserves the privacy of the actual message. This version is supported only on DeFi vaults |
Response
The response of the method includes the WalletMessage
model:
Field | Data type | Description |
---|---|---|
externalMessageId | String |
Unique message identifier given by a client (should be unique for a portfolio) |
messageId | String |
Unique message identifier |
status | MessageStatus |
Message processing working status (Processing the message: waiting for a client signature) |
portfolioId | String |
Unique identifier of a portfolio containing the message |
mainCurrency | 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 |
accountId | String |
Unique account identifier |
createdAt | Long |
Timestamp of message creation |
WalletMessageExtra
Field | Data type | Description |
---|---|---|
messageRequest | MessageRequest |
Message request data (see below) |
MessageRequest
Field | Data type | Description |
---|---|---|
publicKeyHash | String |
Wallet public key hash |
currency | String |
Wallet currency |
mainCurrency | String |
Wallet currency |
message | String |
Message to be signed |
version | MessageVersion |
Version of the message |
nonceNumber | String |
Message number in this portfolio |
Get all messages
+ GET /platform/wallet-messages?limit=1&offset=0
This method allows to retrieve information about all blockchain messages of the organisation.
Required API Key permissions: View
Properties
+ 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": "test",
"accountId": "77bd1eec-7189-48fa-8e66-d3c114ff1e3e",
"createdAt": "1611913442234"
}
],
"total": "1"
}
Request
The request can include the 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 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
MessageStatus
is an enum with following values:
Status | Description |
---|---|
working |
Processing the message: waiting for a client signature |
canceled |
The message has been canceled |
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}
This method retrieves information about a specific message.
Required API Key permissions: View
Properties
+ Response 201 (application/json)
{
"externalMessageId": "ckf2lcuv4000g3i5uv3x4xn6f",
"messageId": "11",
"status": "full-signed-tx-added",
"portfolioId": "ck8owwcvj000f3j5wrjoyip4d",
"mainCurrency": "XZC",
"extra": {
"messageRequest": {
"publicKeyHash": "d9f3c6b1066c188aa039e0f4a67dd8b10caf3de3e9c7862a8d0fb17320d57b14",
"currency": "XZC",
"message": "test",
"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": "TEST",
"accountId": "67126cc0-357d-4642-9596-ac0c0bdf4006",
"createdAt": "1600091821812"
}
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}
This method cancels processing of 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
.
Properties
+ Header
Content-Type: application/vnd.cancel-wallet-message+json
+ Request
{}
+ Response 200 (application/json)
{}
Request
The messageId
parameter is mandatory. The method does not require any request fields.
Response
The response of the method includes only the status code.
Loans API
The loans api allows you to interact with our collateral management system, booking and managing loans between two organizations.
Create a loan
+ POST /loans
+ Request
{
"loanType": "secured-pledged",
"externalId": "externalId1",
"lenderOrganizationId": "org1",
"borrowerOrganizationId": "org2",
"terms": {
"termType": "fixed",
"amount": 100000.00,
"loanCurrency": "BTC",
"loanNetworkCurrency": "BTC",
"collateralCurrency": "ETH",
"collateralNetworkCurrency": "ETH",
"marginCallPercentage": 100,
"defaultPercentage": 120,
"rebalancePercentage": 80,
"borrowFeeCurrency": "USD",
"borrowFeePercentage": 4.5,
"borrowFeeCalculationMethod": "daily",
"valuationTimezone": "Europe/London",
"dayCountConvention": "Act/360",
"startDate": 1660344486232,
"maturityDate": 1676245686234,
}
}
+ Response 201 Created
{
"actions": [],
"pendingUserActions": [],
"borrowerOrganizationId": "02392-2932",
"createdAt": "1666345839849",
"createdBy": "23e78c83-677a-48b1-aa3c-f5ef878120e6",
"externalId": "123456678",
"lenderOrganizationId": "85439-3232",
"loanArranger": "<your loan arranger ID>",
"loanType": "secured-pledged",
"loanStatus": "created",
"loanId": "896",
"terms": {
"termType": "fixed",
"amount": 100000.00,
"loanCurrency": "BTC",
"loanNetworkCurrency": "BTC",
"collateralCurrency": "ETH",
"collateralNetworkCurrency": "ETH",
"borrowFeeAmount": 100,
"borrowFeeCurrency": "USD",
"borrowFeePercentage": 4.5
"collateralAmount": 100,
"marginCallPercentage": 85,
"defaultPercentage": 65,
"rebalancePercentage": 125,
"startDate": 1660344486232,
"maturityDate": 1676245686234,
}
}
Required API Key permissions: Lending
or Lending Arranger
This allows the creation of a loan.
Model
Request
Parameter | Data type | Description |
---|---|---|
loanType | Loan Type |
Unique identifier for the loan type. |
externalId | Optional<String> |
Unique identifier for externally originated loans, must be unique per loan arranger. |
pricingSource | Optional<Pricing Source> |
The source for where the prices come which keep the LTV up to date. Defaults to external. |
lenderOrganizationId | String |
The organization id of the lender. |
borrowerOrganizationId | String |
The organization id of the borrower. |
terms | Terms |
The terms of the loan. |
Response
See Loan
Cancel
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.cancel+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to cancel the loan before it has been disbursed.
Write Off
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.write-off+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to write off a loan in open, margin call, defaulting or repaying.
Start Repayment
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.start-repayment+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to start the repayment of the loan.
Start Default
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.start-default+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to start the default of the loan.
Cancel Default
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.cancel-default+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to cancel the default of the loan.
Start Margin Call
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.start-margin-call+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to start a margin call on the loan.
Model
Request
Parameter | Data type | Description |
---|---|---|
targetPercentage | Optional<Numeric> |
The target ltv to rebalance to, mutually exclusive with targetAmount . |
targetAmount | Optional<Numeric> |
The target collateral to rebalance to, mutually exclusive with targetPercentage . |
Start Rebalance
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.start-rebalance+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to rebalance the loan. Can optionally specify the target ltv (calculated from the last valuation) or the target collateral. If neither are specified it will use the collateral required to keep the loan at the maintenance percentage.
Model
Request
Parameter | Data type | Description |
---|---|---|
targetPercentage | Optional<Numeric> |
The target ltv to rebalance to, mutually exclusive with targetAmount . |
targetAmount | Optional<Numeric> |
The target collateral to rebalance to, mutually exclusive with targetPercentage . |
Cancelling a Loan
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.cancel+json
+ Request
{
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a borrower or lender to trigger the cancellation of a loan before the funds have been released.
Updating a Loan
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.update+json
+ Request
{
"startDate": 1660344486232,
"maturityDate": 1676245686234,
"loanNetworkCurrency": "BTC",
"collateralNetworkCurrency": "ETH",
"borrowFeeAmount": 100,
"borrowFeePercentage": 4.5
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a borrower or lender to update the loan if various things have changed.
Model
Request
Parameter | Data type | Description |
---|---|---|
startDate | Optional<Long> |
Timestamp in epoch milliseconds of the start date. |
maturityDate | Optional<Long> |
Timestamp in epoch milliseconds of the maturity date. |
borrowFeeAmount | Optional<Numeric> |
The total amount of the borrow fee over the term of the loan, this will be pro-rated in billing. |
borrowFeePercentage | Optional<Numeric> |
The LTV of the borrow fee. |
loanNetworkCurrency | Optional<Currency> |
Currency code of the network being used to transfer the asset. |
collateralNetworkCurrency | Optional<Currency> |
Currency code of the network being used to transfer the collateral. |
Assign Lender Portfolio
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.update-lender-portfolio+json
+ Request
{
"portfolioId": "<lender portfolio ID>"
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a lender or loan arranger to assign the lender portfolio ID.
Model
Request
Parameter | Data type | Description |
---|---|---|
portfolioId | String |
The ID of the portfolio to be assigned. |
Assign Borrower Portfolio
+ PATCH /loans/{loanId}
+ Headers
Content-Type: application/vnd.update-borrower-portfolio+json
+ Request
{
"portfolioId": "<borrower portfolio ID>"
}
+ Response 200 OK
Required API Key permissions: Lending
or Lending Arranger
This allows a borrower or loan arranger to assign the lender portfolio ID.
Model
Request
Parameter | Data type | Description |
---|---|---|
portfolioId | String |
The ID of the portfolio to be assigned. |
Update Loan Valuations
+POST /loan-valuations
+ Request
{
"organizationId": "12345",
"pricedAt": 1676245686234,
"loanIds": [
"3000819"
],
"marketPrices": [
{
"baseCurrency": "BTC",
"quoteCurrency": "USDC",
"price": 10
}
]
}
+Response 201 CREATED
Required API Key permissions: Lending
or Lending Arranger
This allows a lender to batch update the valuation of a loan where the cross pair valuation is provided between loan and collateral asset and the ltv and required collateral to keep the loan at the maintenance percentage is calculated.
Model
Request
Parameter | Data type | Description |
---|---|---|
organizationId | String |
Unique identifier of the lender organization. |
pricedAt | Optional<Long> |
The time the prices were fetched from the market. |
loanIds | Optional<List<String>> |
An optional list of loan ids to apply the values to. |
organizationId | String |
Unique identifier of the lender organization. |
marketPrices | List<MarketPrice> |
The list of cross pair valuations. |
Shared Model
The following are common types used throughout the loan api.
Loan
Parameter | Data type | Description |
---|---|---|
loanId | String |
Unique identifier of the loan. |
loanArranger | Optional<String> |
Unique identifier of the loan arranger. |
externalId | Optional<String> |
Unique identifier for externally originated loans, must be unique per loan arranger. |
loanStatus | Loan Status |
The status of the loan. |
connectionId | String |
The id of the connection which defines whether there is a signed account control agreement in place. |
borrowerCollateralPortfolioId | String |
The id of the account which is to be used for collateral between the lender and borrower. |
lenderOrganizationId | String |
The organization id of the lender. |
lenderPortfolioId | Optional<String> |
The account id of the lender. |
borrowerOrganizationId | Optional<String? |
The organization id of the borrower. |
borrowerPortfolioId | String |
The account id of the borrower. |
terms | Terms |
The terms of the loan. |
createdBy | String |
The id of the user who created the loan. |
createdAt | Long |
Epoch millis of when the loan was created. |
updatedBy | Optional<String> |
The id of the user who last updated the loan. |
updatedAt | Optional<Long> |
Epoch millis of when the loan was last updated. |
securedCollateralAmount | Numeric |
How much collateral has been secured. |
collateralSecuredAt | Optional<Long> |
Epoch millis of when the collateral was first secured. |
collateralReleasedAt | Optional<Long> |
Epoch millis of when the collateral was released. |
collateralClaimedAt | Optional<Long> |
Epoch millis of when the collateral was claimed. |
loanDisbursedAt | Optional<Long> |
Epoch millis of when the loan was was disbursed. |
loanReturnedAt | Optional<Long> |
Epoch millis of when the loan was repaid. |
collateralPercentage | Numeric |
The percentage of collateral secured vs required. |
ltvPercentage | Numeric |
The ltv percentage of the loan as per the last valuation. |
closedReason | Optional<ClosedReason> |
The reason the loan was closed. |
actions | List<Action> |
The actions that have happened to the loan. |
pendingUserActions | List<RequestedUserAction> |
The requested user actions the calling user needs to perform. |
pricingSource | Optional<Pricing Source> |
The source for where the prices come which keep the LTV up to date. Defaults to external. |
Terms
The terms contain details about the loan agreement.
Parameter | Data type | Description |
---|---|---|
amount | Numeric |
The amount of the loan. |
loanCurrency | Currency |
Currency code of the asset being lent. |
loanNetworkCurrency | Currency |
Currency code of the network being used to transfer the asset. |
collateralAmount | Numeric |
The amount of the collateral required. |
collateralCurrency | Currency |
Currency code of the asset being used for collateral. |
collateralNetworkCurrency | Currency |
Currency code of the network being used to transfer the collateral. |
termType | Term Type |
The type of the term of the loan. |
startDate | Long |
Timestamp in epoch milliseconds of the start date. |
maturityDate | Optional<Long> |
Timestamp in epoch milliseconds of the maturity date. |
borrowFeeCalculationMethod | BorrowFeeCalculationMethod |
The method used to calculate the borrow fees. |
borrowFeeCurrency | Optional<Currency> |
The currency of the borrow fee. |
borrowFeeAmount | Optional<Numeric> |
The total amount of the borrow fee over the term of the loan, this will be pro-rated in billing. |
borrowFeePercentage | Optional<Numeric> |
The APR to be used in the borrow fee calculation. |
dayCountConvention | Optional<Day Count Convention> |
The day count convention to be used in the borrow fee calculation. |
valuationTimezone | Optional<String> |
The timezone in which to use when applying the borrow fee, in ISO standard. |
marginCallPercentage | Optional<Numeric> |
The LTV of collateral at which a margin call is made. |
defaultPercentage | Optional<Numeric> |
The LTV of collateral at which default occurs. |
rebalancePercentage | Optional<Numeric> |
The LTV of collateral at which a rebalance occurs. |
requireNoticeOfExclusiveControl | Optional<Boolean> |
Whether this loan must have an explicit notice of exclusive control on a default. |
Action
An action contains details about events that have happened to a loan, i.e. repayment started
.
Parameter | Data type | Description |
---|---|---|
actionId | String |
The id of the action. |
actionName | String |
The name of the action. |
payload | Object |
The command that caused the action to happen. |
createdAt | Long |
Timestamp in epoch milliseconds of the start date. |
createdBy | String |
The id of the user who triggered the action. |
loanId | String |
The id of the loan the action happened too. |
Requested User Action
A requested user action identifies what action if any a user needs to take (either lender or borrower) to progress the loan.
Id | Detail |
---|---|
assign-lender-portfolio | Lender needs to select the account for the loan. |
assign-borrower-portfolio | Borrower needs to select the account for the loan. |
deliver-additional-collateral | Borrower needs to add additional funds to the account for securing collateral. |
deliver-additional-lending-funds | Lender needs to add additional funds to the account for disbursing the loan. |
deliver-additional-repayment-funds | Borrower needs to add additional funds to the account for repaying the loan. |
sign-lending-funds-disbursal | Lender needs to sign the transaction for disbursing the loan. |
sign-lending-funds-return | Borrower needs to sign the transaction for repaying the loan. |
sign-claiming-collateral | Borrower needs to sign the transaction for the collateral to be claimed by the lender. |
treasury-approve-lending-funds-disbursal | Disbursing the loan requires account manager assistance. |
treasury-approve-lending-funds-return | Repaying the loan requires account manager assistance. |
treasury-approve-claiming-collateral | Claiming the collateral requires account manager assistance. |
notice-of-exclusive-control-required | Claiming the collateral requires account manager assistance. |
collateral-asset-activation | The collateral assets needs activating on the borrowers collateral vault. |
Loan Type
The loan type identifies how the loan is collateralized.
Loan Types |
---|
secured-pledged |
Pricing Source
The pricing source identifies where the prices come from that are used to keep the ltv up to date.
Name | Description |
---|---|
external | They are provided by an external partner using the valuations api. |
copper | Copper uses its internal pricing providers to update the ltv on an hourly basis. |
Loan Status
The loan status identifies the current state of a loan.
Name | Description |
---|---|
created | Newly booked loan. |
awaiting-configuration | The borrower and lender must configure the loan. |
configured | The loan is configured and we are waiting for the start date. |
securing-collateral | The collateral is being secured. |
disbursing-loan | The loan is being sent to the borrower. |
open | The loan is open. |
margin-call | A margin call has been started and collateral being secured. |
rebalancing | A rebalance has been started and collateral being released. |
releasing-collateral | The collateral is being released after repayment. |
repaying-loan | The loan is being repaid to the lender. |
defaulting | The collateral is being claimed after default has been started. |
closed | The loan has been closed. See Closed Reason . |
errored | The loan has errored. |
cancelling | The loan has been canceled. |
Term Type
The term type identifies the type of duration that has been agreed.
Name | Description |
---|---|
fixed | The loan is active between the start date and the maturity date. |
open | The loan is active on the start date but has no fixed maturity date. |
Closed Reason
The closed reason identities why the loan was closed.
Name | Description |
---|---|
defaulted | The loan was defaulted. |
cancelled | The loan was cancelled before the funds were released. |
repaid | The loan was repaid. |
Market Price
Parameter | Data type | Description |
---|---|---|
price | Numeric |
The cross pair valuation where it should be 1 baseCurrency is valued at (n) quoteCurrency. |
baseCurrency | Currency |
Currency code of the asset being lent. |
quoteCurrency | Currency |
Currency code of the asset being used for collateral. |
Borrow Fee Calculation Method
The borrow fee calculation method identifies how fees are applied for the cost of borrowing the loan.
Name | Description |
---|---|
none | No calculation takes place for this loan. |
daily | The borrow fee percentage is calculated over the day count convention and is applied daily in the specified timezone. |
Day Count Convention
The day count convention defines how the apr is applied to the loan each day.
Name | Description |
---|---|
Act/360 | The 'Act/360' day count, which divides the actual number of days by 360. |
Act/365A | The 'Act/365 Actual' day count, which divides the actual number of days by 366 if a leap day is contained, or by 365 if not. |
1/1 | The '1/1' day count, which always returns a day count of 1. |
Copper Unlimited Online
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. There is an option to pass
APP_PORT
environmental variable to specify a port within the container. - the required environment set by
APP_ENVIRONMENT
environment variable. The choice depends on a platform you are going to operate on.APP_NETWORK
variable is determined automatically and can be omitted. However, ifAPP_NETWORK
is specified, it must match the table below. The environment is set as follows:
- a path to your folder with the
APP_ENVIRONMENT | APP_NETWORK | Environment |
---|---|---|
prod |
mainnet |
copper.co |
mainnet |
mainnet |
copper.co |
stage |
mainnet |
demo.copper.co |
demo |
mainnet |
demo.copper.co |
testnet |
testnet |
testnet.copper.co (default) |
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', 'prod', 'demo' or 'mainnet' (see details above).
After starting 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
"toAddress": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
"toCryptoAddress": "cl5tgou1k000x3b5nb0f03ugv",
"includeFeeInWithdraw": true,
"feeLevel": "low",
"description": "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",
"toCryptoAddress": {
"cryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv",
"accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
"organizationId": "NTESTORG",
"currency": "BTC",
"mainCurrency": "BTC",
"name": "Autogenerated NTESTORG BTC",
"address": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
"createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa",
"createdAt": "1658312909707",
"isWhitelist": false,
"travelRuleInfo": {
"beneficiaryVerificationMethod": "vasp",
"beneficiaryVerificationStatus": "verified",
"beneficiaryName": "BeneficiaryName",
"beneficiaryType": "legal-person",
"beneficiaryVaspId": "did:ethr:123456789",
"beneficiaryVaspName": "VASPname"
}
}
},
"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": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
"includeFee": true,
"depositTargetId": "532443055",
"transactionType": "send",
"version": "0",
"transactionRequest": {
"fee": "231000000000000",
"transactionType": "send",
"outputs": [
{
"value": "10000000000000000",
"address": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6"
}
],
"gasLimit": "21000",
"gasPrice": "11000000000",
"sequence": "4",
"includeFee": true,
"nonceNumber": "15"
}
},
"toAddress": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
"reportingCurrencyRate": "338.15",
"feesPercent": "0",
"feeLevel": "low",
"includeFeeInWithdraw": true,
"withdrawFee": "0.000231000000000000",
"toCryptoAddress": {
"cryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv",
"accountId": "d961e420-cbcf-4642-83fd-82b184828a1e",
"organizationId": "NTESTORG",
"currency": "BTC",
"mainCurrency": "BTC",
"name": "Autogenerated NTESTORG BTC",
"address": "rwCQk17fhC8G9UCoMgaxsEQb6fVy8HhUY6",
"createdBy": "cc1bafa6-eb87-4a1e-ae6d-d27d0ea921aa",
"createdAt": "1658312909707",
"isWhitelist": false,
"travelRuleInfo": {
"beneficiaryVerificationMethod": "vasp",
"beneficiaryVerificationStatus": "verified",
"beneficiaryName": "BeneficiaryName",
"beneficiaryType": "legal-person",
"beneficiaryVaspId": "did:ethr:123456789",
"beneficiaryVaspName": "VASPname"
},
},
},
"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,
"depositTargetId": "532443055",
"transactionType": "send",
"version": "0",
"transactionRequest": {
"fee": "231000000000000",
"transactionType": "send",
"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 |
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", "demo" or "mainnet"
APP_NETWORK: "testnet"
restart: always
healthcheck:
test: "timeout 10s bash -c ':> /dev/tcp/127.0.0.1/3010' || exit 1"
interval: 30s
timeout: 10s
retries: 10
start_period: 10s
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: "" # Your Master password
restart: always
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.
Fees Vaults
Fees vaults are a type of MPC vault that are used to pay fees for token transfers from proxy wallets to the destination accounts.
In order to sign and broadcast the required transactions, a dockerised application made by Copper is provided to process transactions along with 'Copper Unlimited Online'.
When orders are created by the Copper platform to pay fees for token transfers from proxy wallets, the dockerised application will them sign using 'Copper Unlimited Online' and broadcast the transactions to the blockchain automatically.
Note: if you want to use your own fees wallets to pay fees, contact your account manager to set up a specific fees wallet account in your organisation.
Software requirements
In order to operate the dockerised application, an instance of 'Copper Unlimited Online' must be configured with the required wallet shards for the associated fees vault.
The fees vault service is provided as a Docker image based on node:lts-alpine
and can be run using Docker Compose.
The image is publicly available in Copper DockerHub.
Network characteristics of the image:
- connects with the Copper API, depending on a chosen
APP_ENVIRONMENT
; - connects with a Copper Unlimited Online, depending on the given
APP_CUSTODY_DOCKER_URL
configuration;
How to launch
Wallet configuration
Before launching, a wallet configuration file must be created. This is a JavaScript file containing a JSON object that describes the wallets that the application can sign transactions for. The file is in the following format:
module.exports = [
{
portfolioId: '<fees vault account ID>',
currency: 'ETH',
walletFilename: 'eth-wallet.copper',
walletPassword: process.env.ETH_WALLET_PASSWORD,
},
{
portfolioId: '<fees vault account ID>',
currency: 'TRX',
walletFilename: 'trx-wallet.copper',
walletPassword: process.env.TRX_WALLET_PASSWORD,
},
];
Any number of wallets can be configured in this file, but each wallet must have the following properties:
portfolioId
- the ID of the fees vault account that the wallet is associated withcurrency
- the currency that the wallet is associated withwalletFilename
- the filename of the wallet backup file as used in the Copper Unlimited Online instancewalletPassword
- the password used to encrypt the wallet backup file (in the example given above, this is an environment variable)
Launching the application
- Configure and run the Copper Unlimited Online instance with shards for the configured MPC wallets in your organization's fees vault
- Start the dockerised CU Online.
Before running, specify following fields:
- a path to your folder with the
*.copper
file. - 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.
- the URL of the CU Online instance.
- the API key and secret that the application will use to connect to the Copper API.
- the withdrawal password of the organization that the application will use to authenticate for withdrawals.
- Any other environment variables used in the wallet configuration file. (e.g. wallet passwords)
- 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}/wallets-config.js:/app/wallets-config.js \
-e APP_ENVIRONMENT='testnet' \
-e APP_CUSTODY_DOCKER_URL='<URL of CU Online>:3010' \
-e APP_API_KEY='<API key>' \
-e APP_API_SECRET='<API secret>' \
-e APP_WITHDRAWAL_PASSWORD='<withdrwal password>' \
copperexchange/hot-wallet:latest
# ${PWD}/wallets-config.js is the wallet config file described above.
# The APP_ENVIRONMENT variable can be 'testnet', 'stage' or 'mainnet' (see details above).
# The APP_CUSTODY_DOCKER_URL variable is the URL of the CU Online instance that the application will connect to.
# The APP_API_KEY and APP_API_SECRET variables are the API key and secret that the application will use to connect to the Copper API.
# The APP_WITHDRAWAL_PASSWORD variable is the withdrawal password of the organization that the application will use to authenticate for withdrawals.
After starting the server, it should now be possible to send token transfers from proxy addresses paying the fees from the fees vault account. In this flow, orders will be created automatically to cover the fees amounts and the dockerised application will sign and broadcast the transactions to the blockchain.
Activity API
Get information about the organisation account activity.
Retrieve activities
+ GET /platform/organizations/{organizationId}/activities
Required API Key permission: view
Make sure you have granted access to the user: you will not be able to retrieve an organizations activities if the user tied to the API key does not have assigned permissions.
Properties
+ Response 200 OK
{
"activities": [
{
"activityId": "",
"name": "",
"description": "",
"userId": "",
"organizationId": "",
"portfolioId": "",
"correlationId": ""
"createdAt": "",
"extra": {
"externalId": "",
"roles":[]
}
],
}
Request
The method request can include following parameters:
Parameter | Data type | Description |
---|---|---|
search | Optional<String> |
String used to find one or more activities according to their description . This string can include minimum three characters. |
createdBy | Optional<String> |
User ID of the activity creator |
createdFrom | Optional<Long> |
Timestamp from when to return activities |
createdTo | Optional<Long> |
Timestamp to when to return activities |
limit | Optional<Integer> |
Number of records to return, default as 100 if parameter is absent |
offset | Optional<Integer> |
Number of records to skip over, default as 0 if parameter is absent |
Response
The main field of the method response is "activities"
including following fields:
Field | Data type | Description |
---|---|---|
activityId | String |
Unique identifier of the activity |
name | String |
Name of the activity |
description | String |
Description of the activity |
userId | String |
Unique user identifier |
organizationId | String |
Unique organization identifier |
createdAt | Long |
Timestamp of activity creation |
extra | ActivityExtra |
Extra activity data(see the ActivityExtra below) |
ActivityExtra
Parameter | Data type | Description |
---|---|---|
externalId | Optional<String> |
Unique external identifier |
roles | Optional<String> |
List roles of team member |
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 |
clearloop-delegation-created |
ClearLoop delegation created |
clearloop-delegation-completed |
ClearLoop delegation completed |
clearloop-delegation-failed |
ClearLoop delegation failed |
clearloop-undelegation-created |
ClearLoop undelegation created |
clearloop-undelegation-completed |
ClearLoop undelegation completed |
clearloop-undelegation-failed |
ClearLoop undelegation failed |
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.
Webhook API
The /platform/organizations/<organization>/webhooks
endpoints of the Copper API are used for creating, managing and removing subscriptions. There are also used to retrieve and re-sent events.
Events types
You can create a subscription (see below) to the following events:
Event | Description |
---|---|
deposit-status-updated | Status of deposit order changed |
deposit-completed | Deposit order is completed |
deposit-created | Deposit order is created |
proxy-transaction-completed | Proxy transaction is completed |
proxy-transaction-created | Transaction is created |
withdraw-status-updated | Status of withdraw order changed |
withdraw-failed | Withdraw order failed |
withdraw-transaction-sent | Withdraw order is send to blockchain |
withdraw-completed | Withdraw order is completed |
withdraw-created | Withdraw order is created |
order-master-password-required | Master password is required |
delegation-created | Delegation order is created |
delegation-completed | Delegation order is completed |
delegation-failed | Delegation order failed |
undelegation-created | Undelegation order is created |
undelegation-completed | Undelegation order is completed |
undelegation-failed | Undelegation order failed |
undelegation-blocked | Undelegation order is blocked |
undelegation-unblocked | Undelegation order is unblocked |
blockchain-deposit-confirmed | Copper broadcasted confirmation of the deposit order after receiving enough on-chain confirmations. The number of confirmations depends on the currency |
1. Create subscription
This method allows to create new subscription.
Required permissions: create-webhook-subscription
Request
Field | Data type | Description |
---|---|---|
subscriptionId | String |
Unique subscription identifier |
portfolioIds | Set <String> |
List of portfolio identifiers the subscription should listen to. If empty then listen to all portfolios. |
events | Set <String> |
List of event types to listen to. Please see available list above. |
webhookUrl | String |
URL to send webhooks to. |
secret | <Optional> String |
Secret value |
ecdsaPrivate | <Optional> String |
ECDSA private key |
loanArrangers | Set <String> |
List of loan arrangers that the subscription should listen to. If empty then listen to all. Valid values are copper , clst . |
NOTE:
Only one of the value secret
or ecdsaPrivate
value is required.
+ POST /platform/organizations/<organization>/webhooks
+ Headers
Content-Type: application/vnd.create-webhook-subscription+json
+Body
{
"webhookUrl": "https://local.com/webhook",
"portfolioIds": [],
"subscriptionId": "cl96u174k000p3b5rgcxjdj8f",
"events": [
"deposit-status-updated",
"deposit-completed",
"deposit-created",
"proxy-transaction-completed",
"proxy-transaction-created",
"withdraw-status-updated",
"withdraw-failed",
"withdraw-transaction-sent",
"withdraw-completed",
"withdraw-created",
"order-master-password-required"
],
"secret": "5jAnjkpbi0vBBS2LW3QLDK09NYkveafh",
"loanArrangers": []
}
Response
Fields:
Field | Data type | Description |
---|---|---|
subscriptionId | String |
Unique subscription identifier |
organizationId | String |
Unique organization identifier |
portfolioIds | Set <String> |
List of portfolio identifiers the subscription should listen to. If empty then listen to all portfolios. |
events | Set <String> |
List of event types to listen to. Please see available values above. |
webhookUrl | String |
URL to send webhooks to. |
isActive | Boolean |
Flag indicates if subscription is active or inactive. |
isPaused | Boolean |
Flag indicates if subscription is paused or not. |
createdAt | Long |
Timestamp when the subscription has been created. |
createdBy | String |
Identifier of the subscription creator. |
loanArrangers | Set <String> |
List of loan arrangers that the subscription should listen to. If empty then listen to all. |
+ Response 200
{
"subscriptionId": "cl96u174k000p3b5rgcxjdj8f",
"organizationId": "ONDREJ",
"portfolioIds": [],
"events": [
"proxy-transaction-completed",
"withdraw-status-updated",
"order-master-password-required",
"deposit-status-updated",
"withdraw-failed",
"withdraw-completed",
"proxy-transaction-created",
"deposit-created",
"withdraw-created",
"withdraw-transaction-sent",
"deposit-completed"
],
"webhookUrl": "https://local.com/webhook",
"isActive": true,
"isPaused": false,
"createdBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"createdAt": "1665651745441",
"loanArrangers": []
}
2. Get subscriptions
This method allows to retrieve all webhook subscriptions for user invoking the request for specified organization.
Required permissions: get-webhook-subscriptions
Request
+ GET /platform/organizations/<organization>/webhooks
The request of the method can have the following optional path parameters:
Parameter | Data type | Description |
---|---|---|
offset | Optional <Long> |
Number of subscription skiped from response. Defualt value: 0 |
limit | Optionl <Long> |
Maximum number of subscription returned. Default value: 100 |
Response
Fields:
Field | Data type | Description |
---|---|---|
webhookSubscriptions | List <Webhook subscription> |
See below for details |
_embedded | Embedded |
See below for details |
Webhook subscription fields:
Field | Data type | Description |
---|---|---|
subscriptionId | String |
Unique subscription identifier |
organizationId | String |
Unique subscription identifier |
portfolioIds | Set <String> |
List of portfolio identifiers the subscription should listen to. If empty then listen to all portfolios. |
events | Set <String> |
List of event types to listen to. Please see availalbe values above. |
webhookUrl | String |
URL to send webhooks to. |
isActive | Boolean |
Flag indicates if subscription is active or inactive. |
isPaused | Boolean |
Flag indicates if subscription is paused or not. |
createdAt | Long |
Timestamp when the subscription has been created. |
createdBy | String |
Identifier of the subscription creator. |
updatedAt | Long |
Timestamp when the subscription has been last time update. |
updatedBy | String |
Identifier of user updating subscription. |
loanArrangers | Set <String> |
List of loan arrangers that the subscription should listen to. If empty then listen to all. |
Embedded fields:
Field | Data type | Description |
---|---|---|
webhookEventTypes | List <WebhookEventType> |
List of webbhook event types |
WebhookEventType fields:
Field | Data type | Description |
---|---|---|
webhookEventTypeId | String |
Webhook type identifier |
category | String |
Webhook category (UI used) |
webhookEventTypeReadable | String |
Webhook human readable name (UI used) |
isInternal | Boolean |
Flag indicates if webhook is internal or external |
+ Response 200
{
"webhookSubscriptions": [
{
"subscriptionId": "cl96u174k000p3b5rgcxjdj8f",
"organizationId": "ONDREJ",
"portfolioIds": [],
"events": [
"proxy-transaction-completed",
"withdraw-status-updated",
"order-master-password-required",
"deposit-status-updated",
"withdraw-failed",
"withdraw-completed",
"proxy-transaction-created",
"deposit-created",
"withdraw-created",
"withdraw-transaction-sent",
"deposit-completed"
],
"webhookUrl": "https://local.com/webhook",
"isActive": true,
"isPaused": false,
"createdBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"createdAt": "1665651745441",
"loanArrangers": []
},
{
"subscriptionId": "cl94fsw6b000m3b5r4mf0mbpo",
"organizationId": "ONDREJ",
"portfolioIds": [],
"events": [
"proxy-transaction-completed",
"withdraw-status-updated",
"order-master-password-required",
"deposit-status-updated",
"withdraw-failed",
"withdraw-completed",
"proxy-transaction-created",
"deposit-created",
"withdraw-created",
"withdraw-transaction-sent",
"deposit-completed"
],
"webhookUrl": "https://webhook.site/7b9b4930-d68f-4f72-aa76-bd1494d2608a",
"isActive": true,
"isPaused": false,
"createdBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"createdAt": "1665506905008",
"updatedBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"updatedAt": "1665508930333",
"loanArrangers": []
},
{
"subscriptionId": "cl8lipatb000l3b5rb3uj8rv5",
"organizationId": "ONDREJ",
"portfolioIds": [],
"events": [
"deposit-status-updated",
"deposit-created",
"deposit-completed"
],
"webhookUrl": "https://webhook.site/d928f3a4-c3e1-4737-b1dc-a5d4c7581b7c",
"isActive": true,
"isPaused": false,
"createdBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"createdAt": "1664362921728",
"loanArrangers": []
}
],
"_embedded": {
"webhookEventTypes": [
{
"webhookEventTypeId": "deposit-created",
"category": "Deposit",
"webhookEventTypeReadable": "Created",
"isInternal": false
},
{
"webhookEventTypeId": "deposit-completed",
"category": "Deposit",
"webhookEventTypeReadable": "Completed",
"isInternal": false
},
{
"webhookEventTypeId": "proxy-transaction-created",
"category": "Proxy-transaction",
"webhookEventTypeReadable": "Created",
"isInternal": false
},
{
"webhookEventTypeId": "proxy-transaction-completed",
"category": "Proxy-transaction",
"webhookEventTypeReadable": "Completed",
"isInternal": false
},
{
"webhookEventTypeId": "withdraw-created",
"category": "Withdraw",
"webhookEventTypeReadable": "Created",
"isInternal": false
},
{
"webhookEventTypeId": "withdraw-completed",
"category": "Withdraw",
"webhookEventTypeReadable": "Completed",
"isInternal": false
},
{
"webhookEventTypeId": "withdraw-transaction-sent",
"category": "Withdraw",
"webhookEventTypeReadable": "Transaction sent",
"isInternal": false
},
{
"webhookEventTypeId": "order-master-password-required",
"category": "Transfer",
"webhookEventTypeReadable": "Conditional Transfers - Password Required",
"isInternal": false
},
{
"webhookEventTypeId": "withdraw-failed",
"category": "Withdraw",
"webhookEventTypeReadable": "Failed",
"isInternal": false
},
{
"webhookEventTypeId": "withdraw-status-updated",
"category": "Withdraw",
"webhookEventTypeReadable": "Withdraw status updated",
"isInternal": false
},
{
"webhookEventTypeId": "deposit-status-updated",
"category": "Deposit",
"webhookEventTypeReadable": "Deposit status updated",
"isInternal": false
}
]
}
}
3. Update subscription
This method allows to update webhook subscription.
Required permissions: update-webhook-subscription
Request
Field | Data type | Description |
---|---|---|
portfolioIds | Set <String> |
List of portfolio identifiers the subscription should listen to. If empty then listen to all portfolios. |
events | Set <String> |
List of event types to listen to. Please see available values above. |
webhookUrl | String |
URL to send webhooks to. |
loanArrangers | Set <String> |
List of loan arrangers that the subscription should listen to. If empty then listen to all. Valid values are copper , clst . |
+ PATCH /platform/organizations/<organization>/webhooks/<subscriptionId>
+ Headers
Content-Type: application/vnd.update-webhook-subscription+json
+ Body
{
"webhookUrl": "https://local.com/webhook",
"portfolioIds": [],
"events": [
"withdraw-created"
],
"loanArrangers": []
}
Response
Fields:
Field | Data type | Description |
---|---|---|
subscriptionId | String |
Unique subscription identifier |
organizationId | String |
Unique subscription identifier |
portfolioIds | Set <String> |
List of portfolio identifiers the subscription should listen to. If empty then listen to all portfolios. |
events | Set <String> |
List of events to listen to. Please see availalbe values on request. |
webhookUrl | String |
URL to send webhooks to. |
isActive | Boolean |
Flag indicates if subscription is active or inactive. |
isPaused | Boolean |
Flag indicates if subscription is paused or not. |
createdAt | Long |
Timestamp when the subscription has been created. |
createdBy | String |
Identifier of the subscription creator. |
updatedAt | Long |
Timestamp when the subscription has been last time update. |
updatedBy | String |
Identifier of user updating subscription. |
loanArrangers | Set <String> |
List of loan arrangers that the subscription should listen to. If empty then listen to all. |
+ Response 200
{
"subscriptionId": "cl96u174k000p3b5rgcxjdj8f",
"organizationId": "ONDREJ",
"portfolioIds": [],
"events": [
"withdraw-created"
],
"webhookUrl": "https://local.com/webhook",
"isActive": true,
"isPaused": false,
"createdBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"createdAt": "1665651745441",
"updatedBy": "d9e38c60-12b0-4ca3-9fe4-5d848e5411a7",
"updatedAt": "1665654329162",
"loanArrangers": []
}
4. Pause subscription
This method allows to pause webhook subscription for user invoking the request for specified organization.
Required permissions: pause-webhook-subscription
Request
Fields:
Field | Data type | Description |
---|---|---|
isPaused | Boolean |
If set to true then subscription is paused and not webhook are send. |
+ PATCH /platform/organizations/<organization>/webhooks/<subscriptionId>
+ Headers
Content-Type: application/vnd.pause-webhook-subscription+json
+ Body
{
"isPaused": true
}
Response
This method does not return any fields.
5. Deactivate subscription
This method allows to remove webhook subscription.
Required permissions: deactivate-webhook-subscription
Request
+ DELETE /platform/organizations/<organization>/webhooks/<subscriptionId>
Response
This method does not return any fields.
6. Get webhook events
This method allows to get events for the subscription.
Required permissions: get-webhook-events
The request of the method can have the following optional path parameters:
Parameter | Data type | Description |
---|---|---|
payloadId | String |
Payload identifier. |
event | String |
Type of the events to retrieve. |
delivered | Boolean |
Flag indicates if the event has been delivered or not. |
from | Long |
Timestamp from when to returns events |
to | Long |
Timestamp to when retrieve events |
offset | Optional <Long> |
Number of events skipped from response. Default value: 0 |
limit | Optional <Long> |
Maximum number of events returned. Default value: 100 |
Request
+ GET /platform/organizations/<organization>/webhooks/<subscriptionId>/events
Response
Fields:
Field | Data type | Description |
---|---|---|
webhookEvents | List <Webhook event> |
List of webhook events |
Webhook event fields:
Field | Data type | Description |
---|---|---|
eventId | String |
Event identifier. |
event | String |
Event type. |
subscriptionId | String |
Subscription identifier. |
payload | Json |
Json representation of payload. |
response | WebhookResponse |
See below. |
payloadId | String |
Payload identifier. |
payloadType | Enum |
Values: order , transaction |
createdAt | Long |
Timestamp when the event has been created. |
sentAt | Long |
Timestamp when the event has been send. |
Webhook response event fields:
Field | Data type | Description |
---|---|---|
statusCode | Integer |
Response code |
response | String |
Response message |
+ Response 200
{
"webhookEvents": [
{
"eventId": "cl94fsw6b000m3b5r4mf0mbpo-87cdd43428b476e1e3f404f6a47195b1",
"event": "deposit-status-updated",
"subscriptionId": "cl94fsw6b000m3b5r4mf0mbpo",
"payload": {
"extra": {
"confirmations": "1",
"fromAddresses": [
"rB5kHM3KyiUBrbcTsR4VxBHpfLPxSfK2B2"
],
"transactionId": "11EDD1EDCE57C1A0C7B29E383D485A80F5A5B88577CC196D5AF25E78FF557984",
"depositTargetId": "b4f844fe-2d14-43bd-88de-9a5be37bb90c",
"fromPortfolioId": "cl94h8ija000o3b5r0agztb0w",
"withdrawOrderId": "30",
"reportingCurrencyRate": "0.255206"
},
"amount": "50",
"status": "executed",
"orderId": "31",
"accountId": "f1ca3a79-29a3-4ae2-85d2-bede2f878609",
"createdAt": "1665509841000",
"orderType": "deposit",
"updatedAt": "1665509979859",
"portfolioId": "cl8ld1ci700133b5r8hi25usk",
"baseCurrency": "XRP",
"mainCurrency": "XRP",
"terminatedAt": "1665509979859",
"portfolioType": "custody",
"organizationId": "ONDREJ",
"externalOrderId": "XRP:3e82d0e4-e460-4017-ad7f-5a4e36a68240"
},
"response": {
"statusCode": "200",
"response": ""
},
"payloadId": "31",
"payloadType": "order",
"createdAt": "1665509979878",
"sentAt": "1665509980795"
}
]
}
7. Resent events
This method allows to re-sent selected events.
Required permissions: send-webhook-event
Request
Field | Data type | Description |
---|---|---|
eventIds | List <String> |
List of event identifiers to resent |
+ PATCH /platform/organizations/<organization>/webhooks/<subscriptionId>/events
+ Headers
Content-Type: application/vnd.send-webhook-events+json
+Body
{
"eventIds": [
"cl94fsw6b000m3b5r4mf0mbpo-87cdd43428b476e1e3f404f6a47195b1",
"cl94fsw6b000m3b5r4mf0mbpo-69ef3f24482af2a40303b5f95ac53d35"
]
}
Response
Field | Data type | Description |
---|---|---|
eventIds | List <String> |
List of resend event identifiers |
+ Response 200
{
"eventIds": [
"cl94fsw6b000m3b5r4mf0mbpo-87cdd43428b476e1e3f404f6a47195b1",
"cl94fsw6b000m3b5r4mf0mbpo-69ef3f24482af2a40303b5f95ac53d35"
]
}
Address book
Manage wallet addresses and whitelisting for safe and easy transfers.
Create crypto address
This method adds a crypto address to the address book in the External tab.
Note: to use Transfer API the address must be created in the address book and linked to an address Owner. Owner can only be created via Copper Platform UI and requires filling in the owner information: address, name etc. In order to link the address to the Owner properly, it is recommended to create the addresses with the owners via the Copper Platform UI first.
+ POST /platform/crypto-addresses
+ Request
{
"cryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv",
"accountId": "8A85A7E8-B56D-4B20-A098-900911759E85",
"currency": "BTC",
"mainCurrency": "BTC",
"ownerId": "ownerID",
"name": "Crypto Address Name",
"address": "hsdf892q4asdkgq20adfkhgq2987sdfjkasdfasdf",
"beneficiaryName": "Some name",
"beneficiaryType": "legal-person",
"beneficiaryVaspId": "did:ethr:123456789",
"beneficiaryVaspName": "VASP Name"
}
+ Response 201 Created (application/json)
{
"cryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv",
"accountId": "8A85A7E8-B56D-4B20-A098-900911759E85",
"organizationId": "NTESTORG",
"ownerId": "ownerID",
"currency": "BTC",
"mainCurrency": "BTC",
"name": "Crypto Address Name",
"address": "hsdf892q4asdkgq20adfkhgq2987sdfjkasdfasdf",
"createdBy": "uuid",
"updatedBy": "uuid",
"createdAt": "1658312909707",
"isWhitelist": false,
"travelRuleInfo": {
"beneficiaryVerificationMethod": "vasp",
"beneficiaryVerificationStatus": "verified",
"beneficiaryName": "Some name",
"beneficiaryType": "legal-person",
"beneficiaryVaspId": "did:ethr:123456789",
"beneficiaryVaspName": "VASP Name"
}
}
Request
Parameter | Data type | Description |
---|---|---|
cryptoAddressId | <String> |
Unique crypto address identifier. Maximum size is 64 |
accountId | <String> |
Unique account identifier |
organizationId | Optional <String> |
Unique organization identifier |
ownerId | <String> |
Unique owner identifier from Copper Platform UI. Open the Owner details in the Copper Platform UI and copy the ownerId value from the address bar of the browser. Owner must be created via Copper Platform UI first |
createdBy | <String> |
User ID of the crypto address creator |
portfolioIds | Optional <Set<String>> |
Filter entries by a number of portfolio identifiers |
currency | <Currency> |
Crypto address currency. Maximum size is 10 |
mainCurrency | Optional <Currency> |
Currency of main blockchain of the vault (e.g. For USDT, it could be either ETH or BTC). Maximum size is 10 |
address | <String> |
Address string |
name | <String> |
Name of the crypto address |
memo | Optional <String> |
Address memo |
acceptTokens | Optional<Boolean> |
null(default value), true - allow ERC20 token withdrawals to this address. It works only for ETH currency |
isWhitelist | Optional <String> |
false (default value) - the crypto address isn't whiteListed, true - the crypto address is whiteListed |
Note: The following fields are used to provide travel rules information when creating an address. Travel rules for withdrawal orders are currently under construction. Using following parameters may not be reliable.
Field | Data type | Description |
---|---|---|
beneficiaryType | BeneficiaryType |
Type of beneficiary: legal-person (default) or natural-person |
beneficiaryName | String |
Name of beneficiary receiving funds. The field may become mandatory in the future |
beneficiaryVaspId | Optional<String> |
The VASP ID associated with beneficiary address. To enable VASP verification VASP ID must be provided along with beneficiaryVaspName . If either parameter is missing, manual verification will be used |
beneficiaryVaspName | Optional<String> |
The VASP name associated with beneficiary address. To enable VASP verification VASP name must be provided along with beneficiaryVaspId . If either parameter is missing, manual verification will be used |
Response
Parameter | Data type | Description |
---|---|---|
cryptoAddressId | <String> |
Unique crypto address identifier. Maximum size is 64 |
accountId | <String> |
Unique account identifier. Maximum size is 64 |
ownerId | <String> |
Unique owner identifier |
organizationId | Optional <String> |
Unique organization identifier. |
portfolioIds | Optional <Set<String>> |
Filter entries by a number of portfolio identifiers |
currency | <Currency> |
Crypto address currency. Maximum size is 10 |
mainCurrency | Optional <Currency> |
Currency of main blockchain of the vault (e.g. For USDT, it could be either ETH or BTC). Maximum size is 10 |
name | <String> |
Name of the crypto address |
address | <String> |
Address string |
destinationTag | Optional <Long> |
Destination tag (for XRP addresses) |
memo | Optional <String> |
Address memo |
acceptTokens | Optional<Boolean> |
Flag allows ERC20 token withdrawals to this address. It works only for ETH currency |
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 |
lastUsedAt | Optional <Long> |
Time of last usage of the crypto address |
isWhitelist | Optional <String> |
false (default value) - the crypto address isn't whiteListed, true - the crypto address is whiteListed |
travelRuleInfo | Optional<travelRuleInfo> |
Information about beneficiaries (see below) |
travelRuleInfo
contains the following fields:
Parameter | Description |
---|---|
beneficiaryVerificationMethod | Verification method: manual , signature or VASP |
beneficiaryVerificationStatus | Verification status |
beneficiaryType | Type of beneficiary: legal-person (default) or natural-person |
beneficiaryName | Name of beneficiary receiving funds. |
beneficiaryVaspId | The VASP ID associated with beneficiary address. |
beneficiaryVaspName | The VASP name associated with beneficiary address. |
Get crypto address
+ GET /platform/crypto-addresses/{cryptoAddressId}
+ Response 200 (application/json)
{
"cryptoAddressId": "cl5tgou1k000x3b5nb0f03ugv",
"accountId": "uuid",
"organizationId": "NTESTORG",
"ownerId": "ownerID",
"currency": "BTC",
"mainCurrency": "BTC",
"name": "Crypto Address Name",
"address": "hsdf892q4asdkgq20adfkhgq2987sdfjkasdfasdf",
"memo": "45",
"createdBy": "uuid",
"updatedBy": "uuid",
"createdAt": "1658312909707",
"lastUsedAt": "1606237167221",
"isWhitelist": true,
"travelRuleInfo": {
"beneficiaryVerificationMethod": "vasp",
"beneficiaryVerificationStatus": "verified",
"beneficiaryName": "Some name",
"beneficiaryType": "legal-person",
"beneficiaryVaspId": "did:ethr:123456789",
"beneficiaryVaspName": "VASP Name"
}
}
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"
}
}
}
]
}
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 ClearLoop account
"toPortfolioId": "Bahng9nai9ieGhaeg8Heasokahshee7A" # To the parent Trading 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.
The response contains the following information about the funds:
Field | Data type | Description |
---|---|---|
balance |
BigDecimal |
Total amount of currency |
locked |
BigDecimal |
Delegated amount of currency, including the funds delegated to the ClearLoop sub accounts |
available |
BigDecimal |
Unused funds |
reserve |
BigDecimal |
The amount of funds reserved for all active orders |
totalBalance |
BigDecimal |
A sum of balance and stakeBalance for all portfolios. |
stakeBalance |
BigDecimal |
The balance of funds that are locked in staking. Applies only for portfolios with custody and trading-vault types(#portfolio-types) |
The following formula shows how the balance is calculated:
balance
= available
+ reserve
+ locked
If you query a ClearLoop portfolio for its balance then keep in mind the following:
- Any successful delegation operation will add to the
available
andbalance
fields. - Any successful undelegation opearion will substract from the
available
andbalance
fields. Initially there is a transition fromavailable
toreserve
with balance unchanged and then deducting from bothbalance
andreserve
. - When a settlement happens the profit or loss associated with those settlement orders is added (in case of profit) or deducted (in case of loss) from the
available
andbalance
fields. In case of loss there is a transition fromavailable
toreserve
with balance unchanged and then deducting from bothbalance
andreserve
.
If you query the trading portfolio (or trading-vault) that has a clearloop portfolio underneath it then keep in mind the following details:
available
: the funds that are not delegated or involved in any operation.locked
: the funds that are delegated from this trading portfolio to clearloop portfolios.- One trading portfolio can have several clearloop portfolios underneath it. The trading portfolio then contains the aggregated values of these clearloop portfolios.
- Any settlement operations lead to an increase (profit) or decrease (loss) in the trading portfolio. If there is a profit then the sum of
locked
andbalance
will be increased on the trading portfolio. If there is a loss then the sum oflocked
andbalance
will decrease.
+ GET /platform/wallets?portfolioId={clearLoopPortfolioId}
+ Response 200 OK
{
"wallets": [
{
"walletId": "cl122gxq1000h386585dgi2vw",
"portfolioId": "ulCJwlxHCV0VOZoZGrLJkYT1",
"currency": "ETH",
"mainCurrency": "BSC",
"balance": "0.000202725",
"stakeBalance": "0",
"totalBalance": "0.000202725",
"reserve": "0.000000000",
"locked": "0.0001012",
"available": "0.000101525",
"pledged": "0",
"createdAt": "1647949309870",
"createdBy": "6cba908a-763b-49b9-bdf9-4559ec28e738",
"updatedAt": "1660811782426",
"extra": {
"walletShardUploadedBy": "admin"
},
"accountId": "29af7ea0-5878-4a6a-93de-6647e0d287fa",
"organizationId": "1234567",
"portfolioType": "custody",
"_embedded": {
"depositTargets": [
{
"targetType": "crypto",
"depositTargetId": "69c7192d-d745-4f91-b762-7eb850a5e49f",
"mainCurrency": "BSC",
"address": "0xc7eed7ddf7c17a11d34fe067d186bc873ae271d7",
"status": "enabled"
}
],
"pendingDepositTargets": []
},
"isActive": true
}
]
}
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
Fetch all updated orders
#!python
import hashlib
import hmac
import json
import os
import requests
import time
ApiKey = os.getenv("COPPER_LIVE_API_KEY")
ApiSecret = os.getenv("COPPER_LIVE_API_SECRET")
def copper_api(method, path, body=None):
timestamp = str(round(time.time() * 1000))
body_string = json.dumps(body) if body else ""
signature = hmac.new(
key=bytes(ApiSecret, 'utf-8'),
msg=bytes(timestamp + method + path + body_string, 'utf-8'),
digestmod=hashlib.sha256
).hexdigest()
url = 'https://api.copper.co' + path
resp = requests.request(method, url, data=body_string, headers={
'Authorization': 'ApiKey ' + ApiKey,
'X-Signature': signature,
'X-Timestamp': timestamp
})
print("Copper API ~~~> " + method + " " + url + " <~~~ " + str(resp.status_code) + " " + resp.reason)
if resp.status_code >= 400:
raise Exception("Copper API Error: " + str(resp.status_code) + " " + resp.reason + " <~~~ " + resp.text)
return resp.json()
def get_latest_updated_at():
# retrieve the updated_at value from a database or return 0
return 0
def save_latest_updated_at(updated_at):
# store the updated_at value in a database
pass
def fetch_updated_orders(last_updated_at):
# fetch all orders from Copper that have been updated since updated_at
# return a list of orders
limit = 100
response = copper_api("GET", "/platform/orde1rs?orderType=deposit&updatedSince=" + str(last_updated_at) + "&limit=" + str(limit))
orders = response.get('orders', [])
if len(orders) > 0:
for order in orders:
# do something with the order
print(order.get('orderId') + " - " + order.get('updatedAt'))
pass
last_updated_at = orders[-1].get('updatedAt')
save_latest_updated_at(last_updated_at)
if len(orders) != limit:
time.sleep(10) # wait 10 seconds before fetching the next batch of orders
fetch_updated_orders(last_updated_at)
if __name__ == "__main__":
fetch_updated_orders(get_latest_updated_at())
Models
The following are common types used throughout the API.
Order
Parameter | 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 |
Type of the order |
portfolioId | String |
Unique identifier of the portfolio, for which the order will be created |
portfolioType | Enum<PortfolioType> |
Type of the portfolio |
accountId | String |
Account identifier |
amount | BigDecimal |
Order execution amount |
baseCurrency | Currency |
Currency of the amount |
mainCurrency | Optional<Currency> |
Currency defining a blockchain network for baseCurrency |
quoteCurrency | Optional<Currency> |
Quote currency of the trading order |
quoteMainCurrency | Optional<Currency> |
Currency defining a blockchain network for quoteCurrency |
limitType | Optional<LimitType> |
Limit type of the order |
priceLimit | Optional<BigDecimal> |
Price of a settle or trading order |
extra | OrderExtra |
Additional order data |
createdBy | Optional<String> |
User ID of the order creator |
organizationId | String |
Unique ID of the organisation of the creator |
createdAt | Long |
Timestamp of order creation |
updatedAt | Optional<Long> |
Timestamp of the latest order update |
terminatedAt | Optional<Long> |
Timestamp of the order termination |
Order Types
Name | Description |
---|---|
buy | Buy order |
sell | Sell order |
withdraw | Withdraw order |
multi-withdraw | Withdraw to multiple addresses order |
deposit | Deposit order |
earn-reward | Order to earn rewards for staking the assets |
retrieved-deposit | Order is generated automatically to move the funds that are too small to cover the fee (dust) from the proxy to the main wallet/custody with next sufficient deposit order |
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 canceled |
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 |
atomic-settlement-reservation-completed | all the orders for clearloop settlement can proceed and funds are reserved |
Limit Types
Name | Description |
---|---|
otc | Limit type of the settle order |
rfq | Limit type of a trading order |
Blockchain Transaction Type
Value | Description |
---|---|
stake-delegation | Delegate funds to staking or move them to other chains/wallets where it will be used for staking in future with other transactions |
stake-nomination | Nominate stake to specific pools |
stake-undelegation | Request funds back from staking to make them operable |
complete-withdrawal | Use to wait the unbonding period and sign transaction (required for some blockchains to get funds to operable balance after undelegation) |
stake-complete-deposit | Use to accept exported (via stake-delegation ) transactions to perform stake operations for AVAX |
take-reward | Take rewards that were issued to operable balance |
pool-creation | Create transaction that registers new staking pool with specified vault address |
unjail | Unjail pool that is controlled by wallet (BSC) |
importance-transfer | Associate importance for XEM wallet to specific public key |
transfer-stake | Move stake from one pool to another |
rebond-stake | Stake funds in unbonding period before it ends |
chill | Disable active stake to get permission to unstake funds (DOT) |
register-online | Register ALGO funds to staking |
register-offline | Request ALGO funds from staking to make them operable |
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 | PortfolioType |
Type of the portfolio |
createdBy | String |
User ID of the portfolio creator |
updatedBy | Optional<String> |
User ID of the last portfolio updater |
createdAt | Long |
Timestamp of portfolio creation |
updatedAt | Optional<Long> |
Timestamp 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) |
PortfolioExtra
Field | Data type | Description |
---|---|---|
exchange | Optional<Exchange> |
External exchange associated with this portfolio (see the Exchange list below) |
exchangeAccountType | Optional<ExchangeAccountType> |
External portfolio exchange account type (see the ExchangeAccountType list belo |
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 |
Portfolio Types
Name | Description |
---|---|
custody | Portfolio type of a vault portfolio |
trading-vault | Portfolio type of a trading vault portfolio |
trading | Portfolio type of a trading portfolio |
external | Portfolio type of an external portfolio (Walled-Garden accounts) |
clearloop | Portfolio type of a ClearLoop portfolio |
Wallet
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 |
availableToUndelegate | Optional<BigDecimal> |
Current available balance to undelegate. This field only appears on ClearLoop portfolio wallets |
reserve | Optional<BigDecimal> |
Reserved balance |
createdBy | String |
User ID of wallet creator |
updatedBy | Optional<String> |
User ID of the last wallet updater |
createdAt | Long |
Timestamp of wallet creation |
updatedAt | Optional<Long> |
Timestamp of the latest wallet update |
extra | WalletExtra |
Additional wallet data (includes the WalletExtra model below) |
accountId | String |
unique account identifier that includes this wallet |
organizationId | Optional<String> |
Unique identifier of an organisation including this wallet |
_embedded | Optional<WalletEmbedded> |
Additional information on the wallet (includes the WalletEmbedded model below) |
WalletExtra
Field | Data type | Description |
---|---|---|
externalAccountId | Optional<String> |
Third-party identifier (ID of an external account) |
WalletEmbedded
Field | Data type | Description |
---|---|---|
depositTargets | List<WalletDepositTarget> |
List of deposit targets attached to the wallet |
outstandingBalance | Optional<BigDecimal> |
Amount of outstanding balances, if any |
WalletDepositTarget
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 |
CreateOrder
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). This value is mandatory for Custody, Trading or Settlement Lite portfolios. |
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 |
blockchainTransactionType | Optional<String> |
Blockchain transaction type |
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 |
Address Book - BankAccount
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 |
Timestamp of bank account creation |
updatedAt | Optional<Long> |
Timestamp 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
Address Book - 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 |
|
isWhitelist | Boolean |
Defines, if the address is whitelisted or not |
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 |
Timestamp of crypto address creation |
updatedAt | Optional<Long> |
Timestamp of last crypto address update |
Counterparties
Field | Data type | Description |
---|---|---|
counterparties | List<Counterparty> |
List of counterparties |
Counterparty
Field | Data type | Description |
---|---|---|
counterpartyId | String |
Unique identifier of a counterparty on the Copper platform |
counterpartyName | String |
Counterparty name as shown on the Copper platform |
counterpartyDescription | String |
Counterparty description as shown on the Copper platform |
networkTag | String |
Network Tag as shown on the Copper platform |
counterpartyType | CounterpartyType |
Counterparty type indicated access type to the network |
_embedded | Optional<CounterpartyEmbedded> |
Additional information of the counterparty |
Counterparty Types
Name | Description |
---|---|
standard | has full access to the network |
lite | has limited access to the network |
Counterparty Embedded
Name | Data type |
---|---|
counterpartyConnection | Optional<CounterpartyConnection> |
counterpartyDetails | Optional<CounterpartyDetails> |
Counterparty Connection
Name | Data type | Description |
---|---|---|
connectionId | String |
Unique identifier of a counterparty connection on the Copper platform |
requestorCounterpartyId | String |
Identifier of a counterparty who requested a connection |
receiverCounterpartyId | String |
Identifier of a counterparty who received a connection request |
requestStatus | RequestStatus |
Status of the connection |
Counterparty Request Status
Name | Description |
---|---|
accepted | Accepted connection |
pending | Pending connection |
declined | Declined connection |
Counterparty Details
Name | Data type | Description |
---|---|---|
connectionId | String |
Unique identifier of a counterparty connection on the Copper platform |
counterpartyAddress | Optional<String> |
Counterparty address |
counterpartyEmail | Optional<String> |
Counterparty email |
counterpartyPhoneNumber | Optional<String> |
Counterparty phone number |
DeliveryType
Enum with the following values:
Name | Data type | Description |
---|---|---|
free-of-payment | String |
Settlement order type: free of payment |
payment-vs-payment | String |
(default) Settlement order type: payment versus payment |
Changelog
January 2024
- The Copper Network section has been updated: delivery type description and
quoteAmount
support were added,mainCurrency
parameter became mandatory. - The description of
feeLevel
was added to Dry-run for withdrawal orders request. - The Address book section has been updated: Travel Rules for outgoing withdrawal orders were implemented.
November 2023
The new Activity API section has been created: it includes operations related to retrieving activity events.
May 2023
The new Bulk BTC transfer order function has been described.
January 2023
- The new DeFi API section has been created: it includes operations related to DeFi orders.
November 2022
- The new Staking API section has been created: it includes operations related to staking reward orders.
August 2022
The new Common API operations section has been created: it includes operations that are same for subsequent specific APIs:
- Validate a blockchain address: removed from Account API
- Get information about latest orders of an organisation or a particular order: removed from Transfer API, Trading API, Settle API
- Create a new order: new article, general information about creation of platform orders
- Cancel an order: removed from Transfer API, Trading API, Settle API
- Get supported currencies and tokens: removed from User flows
The Transfer API section has been moved up in the table of contents. Following articles were added into this section:
The Webhooks section has been updated and expanded with webhook message examples. New webhook messages:
withdraw-failed
order-master-password-required
The new Copper Network API section has been created: it includes operations related to OTC trading with the use of the Copper Network.
Documentation wording and content have been reviewed in following articles:
The deprecation warning in the Copper Unlimited Online article has been removed.
July 2022
- The Example of the service section has been included into the Copper Unlimited Online article.
May 2022
- The Webhooks article has been changed in accordance with the UI webhook release.
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.