Use Case 1: Buy-Side - Investor Trading

Overview

The following is a step by step guide, that highlights the association of the key values in each of the messages that are involved in onboarding the investor, the asset, and the creation and execution of the primary sale.

This includes from the investor (buyer) perspective:

  1. The creation of the owner profile, which creates a FinID that is used to identify the investor (buyer in this case).
  2. The deposit request of funds that will be used to pay for the transaction, and routing the request to the payment organization.
  3. The execution against an existing primary sale intent.
  4. The posting of a secondary market sell intent for the asset.
  5. The execution of a posted secondary sell intent.
  6. The execution of a posted secondary buy intent.

API Integration Flow

The following table will walk you through step-by-step involved in the trading interface integration, which enables the investor to be onboarded, invest in primary sale, and participate in secondary market:

# API ReferenceDescription

Onboard the Investor
1Create Investor AccountRegisters the investor on FinP2P network.
2Bind Investor to a CustodianSend a request to the associated custodian to onboard the investor on the custody system, which in turn will provide the public key (finID) that is associated with the investor.
3(Add Certificates)[Optional] Attach certificates such as KYC and AML.

For FinP2P proposed certificate specifications, please refer to FinP2P Certificates Spec reference page.
4Attach Documentation [Optional] Add additional documentation to provide additional information about the issuer.
5Share Investor with Payments ServiceLink the investor to the applicable payments organization responsible for handling the payments leg for the investor.

Note: If the user is associated with an organization offering escrow payment services to the user in question, this step can be omitted

Fund the Account
6Create a Deposit Instructions RequestThis step creates a deposit
instructions request, which will be routed to the given payment service organization.

Please note based on the integration to the payment system, the response to this message could take time to process by that organization. In such case the response will not contain the instructions immediately (processed asynchronously).

Otherwise, response will contain deposit instruction that could be used in the case funds wire transfer is required.
7Process Deposit Instructions Response OR,

If the message is processed asynchronous, use the Get operation message to poll the status and content for the response to the request.

Perform an Investment in a Primary Sale of a Given Asset
8Query Assets for Open Primary Sale Intent Get assets that were made available with for the organization, and look for open intents to inform the investor of availability to buy distributed assets.

Look for intents of type PrimarySale that have a status of Active.
9Execute the Intent Invest in the given open
Primary Sale by executing the intent.

This will create and send an execution plan to all the participants in this token issuance that is part of the primary sale.
10Query Execution Plan for ProgressUse the GraphQL subscription to listen to the event when an execution plan based on the execution plan id received during the intent (token) execution, in order to track for the progress of the execution plan.

Participate in Secondary Trading for a Given Asset - Sell the Asset
11Create a Selling IntentCreate a sell intent against the given asset that the investor owns, which can be executed by a buyer investor.

The intent is of type "SELLINGINTENT" which will include the asset transfer and payment settlement details required to execute the intent from the seller perspective.

This will include the assets being sold, and the organization and account in which you wish the sale proceeds to be routed to.

Please note once a buyer request an execution of the intent, it will need to be signed on-behalf of the seller as well (in addition to buyer). Since the signing occurs upon intent execution, the method used will be that of a manual signing. This is achieved by creating an endpoint that will be able to sign on-behalf of the seller upon execution request. The endpoint is supplied in the "MANUALPOLICY" section.

For the integration required for the manual signing endpoint, please refer to the section titled "manualSigningCallback".

You can either develop the endpoint to response immediately (synchronously) by responding with type "signature". Or acknowledge request, and provide a signature later (asynchronously) by setting type to "acknowledgement".
12Signature Asynchronous ResponseIf signing is asynchronous, you will need to make a call to the signature results API.

You will need to respond with the "requestId" value that was supplied during the signature request.
13Update Intent

Enable Intent

Disable Intent
In the case you want to created an intent but not make it available for trading yet, you use the disable and then in turn the enable intent functionality.
14Subscribe to Intent Execution EventUse GraphQL subscription to listen to the event when an execution plan is created (added), and look for the plan that is associated with the given intent Id that was assigned when the intent was created. This will indicate that intent execution was requested. Retain the execution plan Id to track it.
15<https://finp2p-docs.ownera.io/reference/the-graphql-schema>Use the GraphQL subscription to listen to the event when an execution plan based on the execution plan id you got from the previous step, in order to track for the progress of the execution plan.

Participate in Secondary Trading for a Given Asset - Request an execution against an Intent
16<https://finp2p-docs.ownera.io/reference/the-graphql-schema> Get assets that are shared with the given organization, and look for open intents to inform the investor of availability to buy assets.

Look for intents of type “BuyingIntent” or “SellingIntent”.
17<https://finp2p-docs.ownera.io/reference/the-graphql-schema>Send an execution request against the given intent (buy or sell).

If the message was handled synchronously, the response section will contain the receipt which is the proof of ownership on the token(s) received in the trade.

Rejection could be due to varying reasons such as investor accreditation failure, lack of funding, timeout on the execution operation, etc.
18Subscribe to Intent Execution EventUse GraphQL subscription to listen to the event when an execution plan is created (added), and look for the plan that is associated with the given intent Id that was assigned when the intent was created. This will indicate that intent execution was requested. Retain the execution plan Id to track it.
19Subscribe for receipts Uses GraphQL call in order to receive the cryptographically signed receipt for the payment or for the token transfer.

Request Funds Withdrawal
20Request Funds Withdrawal The user has the option to withdraw the funds that are in the given account by putting in a request for withdrawal. This request is routed to the given payment service provider to process.

If the response is processed synchronously, the response section will contain the withdrawal details.
21Poll for Response from Payment ServiceIf the request is processed asynchronously, use the get operations to receive the response.

Testing Your Integration

You can test your buy-side integration by requesting from Ownera a sell-side sandbox which will provide you with a full suite of simulation for tokenization and payment processing.

Example: Investment in Primary Sale

The following is an example for the onboarding and funding of the user, and the execution of an investment in a given primary sale:

Create user profile:

Create the investor profile that is going to be trading against primary/secondary intents, which will assign a unique Resource ID for the given investor to be used when performing actions on-behalf of investor.

curl --location --request POST '<router url>/finapi/profiles/owner' \
--header 'Content-Type: application/json' \
--data-raw '{}'
{
    "isCompleted": true,
    "response": {
        "id": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
    },
    "type": "profile"
}

Bind the user to the given custodian:

Send a request to the custodian to onboard the investor on the custody platform, which will return the public key that will be used to identify the investor. The process is an asynchronous process, and therefore you will need to

curl --location --request POST '<router url>/finapi/profiles/owner/bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144/account' \
--header 'Content-Type: application/json' \
--data-raw '{ 
  "orgId": "custody-service"
}'
{
 "cid":"e3c59abb-f296-4556-a4c6-9c0e397ad6f9",
 "isCompleted":false,
 "type":"addAccount"
}

Poll the request until it is completed:

Poll for the completion of the custodian investor onboarding.

curl --location --request POST '<router url>/operations/status/e3c59abb-f296-4556-a4c6-9c0e397ad6f9' \
--header 'Content-Type: application/json' \
--data-raw '{}'
{
    "cid": "e3c59abb-f296-4556-a4c6-9c0e397ad6f9",
    "isCompleted": true,
    "response": {
        "custodyOrgId": "custody-service",
        "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835"
    },
    "type": "account"
}

Attach certificates to the given user:

The attached certificate in this case is called "ownerInfo" which is used to assign a name, email, and what type the investor is.

curl --location --request POST 'http://<router url>/finapi/profiles/bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144/certificates' \
--header 'Content-Type: application/json' \
--data-raw '{
  "type": "ownerInfo",
  "issuanceDate": 1668598695,
  "expirationDate": 1700134695,
  "data": "{\"email\":\"[email protected]\",\"name\":\"Investor\",\"type\":\"individual\"}"
}'
{
    "id": "ec634170-8c62-4d55-b324-0391eb30fac1"
}

Additional certificate include a KYC/AML

{
  "type": "KYC/AML",
  "issuanceDate": 1692605934,
  "expirationDate": 1700134695,
  "data": "{\"name\":\"AML/KYC Compliance\",\"country\":\"usa\",\"info\":[{\"type\":\"text\",\"name\":\"Certificate ID\",\"value\":\"WFJXV5HQTO\"},{\"type\":\"text\",\"name\":\"Country\",\"value\":\"usa\"}]}"
}
{
    "id": "ec634170-8c62-4d55-b324-0391eb30fac1"
}

And Accreditation certificate

{
  "type": "Accreditation",
  "issuanceDate": 1692605934,
  "expirationDate": 1700134695,
  "data": "{\"name\":\"Certificate of Accreditation\",\"country\":\"usa\",\"info\":[{\"type\":\"text\",\"name\":\"Certificate ID\",\"value\":\"NC368IV14VR\"},{\"type\":\"text\",\"name\":\"Country\",\"value\":\"usa\"}]}"
}
{
    "id": "ec634170-8c62-4d55-b324-0391eb30fac1"
}

Upload and attached documents to certificates:

Upload a document to the given certificate, pointing to a location and name of the file to upload.

curl --location --request POST 'http://<router url>/finapi/profiles/bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144/certificates/ec634170-8c62-4d55-b324-0391eb30fac1' \
--form 'kya doc=@"/kyc.pdf"'

Associate the user with the given payments processing organization:

Associate (share) the user to a given organization, in this case, to the organization that is going to provide escrow/payments services for the investor.

curl --location --request POST 'http://<router url>/profiles/bank-il:101:a0f25042-c27c-4184-ae93-6488e43541a8/share' \
--header 'Content-Type: application/json' \
--data-raw '{
     "organizations": [
          "payment-service"
     ]
}'
n/a

Request deposit instructions:

Place a deposit request for funds into the given escrow account. The account is designated by the buyer fin ID and its associated escrow organization ID. The instruction below requests a USD fiat deposit in the amount of $100,000 into "payment-service" organization. The custody service supplied will be used to send a deposit signature request onbehalf of investor.

curl --location --request POST 'http://<router url>/finapi/payments/deposit' \
--header 'Content-Type: application/json' \
--data-raw '{
  "profileId": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144",
  "account": {
    "account": {
      "type": "finId",
      "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
      "orgId": "payment-service",
        "custodian": {
           "orgId": "custody-service"
        }      
    },
    "asset": {
      "type": "fiat",
      "code": "USD"
    }
  },
  "amount": "1000000",
  "nonce":  "712a41ae225cf0b64f09c2a1ecf6b436b126276d3247da3a0000000000000000"
}'
{
    "cid": "9cd41679a9cfb99e856f1351908df952cae259296a6f49660000000063aaf015",
    "isCompleted": false,
    "type": "deposit"
}

Get status on request:

Run a get operations to pull for the response on the deposit request.

curl --location --request GET 'http://<router url>/finapi/operations/status/9cd41679a9cfb99e856f1351908df952cae259296a6f49660000000063aaf015'
{
    "isCompleted": true,
    "response": {
        "depositInstruction": {
            "depositInstruction": {
                "account": {
                    "account": {
                        "finId": "035049f22c30b46477c0991c6de41cf6428cee58bc5dcfe56513b7f16a624185b2",
                        "orgId": "ownera-escrow",
                        "type": "finId"
                    },
                    "asset": {
                        "code": "USD",
                        "type": "fiat"
                    }
                },
                "description": "Bank Adress|100 West Park Avenue|Beneficiary Name|Bank ABC, LCC|Bank Name|First International Bank|Account number|1292929292|Account type|Custodial|Routing number|10299393393|Bic Swift Code|FIRBILITXXX|Reference number|1J2JDJDJDFHJ"
            },
            "operationId": "690c41f1-bfb6-480f-bd92-8470b8183db6"
        }
    },
    "type": "deposit"
}

Query for open primary sales that are open for investment:

Query for open intents that are of type "primarySale" that have status of "ACTIVE". The intent information will provide you with the details required to execute the intent. The example shows a token of type building that has 100000 tokens available for investment in valued at 2 USD each. The intent will be executed via the given payments processing organization "payments-service".

query OpenIntents {
  assets {
    nodes {
      id
      name
      organizationId
      issuerId
      denomination {
        code
      }
      certificates {
        nodes {
          data
          documents {
            nodes {
              id
              uri
            }
          }
        }
      }
      intents(
        filter: [{key: "type", operator: EQ, value: "primarySale"}, {key: "status", operator: EQ, value: "ACTIVE"}]
      ) {
        nodes {
          id
          type
          start
          end
          status
          remainingQuantity
          intent {
            ... on PrimarySale {
              issuerId
              assetTerm {
                amount
                asset {
                  ... on FinP2PAsset {
                    resourceId
                  }
                }
              }
              assetInstruction {
                account {
                  identifier {
                    ... on FinP2PAssetAccount {
                      finId
                      orgId
                      custodian {
                        orgId
                      }
                    }
                  }
                }
                destinationAccount {
                  identifier {
                    ... on FinP2PAssetAccount {
                      finId
                      orgId
                      custodian {
                        orgId
                      }
                    }
                  }
                }
              }
              settlementTerm {
                unitValue
                asset {
                  ... on FiatAsset {
                    code
                  }
                }
              }
              sellingSettlementInstruction {
                accounts {
                  identifier {
                    ... on Iban {
                      code
                    }
                    ... on FinP2PAssetAccount {
                      finId
                      orgId
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
{
  "data": {
    "assets": {
      "nodes": [
        {
          "id": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0",
          "name": "A-9499371996",
          "organizationId": "bank-de",
          "issuerId": "bank-uk:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
          "denomination": {
            "code": "USD"
          },
          "certificates": {
            "nodes": [
              {
                "data": "{\"publicName\":\"A-9499371996\",\"officialName\":\"Asset 9499371996, Inc\",\"description\":\"Asset 9499371996 description\",\"info\":[]}",
                "documents": {
                  "nodes": [
                    {
                      "id": "6406e901-9ddf-404e-9222-71934cb36554",
                      "uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/6406e901-9ddf-404e-9222-71934cb36554"
                    },
                    {
                      "id": "deb86f68-dc25-4d33-bfe6-83ff817cdd5c",
                      "uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/deb86f68-dc25-4d33-bfe6-83ff817cdd5c"
                    },
                    {
                      "id": "9c405932-e894-4661-a15b-60802d3c782d",
                      "uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/9c405932-e894-4661-a15b-60802d3c782d"
                    }
                  ]
                }
              },
              {
                "data": "{\"currentNAV\":{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140},\"history\":[{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140}]}",
                "documents": {
                  "nodes": []
                }
              }
            ]
          },
          "intents": {
            "nodes": [
              {
                "id": "bank-uk:105:d07ab369-8bf2-4740-a055-1d11d2edfd38",
                "type": "primarySale",
                "start": 1716991745,
                "end": 1811538000,
                "status": "ACTIVE",
                "remainingQuantity": "10000",
                "intent": {
                  "issuerId": "bank-de:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
                  "assetTerm": {
                    "amount": "1000",
                    "asset": {
                      "resourceId": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884"
                    }
                  },
                  "assetInstruction": {
                    "account": {
                      "identifier": {
                        "finId": "0284550512e33ea4215a55f164c286fc27e0a474a9a15becbc4a63d89a885d1b1e",
                        "orgId": "bank-uk",
                        "custodian": {
                          "orgId": "custody-service"
                        }
                      }
                    },
                    "destinationAccount": null
                  },
                  "settlementTerm": {
                    "unitValue": "2",
                    "asset": {
                      "code": "USD"
                    }
                  },
                  "sellingSettlementInstruction": {
                    "accounts": [
                      {
                        "identifier": {
                          "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
                          "orgId": "payments-service"
                        }
                      }
                    ]
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Place a Primary Sale Execution Request:

The open primary sale intent can be executed using the token execute call, which will generate an execution plan for the primary sale.

The values in this examples are determined as follows:

ParameterDescriptionExample
resourceId (in both asset term and instruction sections)The asset being issued that has been distributed by the issuing organizationbank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0
amountThe amount of tokens requests to be issued to the investor. This amount should not exceed the amount available in the open primary sale intent being executed10,000
finIdThe finId of the investor who is requesting for the issuance of the tokens02d6fea8153a9a64d13e198379dfd4e
a3945d03198770e0e5b94f556c4e69f6835
orgIdThe organization id of the asset distributer (note this is not the organization id which the investor belongs to)bank-uk
custodianThe organization in charge of the custody servicecustody-service
amountAmount in settlement section designates the funds stated in the given currency to transfer from investor to issuer account, which is the amount of tokens multiplied by the price per token as stated in the primary sale intent20,000 USD
source finId The investor finId at the payments organization which will have funds transfer from02d6fea8153a9a64d13e198379dfd4ea
3945d03198770e0e5b94f556c4e69f6835
destination finIdthe issuer finId at the payments organization which will have the funds transfer to03565ed4e4d889ee24b7a6f830aa0df
31d7ba2ad88e9b1839d84c82de951397524
orgIdThe payments organization Idpayment-service
issuerThe owner registered id for the issuerbank-uk:101:ff60289e-19f0-4f4c-a291-d587fb463999
buyerThe owner registered id for the buyerbank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144
userThe owner registered id for the buyerbank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144
intentIdThe intent Id for the primary sale being executedbank-uk:105:d07ab369-8bf2-4740-a055-1d11d2edfd38
signatureFollow the instruction for generating the proper signature to sign this given transaction.10c518775478a07d75b577e38f96187cf3fede
0352998aa8846d6bfe812da8c31cd995308752e
626730ba1a03cb659117138ddaef18059e743b0725167a2286f
exedcutionIdThis is optional. You can either supply your own id, or if not supplied (do not include field in payload), id will be generated automatically.424d9d9c-7cd3-447b-840a-a3466a261422
curl --location 'https://<router url>/finapi/tokens/execute' \
--header 'Content-Type: application/json' \
--data '{
  "intent": {
    "type": "primarySaleExecution",
    "asset": {
      "term": {
        "asset": {
          "type": "finp2p",
          "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
        },
        "amount": "10000"
      },
      "instruction": {
        "destinationAccount": {
          "account": {
            "type": "finId",
            "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
            "orgId": "bank-uk"
             "custodian": {
                "orgId":  "custody-service"
            } 
          },
          "asset": {
            "type": "finp2p",
            "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
          }
        }
      }
    },
    "settlement": {
      "term": {
        "asset": {
          "type": "fiat",
          "code": "USD"
        },
        "amount": "20000"
      },
      "instruction": {
        "type": "escrow",
        "sourceAccount": {
          "account": {
            "type": "finId",
            "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
            "orgId": "payment-service"
             "custodian": {
                "orgId":  "custody-service"
            } 
          },
          "asset": {
            "type": "fiat",
            "code": "USD"
          }
        },
        "destinationAccount": {
          "account": {
            "type": "finId",
            "orgId": "payment-service",
            "finId": "03565ed4e4d889ee24b7a6f830aa0df31d7ba2ad88e9b1839d84c82de951397524"
             "custodian": {
                "orgId":  "custody-service"
            } 
          },
          "asset": {
            "type": "fiat",
            "code": "USD"
          }
        },
      }
    },
    "nonce": "45a0b9d8c316ad6ac6b7919493d679ce31d89e969101675b00000000655e1611",
    "issuer": "bank-uk:101:ff60289e-19f0-4f4c-a291-d587fb463999",
    "buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
  },
  "executionId": "424d9d9c-7cd3-447b-840a-a3466a261422",
  "user": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144",
  "intentId": "bank-uk:105:d07ab369-8bf2-4740-a055-1d11d2edfd38"
}'
{
  "isCompleted": true,
  "response": {
    "executionPlanId": "424d9d9c-7cd3-447b-840a-a3466a261422"
  }
}

Query for progress of execution plan:

Use GraphQL to poll for the progress of the execution plans being processed that your organization is participating in. Look for the execution plan id value of the plan you executed. Plan is finished either in a "completed" status, or "rejected" or "failed".

subscription planChanged{
  plansChangedBy(fieldNames:Status) {
    id
    status
    creationTimestamp
    intent {id}
  }
}
{
  "data": {
    "plansChangedBy": {
      "id": "424d9d9c-7cd3-447b-840a-a3466a261422",
      "status": "Completed",
      "creationTimestamp": 1703495180,
      "intent": {
        "id": "bank-uk:105:d07ab369-8bf2-4740-a055-1d11d2edfd38"
      }      
    }
  }
}

Example: Execute a Secondary Selling Intent

The following example is a walkthrough on how to send a request to execution against an open secondary selling intent posted by another investor:

Query for open secondary selling intents that are open for investment:

Query for open intents that are of type "sellingIntent" that have status of "ACTIVE". The intent information will provide you with the details required to execute the intent. The example shows an asset of a building that has 10,000 tokens available for investment valued at 3 USD each. The intent will be executed via the given payments processing organization "payments-service", during which asset tokens will be transferred from seller to buyer, while funds will be transferred from buyer to seller.

query OpenIntents {
  assets {
    nodes {
      id
      name
      organizationId
      issuerId
      denomination {
        code
      }
      certificates {
        nodes {
          data
          documents {
            nodes {
              id
              uri
            }
          }
        }
      }
      intents(
        filter: [{key: "type", operator: EQ, value: "secondaryIntent"}, {key: "status", operator: EQ, value: "ACTIVE"}]
      ) {
        nodes {
          id
          type
          start
          end
          status
          remainingQuantity
          intent {
            ... on PrimarySale {
              issuerId
              assetTerm {
                amount
                asset {
                  ... on FinP2PAsset {
                    resourceId
                  }
                }
              }
              assetInstruction {
                account {
                  identifier {
                    ... on FinP2PAssetAccount {
                      finId
                      orgId
                      custodian {
                        orgId
                      }
                    }
                  }
                }
                destinationAccount {
                  identifier {
                    ... on FinP2PAssetAccount {
                      finId
                      orgId
                      custodian {
                        orgId
                      }
                    }
                  }
                }
              }
              settlementTerm {
                unitValue
                asset {
                  ... on FiatAsset {
                    code
                  }
                }
              }
              sellingSettlementInstruction {
                accounts {
                  identifier {
                    ... on Iban {
                      code
                    }
                    ... on FinP2PAssetAccount {
                      finId
                      orgId
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
{
  "data": {
    "assets": {
      "nodes": [
        {
          "id": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884",
          "name": "A-9499371996",
          "organizationId": "bank-de",
          "issuerId": "bank-de:101:3dd376f0-f03b-43dc-8229-134918f62ad9",
          "denomination": {
            "code": "USD"
          },
          "certificates": {
            "nodes": [
              {
                "data": "{\"publicName\":\"A-9499371996\",\"officialName\":\"Asset 9499371996, Inc\",\"description\":\"Asset 9499371996 description\",\"info\":[]}",
                "documents": {
                  "nodes": [
                    {
                      "id": "6406e901-9ddf-404e-9222-71934cb36554",
                      "uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/6406e901-9ddf-404e-9222-71934cb36554"
                    },
                    {
                      "id": "deb86f68-dc25-4d33-bfe6-83ff817cdd5c",
                      "uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/deb86f68-dc25-4d33-bfe6-83ff817cdd5c"
                    },
                    {
                      "id": "9c405932-e894-4661-a15b-60802d3c782d",
                      "uri": "bank-de:102:231a1ffb-411e-47c5-af00-8c67cdaf0884/4b7bd87f-0646-447e-a9f9-89425bcc79bf/9c405932-e894-4661-a15b-60802d3c782d"
                    }
                  ]
                }
              },
              {
                "data": "{\"currentNAV\":{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140},\"history\":[{\"navValue\":20,\"description\":\"The unit price that was set in the Primary Sale\",\"date\":1716991748140}]}",
                "documents": {
                  "nodes": []
                }
              }
            ]
          },
          "intents": {
            "nodes": []
          }
        }
      ]
    }
  }
}

Place a Secondary Sell Execution Request:

The open secondary selling intent can be executed using the token execute call, which will generate an execution plan for the secondary selling execution. In this case we are executing the full amount of tokens that was posted in the intent of 10,000.

The values in this examples are determined as follows:

ParameterDescriptionExample
resourceId (in both asset term and instruction sections)The asset being issued that has been distributed by the issuing organizationbank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0
amountThe amount of tokens requests to be issued to the investor. This amount should not exceed the amount available in the open primary sale intent being executed10,000
source finIdThe finId of the selling investor whose tokens will be transferred from02af7088141665f96ce1eb3db1bb2b4
5af58a8b3a09ee0dd64ee921e1b197fe2d5
orgIdThe organization Id that is distributing the asset.bank-uk
destination finIdThe finId of the buying investor who will be receiving the tokens.02d6fea8153a9a64d13e198379dfd4e
a3945d03198770e0e5b94f556c4e69f6835
orgIdThe organization Id that is distributing the asset.bank-uk
amountAmount in settlement section designates the funds stated in the given currency to transfer from investor to issuer account, which is the amount of tokens multiplied by the price per token as stated in the secondary selling intent.30,000 USD
source finId the investor finId at the payments organization which will have funds transfer from02d6fea8153a9a64d13e198379dfd4ea
3945d03198770e0e5b94f556c4e69f6835
destination finIdthe issuer finId at the payments organization which will have the funds transfer to02af7088141665f96ce1eb3db1bb2b4
5af58a8b3a09ee0dd64ee921e1b197fe2d5
orgIdThe payments organization Idpayment-service
buyerThe owner registered id for the buyerbank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144
userThe owner registered id for the buyerbank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144
intentIdThe intent Id for the primary sale being executedbank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca
signatureFollow the instruction for generating the proper signature to sign this given transaction.078e73c87b82183c9a2db2756098218a2d2409fed4b8
984d051f7c3b6ec1c94f6535e5b87db69d94d7ff0231ac
2ef58fd2a24f81a00e3e24da1d9667f4f5c58a
exedcutionIdThis is optional. You can either supply your own id, or if not supplied (do not include field in payload), id will be generated automatically.424d9d9c-7cd3-447b-840a-a3466a261423
custodianthe organization in charge of the custody servicescustody-service
curl --location 'http://<router url>/finapi/tokens/execute' \
--header 'Content-Type: application/json' \
--data '
{
  "intent": {
    "type": "sellingIntentExecution",
    "asset": {
      "term": {
        "asset": {
          "type": "finp2p",
          "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
        },
        "amount": "4"
      },
      "instruction": {
        "destinationAccount": {
          "account": {
            "type": "finId",
            "custodian": {
              "orgId": "custody-service"
            },
            "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
            "orgId": "bank-uk"
          },
          "asset": {
            "type": "finp2p",
            "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
          }
        },
        "sourceAccount": {
          "account": {
            "type": "finId",
            "custodian": {
              "orgId": "simulation"
            },
            "finId": "02af7088141665f96ce1eb3db1bb2b45af58a8b3a09ee0dd64ee921e1b197fe2d5",
            "orgId": "bank-uk"
          },
          "asset": {
            "type": "finp2p",
            "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
          }
        }
      }
    },
    "settlement": {
      "term": {
        "asset": {
          "type": "fiat",
          "code": "USD"
        },
        "amount": "12"
      },
      "instruction": {
        "sourceAccount": {
          "account": {
            "type": "finId",
            "custodian": {
              "orgId": "custody-service"
            },
            "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
            "orgId": "payment-service"
          },
          "asset": {
            "type": "fiat",
            "code": "USD"
          }
        },
        "destinationAccount": {
          "account": {
            "type": "finId",
            "custodian": {
              "orgId": "simulation"
            },
            "finId": "02af7088141665f96ce1eb3db1bb2b45af58a8b3a09ee0dd64ee921e1b197fe2d5",
            "orgId": "payment-service"
          },
          "asset": {
            "type": "fiat",
            "code": "USD"
          }
        }
      }
    },
    "nonce": "0bf0068f05ea8eea6d340f386c42bf969322b97732d0b79e0000000000000000",
    "buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
  },
  "intentId": "bank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca",
  "user": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
}
'
{
    "isCompleted": true,
    "response": {
        "executionPlanId": "bank-uk:106:424d9d9c-7cd3-447b-840a-a3466a261423"
    },
    "type": ""
}

Query for progress of execution plan:

Use GraphQL to poll for the progress of the execution plans being processed that your organization is participating in. Look for the execution plan id value of the plan you executed. Plan is finished either in a "completed" status, or "rejected" or "failed".

subscription planChanged{
  plansChangedBy(fieldNames:Status) {
    id
    status
    creationTimestamp
    intent {id}
  }
}
{
  "data": {
    "plansChangedBy": {
      "id": "424d9d9c-7cd3-447b-840a-a3466a261423",
      "status": "Completed",
      "creationTimestamp": 1703495180,
      "intent": {
        "id": "bank-uk:105:cb5e306e-dadf-4e89-9d37-ed4aa1a1e0ca"
      }      
    }
  }
}

Example: Post a Selling or Buying Intent and Processing Execution Request

Post a Secondary Selling Intent:

The investor can post a secondary intent that can is broadcasted to all shared parties. Once an execution request is placed by another investor (during which it is signed by the investor), the token transfer request will be routed to the tokenization platform of the asset to approve or reject the execution. If and once approved, the execution will be sent to be signed by the creator of the intent.

The example below is posting a secondary selling intent for 5,000 units of the token valued at 4 USD a token. The intent is set to be manually signed upon execution of the intent by the set end point.

Note you need to specify an expiry value for a buying intent only. Do not supply it in a selling intent as it is a capability for the buyer to indicate how long they intent on having their funds held for the transaction to occur.

curl --location --request POST 'http://<router url>/finapi/profiles/asset/bank-us:102:234b2028-6362-40fe-bb0c-f71668c08639/intent' \
--header 'Content-Type: application/json' \
--data-raw '{
  "intent": {
    "type": "sellingIntent",
    "assetTerm": {
      "asset": {
        "type": "finp2p",
        "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
      },
      "amount": "5000"
    },
    "assetInstruction": {
      "account": {
        "account": {
          "type": "finId",
          "custodian": {
            "orgId": "custody-service"
          },
          "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
          "orgId": "bank-us"
        },
        "asset": {
          "type": "finp2p",
          "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
        }
      }
    },
    "settlementTerm": {
      "asset": {
        "type": "fiat",
        "code": "USD"
      },
      "unitValue": "4"
    },
    "settlementInstruction": {
      "destinationAccounts": [
        {
          "account": {
            "type": "finId",
            "custodian": {
              "orgId": "custody-service"
            },
            "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
            "orgId": "payment-service"
          },
          "asset": {
            "type": "fiat",
            "code": "USD"
          }
        }
      ]
    },
    "signaturePolicy": {
      "type": "manualPolicy"
    },
    "seller": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
  },
    "start": 1719927761,
  "end": 1719927761
}'

curl --location --request POST 'http://<router url>/finapi/profiles/asset/bank-us:102:234b2028-6362-40fe-bb0c-f71668c08639/intent' \
--header 'Content-Type: application/json' \
--data-raw '
{
  "intent": {
    "type": "buyingIntent",
    "assetTerm": {
      "asset": {
        "type": "finp2p",
        "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
      },
      "amount": "5000"
    },
    "assetInstruction": {
      "account": {
        "account": {
          "type": "finId",
          "custodian": {
            "orgId": "custody-service"
          },
          "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
          "orgId": "simulation"
        },
        "asset": {
          "type": "finp2p",
          "resourceId": "bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0"
        }
      }
    },
    "settlementTerm": {
      "asset": {
        "type": "fiat",
        "code": "USD"
      },
      "unitValue": "4"
    },
    "settlementInstruction": {
      "sourceAccount": {
        "account": {
          "type": "finId",
          "custodian": {
            "orgId": "custody-service"
          },
          "finId": "02d6fea8153a9a64d13e198379dfd4ea3945d03198770e0e5b94f556c4e69f6835",
          "orgId": "payment-service"
        },
        "asset": {
          "type": "fiat",
          "code": "USD"
        }
      }
    },
    "signaturePolicy": {
      "type": "manualPolicy"
    },
    "buyer": "bank-uk:101:edc5c2cc-6688-457a-a0f6-1e7aea28d144"
  },
  "start": 1720090595,
  "end": 1720090595
}
'
{
    "id": "bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c"
}

You can disable/enable the intent for the given asset using the Intent ID

curl --location --request PUT 'http://<router url>/finapi/profiles/asset/bank-uk:102:f96240dc-8365-475b-84e2-9611bb5e5bc0/intent/bank-uk:105:85c1130e-a5b9-4d03-91fa-5814b256495c/disable' \
--header 'Content-Type: application/json' \
--data-raw ''

Example: Redeeming an issued tokens

TBD


Example: Request Funds Withdrawal

Send a withdrawal request to payment service organization

Include in the description the text or object required by the payments organization in order to process the withdrawal.

curl --location --request POST 'https://<router_url>/finapi/payments/withdraw' \
--header 'Content-Type: application/json' \
--data-raw '{
  "profileId": "bank-uk:101:f2ee5840-8b7d-47ae-a4dc-ee9d02b0cee8",
  "account": {
    "account": {
      "type": "finId",
      "finId": "037fcf0db48dceb2195bd0fc24a4dab68c5731b5b8c141f63d017969a55570c4e9",
      "orgId": "payments-service"
    },
    "asset": {
      "type": "fiat",
      "code": "USD"
    }
  },
  "amount": "10000",
  "withdrawInstruction": {
    "account": {
      "account": {
        "type": "iban",
        "code": "GB33BUKB20201555555555"
      },
      "asset": {
        "type": "fiat",
        "code": "USD"
      }
    },
    "description": "Withdrawal instructions"
  }
}'
{
  "cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
  "isCompleted": false,
  "type": "withdraw"
}

Poll to receive the status of the withdrawal request processing

curl --location --request POST 'https://<router_url>/finapi//operations/status/45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d"' \
--header 'Content-Type: application/json' \
--data-raw '{}'
{
  "cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
  "isCompleted": false,
  "type": "withdraw"
}
{
  "cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
  "isCompleted": true,
  "type": "withdraw"
}
{
  "type": "receipt",
  "operation": {
    "cid": "45a1cd773629099b73db2f3915c1320b86d508e2c085689700000000658bfd7d",
    "isCompleted": true,
    "error": {
      "Code":30,
      "Message": "Withdrawal operation failed"
    }
  }
}