New versions of the Qredo API and Signing Agent are now available! To get started, just contact us here.
Qredo Logo

Qredo API

Create an EVM transaction

You can also follow this video tutorial:

Overview

This guide explains how to initiate and approve an EVM-based transaction from your Web3 Wallet to a Layer 1 Wallet. The available transaction types include: legacy, EIP-1559, raw input.

You can approve transactions programmatically (without the Signing App). There are two ways to do it: either with the Signing Agent or just with the Qredo API.

If you're going to approve with the Qredo API, take all steps in this guide. If you're using the Signing Agent, just start the Agent and take Step 2 and Step 6 - initiate and check the transaction.

To learn about main differences between approving with the Signing Agent and Qredo API, see this guide: Approve requests

Prerequisites

Before you start, take these steps:

  1. Get an API key.

  2. Get an authentication token.

  3. To approve transactions programmatically, do one of the following:

  4. Create a Portfolio and Wallet.

  5. In the Qredo Web App, navigate to your Workspace and copy the Workspace ID from the URL:

    https://qredo.network/app/workspace/{workspaceID}
    

Step 1: Open a WS connection

Take this step if you wish to approve the transaction with the Qredo API. If you're using the Signing Agent, just launch it before initiating a transaction. The Agent will start listening to a WebSocket feed that returns transaction requests.

To get the transaction request, you need to start listening to a WebSocket feed that returns the requests to sign.

You can authenticate your call like other Qredo API calls: by passing the authentication token as x-token in the request header.

However, some programming languages, such as JavaScript, don't allow passing custom headers with WebSocket requests. In this case, you can authenticate with a query parameter. See the sections below to learn more.

Authenticate with a header

If the programming language or tool you're using allows passing custom headers with WebSocket requests, you can just call WSS: Get requests to sign:

WS wss://api-v2.qredo.network/api/v2/actions/signrequests
  1. Authentication: Pass the auth token as x-token in the request header.

  2. Result: You'll start receiving a feed of requests (actions) to sign.

Authenticate with a query parameter

If the programming language or tool you're using doesn't allow passing custom headers with WebSocket requests, you need to obtain a WebSocket authentication token. Then you'll open a WebSocket connection and pass the token as a query parameter.

To get a WS token, call Get a WebSocket authentication token:

POST https://api-v2.qredo.network/api/v2/websocket/token
  1. Body parameters: Though it's a POST request, it doesn't require a body.

  2. Authentication: Pass the auth token as x-token in the request header.

  3. Result: Copy the returned wsToken.

Now you can open a WebSocket connection. Call WSS: Get requests to sign:

WS wss://api-v2.qredo.network/api/v2/actions/signrequests?token={wsToken}
  1. Query parameters: Pass the WS token in the token query parameter.

  2. Result: You'll start receiving a feed of requests (actions) to sign.

Step 2: Initiate an EVM transaction

The sections below explain how to initiate EVM transactions of different types (they require different endpoints).

Legacy

Call Create an EVM-based legacy transaction:

POST https://api-v2.qredo.network/api/v2/workspaces/{workspaceID}/web3/networks/evm/transactions/legacy
  1. Query parameters: In the query, replace {workspaceID} with your Workspace ID from Prerequisites.

  2. Body parameters:

    • broadcast: Set to true if you want to broadcast the transaction.
    • from: Your Wallet address obtained when you generated a Web3 Wallet.
    • to: The destination Wallet address.
    • chainID: The ID of the network you wish to use.
    • value: The amount to send.
    • input: The transaction input data.
    • nonce: The nonce.
    • gas: The gas limit (numeric/hex).
    • gasPrice: The gas price (numeric/hex).
    • note: A user-defined note.

    For example, here is a body for sending 10 Wei in the Goerli test network:

    {
        "broadcast": true,
        "from": "YOUR_WALLET_ID",
        "to": "DESTINATION_WALLET_ID",
        "chainID": "5",
        "value": "10",
        "input": "",
        "nonce": "",
        "gas": "",
        "gasPrice": "",
        "note": ""
    }
    
  3. Authentication: Pass the auth token as x-token in the request header.

  4. Result: You initiated a transaction awaiting approval.

    To check the transaction status, copy the returned txID. You can check the status right now or after approving the transaction — see Step 6.

EIP-1559

Call Create an EVM-based EIP-1559 transaction:

POST https://api-v2.qredo.network/api/v2/workspaces/{workspaceID}/web3/networks/evm/transactions/dynamicFee
  1. Query parameters: In the query, replace {workspaceID} with your Workspace ID from Prerequisites.

  2. Body parameters:

    • broadcast: Set to true if you want to broadcast the transaction.
    • from: Your Wallet address obtained when you generated a Web3 Wallet.
    • to: The destination Wallet address.
    • chainID: The ID of the network you wish to use.
    • value: The amount to send.
    • input: The transaction input data.
    • nonce: The nonce.
    • gas: The gas limit (numeric/hex).
    • maxFeePerGas: The maximum fee per gas.(numeric/hex).
    • maxPriorityFeePerGas: The maximum priority fee per gas (numeric/hex).
    • note: A user-defined note.

    For example, here is a body for sending 10 Wei in the Goerli test network:

    {
       "broadcast": true,
       "from": "YOUR_WALLET_ID",
       "to": "DESTINATION_WALLET_ID",
       "chainID": "5",
       "value": "10",
       "input": "",
       "nonce": "",
       "gas": "",
       "maxFeePerGas": "",
       "maxPriorityFeePerGas": "",
       "note": ""
    }
    
  3. Authentication: Pass the auth token as x-token in the request header.

  4. Result: You initiated a transaction awaiting approval.

    To check the transaction status, copy the returned txID. You can check the status right now or after approving the transaction — see Step 6.

Raw input

Call Create an EVM-based transaction using raw input:

POST https://api-v2.qredo.network/api/v2/workspaces/{workspaceID}/web3/networks/evm/transactions/raw
  1. Query parameters: In the query, replace {workspaceID} with your Workspace ID from Prerequisites.

  2. Body parameters:

    • broadcast: Set to true if you want to broadcast the transaction.
    • from: Your Wallet address obtained when you generated a Web3 Wallet.
    • chainID: The ID of the network you wish to use.
    • data: You raw hex-encoded input.
    • value: The amount to send.
    • note: A user-defined note.

    For example, here is a body for sending a transaction the Goerli test network:

    {
        "broadcast": true,
        "from": "YOUR_WALLET_ID",
        "chainID": "5",
        "data": "YOUR_RAW_INPUT",
        "note": ""
    }
    
  3. Authentication: Pass the auth token as x-token in the request header.

  4. Result: You initiated a transaction awaiting approval.

    To check the transaction status, copy the returned txID. You can check the status right now or after approving the transaction — see Step 6.

Step 3: Get the request

Take this step if you wish to approve the transaction with the Qredo API. If you're using the Signing Agent, it'll get the request automatically.

In Step 1, you started receiving a WebSocket feed. After initiating a transaction, go to the feed and find your transaction request. Then copy the action ID from the id field and the content of the messages array.

Here is an example of a transaction request:

{
    "id": "2XUWBgUPScD1Qnita56nFrPmLkJ", // the action ID to copy
    "type": 30,
    "status": 1,
    "description": "",
    "approverID": "a.AWBcMEqSQMYyVC18RYss92RHPMQ4Jx7VFj7x6WSySNYV",
    "dataID": "",
    "senderID": "a.AWBcMEqSQMYyVC18RYss92RHPMQ4Jx7VFj7x6WSySNYV",
    "payload": "eyJhY2NvdW50SUQiOiIyTjVsQnQ3Q3o3RURjQUhCSGRNbkplc0oxQkwiLCJ3YWxsZXRJRCI6IjZSeGdUNEJObTJ1R1c3Sk5yUFhWN0pLN0RZUjFBZDhlMzFpTXkxNXFDb1ZiIiwid2FsbGV0TmFtZSI6Ik1NSSB0ZXN0Iiwid2FsbGV0VHlwZS    I6NCwicmVmZXJlbmNlIjoieHNmeS1kZDIxY2EwIiwiYXNzZXQiOiJFVEgiLCJhbW91bnQiOjAsInR4SUQiOiIyWFVXQmFBVmMxZm9iYWc2UUkyMFhJRHZDOGgiLCJ0eFNpZ25UeXBlIjoic2lnblR4IiwiZmVlcyI6MCwibmV0QW1vdW50IjowLCJyZXF1ZXN0    ZWRCeSI6ImEuQVdCY01FcVNRTVl5VkMxOFJZc3M5MlJIUE1RNEp4N1ZGajd4NldTeVNOWVYiLCJpbml0aWF0b3JEZXRhaWxzIjp7InByb2ZpbGVJRCI6ImEuQVdCY01FcVNRTVl5VkMxOFJZc3M5MlJIUE1RNEp4N1ZGajd4NldTeVNOWVYiLCJmaXJzdE5hbWUiOiJrZXkgIiwibGFzdE5hbWUiOiIgIiwiZW1haWwiOiIgIn0sImV4cGlyZXNPbiI6MTY5ODY4NzYwMywiaW5pdGlhdGVkVGltZSI6MTY5ODY4NDAwMywiZXh0ZXJuYWxFeHRlbnNpb24iOnsidmVyc2lvbiI6MSwidHhTaWduVHlwZSI6InNpZ25UeCIsInR4Q2FsbFR5cGUiOiJ0cmFuc2ZlciIsImRldGFpbHMiOlt7ImtleSI6InRvIiwiZGVzY3JpcHRpb24iOiJUbyIsInZhbHVlIjoiMHhkMzZDYmUzOEQ5MDUwNjcyNUVkMjk1NTNEN2ExNjFmNTIxN2ZFZDgyIn1dLCJuZXR3b3JrIjp7Im5ldHdvcmtJRCI6IiIsIm5hbWUiOiJFdGhlcmV1bSBUZXN0bmV0IEfDtnJsaSIsImNoYWluSUQiOiI1IiwiY2hhaW5OYW1lc3BhY2UiOiIiLCJjaGFpblN1YnR5cGUiOiIiLCJycGNVUkwiOiIiLCJibG9ja2V4cGxvcmVyVVJMIjoiIiwid29ya3NwYWNlSUQiOiIifSwiYW1vdW50Ijp7ImN1cnJlbmN5IjoiRVRIIiwiYW1vdW50IjoiMyIsImRlY2ltYWxzIjoxOH0sInJlY2lwaWVudCI6IiIsInR4Tm9uY2UiOjE0LCJ0eERhdGEiOiIweCIsInR4VmVyc2lvbiI6MCwidHhHYXMiOnsiZ2FzTGltaXQiOjMxNTAwLCJnYXNQcmljZSI6IjE4IiwibWF4RmVlUGVyR2FzIjoiIiwibWF4UHJpb3JpdHlGZWVQZXJHYXMiOiIifSwibm90ZSI6IiJ9fQ==",
    "messages": [
        "CAUSIFCvVPE9gL9inO7dvlFJeyXXwfefE+XC2364Xf002FYqGiBHHAMoRvrQYp2oWlbM9SLE73YXac8fO/3SxxU8EiljCygMMoMBCgVBZG1pbhJ6CA0SFygoYWRtMSA+IDApIHwgKGcxID4gMCkpGigKBGFkbTESIA4IlMoO3/GkHcpblZnduFQX9H7cP4ej5RJlc7nJhIAVGiYKAmcxEiBv0YeXYCzZyvlk4+O6cfGO7XKtFYrSqaM0io/1hrG4VCILZGVzY3JpcHRpb24yVQoQU2lnbmF0dXJlUmVxdWVzdBJBCAwSCChnMSA+IDApGiYKAmcxEiBv0YeXYCzZyvlk4+O6cfGO7XKtFYrSqaM0io/1hrG4VCILZGVzY3JpcHRpb25SILE0MqtaoEdd3b80LIZ2ubTUp63aIOjSP2jipJ05O19TWhByYWRpbyBnbG93IGVuam95eisIAyIlUiDfDhKCewyU02y+ONkFBnJe0pVT16Fh9SF/7YIDgICAgGIBBSgD"
    ], // the messages to copy
    "signatures": null,
    "timestamp": 1698684004,
    "actionSubject": null,
    "actionTime": 0,
    "expireTime": 1698687604,
    "metadata": "e30=",
    "created": 0
}

Step 4: Sign the request

Take this step if you wish to approve the transaction with the Qredo API. If you're using the Signing Agent, it'll sign the request automatically.

In Step 3, you copied message(s) from the messages array. Sign them with your BLS private key.

You can use our JavaScript example.

Step 5: Approve the transaction

Take this step if you wish to approve the transaction with the Qredo API. If you're using the Signing Agent, it'll automatically approve or reject the transaction based on the rules you set.

Call Approve or reject an action:

POST https://api-v2.qredo.network/api/v2/actions/{actionID}
  1. Query parameters: In the query, replace {actionID} with the action ID obtained in Step 3.

  2. Body parameters:

    • Set status to 3 to approve the action.
    • Add the array of signatures you've just created.
    {
      "status": 3,
      "signatures": [ 
          "YOUR_SIGNATURE_1",
          "YOUR_SIGNATURE_2"
      ]
    }
    
  3. Authentication: Pass the auth token as x-token in the request header.

  4. Depending on your Policy threshold, you might need to get other approvals before the transaction is finalized.

  5. Result: Now your transaction is approved! The API will return an empty response. To check the transaction status, see the next step.

When a transaction is initiated by an API key (programmatically), like shown in this guide, no action in the Signing App is required. If a transaction is initiated by a human Member in the Web App, it may require authorization in the Signing App before it can be approved, be it by an API key or the human Member.

Step 6: Check the transaction

After initiating a transaction, you can check its status at any moment, before or after approval.

Call Get an EVM-based transaction by ID:

GET https://api-v2.qredo.network/api/v2/workspaces/{workspaceID}/web3/networks/evm/transactions/{txID}
  1. Query parameters:

    • Replace {workspaceID} with your Workspace ID from Prerequisites.
    • Replace {txID} with the transaction ID obtained in Step 2.
  2. Authentication: Pass the auth token as x-token in the request header.

  3. Result: The endpoint will return the transaction data. You can see the status of the transaction in the status field.

    Here's an example response for an already approved transaction:

    {
        "broadcast": true,
        "caip2ChainID": "eip155:5",
        "chainID": "5",
        "custodyID": "2XUWBdSkBAB0nj6JTCXlbzBANwk",
        "gas": "0x7b0c",
        "gasPrice": "0x12",
        "hash": "0x59866a3afd84f98a55c4c2a27d5af77a29673e84fdcef5dbff3af9e6287153fb",
        "input": "",
        "maxFeePerGas": "",
        "maxPriorityFeePerGas": "",
        "nonce": 14,
        "signedBytes": "0xf85e0e12827b0c94d36cbe38d90506725ed29553d7a161f5217fed8203802d9f053febdd6f3b7df7c9db71165ffb888c558f284e3d60f0e8a61b7af8902f8aa04a869e75e480a8cad42f9b14023cbf763efe4a7293513f6c    71be195e65da88bc",
        "status": "confirmed",
        "to": "0xd36Cbe38D90506725Ed29553D7a161f5217fEd82",
        "txID": "2XUWBaAVc1fobag6QI20XIDvC8h",
        "type": "ethereum-legacy-tx",
        "value": "3"
    }
    

What's next?

Previous
Create a Portfolio and Wallet