## Overview Checkout Deposits allow you to create reusable deposit links where customers can make multiple payments over time. Unlike one-time payments, deposit links remain active and can receive multiple transactions from different users or the same user making recurring deposits. This makes it perfect for: - **Account funding** - Let users add funds to their account balance - **Donations** - Accept multiple donations from supporters - **Recurring payments** - Allow customers to make regular deposits - **Static payment links** - Create permanent payment addresses for your business > **INFO** >**Estimated time:** 5-10 minutes for a basic implementation ## Setup Before you can start accepting deposits, you need to configure your BlockBee account and get your API credentials. ### 1. Create a BlockBee Account If you haven't already, [sign up for a BlockBee account](https://dash.blockbee.io/register) to get access to the dashboard. ### 2. Configure Addresses Set up the cryptocurrency addresses where you want to receive deposits at [Addresses](https://dash.blockbee.io/profile/addresses). > **INFO** >Check this handy [tutorial](https://support.blockbee.io/support/solutions/articles/204000013598-how-to-set-up-the-addresses-) on how to setup your addresses. ### 3. Configure Payment Settings 1. **Set Default Currency:** Go to [Payment Settings](https://dash.blockbee.io/profile/checkout) and configure your default FIAT currency (USD, EUR, GBP, etc.) 2. **Customize Deposit Page:** Optionally customize the appearance and branding of your deposit pages ### 4. Generate API Key 1. Navigate to the [API Keys section](https://dash.blockbee.io/profile/api-keys) in your dashboard 2. Click "Generate New API Key" 3. Copy the generated API key - you'll need this for all API requests > **INFO** >Check this handy [tutorial](https://support.blockbee.io/support/solutions/articles/204000013926-how-to-generate-a-new-api-key) on how to generate an API Key. > **WARNING** >**Keep your API key secure:** Never expose your API key in client-side code or public repositories. Store it securely in environment variables or server-side configuration. ## Step 1: Create Deposit Link First, make a request to our Deposit API. This will generate a unique deposit link that can receive multiple payments. ### API Endpoint **Method:** `GET` **URL:** `https://api.blockbee.io/deposit/request/` > **INFO: Tracking Deposits with Custom Parameters** >You can add your own query parameters to `notify_url` to track deposits. For example, adding `?user_id=123` will ensure that `user_id=123` is included in the webhook payload for each deposit. This is the recommended way to link deposits to specific users or accounts in your system. > > **Important:** Always include a unique identifier (like `user_id`, `account_id`, or `deposit_id`) in your `notify_url` to properly track which user/account the deposit belongs to. This identifier will be returned in the webhook payload, allowing you to credit the correct user account in your database. > **TIP** >**API Reference:** For complete parameter documentation, see our [Deposit Request API Reference](/api/depositrequest). ### Code Examples ```javascript // Create a deposit link const createDepositLink = async (userId) => { const params = new URLSearchParams({ apikey: 'YOUR_API_KEY', notify_url: `https://yoursite.com/webhook/?user_id=${userId}`, currency: 'usd', item_description: 'Account Deposit', post: '1' }); const response = await fetch(`https://api.blockbee.io/deposit/request/?${params}`); const result = await response.json(); if (result.status === 'success') { return { paymentId: result.payment_id, paymentUrl: result.payment_url }; } else { throw new Error('Failed to create deposit link: ' + result.message); } }; ``` ```php 'YOUR_API_KEY', 'notify_url' => 'https://yoursite.com/webhook/?user_id=' . $userId, 'currency' => 'usd', 'item_description' => 'Account Deposit', 'post' => '1' ]; $url = 'https://api.blockbee.io/deposit/request/?' . http_build_query($params); $response = file_get_contents($url); $result = json_decode($response, true); if ($result['status'] === 'success') { return [ 'paymentId' => $result['payment_id'], 'paymentUrl' => $result['payment_url'] ]; } else { throw new Exception('Failed to create deposit link: ' . $result['message']); } } ?> ``` ```python import requests def create_deposit_link(user_id): params = { 'apikey': 'YOUR_API_KEY', 'notify_url': f'https://yoursite.com/webhook/?user_id={user_id}', 'currency': 'usd', 'item_description': 'Account Deposit', 'notify_url': f'https://yoursite.com/webhook/?user_id={user_id}', 'post': '1' } response = requests.get('https://api.blockbee.io/deposit/request/', params=params) result = response.json() if result['status'] == 'success': return { 'paymentId': result['payment_id'], 'paymentUrl': result['payment_url'] } else: raise Exception(f'Failed to create deposit link: {result.get("message", "Unknown error")}') ``` ```ruby require 'net/http' require 'json' require 'uri' def create_deposit_link(user_id) params = { 'apikey' => 'YOUR_API_KEY', 'notify_url' => "https://yoursite.com/webhook/?user_id=#{user_id}", 'currency' => 'usd', 'item_description' => 'Account Deposit', 'post' => '1' } uri = URI('https://api.blockbee.io/deposit/request/') uri.query = URI.encode_www_form(params) response = Net::HTTP.get_response(uri) result = JSON.parse(response.body) if result['status'] == 'success' { paymentId: result['payment_id'], paymentUrl: result['payment_url'] } else raise "Failed to create deposit link: #{result['message']}" end end ``` ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Newtonsoft.Json; public class DepositService { private static readonly HttpClient client = new HttpClient(); public async Task CreateDepositLink(string userId) { var parameters = new Dictionary { ["apikey"] = "YOUR_API_KEY", ["notify_url"] = $"https://yoursite.com/webhook/?user_id={userId}", ["currency"] = "usd", ["item_description"] = "Account Deposit", ["post"] = "1" }; var queryString = string.Join("&", parameters.Select(p => $"{p.Key}={Uri.EscapeDataString(p.Value)}")); var url = $"https://api.blockbee.io/deposit/request/?{queryString}"; var response = await client.GetStringAsync(url); var result = JsonConvert.DeserializeObject>(response); if (result["status"].ToString() == "success") { return new DepositResult { PaymentId = result["payment_id"].ToString(), PaymentUrl = result["payment_url"].ToString() }; } else { throw new Exception($"Failed to create deposit link: {result.GetValueOrDefault("message", "Unknown error")}"); } } } public class DepositResult { public string PaymentId { get; set; } public string PaymentUrl { get; set; } } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; public class DepositLink { private static final HttpClient client = HttpClient.newHttpClient(); private static final ObjectMapper mapper = new ObjectMapper(); public DepositResult createDepositLink(String userId) throws Exception { String baseUrl = "https://api.blockbee.io/deposit/request/"; String queryParams = String.format( "apikey=%s¬ify_url=%s¤cy=usd&item_description=%s&post=1", "YOUR_API_KEY", URLEncoder.encode("https://yoursite.com/webhook/?user_id=" + userId, StandardCharsets.UTF_8), URLEncoder.encode("Account Deposit", StandardCharsets.UTF_8) ); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(baseUrl + "?" + queryParams)) .GET() .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); Map result = mapper.readValue(response.body(), Map.class); if ("success".equals(result.get("status"))) { return new DepositResult( (String) result.get("payment_id"), (String) result.get("payment_url") ); } else { throw new Exception("Failed to create deposit link: " + result.getOrDefault("message", "Unknown error")); } } } class DepositResult { private String paymentId; private String paymentUrl; public DepositResult(String paymentId, String paymentUrl) { this.paymentId = paymentId; this.paymentUrl = paymentUrl; } // Getters public String getPaymentId() { return paymentId; } public String getPaymentUrl() { return paymentUrl; } } ``` ```go package main import ( "encoding/json" "fmt" "net/http" "net/url" ) type DepositResult struct { PaymentID string `json:"payment_id"` PaymentURL string `json:"payment_url"` } func createDepositLink(userID string) (*DepositResult, error) { baseURL := "https://api.blockbee.io/deposit/request/" params := url.Values{} params.Add("apikey", "YOUR_API_KEY") params.Add("notify_url", fmt.Sprintf("https://yoursite.com/webhook/?user_id=%s", userID)) params.Add("currency", "usd") params.Add("item_description", "Account Deposit") params.Add("post", "1") resp, err := http.Get(baseURL + "?" + params.Encode()) if err != nil { return nil, err } defer resp.Body.Close() var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return nil, err } if result["status"] == "success" { return &DepositResult{ PaymentID: result["payment_id"].(string), PaymentURL: result["payment_url"].(string), }, nil } message := "Unknown error" if msg, ok := result["message"].(string); ok { message = msg } return nil, fmt.Errorf("failed to create deposit link: %s", message) } ``` ```bash # Create deposit link curl -G "https://api.blockbee.io/deposit/request/" \ --data-urlencode "apikey=YOUR_API_KEY" \ --data-urlencode "notify_url=https://yoursite.com/webhook/?user_id=12345" \ --data-urlencode "currency=usd" \ --data-urlencode "item_description=Account Deposit" \ --data-urlencode "post=1" ``` > **INFO: Using Our Official Libraries** >For a simpler integration, you can also use our official libraries. Here's how you would create a deposit link: > > ```javascript > // Using the official Node.js library > const BlockBee = require('@blockbee/api'); > > const params = { > user_id: userId, > }; > > const blockbeeParams = { > currency: 'usd', > item_description: 'Account Deposit', > post: '1' > }; > > const deposit = await BlockBee.depositRequest( > 'https://yoursite.com/webhook/', > 'YOUR_API_KEY', > params, > blockbeeParams > ); > // deposit.payment_url and deposit.payment_id > ``` > > ```php > // Using the official PHP library > $params = ['user_id' => $userId]; > $blockbeeParams = [ > 'currency' => 'usd', > 'item_description' => 'Account Deposit', > 'post' => '1' > ]; > > $bb = new BlockBee\Checkout('YOUR_API_KEY', $params, $blockbeeParams); > $deposit = $bb->deposit_request('https://yoursite.com/webhook/'); > // $deposit->payment_url and $deposit->payment_id > ``` > > ```python > # Using the official Python library > from BlockBee import BlockBeeCheckoutHelper > > params = {'user_id': userId} > bb_params = { > 'currency': 'usd', > 'item_description': 'Account Deposit', > 'post': '1' > } > > bb = BlockBeeCheckoutHelper('YOUR_API_KEY', params, bb_params); > deposit = bb.deposit_request('https://yoursite.com/webhook/'); > # deposit.payment_url and deposit.payment_id > ``` > > You can find the full documentation for our libraries here: > - [Node.js Library](/libraries/nodejs) > - [PHP Library](/libraries/php) > - [Python Library](/libraries/python) ### Required Parameters - **`apikey`** - Your BlockBee API key from the [Dashboard](https://dash.blockbee.io/) - **`notify_url`** - Webhook URL where BlockBee sends payment notifications for each deposit. ### Optional Parameters - **`currency`** - Override the default FIAT currency set in your [Payment Settings](https://dash.blockbee.io/profile/checkout) (USD, EUR, GBP, etc.). - **`item_description`** - Description that appears on the deposit page. - **`post`** - Set to `1` to receive webhooks as POST requests. - **`suggested_value`** - Suggested amount for deposits (optional, users can still send any amount). ### Response The API returns a JSON response containing the `payment_url` and `payment_id`. ```json { "status": "success", "payment_url": "https://pay.blockbee.io/deposit/fG78jtx96ugjtu0eIbeLmFB9z0feJf9N/", "payment_id": "fG78jtx96ugjtu0eIbeLmFB9z0feJf9N" } ``` > **TIP** >**API Reference:** For complete response field documentation, see our [Deposit Request API Reference](/api/depositrequest). ## Step 2: Share the Deposit Link After creating the deposit link in Step 1, you will receive a `payment_url` in the API response. You can share this URL with your customers in multiple ways: - **Direct link** - Send the URL directly to customers - **QR code** - Generate a QR code for the deposit URL - **Embed in your app** - Display the deposit link in your application - **Static page** - Create a permanent deposit page using this URL ```javascript // Share deposit link with customer const shareDepositLink = (depositResult) => { // Option 1: Direct link console.log(`Share this link: ${depositResult.paymentUrl}`); // Option 2: Generate QR code (using a QR library) // const qrCode = generateQRCode(depositResult.paymentUrl); // Option 3: Embed in your app // document.getElementById('deposit-link').href = depositResult.paymentUrl; }; ``` ```php // Share deposit link with customer function shareDepositLink($depositResult) { // Option 1: Direct link echo "Share this link: " . $depositResult['paymentUrl']; // Option 2: Generate QR code // $qrCode = generateQRCode($depositResult['paymentUrl']); // Option 3: Embed in your app // echo 'Make a Deposit'; } ``` ```python # Share deposit link with customer def share_deposit_link(deposit_result): # Option 1: Direct link print(f"Share this link: {deposit_result['paymentUrl']}") # Option 2: Generate QR code # qr_code = generate_qr_code(deposit_result['paymentUrl']) # Option 3: Embed in your app # return f'Make a Deposit' ``` > **TIP** >**Pre-select cryptocurrency:** You can append `?coin=btc` to the deposit URL to pre-select Bitcoin (or any other supported cryptocurrency) on the checkout page. ## Step 3: Handle the Webhooks This is the most important step. When a deposit is made, BlockBee will send a notification (webhook) to the `notify_url` you provided. Your application needs to listen for these webhooks to process each deposit. ### Webhook Endpoint Create an endpoint in your application to receive the webhook. The payload will contain all the details of the transaction. ```javascript // Express.js webhook handler app.post('/webhook', express.json(), (req, res) => { // 1. Verify the webhook signature if (!verifyWebhookSignature(req)) { return res.status(401).send('Unauthorized'); } // 2. Extract data from the payload const { is_paid, uuid, paid_amount, paid_coin, txid, status, user_id } = req.body; // Note: user_id comes from the custom parameter you added to notify_url when creating the deposit link // 3. Check for duplicates using UUID if (isWebhookAlreadyProcessed(uuid)) { return res.status(200).send('*ok*'); } // 4. Check if the payment is complete and the status is 'done' if (is_paid === 1 && status === 'done') { // 5. Find the user in your database using the user_id console.log(`User ${user_id} has made a deposit: ${paid_amount} ${paid_coin}`); // 6. Update the user's account balance // e.g., db.users.update({ id: user_id }, { // $inc: { balance: paid_amount }, // $push: { transactions: { amount: paid_amount, coin: paid_coin, txid: txid } } // }); // 7. Send confirmation to the user console.log(`Crediting ${paid_amount} ${paid_coin} to user ${user_id}...`); } // 8. Mark this webhook as processed using its unique UUID markWebhookAsProcessed(uuid); // Respond with *ok* to let BlockBee know you've received the webhook res.status(200).send('*ok*'); }); ``` ```php query("UPDATE users SET balance = balance + '{$paid_amount}' WHERE id = '{$user_id}'"); // 7. Send confirmation to the user error_log("Crediting {$paid_amount} {$paid_coin} to user {$user_id}..."); } // 8. Mark this webhook as processed using its unique uuid markWebhookAsProcessed($uuid); // Respond with *ok* to let BlockBee know you've received the webhook http_response_code(200); echo '*ok*'; ?> ``` ```python # Flask webhook handler @app.route('/webhook', methods=['POST']) def webhook(): # 1. Verify the webhook signature if not verify_webhook_signature(request): return 'Unauthorized', 401 # 2. Extract data from the payload data = request.get_json() is_paid = data.get('is_paid') uuid = data.get('uuid') user_id = data.get('user_id') # This comes from the custom parameter you added to notify_url paid_amount = data.get('paid_amount') paid_coin = data.get('paid_coin') txid = data.get('txid') status = data.get('status') # 3. Use the uuid to prevent processing the same webhook twice if is_webhook_already_processed(uuid): return '*ok*', 200 # 4. Check if the payment is complete and status is 'done' if is_paid == 1 and status == 'done': # 5. Find the user in your database print(f"User {user_id} has made a deposit: {paid_amount} {paid_coin}") # 6. Update the user's account balance # e.g., User.objects.filter(id=user_id).update( # balance=F('balance') + paid_amount # ) # 7. Send confirmation to the user print(f"Crediting {paid_amount} {paid_coin} to user {user_id}...") # 8. Mark this webhook as processed using its unique uuid mark_webhook_as_processed(uuid) # Respond with *ok* to let BlockBee know you've received the webhook return '*ok*', 200 ``` > **TIP** >**Full Webhook Fields:** For a complete list of all fields provided in the webhook payload, please see our [Checkout Deposits Webhook reference](/webhooks/checkout-deposits-webhook). ### Best Practices - **Verify Signatures:** Always verify the webhook signature to ensure the request is from BlockBee. - **Idempotency:** Use the `uuid` from the webhook payload to ensure you only process each transaction once. - **Respond Quickly:** Always respond with a `*ok*` and a `200` status code to prevent BlockBee from resending the webhook. - **Asynchronous Processing:** For long-running tasks (like calling other APIs), process them in a background job after responding to the webhook. > **TIP** >**Implementation Guide:** For detailed instructions and code examples on how to verify webhook signatures, please see our [Verify Webhook Signature guide](/webhooks/verify-webhook-signature). ### Alternative: Checking Logs Manually While webhooks are recommended, you can also check the deposit status by polling our [Deposit Logs API endpoint](/api/depositlogs). This can be useful for reconciliation or as a backup if your webhook endpoint fails. You will need the `payment_id` returned in Step 1. > **INFO: Using Our Official Libraries** >You can also check deposit logs using our official libraries: > > ```javascript > // Using the official Node.js library > const BlockBee = require('@blockbee/api'); > > const logs = await BlockBee.depositLogs(paymentId, 'YOUR_API_KEY'); > // logs.notifications contains the deposit history > ``` > > ```php > // Using the official PHP library > $logs = BlockBee\Checkout::deposit_logs($paymentId, 'YOUR_API_KEY'); > // $logs->notifications contains the deposit history > ``` > > ```python > # Using the official Python library > from BlockBee import BlockBeeCheckoutHelper > > logs = BlockBeeCheckoutHelper.deposit_logs(payment_id, 'YOUR_API_KEY') > # logs['notifications'] contains the deposit history > ``` ## Testing Your Integration Test your deposit flow using real cryptocurrency with minimal cost. ### 1. Use Litecoin for Testing We recommend using **Litecoin (LTC)** for testing because: - Low transaction fees (typically under $0.01) - Fast confirmation times (2.5 minutes average) - Real blockchain testing without high costs ### 2. Test with a Small Amount - Create a deposit link - Make a small deposit (e.g., $2.00) using Litecoin - This covers all fees with minimal cost (typically under $0.10) - Test multiple deposits to the same link ### 3. Testing Checklist - ✅ Deposit link creation works as expected - ✅ Webhooks are received for each deposit - ✅ User account balance is updated correctly - ✅ Duplicate webhooks are properly handled - ✅ Multiple deposits to the same link work ### 4. Local Webhook Testing To test webhooks on your local machine, you need to expose your server to the internet. `ngrok` is a great tool for this. ```bash # Use ngrok for local webhook testing ngrok http 3000 # Your test webhook URL: https://abc12345.ngrok.io/webhook # Use this as the notify_url when creating the deposit link. ``` > **SUCCESS** >**Ready for production?** Once testing is complete, switch to your production API Key and ensure your `notify_url` points to your live production server.