Skip to main content

Documentation Index

Fetch the complete documentation index at: https://kraken-sandbox.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through enabling crypto deposits and withdrawals for your users via the Payward Embed API.

Prerequisites

Only cryptocurrency deposits are supported. Fiat deposits are not available through the Embed API.

Crypto deposits

Deposit workflow

┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│ List Deposit     │──▶ │ Create Deposit   │──▶ │ Display Address  │──▶ │ User Sends       │──▶ │ Receive          │
│ Methods          │    │ Address          │    │ to User          │    │ Crypto           │    │ Webhooks         │
└──────────────────┘    └──────────────────┘    └──────────────────┘    └──────────────────┘    └──────────────────┘
 GET /funds/deposits/    POST /funds/deposits/   GET /funds/deposits/    (external wallet)       deposit.
     methods/{asset}         addresses                addresses                                  status_updated
  1. List Deposit Methods: Query available networks, fees, and limits for an asset.
  2. Create Deposit Address: Generate an address for the chosen method.
  3. Display Address to User: Show the address (and any tag/memo) so the user can send crypto from an external wallet.
  4. Deposit to Address: Instruct the user to send crypto from their external wallet to the displayed deposit address. Ensure they include any required tag or memo.
  5. Receive Webhooks: Get notified via deposit.status_updated when the deposit is processed.
Completed deposits will appear in GET /b2b/portfolio/transactions?user={iiban}&types=deposit.

Step 1: List deposit methods

Query available deposit methods for a crypto asset. Use the method_id from the response when creating an address in Step 2.
Most cryptocurrency deposits are free, with minimum deposit amounts varying by asset. A few cryptocurrencies are charged an address_setup_fee (a one-time fee on the user’s first deposit to a new address) or a per-deposit fee. See Cryptocurrency deposit fees and minimums for a full breakdown.
def list_deposit_methods(user_id, asset):
    endpoint = f"/b2b/funds/deposits/methods/{asset}"
    nonce = int(time.time() * 1000000000)

    params = {"user": user_id}
    signature = get_payward_signature(endpoint, None, API_SECRET, nonce, params)

    headers = {
        "API-Key": API_KEY,
        "API-Sign": signature,
        "API-Nonce": str(nonce),
    }

    response = requests.get(
        f"{BASE_URL}{endpoint}",
        headers=headers,
        params=params,
    )
    return response.json()


methods = list_deposit_methods(user_id, "BTC")
for m in methods["result"]["methods"]:
    print(f"{m['network']} (method_id: {m['method_id']})")

Response example

{
  "result": {
    "methods": [
      {
        "method_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "network": "Bitcoin",
        "fee": { "asset": "BTC", "amount": "0.00000000" },
        "fee_percentage": "0.00",
        "minimum": { "asset": "BTC", "amount": "0.00010000" },
        "maximum": { "asset": "BTC", "amount": "100.00000000" },
        "address_setup_fee": { "asset": "BTC", "amount": "0.00000000" },
        "network_info": {
          "explorer": "https://blockchair.com/bitcoin",
          "confirmations": "3",
          "est_confirmation_time": "45"
        }
      }
    ]
  }
}
Key fields to display to users: network, fee, minimum, and est_confirmation_time.

Step 2: Create a deposit address

Generate a deposit address using the method_id from Step 1. Display the address to the user so they can send crypto from an external wallet.
def create_deposit_address(user_id, asset, method_id):
    endpoint = "/b2b/funds/deposits/addresses"
    nonce = int(time.time() * 1000000000)

    body = {
        "asset": asset,
        "method_id": method_id,
    }

    params = {"user": user_id}
    signature = get_payward_signature(endpoint, body, API_SECRET, nonce, params)

    headers = {
        "API-Key": API_KEY,
        "API-Sign": signature,
        "API-Nonce": str(nonce),
        "Content-Type": "application/json",
    }

    response = requests.post(
        f"{BASE_URL}{endpoint}",
        headers=headers,
        params=params,
        json=body,
    )
    return response.json()


address = create_deposit_address(
    user_id, "BTC", "3fa85f64-5717-4562-b3fc-2c963f66afa6"
)
print(f"Deposit address: {address['result']['address']}")

Response example

{
  "result": {
    "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
    "name": "Bitcoin",
    "tag": null,
    "memo": null,
    "expire_time": null,
    "is_new": true
  }
}
Some networks (e.g., XRP, XLM) require a tag or memo in addition to the address. If tag or memo is present in the response, your UI must display it and instruct the user to include it when sending funds. Deposits sent without the required tag/memo may be lost.

Step 3: List deposit addresses

Retrieve existing deposit addresses for a given asset and method. Use this to display previously generated addresses to users without creating new ones each time.
def list_deposit_addresses(user_id, asset, method_id, cursor=None):
    endpoint = "/b2b/funds/deposits/addresses"
    nonce = int(time.time() * 1000000000)

    params = {
        "user": user_id,
        "asset": asset,
        "method_id": method_id,
    }
    if cursor:
        params["cursor"] = cursor

    signature = get_payward_signature(endpoint, None, API_SECRET, nonce, params)

    headers = {
        "API-Key": API_KEY,
        "API-Sign": signature,
        "API-Nonce": str(nonce),
    }

    response = requests.get(
        f"{BASE_URL}{endpoint}",
        headers=headers,
        params=params,
    )
    return response.json()


addresses = list_deposit_addresses(
    user_id, "BTC", "3fa85f64-5717-4562-b3fc-2c963f66afa6"
)
for addr in addresses["result"]["addresses"]:
    print(f"Address: {addr['address']}")

Response example

{
  "result": {
    "addresses": [
      {
        "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
        "tag": null,
        "memo": null,
        "method_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "asset": "BTC",
        "fee": { "asset": "BTC", "amount": "0.00000000" },
        "minimum": { "asset": "BTC", "amount": "0.00010000" },
        "maximum": { "asset": "BTC", "amount": "100.00000000" },
        "expire_time": null,
        "last_deposit_at": null
      }
    ],
    "next_cursor": null
  }
}

Best practices

  1. Always display tag/memo: For networks that require a tag or memo (XRP, XLM, etc.), prominently display it alongside the address. Missing tags/memos can result in lost funds.
  2. Set expectations: Show minimum amounts and est_confirmation_time from the methods response so users know what to expect before sending funds.
  3. Use fresh responses: Available methods, addresses and limits are user-specific and may change based on account standing, remaining limits, or regional regulations. Fetch fresh data before displaying options rather than relying on cached results.

Crypto withdrawals

Crypto withdrawal support via the Embed API is coming soon. This section will be updated when available.

Statuses

StatusDescription
pendingDetected and being processed
heldHeld for review
successFunds credited
failureFailed (terminal)

Error handling

ErrorCauseSolution
ENexus:Unknown assetAsset not recognizedVerify the asset code (e.g., BTC, ETH)
EGeneral:Bad dataInvalid method_id or malformed requestUse a valid method_id from the list methods response
EFunding:Too many addressesAddress limit reached for this methodReuse an existing address via GET /b2b/funds/deposits/addresses

API reference

EndpointMethodDescription
/b2b/funds/deposits/methods/{asset}GETList deposit methods for an asset
/b2b/funds/deposits/addressesPOSTCreate a new deposit address
/b2b/funds/deposits/addressesGETList existing deposit addresses
/b2b/webhooksPOSTRegister for deposit.status_updated webhooks