Partner API
Walkthrough
The step-by-step walkthrough is designed to help you get started with the Qredo Partner API. The steps are organized in a basic flow to have your account set up for all basic asset transfer scenarios. This section doesn't discuss the Signing Agent.
Overview of steps
This section presents a sequence of suggested steps to help you get started with the Partner API.
Step 1. Create a company and get your company ID. You'll be completing all remaining steps on behalf of your company.
Step 2. Add a trusted party to start building your trusted network of approvers. Your newly-enlisted approver must accept an enrollment request before they can be eligible for performing custodial actions.
Step 3. Create a Fund and appoint approvers as created in the previous step. Your company requires a Fund that holds Wallets you can deposit assets to. In this step you create Fund custodial policies: one for transactions and one for withdrawals. At this step, you also appoint trusted parties with the respective policy.
Step 4. Perform a deposit transfer assets from a Level 1 Wallet to your Fund Wallet address.
Step 5. Perform a transfer transaction within the Qredo Network: move assets from one Qredo Wallet to another. Completion of this step requires a custodial action.
Step 6. Perform a withdrawal and finalize the walkthough by transferring assets to a whitelisted Level 1 Wallet: one that resides outside the Qredochain, such as BTC, ETH, etc. Completion of this step requires a custodial action.
Each of these steps is detailed in a dedicated subsection.
Whatever you do in the API is not visible in the Qredo Web app
You will use the same account to access the Qredo Web app and the API. However, what happens in the Web app will not be visible or accessible in the API, and vice versa. For example, Funds, Wallets and assets contained in these Wallets will remain where created: either in Web App or the API.
High-level overview of API-specific terms
Before you continue, you should understand the underlying concepts for operations on the Qredo Network:
All transactions across and out the Qredochain undergo custody. In other words: all transactions out a Qredo Wallet require approvals (or rejections) by approvers that you appoint. These include transfers and withdrawals.
You will be dealing with one or more of the following terms in most most API use cases:
A short glossary with Qredo-specific terms
Company - This is the entity on behalf of which you perform most API call actions. Think of it as an office that manages one or more Funds and employs all approvers for asset transfers.
Trusted party - This is the Qredo approver: a dedicated Qredo account who approves or rejects transactions. The collection of trusted parties in a company is called a trusted network. Every trusted party user performs custody via their Qredo mobile Signing app. The API offers a dedicated user type for "API custody": the Signing Agent. You will learn about it in the next chapter.
Fund - The Fund is the actual sub-entity to a company that contains Qredo Wallets and the approval rules for transactions with these Wallets: the so-called custodial policies. These policies also include the trusted parties that perform custody over transactions within that Fund.
Custodial policies - A custodial policy defines the number of approvals (also called the threshold) necessary for a transfer or withdrawal transaction to be completed; plus it also includes the approvers eligible to perform these approvals. Every Fund has a "global" policy for transfers and withdrawals. A Wallet can have custom policies as well but this is not required. If a given Wallet lacks policies, the global ones apply. Note that each policy definition includes a selection (a subset or all) of the company trusted parties for custodial actions.
Do not worry if these concepts are not entirely clear yet. You will learn more about each when you complete all steps.
API specifics in this walkthrough
All steps are designed to follow a natural flow to build up comfort with Qredo specifics.
- API resources in titles and explanation paragraphs are shown simplified with base URLs excluded: e.g.
POST /company
. - Not all API calls are covered: just the ones to get you started, so visit the Swagger UI documentation on Sandbox for more info.
- Headers are not included in request examples. See Sign Partner API calls for more info.
- Descriptions of body parameters are added in their respective request and response examples in the stead of actual values.
- Some steps require the use of a trusted party. For testing, custodial actions can be performed by either a Qredo account that you own or a Signing Agent set for custody. However, this walkthrough will not go into detail with the Signing Agent use.
Use testnet assets when testing
Qredo strongly recommends that you use testnet assets for test transactions until you get familiar with the Partner API.
Step 1: Create a Company
This section guides you through creating a Company. Nearly all API calls are performed on behalf of a Company, including transactions. You must have at least one Company but you can have several for separate asset flows.
The Company sits on top of the hierarchy. Each Company has a list of custodians (approvers) that approve transactions out of Wallets that belong to a Company.
To create a Company, use the POST /company
API endpoint. You must supply a name
. A successful response returns the company_id
. This company_id
is passed in all following API calls.
Your Companies are not visible in Web App
The Company is similar to an Organization in the Qredo Wallet Web App. However, just like Organizations are not visible in the API, the companies are not visible in the Web App.
Example request: POST /company
This example creates a Company called random_inc
to this endpoint:
curl -X POST "https://api.qredo.network/api/v1/p/company"
Request body
name
is required. All other parameters are optional. You can update any of these later, including the name.
{
"name": "random_inc",
"city": "<name of city, e.g. 'Paris'>",
"country": "<ISO 3166-1 country code, e.g. 'FR'>",
"domain": "randomincorporated.com",
"ref": "<a Company reference ID, e.g. '9827feec-4eae-4e80-bda3-daa7c3b97add'>"
}
Example response: POST /company
Upon success, the response returns the company_id
hash as a string value.
{
"company_id": "1va2cJ2pqdLSFAN5t1knBrnuMvw",
"city": "Paris",
"country": "FR",
"domain": "randomincorporated.com",
"ref": "9827feec-4eae-4e80-bda3-daa7c3b97add"
}
Step 2: Add a trusted party
This section guides you through adding approvers to your Company. Approvers may be (human) trusted parties i.e. Signing App approvers or automated Signing Agents.
Trusted parties approve *transfer out* transactions
Trusted parties perform custody on all transactions that move assets out of a Qredo Wallet.
Your trusted parties are not visible in the Qredo Web App
As with Companies instantiated via the API, the trusted parties you enlist with your Company will not be visible in the Web App.
1. Add Signing App approver/s
Policies are editable
You can always add or remove trusted parties at a later stage.
1.1. Enlist a trusted party
To enlist a trusted party, use POST /trustedparty
:
- Identify the Company by
company_id
in the path. - Pass the trusted party user's registered email
address
in the body of the request.
This must be the email address used with their Qredo account.
Example request:
curl -X 'POST' \
'https://play-api.qredo.network/api/v1/p/company/{company_id}/trustedparty' \
-H 'accept: application/json' \
-H 'x-timestamp: 1668069089' \
-H 'x-sign: r76j7xH....QpUxEw' \
-H 'X-API-KEY: eyJrZXl...6dHJ1ZX0' \
-H 'Content-Type: application/json' \
-d '{"address":"[email protected]"}'
Example response:
{"code":200,"msg":"OK"}
You can add several trusted parties at once
You can supply several entries in the JSON body, for example:
{
"address": "[email protected]",
"address": "[email protected]",
"address": "[email protected]"
}
A successful response returns a HTTP 200 OK
confirmation via the API, and the appointed user will receive a notification on their mobile device with the Qredo Signing App installed.
Enlisted trusted parties cannot perform custody yet
This step add users to your trusted network. They will not be able to approve transactions until appointed to do so, as described in the next guide: Step 3. Create a fund.
1.2. Wait for trusted party approval
Your appointed user must approve (authorize) their addition to your trusted network via the Mobile Signing App.
1.3. Verify trusted party addition
Either communicate with your nominated trusted parties to verify their acceptance, or check GET /trustedparty
to retrieve a list of all trusted parties in a Company.
2. Add a Signing Agent approver
A Signing Agent may be added as a trusted party to your Company.
2.1. Enlist a Signing Agent as an approver
To enlist a trusted party, use POST /trustedparty
:
Identify the Company by company_id
in the path. Pass the Signing Agent's identifier, agentID
as the address
in the body of the request.
You can add several Signing Agents at once
You can supply several entries in the JSON body, for example:
{
"address": "HNRosks34HS0ILtlRtEzNlITDlPEoirgXTxzY52qPG7w",
"address": "CBApocs97bS7SgE21Ht5xRHFWRbcrH9AMZHgsoUd2gpp",
"address": "JSOwasg92vW1eJNRGz3qb20K7GUxy7f5jtEBZrX4bTsa"
}
2.2. Verify trusted party addition
Verify the addition of your Signing Agent with GET /trustedparty
to retrieve a list of all trusted parties in a Company.
How to verify trusted party addition
Example request: GET /trustedparty
Retrieve a list of all trusted parties in a Company. Again, you need to pass the company_id
as a URL parameter.
curl -X GET "https://api.qredo.network/api/v1/p/company/{company_id}/trustedparty"
No body parameters are sent with this request.
Example response: GET /trustedparty
A successful response returns a list with trusted network members.
{
"company_id": "<company ID>",
"total_count": "<total number of trusted parties>",
"list": [
{
"list": {
"trusted_entity_id": "<user's approver ID>",
"name": "<first and last name>",
"address": "<email address>",
"type": "<user type>",
"created": "<Epoch timestamp when user was added as a trusted entity>"
}
}
]
}
Obviously, your selected trusted party must accept the enrollment request before you can expect this response to include them.
Add approvers to a Fund
Even after becoming part of your trusted network, trusted parties cannot perform custodial actions. Before you can add them to a custody policy, you must create a Fund with Wallet/s.
Step 3. Create a Fund
A Fund is the sub-entity to the Company that contains one or more Wallets and defines the custodial policies for transfers and withdrawals of assets out of these Wallets. With Qredo, a Wallet always belongs to a Fund and any transaction that moves assets out of a given Qredo Wallet, undergoes custody.
Every transaction out of a Qredo Wallet requires an approval
- On the Qredo Network, a transaction to move assets out of a Qredo Wallet can only take place after it has been approved by the approvers of that Wallet. This includes transactions out of a Wallet: transfers or withdrawals.
- The approval process on Qredo requires that a minimum threshold of enlisted approvers must provide their approval for a transfer out transaction to go through.
Fund and Wallet definition
A Company must have at least one Fund. The Fund can contain one or multiple Wallets In terms of the Partner API, a Fund
definition contains:
- a Fund custodial policy:
custodygroup_withdraw
. The policy includes its dedicated list of appointed approvers and athreshold
value: the number of required approvals. Default configuration to all Wallets with no such custom policy configured. - a Fund transfer out custodial policy:
custodygroup_tx
. The policy includes its dedicated list of appointed approvers and athreshold
value: the number of required approvals. Default configuration to all Wallets with no such custom policy configured. - one or more
wallets
(per asset, such as BTC or ETH). You can configure custodial policies in the Wallet definition to override Fund policies.
Fund definition object
Use POST /company/{company_id}/fund
to create a Fund. You can see the simplified view of what the Fund definition contains.
{
"name": "Fund 01",
"description": "Fund for demonstration purposes",
"custodygroup_withdraw": {
"threshold": 2,
"members": [ list of withdrawal approvers
]
},
"custodygroup_tx": {
"threshold": 2,
"members": [ list of tx approvers
]
},
"wallets": [ list of Wallet definitions
]
}
]
}
Make sure your Fund definition has valid definitions of:
- withdrawal custody policy
- transfer custody policy
- at least one Wallet
It is not required for the Wallet definition to have custom custodial policies.
Wallet definition object
You can add more Wallets to your Fund at a later stage using POST /company/{company_id}/fund/{fund_ID}/wallet
.
{
"name": "New Wallet with custom custody group",
"asset": "BTC-TESTNET",
"custodygroup_withdraw": {
"threshold": 1,
"members": [ list of withdrawal approvers
]
},
"custodygroup_tx": {
"threshold": 1,
"members": [ list of tx approvers
]
}
}
If the Wallet definition doesn't include a custodial policy, it automatically inherits the corresponding one of the Fund. You are not required to add custom (per Wallet) custodial policies.
<<<<<<< HEAD A Fund can have multiple Wallets. It is up to you to define a structure that suits your purposes and use cases.
Fund and Wallets created in Partner API not visible in Qredo Web App
Similar to the Company and trusted parties, the Funds (and Wallets) you create in the API will not be visible in the Web App.
Example request: POST /fund
To create your Fund, you must use POST /fund
. Along with a Fund name, you will add custodial policies and Wallets to your Fund.
This example creates a Fund named "Awesome Fund" that contains the following definitions:
- a
custodygroup_withdraw
policy withthreshold
set to2
and 3 specified trusted networkmembers
- a
custodygroup_tx
policy withthreshold
set to3
and 4 specified trusted networkmembers
- two
Wallets
: one with global custodial policies and one with custom custodial policies
With this API resource, you pass company_id
as a URL parameter.
curl -X POST "https://api.qredo.network/api/v1/p/company/{company_id}/fund"
Request body
The following top-level parameters are required: name
, description
, custodygroup_withdraw
, custodygroup_tx
. You can add more Wallets
at a later stage but, once created, you cannot remove Wallets.
{
"name": "Awesome fund",
"description": "A demo fund",
"custodygroup_withdraw": {
"threshold": 3,
"members": [
"<withdrawal trusted party01 id>",
"<withdrawal trusted party02 id>",
"<withdrawal trusted party03 id>"
]
},
"custodygroup_tx": {
"threshold": 2,
"members": [
"<tx trusted party 01 id>",
"<tx trusted party 02 id>",
"<tx trusted party 03 id>",
"<tx trusted party 04 id>"
]
},
"wallets": [
{
"name": "Demo ETH-TESTNET Wallet that uses global custodial policies",
"asset": "<asset type: BTC, ETH, etc.>",
},
{
"name": "Demo ETH-TESTNET Wallet with custom custodial policies",
"asset": "<asset type: BTC, ETH, etc.>",
"custodygroup_withdraw": {
"threshold": 2,
"members": [
"<withdrawal trusted party01 id>",
"<withdrawal trusted party02 id>"
]
},
"custodygroup_tx": {
"threshold": 1,
"members": [
"<tx trusted party 01 id>",
"<tx trusted party 02 id>"
]
}
}
]
}
You cannot update the Fund's custodial policies!
Once you create a Fund, you cannot update the custodial policies. You can update the custodial policies of a Wallet.
Custodial policies explained
The custodygroup_withdraw
on top level is the global (per Fund) withdrawal custodial policy definition. The custodygroup_withdraw
, part of the "Demo ETH-TESTNET Wallet with custom custodial policies" is the definition the overriding policy.
It is the same with the global vs. custom transfer policies.
Both with transfers and withdrawals, a custody policy includes:
threshold
: this value defines how many approvals are required for a transaction to go through. In this case it is set to2
members
: this list includes IDs of members of your trusted network. In this case, three members are listed and at least two approvals are required
Obviously, for transactions to pass through custody, the threshold
value must be less than or equal to the number of specified members
.
The custodygroup_tx
is configured similarly to custodygroup_withdraw
and in this case is set to require 3 approvals (threshold
set to 3
) from three of the four specified members
.
Always define custodial policies per Fund!
If you create a Fund without custodial policies and you add Wallets without custodial policies, transactions using these addresses may get stuck in the custodial approval process.
Definitions of custom (per Wallet) custodial policies have the exact same structure.
Wallet definitions explained
- A Wallet on the Qredochain is not merely an address per asset type: it is rather a definition, that may or may not include custodial policies and dedicated approvers.
- A Wallet on the Qredochain always belongs to the Fund it was created in: with Qredo, there are no Wallets outside a Fund.
The wallets
object lists two Wallets: one that uses the global custodial policies (has no custom policy definitions) and another that uses custom ones.
Example response: POST /fund
Upon success, the response returns the fund_id
hash as a string value plus policies, assets, trusted network members and Wallets.
{
"fund id": "<ID of your Fund>",
"name": "<name of your Fund>",
"description": "<description of your Fund>",
"custodygroup withdraw": "<Fund custodial policy ID for withdrawals>",
"custodygroup tx": "<Fund custodial policy ID for transactions>",
"policy withdraw": "<object containing withdraw policy info>",
"policy tx": "<object containing withdraw policy info>",
"members": "<list of Fund members and details of each>",
"assets": "<list of supported assets in your Fund>",
"wallets": "<list of Wallet objects with info like addresses and balances>"
}
The response, as shown, is significantly shortened: objects are presented as "collapsed". This is intentional and aims to keep things simple.
Pass `fund_id` with deposits, withdrawals, Wallets, ledger, etc.
Save the fund_id
value to perform different Fund-specific actions, such as deposit and withdrawal transactions, creation of additional Wallets and retrieving ledger tx history. Transfer transactions do not require fund_id
.
For brevity, Wallets omitted from response
The above response contains the Wallet definitions as well. However, Wallet definitions with custom custodial policies also contain the definitions for these policies. For the sake of brevity Wallets will not be discussed in detail just yet.
Optional step: Create a Wallet
While it is not a necessary step to complete this tutorial, you should know more about how to create and use your Wallets.
Example request POST /wallet
This example creates a single Wallet in a Fund and appoints two custodians for both transfer and withdrawal transactions. The approval threshold is 1, which means one approval is enough for a transaction out your Wallet. A successful response returns the Wallet ID.
With this API resource, you pass company_id
and fund_id
as URL parameters:
curl -X 'POST' 'https://api.qredo.network/api/v1/p/company/{company_id}/fund/{fund_id}/wallet'
Request body
You can create any type of Wallet, depending on what you specify in the request body.
For this Wallet custody policies are not specified. It inherits them from the Fund.
{
"wallets": [
{
"name": "New wallet",
"asset": "BTC-TESTNET",
}
]
}
you can create several wallets at once
You can create several Wallets at once: just pass multiple objects in the wallets
array.
Example response POST /wallet
A successful response returns the wallet_id
.
{"wallets":["3Hqis3UuRGTvJVQ7AxCj9nesDBydPKWfZge6hj31sRop"]}
Wallet ID vs Wallet address
Wallet ID is pertinent to Qredo network only. Do not mistake this ID with the Wallet address. In terms of Qredo, a Wallet address is used only when moving assets from L1 blockchain to Qredochain (deposits), or vice versa: from Qredochain to L1 blockchain (withdrawals). Only deposit Wallets have addresses. In all API calls for moving assets within the Qredo Network, or query Wallet details, use this wallet_id
parameter.
Optional step: Query for Wallet details
You would not always need to retrieve Wallet details but it certainly might come in handy.
Example request GET /wallet/{wallet_id}
This example fetches details of a Wallet, identified by its wallet_id
.
Example response GET /wallet/{wallet_id}
The response returns very detailed info about this Wallet, including address
and balance
. In fact, the response is a bit large, especially with custom trusted policies and multiple trusted parties.
{
"wallet_id": "3Hqis...1sRop",
"name": "BTC-Testnet wallet",
"asset": "BTC-TESTNET",
"type": 0,
"status": "ready",
"address": "mm1Bvy1iXQUJA1eh1edhoDG4yGzdo583iE",
"address_type": "P2PKH",
"short_code": "trophy turtle metal",
"balance": 0,
"custodygroup_withdraw": "21cDwa2ap1jUytjwdtyrgaRxZ74",
"custodygroup_tx": "21cDwSnWn8VzSsfKVU9UbSxXDeL",
"policy_withdraw": {
"id": "21cDwa2ap1jUytjwdtyrgaRxZ74",
"entityID": "",
"name": "Wallet BTC-Testnet wallet Withdraw policy",
"locked": false,
"lockedTxID": "",
"members": [
{
"dedicated": false,
"entity": {
"id": "13DCS...vDiag",
"accountCode": "2VvnB...wH41h",
"name": "Trent Kryptor",
"initials": "TK",
"type": "user",
"user": {
"firstName": "Trent",
"lastName": "Kryptor",
"email": "[email protected]",
"username": "apiSign"
}
}
},
{
"dedicated": false,
"entity": {
"id": "9niR8...RW3xu",
"accountCode": "9niR8...RW3xu",
"name": "Demo Core Client",
"initials": "C",
"type": "core-client",
"coreClient": {
"name": "Demo Core Client"
}
}
}
],
"threshold": 1,
"membersCount": 2,
"walletCount": 0,
"dedicatedWalletCount": 0,
"fundsCount": 0,
"funds": null
},
"policy_tx": {
"id": "21cDwSnWn8VzSsfKVU9UbSxXDeL",
"entityID": "",
"name": "Wallet BTC-Testnet wallet Tx policy",
"locked": false,
"lockedTxID": "",
"members": [
{
"dedicated": false,
"entity": {
"id": "13DCS...vDiag",
"accountCode": "2VvnB...wH41h",
"name": "Trent Kryptor",
"initials": "TK",
"type": "user",
"user": {
"firstName": "Trent",
"lastName": "Kryptor",
"email": "[email protected]",
"username": "apiSign"
}
}
},
{
"dedicated": false,
"entity": {
"id": "9niR8...RW3xu",
"accountCode": "9niR8...RW3xu",
"name": "Demo Core Client",
"initials": "C",
"type": "core-client",
"coreClient": {
"name": "Demo Core Client"
}
}
}
],
"threshold": 1,
"membersCount": 2,
"walletCount": 0,
"dedicatedWalletCount": 0,
"fundsCount": 0,
"funds": null
}
}
Step 4: Perform a deposit
A deposit on the Qredo network is a transaction that transfers Funds from a L1 blockchain address to a Qredochain (L2) address. You perform a deposit to a Wallet in your Fund using external Wallet services such as MetaMask, Exodus, Electrum, etc.
Now that you have a Fund with one or more Wallets, you can deposits assets.
Transaction types in this walkthrough
The transactions you will perform in this walkthrough are:
- deposit - transfer assets from a Level 1 Wallet (outside Qredochain) to a Qredo Wallet: L1 to L2 transaction
- transfer - transfer assets from one Qredo Wallet to another Qredo Wallet: L2 to L2 transaction
- withdrawal - transfer assets from a Qredo Wallet to a L1 Wallet outside Qredochain: L2 to L1 transaction
Don't forget that approvers do not approve deposit transactions.
To complete this step, you must:
- Use the
GET /deposit
resource in this example to fetch Wallet information such as address, asset type and current (initial) balance of each. Obviously, the balance of a newly created Wallet equals0
. - Perform a deposit transfer from an external Wallet (Metamask, Exodus, Electrum, or an exchange, etc.).
- Use the
GET /deposit
resource again to verify that your Wallet balance has reflected this deposit transaction on the Qredo network.
1. Retrieve address for deposit
Each Fund contains one or more deposit addresses for the different types of assets and you must make sure to get the right ones before you proceed.
!!! Important "Use Wallet L1 address for deposits" From a Qredo standpoint, your L2 Wallet has an ID and a L1 address. To deposit assets from a L1 Wallet, you must always identify the deposit Wallet on Qredo using its L1 address.
Example request: GET /deposit
This example retrieves details of all deposit Wallets in a Fund. With this API resource, you pass company_id
and fund_id
as URL parameters.
curl -X GET "https://api.qredo.network/api/v1/p/company/{company_id}/fund/{fund id}/deposit"
No body parameters are sent with this request.
Example response: GET /deposit
The response returns a list with all deposit Wallet addresses.
{
"total_count": 1,
"list": [
{
"asset": "<L1 asset type: `BTC`, `ETH`, ETH-TESTNET, BTC-TESTNET, etc",
"address": "<deposit Wallet address>",
"balance": "<deposit Wallet balance in base unit per 'asset': satoshis, gweis, etc.>"
}
]
}
2. Make your deposit using external Wallet
Use your preferred external Wallet service to deposit assets from a Level 1 Wallet into your Qredo Wallet address you just retrieved. Note that this guide doesn't include instructions on services external to Qredo.
3. Verify deposit success
When you submit the deposit amount, make sure the balance in the Qredo deposit Wallet reflects this transaction. Use GET /deposit
once again to ensure the response returns the deposit Wallet balance updated with your deposit amount.
Once your balance reflects the transaction, you can proceed with the next step.
`balance` returned in base units per asset type
The value of your balance
is returned denominated in smallest base units per asset: for example, 100000000 satoshis equals 1 BTC (scale of 100000000) and 1000000000 gweis with ETH (scale of 1000000000).
Step 5: Perform a transfer
With Qredo, a transfer transaction means to move assets from one Qredo Wallet (originating) ID to another Qredo Wallet (destination) ID. Note that when we talk a transfer on the Qredochain, this is a L2 to L2 transaction and the Wallets are identified by their IDs and not their Wallet addresses. Naturally, the transfer flow means you submit a transfer request which will remain in pending status until custody approval / rejection or expiry.
Use Wallet IDs for transfers
From a Qredo standpoint, L2 Wallets on both sides of a transfer transactions are always identified by their Wallet IDs and never by their L1 addresses.
From an approver's standpoint, the transfer transaction is also called a transfer out transaction.
To complete this step, you must:
- Use
GET /fund
to retrieve your Qredo Wallet ID. - Use
POST /transfer
to submit transfer request. - Wait for custodial approval to take place.
- Use
GET /transfer/{tx_id}
to verify that the transaction is approved.
1. Retrieve Wallet ID
This example retrieves detailed information about the Fund, including the custodial policies, list of trusted network members, and all Wallets that belong to the Fund.
Example request: GET /fund
With this request, you pass company_id
and the fund_id
as URL parameters.
curl -X GET "https://play-api.qredo.network/api/v1/p/company/{company_id}/fund/{fund_id}"
No body parameters are sent with this request.
Example response: GET /fund
The response returns a large object with Fund-specific data. For sake of brevity, objects and lists are collapsed in the example.
{
"fund_id": "<ID of your Fund>",
"name": "<name of your Fund>",
"description": "<description of your Fund>",
"custodygroup withdraw": "<Fund custodial policy ID for withdrawals>",
"custodygroup tx": "<Fund custodial policy ID for transactions>",
"policy withdraw": "<object containing Fund withdraw policy info>",
"policy tx": "<object containing Fund withdraw policy info>",
"members": "<list of Fund trusted members and details of each>",
"assets": "<list of supported assets in your Fund>",
"wallets": [
{
"wallet_id": "<ID of Wallet>",
"name": "<Wallet name>",
"asset": "BTC-TESTNET",
"type": 0,
"status": "ready",
"address": "n3L2rkVup9xGbCfP4rnoJZJF5MqJFAiBS1",
"address_type": "P2PKH",
"short_code": "<firstword secondword thirdword>",
"balance": 10000,
"custodygroup_withdraw": "<Wallet custodial policy ID for withdrawals>",
"custodygroup_tx": "<Wallet custodial policy ID for transactions>",
"policy_withdraw": "<object containing Wallet withdraw policy info>",
"policy_tx": "<object containing Wallet withdraw policy info>"
}
]
}
Note that a Wallet always holds one asset type. In this example, there are 10000 satoshis worth of BTC-TESTNET available in the Wallet.
Shortcodes vs. Wallet IDs
Wallets on the Qredo Network have short_code
values which are interchangeable with Wallet IDs. The "short code" is a combination of three unique English words separated by space intervals, in the format:
"short_code": "firstword secondword thirdword"
.
To view the short code of a Wallet, you can either call GET fund/{fund_id}
or GET wallet/{wallet_ID}
.
This example doesn't provide a specific combination of shortcode words as it may turn out to correspond to an actual Wallet on the Qredo Network.
2. Submit a transfer request
This example submits a request for transferring assets from one Qredo Wallet to another.
Example request: POST /transfer
This example submits a transfer request. With this API resource, you pass company_id
as a URL parameter.
curl POST "https://api.qredo.network/api/v1/p/company/{company_id}/transfer"
Request body
All described fields are required. Note the distinction the originating Wallet is specified by wallet_id
while the destination Wallet is defined by counterparty_wallet_address
.
{
"wallet_id": "<Wallet ID of origin Wallet: not the address>",
"counterparty_wallet_address": "<Wallet ID of destination Wallet: not the address>",
"expires": "<Epoch timestamp when transfer request expires if not approved>",
"benefit_of": "<beneficiary name",
"account_no": "<account number: a custom field>",
"reference": "<reference value: a custom field>",
"partner_txID": "<a transaction ID: a custom field>",
"send": {
"symbol": "<asset symbol (BTC, ETH, etc.)>",
"amount": "<asset amount (satoshis, gweis, etc.)>"
}
}
Use shortcodes instead of both Wallet IDs
As a reminder, note that with transactions, you can use short codes instead of:
wallet_id
- interchangeable withshort_code
value of origin wallet.counterparty_wallet_address
- interchangeable withshort_code
value of destination Wallet.
TX request body: use partner_txID
to prevent duplicate transactions
The partner_txID
is a custom parameter, and is used as a separate unique identifier of this transaction. This might be an ID with a system external to Qredo, that you want to map the current transaction to, so its value is coupled with the specific tx_id
. This allows you to:
- map a
tx_id
to another identifier which is unique in whatever way you choose. - prevent you from making a duplicate transaction with the same
partner_txID
. If you try to re-use this ID, the response ofPOST /transfer
you will return thetx_id
value of the original transaction with thatpartner_txID
and with"status": "existing"
.
Example response: POST /transfer
A successful response returns the transaction ID and transfer request status.
{
"tx_id": "<transaction ID>",
"status": "new"
}
View tx status using `tx_id`
From this point on, completion of the transfer is pending custodial actions. Save the tx_id
to view the transaction status. The Partner API offers several API calls that pass the tx_id
of transactions.
3. Undergo custodial approval
The custodial approval process is outside the scope of this tutorial. We assume the transfer transaction is approved in order for this step to be completed.
4. View transaction status
As in a regular case you might not know when the custodial process is complete, you can check the transaction status using the GET /transfer/{tx_id}
API resource.
Example request: GET /transfer/{tx_id}
This example retrieves transfer transaction info. With this API resource, you pass company_id
and the transfer tx_id
as URL parameters.
curl -X GET /company/{company_id}/transfer/{tx_id}
No body parameters are sent with this request.
Example response: GET /transfer/{tx_id}
A successful response returns an object containing transaction-specific data.
{
"approvedCount": "<number of custody approvals>",
"expires": "<Epoch timestamp when tx request expires if not approved>",
"initiatedTimestamp": "<Epoch timestamp when tx request is initiated>",
"initiatorAuthorized": "<a flag if tx underwent custody: 'true' or 'false'>",
"initiatorName": "<name of initiator company>",
"reference": "<your reference>",
"status": [
{
"actionID": "<action ID>",
"firstName": "<approver first name>",
"lastName": "<approver first name>",
"status": "<approval status with current approver: e.g. 'approved'>",
"timestamp": "<Epoch time when custody action took place>",
"userID": "<approver user ID>",
"username": "<approver Qredo account>"
}
],
"statusDetails": {
"accountNo": "123-XX",
"amount": "<tx amount in base units>",
"asset": "<asset symbol: BTC, ETH, etc.>",
"benefitOf": "<recipient full name>",
"expires": 0,
"fees": 1,
"fundID": "<Fund ID>",
"netAmount": 800,
"recipientAddress": "<destination Wallet ID>",
"recipientEmail": "<destination account email address>",
"recipientFirstName": "<recipient first name>",
"recipientLastName": "<recipient last name>",
"recipientUsername": "<recipient Qredo account>",
"reference": "CX15R99XX",
"requestedBy": "Rosa Parks"
},
"thresholdRequired": "<number of required custody approvals>",
"txID": "<transaction id>",
"txStatus": "<tx status: pending, approved, rejected, expired>"
}
Details on some tx-specific objects
approvedCount
: the number of approvals. With approved transactions this value is the same as the value ofthresholdRequired
.status
: an object with user data about each approver of the transaction, including theiruserID
, andusername
, etc. Obviously, the number of status objects returned must correspond to theapprovedCount
value.statusDetails
: details including fees incurred, the net amount transferred, and recipient / beneficiary info, etc.
Once approved, the transfer is written to the Qredo Blockchain.
Step 6: Perform a withdrawal
With Qredo, a withdrawal transaction means moving assets from a Wallet ID to an external Wallet address: one that is not on the Qredochain.
To complete this step, you must:
- Use the
POST /whitelist
resource to make a L1 address eligible for withdrawing assets outside the Qredochain. - Use the
POST /withdraw
resource to submit a withdrawal request (to the whitelisted address) for approval. - Wait for custodial approval to take place.
- Use the
GET /withdraw
resource to verify that the transaction is completed.
1. Whitelist a withdrawal address
This example whitelists a counterparty address that is external to the Qredochain and specifies its asset type. For withdrawals, you must always whitelist the destination external address. Note that you can have a single address whitelisted for more than one Fund in a Company.
Example request: POST /whitelist
With this request, you pass company_id
and the fund_id
as URL parameters.
curl -X POST /company/{company_id}/fund/{fund_id}/whitelist
Request body
All described fields are required.
{
"name": "<memorable name for counterparty address>",
"asset": "<asset symbol>",
"address": "<external counterparty address>"
}
Example whitelist response: POST /whitelist
A successful response returns a HTTP 200 OK
confirmation. You can now use the whitelisted address for withdrawals.
2. Submit withdrawal request
Now that you have a whitelisted external Wallet, you can submit the withdrawal request.
Use destination Wallet L1 **address** for withdrawals
From a Qredo standpoint, when you withdraw assets to Level 1 blockchain, you will define the a L1 Wallet address. To deposit assets from a L1 Wallet, you must always identify the deposit Wallet using its L1 address.
Example withdrawal request: POST /withdraw
This example submits for approval a withdrawal request to a whitelisted Wallet that is outside the Qredochain.
POST /company/{company_id}/withdraw
Request body
All described fields are required.
{
"wallet_id": "<Wallet ID of origin Wallet: not the address>",
"address": "<whitelisted Wallet address>",
"expires": "<Epoch timestamp when withdrawal request expires if not approved>",,
"benefit_of": "<names of beneficiary: a custom field>",
"account_no": "<account number: a custom field>",
"reference": "<reference value: a custom field>",
"partner_txID": "<a transaction ID: a custom field>",
"send": {
"symbol": "<asset symbol (BTC, ETH, etc.)>",
"amount": "<asset amount (satoshis, gweis, etc.)>"
}
}
Example withdrawal response: POST /withdraw
A successful response returns a tx_id
. You will use this value when you need to view the withdrawal status.
{
"tx_id": "<withdrawal transaction ID>",
"status": "new"
}
3. Undergo custodial approval
The custodial approval process is outside the scope of this tutorial. Let's assume the withdrawal request is approved in order for this step to be completed.
4. View withdrawal status
As in a regular case you might not know when the custodial process is complete, you can check the withdrawal status using the GET /withdraw/{tx_id}
API resource.
Example request: GET /withdraw/{tx_id}
This example retrieves withdrawal transaction info. With this API resource, you pass company_id
and the withdrawal tx_id
as URL parameters.
curl -X GET /company/{company_id}/withdraw/{tx_id}
No body parameters are sent with this request.
Example response: GET /withdraw/{tx_id}
The response structure with GET /withdraw/{tx_id}
is the same as with GET /transaction/{tx_id}
, discussed in Step 5: Perform a transfer. To avoid repetition, we'll not go into further detail.
This was the final step in this walkthrough
This was the final step in this walkthrough tutorial. By now, you should be familiar with all basic concepts of the Partner API and can move on with some of the more complex concepts, like start using the Signing Agent.