Advanced

Kado offers additional authenticated API routes for partners that choose to undergo some additional setup. If the authenticated route offerings interest you, please reach out to partners@kado.money to kick off your advanced API integration.

Authentication 🔐

Kado utilizes Hash-Based Message Authentication Codes (HMAC) to ensure that incoming messages are authenticated, and that message integrity is maintained throughout the data transit process.

To get started making authenticated requests to Kado, you will first need to obtain your public and private server-to-server API keys from Kado.

👉 Once Kado issues you those, you will need to attach the following headers to authenticate your requests:

  1. X-Timestamp - current UTC timestamp (milliseconds)

  2. X-Public-Key - The public key obtained from Kado

  3. X-Signature - Computed as follows:

    1. method = HTTP method (i.e. "GET", "POST", etc.) timestamp = current UTC timestamp (milliseconds) path = API route excluding base url (i.e. "/v2/ramp/quote")

    2. payloadHex = MD5-hashed payload (after removing whitespace).

      1. This should be empty if the Content-Type is not application/json and the method is not POST.

      2. Calculated in Postman: CryptoJS.MD5(CryptoJS.enc.Utf8.parse(JSON.stringify(JSON.parse(payload)))).toString(CryptoJS.enc.Hex); toSign = method + timestamp + path + payloadHex X-Signature = CryptoJS.HmacSHA256(toSign, privateKey)

Webhooks 📨

For convenience, Kado provides webhook updates throughout the fulfillment process for on and off-ramp orders.

Getting Started with Kado Webhooks

Create an API endpoint that can ingest a Kado webhook. Kado will POST to this API route, with the data specified in the following section. Your API route should promptly return a 200 response back to our server.

Once your API route is up and running, notify your point of contact at Kado of the URL API endpoint you've created and Kado will enable it for you.

Kado Webhook Data Structure

A typical webhook contains the following fields:

  1. id - The unique identifier for the webhook.

  2. resource - The resource for which the webhook was sent.

  3. type - The type of event which triggered the webhook.

  4. data - The associated data. For ramp orders, this will be the same data that can be obtained in the order status route.

  5. message - Description of the event.

Kado Webhook Data Reference

👉 Kado Webhook Demo: POST https://my-api.com/kado

{
   "id": "c46ebe64-7ccc-493e-a640-6457673ed2bf",
   "resource": "order",
   "type": "order_pending",
   "data": {
       "buyAmount": {
           "amount": 5,
           "unit": "USD"
       },
       "receiveAmount": {
           "unit": "USDC"
       },
       "to": "manual_input",
       "from": "debit_card",
       "fundsTransferMethod": "My card 1/2025",
       "exchangeRate": 1,
       "currencyType": "USD",
       "walletAddress": "GBKTITXSISPWPZSUZKI6WSYHLKVJDK3KBVJEHNI6ZUTLIE37TCF4YHSO",
       "totalFeeUsd": 1.99,
       "processingFee": {
           "amount": 1.99,
           "unit": "USD",
           "name": "processingFee",
           "originalAmount": 1.99,
           "promotionModifier": 1,
           "amountInUSD": 1.99,
           "originalAmountInUSD": 1.99
       },
       "bridgeFee": [
           {
               "amount": 0,
               "name": "bridgeFee",
               "unit": "USD",
               "discount": null,
               "originalAmount": 0,
               "promotionModifier": 1,
               "createdAt": "2024-05-22T06:38:55.110Z",
               "updatedAt": "2024-05-22T06:38:55.110Z"
           }
       ],
       "smartContractFees": [],
       "gasFee": {
           "amount": 0,
           "unit": "USD",
           "name": "networkFee",
           "originalAmount": 0,
           "promotionModifier": 1
       },
       "asset": "USDC_STELLAR",
       "assetSymbol": "USDC",
       "blockchain": "stellar",
       "txHash": "",
       "humanStatusField": "Pending Fulfillment",
       "machineStatusField": "PENDING_FULFILLMENT",
       "manualDepositWalletAddress": null,
       "manualDepositMemo": null,
       "createdAt": "2024-05-22T06:38:55.111Z",
       "paymentStatus": "success",
       "transferStatus": "uninitiated",
       "allPossibleTxHashes": {},
       "method": "buy",
       "id": "664d92fd680697c24a844d9b",
       "pricePerUnit": 1,
       "orderType": "onRamp",
       "sendFrom": "Debit Card",
       "sendTo": "GBKTITXSISPWPZSUZKI6WSYHLKVJDK3KBVJEHNI6ZUTLIE37TCF4YHSO",
       "originOfOrder": "Kado Test",
       "userRef": "64a7f203ec433fc4b5cc0be2",
       "usdAmount": 5,
       "appliedPromotion": null,
       "wireInformation": null,
       "anchorTransactionId": "",
       "quote": {
           "amount": 1,
           "price": 0.99943,
           "symbol": "USDC",
           "unit": "USD"
       },
       "paymentFailureMessage": "",
       "desiredPayAmount": "5"
   },
   "message": "The order is pending."
}

Verifying Webhook Integrity

Kado provides additional headers on webhook posts, that your server can use to verify that incoming payloads are indeed coming from Kado, and have not been tampered with. This is just the client side version of the API Authentication Scheme, including all three headers described there: x-timestamp, x-public-key and x-signature.

To verify the incoming payload, check that:

  1. The x-timestamp is recent.

  2. The x-public-key matches your organization public key.

  3. Compute your own HMAC signature from the incoming request based on the method described in the API Authentication Scheme, and ensure that your computed signature matches the incoming x-signature header.

Updating Webhook Config

To change your integration webhook URL, or the secret used above to calculate the x-signature, you must first get set up with API Authentication. Once that is set up, updating your integration's webhook secret is simple:

POST https://api.kado.money/v1/partner/configure-webhook

Use the following payload:

KYC, User Onboarding 🥸

The first step in the KYC process is uploading user information:

Initialize User KYC

[Option 1] Fully Submit KYC Info

If your application already collects all of the required KYC information, this is the recommended option. This option allows your users to completely bypass the KYC flow within Kado.

POST https://api.kado.money/v1/partner/kyc/submit

Request Body

POST 200 https://api.kado.money/v1/partner/kyc/submit
{
    "success": true,
    "message": "KYC initiated successfully.",
    "data": {
        "userId": "64ecbf1f80aa98e2009b7f23"
    }
}

[Option 2] Submit Partial KYC Info

If your application collects only some of the required KYC information, you can pass the user data that you have to Kado's API, so that when the user first comes to the Kado widget to KYC, all of that passed information will be pre-loaded, and the user only has to complete the missing information on their own.

Currently, Kado supports partial KYC for integrations that have all required user KYC info except for phone number.

POST https://api.kado.money/v1/partner/kyc/init-partial

Request Body

POST 200 https://api.kado.money/v1/partner/kyc/init-partial
{
    "success": true,
    "message": "KYC initiated successfully.",
    "data": {
        "userId": "64ecbf1f80aa98e2009b7f23"
    }
}

Upload Identity Documents

Once user information is uploaded, grab the userId from the KYC initialization step, and use it in this step.

POST https://api.kado.money/v2/partner/kyc/:userId/upload-docs

Upload identity documents to complete KYC information gathering process. The request data in the body should be of the type form-data:

Path Parameters

Request Body

POST 200 https://api.kado.money/v2/partner/kyc/userId:/upload-docs
{
    "success": true,
    "message": "Documents uploaded successfully",
    "data": {
        "id": "abc-123-def-456-ghi789",
        "identityId": "abc-123-def-456-ghi789",
        "personalDocumentType": "license",
        "documentCheckStatus": "pending",
        "isVerified": false
    }
}

Once KYC information and documentation are uploaded, we only need to monitor the KYC status while we wait for a user to become verified with the L2 status:

Get KYC Status

GET https://api.kado.money/v1/partner/kyc/:userId

Obtain the KYC status of the user.

L0 means initial information has not been submitted, or there was a problem with the initial validation.

L1 means we are awaiting approval.

L2 means the user is fully KYC'd.

Path Parameters

GET 200 https://api.kado.money/v1/partner/kyc/:userId
{
    "success": true,
    "message": "KYC status fetched successfully.",
    "data": {
        "status": "L2"
    }
}

User Ref, Data Linking 🔗

For some partners, it may be useful to pass along each user's ID from their own system to the Kado Widget. By passing the userRef query-string parameter to the Kado Widget URL, Kado can store that user reference upon user sign-in, to link a Client reference to a Kado user, for a Clients future use.

👉 Add to your query-string when loading the Kado iFrame or Webview ?userRef=c6e2e802-edfb-4478-9ae9-33fae16b7c0a

Simply put, integrators are able to pass an internal user ID to Kado, which Kado will then reference during subsequent API requests instead of the Kado userId, for example:

  • GET userRef KYC Status

  • GET userRef Fiat or Asset Deposit Instructions

  • GET userRef Order History

  • Parse and updated internal DB based on Webhook data

  • etc.

Last updated