# Download ZBD App
Source: https://docs.zbdpay.com/earn/app
Get ZBD App for all your favorite platforms.
## ZBD App
The ZBD App is your key to becoming a true Internet Citizen. It is available for [iOS](https://apps.apple.com/us/app/zbd-earn-bitcoin-rewards/id1484394401?mt=8) and [Android](https://play.google.com/store/apps/details?id=io.zebedee.wallet\&hl=en_US\&pli=1) mobile devices.
> After accessing the ZBD login portal URL and successfully authenticating, the user will be redirected back to your application with `state` and `code` query parameters included. These two properties allow you to hit the `token` endpoint, and get the user's `accessToken`.
### Getting the Token
* Token: `POST` [https://api.zbdpay.com/v1/oauth2/token](https://api.zbdpay.com/v1/oauth2/token)
* Once you have the `code` returned from the previous `authorization` endpoint, you must now make a `POST` request to the token endpoint, with the following properties:
```json theme={null}
{
"client_id": "{{client_id}}",
"client_secret": "{{client_secret}}",
"code": "{{code}}",
"code_verifier": "{{code_verifier}}",
"grant_type": "authorization_code",
"redirect_uri": "{{your_url_callback}}"
}
```
* And, as response, you should receive the user's `accessToken`:
```json theme={null}
{
"accessToken": "{{userAccessToken}}"
}
```
### Getting ZBD User Profile Data
* Profile: `GET` [https://api.zbdpay.com/v1/oauth2/user](https://api.zbdpay.com/v1/oauth2/user)
* You can now call the ZBD API endpoints passing the provided `accessToken` from the previous endpoint on the request authorization header.
```json theme={null}
Response: {
"data": {
"email": "testzebedee2@gmail.com",
"gamertag": "testzebedee",
"id": "6109484f-08e6-479a-a044-be930d89b42a",
"image": "https://lh3.googleusercontent.com/a/AATXAJwNvpB49NrxF41KVrEFX9k1v93WoMAMBb4wBF7Q=s96-c",
"isVerified": true,
"lightningAddress": "testzebedee@zbd.gg",
"publicBio": "Welcome to my zbd.gg page!",
"publicStaticCharge": "lnurl1dp68gurn8ghj7ar9wd6zu7n9vfjkget99e5k7tmkxqhhyet3w4jhxapdwd6xzarfvvkkx6rpwfnk2ue0x56nxvrpxuervtfkxa3rgtf5xu6k2ttzxy6nstt9xsurgvejx5exydpjvc9v9tk7",
"social": {
"twitter": "gamertag",
"website": "https://example.com",
},
},
"success": true,
}
```
### Getting ZBD User Wallet Data
* Profile: `GET` [https://api.zbdpay.com/v1/oauth2/wallet](https://api.zbdpay.com/v1/oauth2/wallet)
* You can now call the ZBD API endpoints passing the provided `accessToken` from the previous endpoints on the request authorization header.
```json theme={null}
Response: {
"data": {
"balance": "98251000",
"remainingAmountLimits": {
"daily": "1000000000",
"maxCredit": "4901749000",
"monthly": "25000000000",
"weekly": "5000000000",
},
},
"message": "Successfully fetched user wallet.",
"success": true,
}
```
It is common for software libraries and prebuilt packages to handle a lot of
this heavy-lifting for you, except for the `Getting the Token` part, which is
a true secret and should be handled in your secure backend system services.
## Integration
### Get Credentials from ZBD Developer Dashboard
In order to be able to implement `ZBD Login` functionality, you must first get your application/game's OAuth2 `Client ID` and `Client Secret`, and set up proper redirect URLs.
### Getting Keys
After creating a game inside of the ZBD Developer Dashboard, head on over to the `OAuth2` tab inside of that game's single details view.
You can now get your `Client ID` (first field) and `Client Secret` (second field).
Keep your secrets secure and safe. Don't share secrets with others. Don't
commit secrets into your code.
### Setting Redirect URLs
Now its time to set up your OAuth2 redirect URLs. Head on over to the OAuth2 settings modal through the `View Settings` button.
> It is a requirement that the same redirect URL be used in the first step of the OAuth2 flow (`authorization endpoint`) - if you set a redirect URL different from the one being used when building the authorization URL, or if you don't set a redirect URL at all, the Authorization redirect will not work.
From the opened OAuth2 Settings modal, you can add up to 3 redirect URLs (whether native mobile URIs or HTTPS-based URLs). To get started use the `+` button.
Once you've added your redirect URLs / app schemas, you can save by clicking `Update`. You're now all set up for using `ZBD Login` on your application. For more detailed examples [check out the OAuth2 Code Walkthrough for source code and LOC explanation](/earn/oauth2/walkthrough).
# Implementation Walkthrough
Source: https://docs.zbdpay.com/earn/oauth2/walkthrough
Detailed walkthrough of an implementation of ZBD Login.
## Client Side
When setting up OAuth2 from client side, you have two options:
* Build the entire flow yourself
* Make a request for building the [authorization URL](/earn/oauth2/walkthrough#building-authorization-url)
* Handling the Webview with the created URL
* Getting the `code` after authenticating with ZEBEDE
* Making another request for [getting the token](/earn/oauth2/walkthrough#getting-the-token-and-accessing-zbd-api)
* Make use of some of the available OAuth libraries available for the language you are working on, which would handle the initial steps of the flow
* Install and set up configs accordingly to the library
* If PKCE is available on the library you might receive the `code_verifier` from the response, after authenticating.
* If PKCE is not available, you might need to [build the code\_challenge and code\_verifier](/earn/oauth2/walkthrough#building-authorization-url) yourself.
* Getting `code` as response
* Making the request for [getting the token](/earn/oauth2/walkthrough#getting-the-token-and-accessing-zbd-api)
If you chose the second option, there are open-source libraries for handling OAuth2 on Mobile using AppAuth ([iOS](https://github.com/openid/AppAuth-iOS) and [Android](https://github.com/openid/AppAuth-Android)), as well as for React Native using [react-native-app-auth](https://github.com/FormidableLabs/react-native-app-auth).
### iOS Webview Configuration
If you are calling the OAuth flow from an iOS webview integration, you need to add the following to your `Info.plist` file in Xcode:
```xml theme={null}
LSApplicationQueriesSchemes
zebedee.oauth2
zbd
```
This allows your iOS app to query and open the ZBD app URL schemes required for the OAuth flow. Without this configuration, the OAuth redirect may not work properly on iOS devices.
## Server Side
### Node.js
This flow go over all the steps for Logging in with ZBD, from Building the authorization URL, with proper PKCE Keys, to getting the accessToken and calling ZBD API.
If you are using a library that provides PKCE guidelines, it will most likely be able to handle the initial flow (building auth URL and getting the code) just fine. In this case, feel free to jump to the [Token Section](/earn/oauth2/walkthrough#building-authorization-url).
### Building Authorization URL
In case you are setting up the PKCE flow yourself (no usage of libraries), we will need to setup the `code_challenge` from a `code_verifier` which will be used later on, on token request.
```js theme={null}
const crypto = require('crypto');
import OAuth from 'oauth';
function sha256(buffer) {
return crypto.createHash('sha256').update(buffer).digest();
}
function base64URLEncode(str) {
return str
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
export function GeneratePKCE() {
const verifier = base64URLEncode(crypto.randomBytes(32));
if (verifier) {
const challenge = base64URLEncode(sha256(verifier));
return { challenge, verifier };
}
}
const createZBDOauth = () => {
const { OAuth2 } = OAuth;
const authorizeUrl = 'oauth2/authorize';
const tokenPath = 'oauth2/token';
const oauth2 = new OAuth2(
ZBD_CONSUMER_KEY, // CLient ID
ZBD_CONSUMER_SECRET, // Client Secret
ZEBEDEE_API_URL, // ZBD API URL: https://api.zbdpay.com/v0/
authorizeUrl, // Authorization URL: oauth2/authorize/
tokenPath, // Token Path: oauth2/token
null,
);
return oauth2;
};
// Called by the app to get a url it will open in a webview/or browser
export const getZBDLoginUrl = async (userId: string) => {
// generate the PKCE key
const { verifier, challenge } = GeneratePKCE();
// save the verifier/key to the user object so we can access it when validating in the callback
await User.findOneAndUpdate({ userId }, { oauthVerifier: verifier });
const scope = 'user';
const state = userId;
const suffix = `&response_type=code&code_challenge=${challenge}&code_challenge_method=S256&state=${state}`;
const oauth2 = createZBDOauth();
// use NPM module to create the url
const res = await oauth2.getAuthorizeUrl({
redirect_uri: ZBD_REDIRECT_URL,
scope,
});
// npm module doesnt support PKCE so append the url with the code_challenge info
const url = res + suffix;
return url;
};
```
**Code explanation**
* `getZBDLoginUrl` function
* In this function, we initially Generate PKCE keys: `verifier` and `code_challenge`
* Then, `findOneAndUpdate` represents an generic ORM call for updating the User model, on the database. This way we can, afterwards, retrieve that value for getting the token.
* We then Build the URL suffix
* Url prefix and generated from `createZBDOauth`, which uses `oauth` library to do so
* `generatePKCE`
* This is where we setup PKCE Keys.
* initially we set the code verifier:
* `const verifier = base64URLEncode(crypto.randomBytes(32));`
* From the code verifier, the code\_challenge is created:
* `const challenge = base64URLEncode(sha256(verifier));`
When logging in using the provided URL, you will get a response including `state` and `code` which should be user now for getting the token, and user data:
### Getting the token and accessing ZBD API
```js theme={null}
// called by ZBD oauth on login
export const zbdLoginCallback = async (payload: Object) => {
const { code, state } = payload;
try {
const user = await User.findOne({ userId: state });
const { oauthVerifier } = user;
// get the verifier generated by the PKCE script
const res = await getAccessToken({
code,
client_secret: ZBD_CONSUMER_SECRET,
client_id: ZBD_CONSUMER_KEY,
code_verifier: oauthVerifier,
grant_type: 'authorization_code',
redirect_uri: ZBD_REDIRECT_URL,
});
const { access_token } = res.data;
// get user data now we have the access token
const response = await getUserData(access_token);
const { data } = response;
const userData = data.data;
const { gamertag, email, isVerified, id } = userData;
if (!gamertag || !id || !email) {
throw new Error('gamer tag not found');
}
// save the details to the user object so we now know their email, verification etc
user.gamerTag = gamertag;
user.gamerTagId = id;
user.email = email;
user.isZBDVerified = isVerified;
user.oauthLoginDate = new Date();
await user.save();
// show a webpage that will redirect back to the app app by calling the app schema url
return {
html: path.resolve(`${__dirname}/../callback/oauth-callback.html`),
};
} catch (e) {
console.error(e);
return {
html: path.resolve(`${__dirname}/../callback/oauth-callback-error.html`),
};
}
};
```
**Code explanation**
Once the user is successfully authenticated on ZBD Client, there is a redirect back to your app, sending `code` and `state` as query params.
Those values are send as payload on this next request:
* First of all, remember we registered the verifier on the User (generic ORM update)? now we retrieve that value:
* `const user = await User.findOne({ userId: state });`
* With the proper verifier, we can now make a post request to the token endpoint, and we should have the token returned.
* `const res = await getAccessToken({…body})`
```js theme={null}
export const getAccessToken = async (payload: Object) => {
const response = await axios({
method: 'POST',
data: payload,
url: `https://api.zbdpay.com/v0/oauth2/token`,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});
return response;
};
```
* Now, by adding the accessToken to request headers, we can fetch data from ZBD API
* `const response = await getUserData(access_token);`
```js theme={null}
export const getUserData = async (accessToken: string) => {
const response = await axios({
method: 'GET',
url: `https://api.zbdpay.com/v0/oauth2/user`,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
Authorization: `Bearer ${accessToken}`,
},
});
return response;
};
```
You are now able to proceed with your login logic and send the user data accordingly ⚡
## Code Examples
See the full source code.
See the full source code.
# ZBD Earn SDK
Source: https://docs.zbdpay.com/earn/sdk
Real money rewards to boost engagement and retention.
## Overview
The ZBD Earn SDK enables you to credit rewards to your users at your discretion (any amount at any time). However, users can only *withdraw* earned rewards up to a specified threshold based on their gameplay time.
For instance, when a user first downloads the game, you may credit the user 100 sats, but they may be limited to withdraw only up to 50 sats for a few minutes.
The player’s withdrawal limit increases the longer they engage with the game. For example, after 20 minutes of gameplay, they may be able to withdraw up to 100 sats. This system enhances the SDK's security while still providing most users with a quick and easy way to earn and withdraw Bitcoin.
In the following sections, we’ll explore how to send rewards and check a user’s withdrawal limit.
# Google Play Store Guidelines
Source: https://docs.zbdpay.com/earn/sdk/android-app-store
Instructions for successfully submitting your game to the Google Play Store.
**It is very important to follow the below guidelines to ensure your game does not run into issues with app reviewers on the Google Play Store.**
# Accessing App Content
In the left sidebar, go to **Monitor and improve** → **Policy and programs** → **App content**. Select the **Actioned** tab.
After accessing **Data Safety**, click **Next** until you reach the **Data Types** section.
Expand the **App Activity** section and select **Installed Apps**.
Expand the **Device or other IDs** section and select **Device or other IDs**.
Click **Next** to proceed to **Data Usage and Handling**.
### 4. Data Usage and Handling
1. In the **Data Usage and Handling** section, expand **App Activity** and click **Start**.
2. Choose **Collected**
3. This is **NOT** processed ephemerally
4. Select **Data collection is required** (users can’t turn off this data collection) if applicable.
5. Under the reasons for data collection, select **Fraud prevention, security, and compliance**.
| Data Types | Collected | Shared | Processed ephemerally | Required or Optional | Purposes |
| ---------------------- | --------- | ------ | --------------------- | -------------------- | ---------------- |
| Installed applications | Yes | No | No | Required | Fraud Prevention |
| User IDs | Yes | No | No | Required | Fraud Prevention |
| Device or other IDs | Yes | No | No | Required | Fraud Prevention |
### 7. Finalizing and Saving
# Attestation Set Up
Source: https://docs.zbdpay.com/earn/sdk/attestation-setup
Configure attestation to ensure your app has not been tampered with using required information for Android and iOS.
In order to ensure we have everything we need to detect whether your app has not been tampered with as part of our attestation check, we require a couple of pieces of information.
Here is a handy video guide:
## Android
For Android, we need your **Bundle ID** or **package name**, i.e.`com.domain.appname`, which you set in your Unity build settings.
This is NOT the appId ZBD provides you.
We also need the **SHA-256 hash** of your signing key.
To find your app's SHA-256 hash key for Google Play:
Sign in to your Google Play Console account.
Choose the app for which you need the SHA-256 hash.
Go to the Release section in the left-hand menu.
Click on Setup in the submenu.
During development, you are likely using a custom keystore in Unity, so we will need that **SHA-256 hash** as well. You can generate the SHA-256 hash key for your keystore using the following command:
```bash theme={null}
keytool -list -v -keystore path/to/your.keystore -alias your_alias -storepass your_keystore_password -keypass your_key_password
```
It should look something like this :
EA:A1:69:AA:2F:FC:6D:16:84:ED:06:11:E0:65:2B:E0:BB:9C:5B:E3:41:96:06:E2:3D:85:8F:2C:22:2A:E9:86
## iOS
### App Attest
For iOS builds, you must have **App Attest** enabled on your provisioning profile. The Earn SDK backend uses App Attest to validate the integrity of your game. Without it, attestation checks will fail.
To enable App Attest:
Make sure to regenerate and download your provisioning profile after enabling App Attest, then update it in Xcode.
### Bundle ID & Team ID
For iOS we need your **Bundle ID** i.e.`app id`, e.g.`com.domain.appname` and your **Team ID**.
To find your app's Team ID for Apple Developer:
Sign in to your Apple Developer account
This is NOT the appId ZBD provides you.
# Best Practices
Source: https://docs.zbdpay.com/earn/sdk/best-practices
Optimize rewards and initialization with best practices for earn rates, withdrawal limits, and SDK failures.
# Balancing Earn Rate with Withdrawal Limit
It’s possible to assign more Bitcoin to a user than they are currently allowed to withdraw.
As outlined in the **Security** section, the TL;DR is: for fraud prevention,
a user's withdrawal limit is tied to how long their device has been continuously online.
Because of this, it’s **recommended to keep a user’s earn rate roughly aligned with their withdrawal capacity**. It's okay to occasionally let users earn more than they can immediately withdraw, this can encourage them to return to your game later and improves retention. However, avoid creating situations where users earn significantly more than they can access. For example, assigning 1,000 sats but allowing only 100 sats to be withdrawn will likely result in a frustrating user experience.
## Ways to Balance Earn and Withdrawal:
Avoid giving out rewards too often
Make early rewards easy (e.g. the first 10 sats), then gradually slow down progression.
Use`ZBDController.Instance.GetBalance`to retrieve the user's current balance and withdrawal cap. Adjust the reward flow based on this data.
### Example: MergeMonsters
In the game [MergeMonsters](https://play.google.com/store/apps/details?id=com.fumbgames.monstermerge\&hl=en_US\&pli=1), rewards are balanced dynamically:
* If the user's balance exceeds 100 sats, the game stops showing coin rewards on tiles.
* If the balance is too high, Bitcoin rewards in boss battles are shown less frequently.
## Handling Initialization Success/Failure
The `ZBDController.Instance.Init` function can take a few seconds to complete, so it's recommended to call it as early as possible ideally when your game first launches. Keep the instance alive using a singleton or a `DontDestroyOnLoad` object that persists across scenes.
In most cases, the SDK initializes successfully. However, initialization may fail due to network issues or security checks, for example, if the user is on a VPN or proxy. When this happens, `Init` will return `false`.
To ensure a smooth user experience, you should still display a call-to-action button that triggers ZBDModalController.Instance.ShowModal(). This gives users the opportunity to:
e.g. VPN detected or no network
# Building
Source: https://docs.zbdpay.com/earn/sdk/building
Comprehensive video guides for mastering Bitcoin apps and games with ZBD.
# Building for Android
### Minimum API Level
Make sure that the minimum API Level is set to **Android 10 API Level 29** in your settings.
### Dependencies
The ZBDSDK in Android requires a few dependenices to be installed. To make this as smooth as possible we included the `External Dependency Manager` in the package. This should automatically install the dependencies and deal with any duplicate classes.
However, you may need to manually resolve the dependencies by going to:
If during the build process you get build errors, specifically mentioning duplicate classes you may need to go to
# Building for iOS
### Target Minimum iOS Version
Make sure that the `Target Minimum iOS Version` is set to at least 13 in your settings.
# Compatibility
Source: https://docs.zbdpay.com/earn/sdk/compatibility
SDK compatibility with Unity and mobile platforms.
The ZBD Earn SDK for Unity is only compatible with **iOS** and **Android** mobile environments.
# Requirements
### Unity Version
```bash theme={null}
2022 and above
```
### iOS Version
```bash theme={null}
Deployment target 13 and above
```
### Android Version
```bash theme={null}
Minimum Api Level OS 11/API 30 and Target API Level 34
Build settings: Stripping level to low or minimum
```
# Upgrading from Time Based SDK
If you are upgrading from the ZBD Time-based Earn SDK version, please follow the steps outlined in this video walkthrough.
# Download SDK
Source: https://docs.zbdpay.com/earn/sdk/download
Setup your Unity project to use the ZBD Earn SDK
Contact your ZBD Customer Success Manager to get access to the ZBD Earn SDK for your Unity project.
# Go-Live Checklist
Source: https://docs.zbdpay.com/earn/sdk/go-live-checklist
Make sure you have completed these steps before going live with the ZBD Earn SDK.
Before releasing your game to production, make sure you have completed the following:
Ensure attestation is fully configured for both Android and iOS. For iOS, this includes enabling App Attest on your provisioning profile. See the [Attestation Set Up](/earn/sdk/attestation-setup) guide.
Your game should gracefully handle ZBD platform maintenance periods by checking the `maintenance` flag on **every** SDK response. See [Handling Maintenance Mode](/earn/sdk/integration#handling-maintenance-mode).
Make sure you have thoroughly tested your game before going live. At a minimum, verify the following:
* **Test init** — confirm the SDK initializes successfully.
* **Test modal shows** — confirm the ZBD modal appears correctly.
* **Test linking ZBD** — if cashout is an option, confirm users can link their ZBD account.
* **Test earning** — confirm rewards are sent and received.
* **Test withdrawal limit increases** — confirm your withdrawal limit increases as you play.
* **Test cashout** — confirm the cashout flow completes successfully.
* **Test attestation** — confirm attestation is working correctly. To do this, verify with your account manager that attestation is enabled for your app, then check that your withdrawal limit increases as you play. If attestation is failing, the withdrawal limit will not increase and you will see errors in Android Logcat or the iOS Console.
# Integrating Earn SDK
Source: https://docs.zbdpay.com/earn/sdk/integration
How to import and initialize the ZBD Earn SDK.
# Import the SDK
Reach out to your ZBD Customer Success Manager to get access to the Unity SDK package.
To import a package, right-click the assets folder in Unity Editor and choose `"Import Package..."`.
Navigate to the newly imported ZBD folder `Prefabs` and drag and drop the ZBDSDK prefab into your scene.
Due to your specific scene resolution settings and orientation you may need to resize/adjust the included UI elements. We will explain how to do this in more detail later in this documentation, but for now we are assuming the UI element has imported correctly.
# Add your App ID
You should have received your `App ID` from your ZBD Customer Success Manager. You’ll need to set this in the `ZBDController` script which is attached to the `ZBDSDK` game object in the ZBDSDK prefab.
If you have not been given an App ID, for testing purposes only you can use the following ID:
```bash theme={null}
sdkdemo.limitedachievementsats
```
# Initialize the SDK
You can optionally pass a `userId` during initialization — this is your own internal identifier for the user. It's used for various analytics and user linking features, but it is not essential.
Please reach out to your ZBD Customer Success Manager if you face any issues.
Once the ZBDSDK prefab is added you can initiate the SDK from another script, such as your main controller, via the following call:
```csharp theme={null}
// Initialize the SDK with your internal userId
using ZBD;
ZBDController.Instance.Init(userId, completion =>
{
if (completion.success) {
Debug.Log("success");
} else if (completion.maintenance) {
// Platform is in maintenance mode — display a message to the user
Debug.Log("ZBD is currently under maintenance. Please try again later.");
} else {
Debug.LogError(completion.error);
}
}
);
```
### Initializing SDK without `userId`
You can also set the `userId` at any time after initialization by calling:
```csharp theme={null}
ZBDController.Instance.SetUserId("user_id");
```
```csharp theme={null}
using ZBD;
ZBDController.Instance.Init(completion =>
{
if (completion.success) {
Debug.Log("success");
} else if (completion.maintenance) {
Debug.Log("ZBD is currently under maintenance. Please try again later.");
} else {
Debug.LogError(completion.error);
}
}
);
```
This will allow the user to start earning, however **in order to withdraw they will need to download the ZBD app, get their ZBD Gamertag and register it with the ZBD Earn SDK**.
The easiest way to do this is to present the ZBD modal. If the user has not registered their ZBD Gamertag then they will be guided through it inside the modal.
### Handling Maintenance Mode
The ZBD platform may occasionally enter maintenance mode. When this happens, the SDK response will include a `maintenance` flag set to `true`. You should check for this flag during initialization and display an appropriate message to your users.
The `Init` response object contains the following fields:
```csharp theme={null}
public class ZBDInitResponse
{
public bool success;
public bool maintenance;
public string userId;
public string error;
public string type;
}
```
When `maintenance` is `true`:
* The SDK will not be fully operational
* Reward sending will be unavailable
* You should display a user-friendly message (e.g. *"Rewards are temporarily unavailable. Please try again later."*)
* You should **not** treat this as an error — maintenance periods are temporary
Maintenance mode can begin at any time, including while players are actively in a session. This means `Init` may succeed normally, but subsequent calls to `SendReward` or `GetBalance` can return `maintenance = true` during gameplay. You must handle the maintenance flag on **every** SDK response, not just during initialization.
The following SDK methods can return the `maintenance` flag:
| Method | Response Class |
| ------------ | ----------------------- |
| `Init` | `ZBDInitResponse` |
| `SendReward` | `ZBDSendRewardResponse` |
| `GetBalance` | `ZBDBalanceResponse` |
### Presenting SDK Modal
```csharp theme={null}
ZBDModalController.Instance.ShowModal();
```
`ShowModal()` will present a modal prompting the user to enter a ZBD Gamertag, or to sign in if they were not signed in automatically.
Users can also **view their balance** and **initiate a withdrawal** from this modal.
### Detecting Modal Visibility
You may want to stop the gameplay or trigger some other event when the SDK modal becomes visible. You can **detect when the modal is visible** via 2 methods:
**Subscribe to the `ModalIsVisible` event**
```csharp theme={null}
private void Start()
{
ZBDController.Instance.ModalIsVisible += WebViewVisible;
}
void WebViewVisible(bool visible)
{
// handle event here
}
private void OnDestroy()
{
ZBDController.Instance.ModalIsVisible -= WebViewVisible;
}
```
**Invoke `IsModalVisible()`**
You can also call `IsModalVisible()` to check the status of the modal.
```csharp theme={null}
ZBDModalController.Instance.IsModalVisible();
```
**Android Back Button**
In Android you can detect whether the modal is open and close it with the following code snippet.
```csharp theme={null}
if (Input.GetKeyDown(KeyCode.Escape))
{
if (ZBDModalController.Instance.IsModalVisible())
{
ZBDModalController.Instance.CloseModal();
}
}
```
# Apple App Store Guidelines
Source: https://docs.zbdpay.com/earn/sdk/ios-app-store
Instructions for successfully submitting your game to the Apple App Store.
**It is very important to follow the below guidelines to ensure your game does not run into issues with app reviewers on the Apple App Store.**
# Privacy Policies
Apple announced that starting [Spring 2024](https://developer.apple.com/news/?id=3d8a9yyh), it will require its developers to declare the reasons for using certain APIs (aka Required Reason APIs) that could be misused to collect data about users' devices within privacy manifest files.
**This needs to be done when integrating the ZBD Earn SDK.**
Once your Xcode project has successfully built, follow these steps:
Right click the new `PrivacyInfo` file and select `Open As -> Source Code` then copy and paste the following.
Add or change any values below based on what your game is doing!
More information on this Apple policy can be found here: [Apple Developer Documentation](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files).
```xml theme={null}
NSPrivacyTracking
NSPrivacyTrackingDomains
NSPrivacyCollectedDataTypes
NSPrivacyCollectedDataType
NSPrivacyCollectedDataTypeDeviceID
NSPrivacyCollectedDataTypeLinked
NSPrivacyCollectedDataTypeTracking
NSPrivacyCollectedDataTypePurposes
NSPrivacyCollectedDataTypePurposeAppFunctionality
NSPrivacyAccessedAPITypes
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategoryFileTimestamp
NSPrivacyAccessedAPITypeReasons
C617.1
```
Your game should now be able to be submitted to the Apple App Store!
If you have any questions, don't hesitate to reach out to your ZBD Customer Success Manager.
# Manage SDK Controls via Dashboard
Source: https://docs.zbdpay.com/earn/sdk/manage-controls-dashboard
Update user country codes and manage your project whitelist
Manage individual user settings through the ZBD Dashboard, including updating country codes and adding users to your project whitelist.
## Access
1. Go to [dashboard.zbdpay.com](https://dashboard.zbdpay.com)
2. Navigate to **SDK User Support** in the sidebar
## Search Users
Enter one of the following in the search field:
* **SDK User ID** → Loads user data directly
* **Support ID** → Shows list of users with that linked ID → select one
* **Gamertag** → Shows list of users with that gamertag → select one
Click **"Load Data"** to search.
After loading, the **User Data** card appears displaying user information such as Withdrawal Limit, Rewards Balance, country code, and more. Below the card, a table displays all user transactions. Click any row to view full transaction details.
***
## Change Country Code
Once the User Data card loads:
1. Click the **Change** button next to the country code
2. Search for the desired country
3. Click **Save**
***
## Whitelist Users
Use the **Whitelist User** card (below SDK User ID card):
1. Enter the **Support ID** in the input field
2. Select a **Rewards App Name** tied to that support ID
3. Click the **Whitelist** button
# Manage Rewards Balance via Dashboard
Source: https://docs.zbdpay.com/earn/sdk/manage-rewards-balance
Increase or decrease user rewards balance via the ZBD Dashboard
Manage user rewards balance through the ZBD Dashboard.
## Access
1. Go to [dashboard.zbdpay.com](https://dashboard.zbdpay.com)
2. Navigate to **SDK User Support** in the sidebar
## Search Users
Enter one of the following in the search field:
* **SDK User ID** → Loads user data directly
* **Support ID** → Shows list of users with that linked ID → select one
* **Gamertag** → Shows list of users with that gamertag → select one
Click **"Load Data"** to search.
***
## Update Rewards Balance
Once the User Data card loads:
1. Click the **edit button** next to the Rewards Balance field
2. Enter a new value:
* **Higher value** = increases the balance
* **Lower value** = decreases the balance
3. Click **save**
The system automatically calculates and applies the change.
Values display in **SATS** (for Bitcoin) or **POINTS** (for point-based currencies) depending on your project configuration.
***
## Related
* **[User Balance Overview](/rewards/sdk/user-balance)** - Retrieve balance via SDK
# Manage User Linking via Dashboard
Source: https://docs.zbdpay.com/earn/sdk/manage-user-linking
Link or unlink users to ZBD gamertags via the ZBD Dashboard
Manage user linking to ZBD gamertags through the ZBD Dashboard.
## Access
1. Go to [dashboard.zbdpay.com](https://dashboard.zbdpay.com)
2. Navigate to **SDK User Support** in the sidebar
## Search Users
Enter one of the following in the search field:
* **SDK User ID** → Loads user data directly
* **Support ID** → Shows list of users with that linked ID → select one
* **Gamertag** → Shows list of users with that gamertag → select one
Click **"Load Data"** to search.
***
## Link User to Gamertag
When no user is linked, you'll see **N/A** and a **Link button**.
1. Click the **Link button**
2. An input field appears
3. Enter the ZBD gamertag
4. Click **save** (green checkmark ✓) or **X** to cancel
After saving, the gamertag shows (instead of N/A) and the button changes to **Unlink**.
***
## Unlink User from Gamertag
When a user is linked, you'll see the **gamertag** and an **Unlink button**.
1. Click the **Unlink button**
2. The gamertag changes back to **N/A**
3. The button changes back to **Link**
***
## Related
* **[User Status Overview](/rewards/sdk/user-status)** - Retrieve user status via SDK
# Manage via Dashboard
Source: https://docs.zbdpay.com/earn/sdk/manage-via-dashboard
Create API keys and control reward settings from the ZBD Dashboard
Manage your Rewards App settings directly from the ZBD Dashboard.
## Access Your Project's SDK Settings
1. Go to [dashboard.zbdpay.com](https://dashboard.zbdpay.com)
2. Navigate to **Projects**
3. Select your project
4. Click the **SDK** tab
5. Click the **Controls** sub-tab
Your Rewards App settings will load automatically under **API Key Control** and **Client Send Control** sections.
If you see "No Rewards App found for this project", contact ZBD support to enable Rewards for your project by adding your project ID to the database.
***
## Create an API Key (Required)
To send rewards from your server, you need an API key for authentication.
### How to Create
1. In the SDK tab → Controls sub-tab, find the **API Key Control** section
2. Check the **Status** badge:
* 🔴 **Disabled** (red) with text "No active API key found" = No API key exists
* 🟢 **Enabled** (green) = API key is active
3. Click **"Create API Key"** button
4. **Click the copy button** next to the API key to copy it
5. **Save the API key in a secure place immediately** (environment variables, secrets manager, etc.)
The API key is shown only once after creation. If you lose it, you'll need to revoke it and create a new one.
**What you'll use it for:**
* Authenticating server-side reward sending requests
* Required for the [Send Rewards API](/rewards/sdk/send-rewards-api)
***
## Control Client-Side Sending (Recommended)
After creating your API key, you can disable client-side reward sending to enforce server-only rewards.
**Important**: You must create an API key first before disabling client-side sending. Without an API key, disabling client-side means no rewards can be sent at all.
### How to Disable Client-Side Sending
1. In the SDK tab, find the **Client Send Control** section
2. Check the **Status** badge:
* 🟢 **Enabled** (green) with text "Client sending is enabled" = Client can send rewards
* 🔴 **Disabled** (red) with text "Client sending is disabled" = Only server can send
3. Click **"Disable Client Send"** button to block client-side rewards
**What this does:**
* Blocks client SDK reward calls
* Only your server (with the API key) can send rewards
* Prevents client-side abuse
### How to Enable Client-Side Again
If you need to allow client-side rewards:
1. In the **Client Send Control** section, click **"Enable Client Send"**
2. Status will change to 🟢 **Enabled** (green)
3. Both client SDK and server can send rewards again
***
## Revoke an API Key
If your API key is compromised or no longer needed, revoke it immediately.
### How to Revoke
1. In the SDK tab, find the **API Key Control** section
2. Make sure the Status is 🟢 **Enabled** (green)
3. Click **"Revoke Key"** button
4. Confirm the action in the dialog
**After revoking:**
* The key is immediately deactivated
* Status changes to 🔴 **Disabled** (red) with "No active API key found"
* Server requests using this key will fail
* Create a new API key if you need to continue sending rewards
***
## Next Steps
Now that you've created your API key and configured your settings, you're ready to send rewards from your server:
* **[Send Rewards from Server](/rewards/sdk/send-rewards-api)** - Use your API key to send rewards securely
# Manage Withdrawal Limits via Dashboard
Source: https://docs.zbdpay.com/earn/sdk/manage-withdrawal-limits
Increase or decrease user withdrawal limits via the ZBD Dashboard
Manage user withdrawal limits through the ZBD Dashboard.
## Access
1. Go to [dashboard.zbdpay.com](https://dashboard.zbdpay.com)
2. Navigate to **SDK User Support** in the sidebar
## Search Users
Enter one of the following in the search field:
* **SDK User ID** → Loads user data directly
* **Support ID** → Shows list of users with that linked ID → select one
* **Gamertag** → Shows list of users with that gamertag → select one
Click **"Load Data"** to search.
***
## Update Withdrawal Limit
Once the User Data card loads:
1. Click the **edit button** next to the Withdrawal Limit field
2. Enter a new value:
* **Higher value** = increases the limit
* **Lower value** = decreases the limit
3. Click **save**
The system automatically calculates and applies the change.
Values display in **SATS** (for Bitcoin) or **POINTS** (for point-based currencies) depending on your project configuration.
***
## Related
* **[Withdrawal Limits Overview](/rewards/sdk/user-withdrawal)** - Retrieve limits via SDK
# Revenue-Based Earning
Source: https://docs.zbdpay.com/earn/sdk/revenue-based-earning
Tie a user's earning potential to the revenue they generate for your app.
## Overview
With the ZBD Earn SDK, a user's ability to withdraw rewards is tied to the value they generate for your app. Rather than letting users earn unlimited rewards, withdrawal limits act as a cap that scales with revenue — whether that's from ad impressions, in-app purchases, or time spent engaging with your app.
This keeps your reward economy sustainable: users only withdraw what they've helped you earn.
## How It Works Automatically
When the ZBD Earn SDK is active on the client, the device pings the server every 20 seconds. Based on the reward schedule configured for your app, the player's withdrawal limit automatically increases every minute by a set amount.
This time-based model works as a rough proxy for revenue — the longer a user is engaged, the more ad impressions and in-app interactions they likely generate, and the more they can withdraw. However, this is a crude estimation. Engagement time doesn't always correlate directly with revenue — a user could be active for a long time without watching ads or making purchases.
For more precise control, use the server-side API to [increase withdrawal limits based on actual revenue events](#increasing-limits-based-on-actual-revenue).
The reward schedule and per-minute increase amount are configured by your ZBD Customer Success Manager.
## Increasing Limits Based on Actual Revenue
The automatic time-based increase covers most cases, but you may want to increase a user's withdrawal limit based on confirmed revenue events from your server. For example:
* An **MMP callback** confirms an ad impression or completed ad view
* A validated **in-app purchase receipt** confirms the user spent money
* Any other server-side event where a user directly monetized for you
When you receive one of these events, call the withdrawal limit API to increase the user's limit accordingly:
```bash Bitcoin (sats) theme={null}
curl --request POST \
--url https://api.zbdpay.com/api/v1/rewards/user//withdrawal-limit \
--header 'Content-Type: application/json' \
--header 'x-api-key: ' \
--data '{
"amount": 5000,
"currency": "MSATS"
}'
```
```bash Points theme={null}
curl --request POST \
--url https://api.zbdpay.com/api/v1/rewards/user//withdrawal-limit \
--header 'Content-Type: application/json' \
--header 'x-api-key: ' \
--data '{
"amount": 5000,
"currency": "POINT"
}'
```
This gives you precise control — users who monetize more can withdraw more.
## Recommended Revenue Share
As a starting point, we recommend giving **10-20% of your ad-generated revenue** back to players through rewards. The exact sweet spot varies by game and geography.
Some partners go deeper and set reward amounts per user based on how much that specific user is earning them. As a simpler starting point, you can take the LTV for each country you're live in and give out a percentage based on the player's location.
For more detail on structuring your reward economy, see the [Introduction to Rewarded Play](/earn/knowledge-base/rewarded-play) guide.
## Best Practices
* **Keep earn rate aligned with withdrawal capacity.** Avoid situations where users earn significantly more than they can withdraw — this leads to frustration. For example, crediting 1,000 sats but only allowing 100 sats to be withdrawn is a poor experience.
* **Scale difficulty over time.** Make early rewards easy to earn, then gradually slow down progression as the session continues.
* **Check limits before rewarding.** Use `ZBDController.Instance.GetBalance` to retrieve the user's current balance and withdrawal cap, and adjust your reward flow based on this data.
* **Use revenue events to boost limits.** When a user watches a rewarded ad or makes an in-app purchase, increase their withdrawal limit from your server to reflect the value they generated.
# Security
Source: https://docs.zbdpay.com/earn/sdk/security
Security features and best practices for the ZBD Earn SDK.
It’s important to explain the security assumptions of the SDK and to reiterate that no game is 100% secure—especially when real-money rewards are involved.
If you do not call the **`SendReward`** endpoint from your own backend server, it must be called from the client, which exposes it to abuse. A malicious attacker could potentially call this endpoint multiple times to reward themselves the maximum amount of Bitcoin.
To mitigate this, **we limit how much a user can withdraw based on how long their device has been online.**
For example, a user may attempt to reward themselves 10,000 sats, but they will only be able to withdraw 2 sats per 5 minutes of "Time Alive", effectively slowing down withdrawals to prevent farming.
# Time Alive
When your app/game is open, the SDK sends a “ping” to the ZBD backend roughly every 20 seconds. This allows the SDK to calculate how long it has been online in a way that cannot be easily spoofed.
Additionally, we use Apple and Google attestation systems to verify that the device is genuine and is running a non-rooted and non-jailbroken OS.
This further restricts malicious users, as they are only able to withdraw a maximum of **X sats every Y minutes per Z real devices**.
However, a more sophisticated operation may involve hundreds of genuine devices kept online in an attempt to farm rewards while passing attestation checks.
To help mitigate this, we can toggle additional verification steps such as CAPTCHAs or facial recognition at the point of withdrawal. We also monitor network and IP address activity —- but none of these measures are foolproof. A determined attacker may still find ways to bypass them.
This is why we **strongly recommend (almost require) calling the `SendReward` method from your own secure backend servers** and providing us with the IP address of that server, so we can restrict access to only trusted sources.
# Attestation
In order to make sure we have everything we need to detect your app/game has not been tampered with as part of our attestation check, we require a couple of pieces of information.
### Android
For Android we need your Bundle ID or package name i.e. `com.domain.appname` -- this is what you set in your Unity build settings.
We also need the SHA256 hash of your app signing key.
To find your app's SHA256 hash key for Google Play:
Find the `App signing key certificate` section and copy the SHA-256 fingerprint.
For development purposes you can generate a SHA256 hash key for your keystore using the following command:
```bash theme={null}
keytool -list -v -keystore path/to/your.keystore -alias your_alias -storepass your_keystore_password -keypass your_key
```
It should look something like this
```bash theme={null}
EA:A1:69:AA:2F:FC:6D:16:84:ED:06:11:E0:65:2B:E0:BB:9C:5B:E3:41:96:06:E2:3D:85:8F:2C:22:2A:E9:86
```
### iOS
For iOS we need your Bundle ID (`com.domain.appname`) and your Team ID.
To find your app's Team ID:
Copy the code from the `Team ID` section.
# Send Rewards from Server
Source: https://docs.zbdpay.com/earn/sdk/send-rewards-api
POST https://api.zbdpay.com/api/v2/rewards/limited-achievement/reward
Use your API key to send rewards securely from your backend using the Earn API (v2).
Send rewards securely from your backend using the **ZBD Earn API (v2)**.
This method ensures all rewards are issued from a trusted environment, preventing client-side abuse and maintaining full control over reward distribution.
Reward Unit Configuration. The reward unit (e.g., 1 satoshi or \$0.10) is defined for your game by your ZBD Customer Success Manager.
## Configuration
### Header Parameters
API key used for authentication. Obtain this from the **Create an API Key** step.
### Body Parameters
The recipient's ZBD Rewards User ID
Reward amount in configured units
Example: `10` (units defined by your ZBD Customer Success Manager)
```json 201 - Success theme={null}
{
"success": true,
"message": "Success.",
"data": [
{
"transactionId": "f7553b31-5ae2-43bf-a200-c0a966e94071"
}
]
}
```
### Response Status Codes
| Code | Description |
| ----- | ----------------------------------------- |
| `201` | Reward sent successfully |
| `400` | Bad request – invalid parameters |
| `401` | Unauthorized – invalid or missing API key |
| `404` | Rewards user not found |
| `500` | Internal server error |
```json 400 - Bad Request theme={null}
{
"success": false,
"message": "Invalid parameters"
}
```
```json 401 - Unauthorized theme={null}
{
"success": false,
"message": "Invalid or missing API key"
}
```
```json 404 - User Not Found theme={null}
{
"success": false,
"message": "Rewards user not found"
}
```
```json 500 - Server Error theme={null}
{
"success": false,
"message": "Internal server error"
}
```
## Response Fields
| Field | Type | Description |
| --------------- | ------- | ------------------------------------ |
| `success` | boolean | Whether the request was successful |
| `message` | string | Response message |
| `data` | array | Array containing transaction details |
| `transactionId` | string | Unique transaction identifier |
***
Security Reminder, Never expose your API key in client-side code. Always send rewards from your backend server where your API key is securely stored.
## Code Examples
```javascript Node.js theme={null}
const apiKey = process.env.REWARDS_API_KEY;
async function sendReward(rewardsUserId, amount) {
const response = await fetch('https://api.zbdpay.com/api/v2/rewards/limited-achievement/reward', {
method: 'POST',
headers: {
'x-api-key': apiKey
},
body: JSON.stringify({
rewardsUserId,
amount
})
});
const data = await response.json();
if (data.success) {
console.log(`Reward sent! Transaction ID: ${data.data[0].transactionId}`);
return data.data[0];
} else {
throw new Error(`Failed to send reward: ${data.message}`);
}
}
// Example: Send 10 reward units
await sendReward('f2154d1a-67e6-46f2-b293-b4b226948dc9', 10);
```
```bash cURL theme={null}
curl --location 'https://api.zbdpay.com/api/v2/rewards/limited-achievement/reward' \
--header 'x-api-key: sdk_live_c21cfd2f98762456cac1729925be494d431c7c08127953c2434f39899c073aa6' \
--data '{
"rewardsUserId": "f2154d1a-67e6-46f2-b293-b4b226948dc9",
"amount": 10
}'
```
```python Python theme={null}
import requests
import os
api_key = os.getenv('REWARDS_API_KEY')
def send_reward(rewards_user_id, amount):
"""Send a reward to a user from your server"""
url = "https://api.zbdpay.com/api/v2/rewards/limited-achievement/reward"
headers = {
"x-api-key": api_key
}
payload = {
"rewardsUserId": rewards_user_id,
"amount": amount
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data["success"]:
print(f"Reward sent! TX ID: {data['data'][0]['transactionId']}")
return data["data"][0]
else:
raise Exception(f"Failed: {data['message']}")
# Example usage
send_reward("f2154d1a-67e6-46f2-b293-b4b226948dc9", 10)
```
## Try It Out
Ready to send your first reward from the server? Use our API playground on the right to test with your API key.
# Send Rewards (Client)
Source: https://docs.zbdpay.com/earn/sdk/send-rewards-client
Instructions for sending rewards to users directly from the client using the ZBD Earn SDK.
# Reward Unit
In the ZBD Earn SDK, rewards are sent as **units**. A **unit** is a **configurable value** determined by your ZBD Customer Success Manager and can represent different amounts, such as **1 satoshi** or **\$0.10**.
For example, if the game is configured so that **1 unit = 1 satoshi**, sending 1 reward will send 1 satoshi. Conversely, if the game is set up so that **1 unit = \$0.10**, sending 1 reward will send the equivalent of \$0.10 in satoshis.
**Your games config** could also be set up so that **a unit would represent a point in your game**, e.g. sending **1 unit** would send **1 "Gem"** which is worth **\$0.10**.
# Sending Rewards
To send a reward to a user you can call:
```csharp theme={null}
ZBDController.Instance.SendReward(1, callback =>
{
if (callback.success)
{
// reward sent
}
else if (callback.maintenance)
{
// Platform is in maintenance mode
Debug.Log("Rewards are temporarily unavailable. Please try again later.");
}
else
{
Debug.LogError("send reward error " + callback.message);
}
});
```
The `SendReward` response object contains the following fields:
```csharp theme={null}
public class ZBDSendRewardResponse
{
public bool success;
public string message;
public bool needsAuthentication;
public bool maintenance;
public ZBDTransactionData[] data;
}
```
Maintenance mode can start while players are actively in a session. Even if `Init` succeeded normally, `SendReward` can return `maintenance = true` at any point during gameplay. Always check the `maintenance` flag on every reward call and display a user-friendly message when it is active. Do not queue or retry rewards during maintenance.
See [Handling Maintenance Mode](/earn/sdk/integration#handling-maintenance-mode) for the full list of affected methods.
For enhanced security and validation, we recommend handling reward distribution from your backend server.
You can learn how to set this up in the **[Server Rewards Overview section](/earn/sdk/send-rewards-server)**
# Overview
Source: https://docs.zbdpay.com/earn/sdk/send-rewards-server
Learn how to securely send rewards from your server using the ZBD Earn API.
The ZBD Earn API allows developers to send in-game or app-based rewards to users securely.
By default, rewards can be issued from **both the client SDK** and your **backend server**.
For stronger security and better control, you can restrict reward sending so that **only your backend** can issue rewards.
This setup uses the **API version blocklist** feature for your Rewards App.
Server-only reward sending is recommended when:
* You perform additional gameplay or business validation before issuing rewards
* Your app offers higher-value rewards or gift card redemptions
* You want to minimize client-side abuse and enforce strict control
## Rate Limiting
The server-side endpoints are rate-limited to **60 requests per second**.
If you exceed this limit, you will receive a `429 Too Many Requests` response. Implement exponential backoff in your retry logic to handle rate limiting gracefully.
## How It Works
Go to Dashboard → Projects → Select Your Project → SDK tab → Controls sub-tab.
Your Rewards App settings will load automatically.
Click "Create API Key" in the dashboard and save it securely.
**Required** for server-side authentication. The key is shown only once.
Click "Disable Client Send" to block client-side reward sending.
Ensures only your server can send rewards. Recommended for security.
Use your API key with the send rewards endpoint to issue rewards securely.
Next, let's begin with **[managing your Rewards App via the dashboard](/earn/sdk/manage-via-dashboard)**, where you'll create your API key and configure your settings.
# Troubleshooting
Source: https://docs.zbdpay.com/earn/sdk/troubleshoot
General troubleshooting guides for the ZBD Earn SDK.
# Build Issues
* If you encounter build issues, it is important to check that the Android and iOS deployment targets and minimum API level are set properly. Refer to [Compatibility](/earn/sdk/compatibility) for more information.
* If you receive a sign up error, please confirm that your Bundle ID / Package Name is the same as the one used whilst setting up the SDK configuration.
* Make sure the stripping level is set to low or minimum in the Unity build settings.
If you get the following build errors on Android please check the **[Building for Android](/earn/sdk/building#building-for-android)** section.
# Performance Issues
The ZBD Earn SDK forces hardware acceleration in Android builds, this can cause some issues with games.
If you notice performance issues after integrating the ZBD Earn SDK you can delete the `ModifyUnityAndroidAppManifestSample.cs` file in the `Assets/Editor/` folder.
# Unity Input Settings Issues
To ensure maximum compatibility when working with the ZBD Earn SDK, it is recommended to adjust Unity’s input configuration.
The Unity Editor’s WebView may influence how input is handled, so setting **Active Input Handling** to **Both** helps maintain consistent support across the Old Input Manager and the New Input System.
In Unity, go to Edit → Project Settings.
In the Project Settings window, select Player, then scroll to the Other Settings section.
Find Active Input Handling and set it to Both — regardless of whether your project uses the Old Input Manager or the New Input System.
# Testing from an Unsupported Region or Unity Editor
If your game is configured to reward players only in specific regions, but you as a developer are located outside of those regions, or if you are testing directly in the Unity Editor, you may run into issues with the SDK's anti-fraud system.
The anti-fraud system may block sign-ups or gameplay from the Unity Editor or from unsupported regions. To work around this during development and testing:
Connect to a VPN set to one of your game's supported regions and sign up for a ZBD account from within the game. This ensures your account is created in a supported region.
Signing up through a VPN may place your account in **limited earnings mode**. This is expected behavior from the anti-fraud system.
Your Support ID is logged to the console when the SDK is initialized. Look for the following log entry:
```
ZBD: SupportId:
```
To remove the limited earnings restriction, you have two options:
* **Contact your ZBD account manager** — Send them your Support ID so they can whitelist your device.
* **Use the Developer Dashboard** — If you have been granted access to the device whitelisting feature, you can whitelist your device directly from the dashboard.
This process is only necessary for development and testing purposes. Your end users in supported regions will not encounter these restrictions during normal gameplay.
# Integrity Check Failures
If you receive either of the following errors:
```
{"success":false,"message":"Failed progress validation.","errorCode":"400P4V"}
```
```
ZBD: Error sending reward: {"success":false,"message":"Failed reward validation.","errorCode":"400R5V"}
```
This means your editor or device is failing ZBD's integrity checks. This typically happens because:
* You are testing from a **non-mobile device** (e.g. Unity Editor on desktop) rather than a real mobile device.
* Your **attestation has not been set up** correctly. Refer to the [Attestation Setup](/earn/sdk/attestation-setup) guide.
To resolve this, contact your ZBD account manager and provide your **Support ID** so they can whitelist it. You can find your Support ID in the console logs when the SDK initializes:
```
ZBD: SupportId:
```
# URL Scheme
Source: https://docs.zbdpay.com/earn/sdk/url-scheme
Handle secure user redirection back to your app after ZBD OAuth login using a custom URL scheme.
To enable the ZBD app to redirect back to your game after the user connects via the ZBD app,we need to know your game's URL scheme.
If you’ve already set this up, please share it with your ZBD contact.
If this is your first time setting it up, don’t worry. The process is straightforward for both iOS and Android.
## In Unity:
If you’ve already added the custom URL scheme to your Android Manifest (AndroidManifest.xml) or iOS plist file, leave the field empty.
# User Balance via SDK
Source: https://docs.zbdpay.com/earn/sdk/user-balance
Retrieve user balance via SDK and manage it via dashboard
## Retrieving User Balance via SDK
Use the `GetBalance` SDK method to retrieve a user's current balance from your client application.
### Implementation
```csharp theme={null}
ZBDController.Instance.GetBalance(callback =>
{
if (callback.success)
{
// User's balance in satoshis (not millisatoshis)
Debug.Log(callback.balance);
}
else if (callback.maintenance)
{
// Platform is in maintenance mode
Debug.Log("Balance is temporarily unavailable. Please try again later.");
}
else
{
Debug.LogError("Get balance error: " + callback.message);
}
});
```
The balance represents the user's current rewards available for withdrawal.
The `maintenance` flag can return `true` at any point, including mid-session. When active, display a user-friendly message instead of the balance. See [Handling Maintenance Mode](/earn/sdk/integration#handling-maintenance-mode) for more details.
***
## Managing Rewards Balance
To increase or decrease user rewards balance, use the dashboard: **[Manage Rewards Balance via Dashboard](/earn/sdk/manage-rewards-balance)**
# User Status via SDK
Source: https://docs.zbdpay.com/earn/sdk/user-status
Retrieve user status via SDK and manage linking via dashboard
## Retrieving User Status via SDK
Use the `GetUserStatus` method to retrieve a user's current linked status from your client application.
### Implementation
```csharp theme={null}
ZBDUtilities.Instance.GetUserStatus(callback =>
{
if (callback.success)
{
Debug.Log("User status: " + callback.data.status);
if (callback.data.status == ZBDConstants.ZBD_LINKED_STATUS)
{
Debug.Log("User is ZBD linked");
}
}
else
{
Debug.LogError("User status error: " + callback.message);
}
});
```
### Response Object
This returns a `ZBDUserStatusResponse` object:
```csharp theme={null}
public class ZBDUserStatusResponse
{
public bool success { get; set; }
public string message { get; set; }
public ZBDUserStatus data { get; set; }
}
public class ZBDUserStatus
{
public string status { get; set; } // User's linked status
public string rewardsUserId { get; set; } // User's SDK ID
public string zbdUserId { get; set; } // User's ZBD ID
}
```
### Status Types
The `status` parameter can be:
* **`unlinked`**: User has not signed up for rewards (hasn't clicked Start Earning)
* **`linked`**: User has signed up for rewards (clicked Start Earning)
* **`zbdlinked`**: User has signed up and linked their ZBD account
***
## Managing User Linking
To link or unlink users to ZBD gamertags, use the dashboard: **[Manage User Linking via Dashboard](/earn/sdk/manage-user-linking)**
# Withdrawal Limits
Source: https://docs.zbdpay.com/earn/sdk/user-withdrawal
Retrieve user withdrawal limits via SDK and manage them via dashboard
## Retrieving Withdrawal Limit via SDK
Use the `GetBalance` SDK method to retrieve a user's current withdrawal limit from your client application.
### Implementation
```csharp theme={null}
ZBDController.Instance.GetBalance(callback =>
{
if (callback.success)
{
// Withdrawal limit in satoshis (not millisatoshis)
long withdrawalLimitSats = callback.withdrawalLimit;
Debug.Log($"Withdrawal limit: {withdrawalLimitSats} sats");
}
else
{
Debug.LogError($"GetBalance failed: {callback.message}");
}
});
```
The withdrawal limit is included in the callback response along with the user's current balance.
***
## Managing Withdrawal Limits
To increase or decrease user withdrawal limits, use the dashboard: **[Manage Withdrawal Limits via Dashboard](/earn/sdk/manage-withdrawal-limits)**
# Walkthrough
Source: https://docs.zbdpay.com/earn/sdk/video-walkthrough
Video instructions for integrating the ZBD Earn SDK into your Unity project.
# Withdrawal Limits (Server)
Source: https://docs.zbdpay.com/earn/sdk/withdrawal-limits
Understand how withdrawal limits work and how to increase them from your server.
## How Withdrawal Limits Work
When the ZBD Earn SDK is active on the client, the device pings the server every 20 seconds. Depending on the reward schedule configured for your app, this automatically increases the player's withdrawal limit every minute by a set amount.
## Increase Withdrawal Limit from Server
You may want to increase a user's withdrawal limit by a fixed amount at any time from your server. For example, if you receive a callback from your MMP or an in-app purchase receipt confirming that a user monetized, you can increase their withdrawal limit accordingly.
```bash Bitcoin (sats) theme={null}
curl --request POST \
--url https://api.zbdpay.com/api/v1/rewards/user//withdrawal-limit \
--header 'Content-Type: application/json' \
--header 'x-api-key: ' \
--data '{
"amount": 5000,
"currency": "MSATS"
}'
```
```bash Points theme={null}
curl --request POST \
--url https://api.zbdpay.com/api/v1/rewards/user//withdrawal-limit \
--header 'Content-Type: application/json' \
--header 'x-api-key: ' \
--data '{
"amount": 5000,
"currency": "POINT"
}'
```
# ZBD Documentation
Source: https://docs.zbdpay.com/get-started
Global Payment Service Provider for Gaming and Interactive Entertainment
The global payment infrastructure built for the speed and scale of gaming. Process thousands of transactions per second, enable true micropayments, and unlock new monetization models – all through a single API.
Lightning-fast global settlements that keep pace with gameplay
Finally make 1 cent transactions profitable with fees under \$0.0001
One API for global payments. No banking relationships needed.
## Why Developers Choose ZBD
**Built for Gaming Scale**
* Handle millions of transactions for players
* Microtransactions that actually make economical sense
**New Monetization Models**
* Pay-per-minute gameplay
* Real-money tournaments
* Cross-game economies
* Player-to-player trading
**Modern Payment Infrastructure**
* Instant global settlements
* Multi-currency support (USD, EUR, BTC)
* Developer-first APIs
**Use Cases**
* Streaming payments
* Creator economy
* International payouts
**Increase Revenue**
* Higher conversion with lower payment friction
* Unlock previously unprofitable price points
* Expand to Tier 1 global markets compliantly instantly
**Reduce Costs**
* 90% lower fees than cards for small payments
* Eliminate chargeback losses
## Products
### 🎮 ZBD Earn
Drive user engagement, boost retention, and unlock new revenue streams by offering real-money rewards and incentives across your experiences.
Unity SDK for adding real-money rewards to your games. Drag, drop, monetize.
Programmatically distribute rewards. Perfect for tournaments and achievements.
OAuth2 authentication with built-in wallet creation and KYC.
ZBD app for players to manage and cash out rewards.
### 💳 Payments
Enable instant global payments in your apps and games with multi-currency support for Bitcoin, Lightning Network, USD, EUR and Stablecoins. We handle the complexity of payments infrastructure so you can focus on building amazing experiences.
Let users buy Bitcoin directly in your app. First widget with Lightning Address support.
Send and receive instant payments globally. Lightning, on-chain, and fiat settlements.
Production-ready SDK with TypeScript examples and starter templates.
Enable AI agents and LLMs to process payments autonomously.
Getting started with ZBD Payments is as simple as:
```bash TypeScript / Node.js theme={null}
pnpm install @zbdpay/payments-sdk
```
```bash Rust theme={null}
cargo add zebedee-rust
```
```bash HTTP theme={null}
curl -X GET https://api.zbdpay.com/v0/wallet \
-H "apikey: YOUR_API_KEY"
```
## Quick Start Guides
[Schedule a 15-minute call](https://zbd.one/sales) with our team to discuss your use case and get access
Pick the products that fit your needs - Payments, Rewards, or both
Use our comprehensive documentation and SDKs to integrate in hours, not weeks
Go live with production access and our team's support
### Start with These Guides
Send your first payment in minutes
Add fiat-to-crypto in your app
Monetize your Unity game
## Developer Resources
Complete API documentation with examples
TypeScript, Go, Rust, C# and more
## Ready to Transform Your Payment Experience?
**Schedule a Demo** - Talk to our team about your use case and get your API keys. Most developers are up and running within 24 hours.
# Add Funds to your Account
Source: https://docs.zbdpay.com/get-started/add-funds
Fund your ZBD wallet to start processing instant global payments
Your ZBD wallet is the heart of your payment operations. Add funds in seconds and start moving money at the speed of the internet. Multiple funding options ensure you can always keep your wallet topped up.
**Lightning Speed** - Deposits via Lightning Network are instant. As soon as you send funds, they're available in your wallet. No waiting for confirmations.
## Funding Options
Instant deposits from any Lightning wallet or exchange
USD to Lightning coming soon via ZBD Ramp
## Lightning Deposits (Instant)
The fastest way to add funds. Generate an invoice and pay from any Lightning-enabled service.
### How to Generate a Lightning Invoice
Go to your project's Wallet tab in the dashboard
Select "Lightning Invoice" as your deposit method
Specify how many satoshis you want to add
Scan QR code or copy invoice to pay from another Lightning-compatible wallet
## Fiat Ramp (Coming Soon)
**Direct USD Deposits** - Soon you'll be able to buy Bitcoin directly in the Developer Dashboard using ACH bank transfers. Funds will arrive instantly at your project's Lightning address.
### What to Expect
* **Bank Transfer** - Connect your business bank account
* **Instant Conversion** - USD → Bitcoin → Your wallet
* **Competitive Rates** - Better than most exchanges
* **No External Accounts** - Everything within ZBD
Want early access to fiat deposits? [Talk to your success manager](https://zbd.one/sales).
## Welcome Vouchers
New to ZBD? Your Customer Success Manager can provide welcome vouchers to help you get started.
### How It Works
Mention you'd like to test the platform
Get an 8-character code via email
Go to Vouchers and enter code
Use funds to test integrations
### Best Practices
Keep 20% extra for payment spikes
Monitor low balance thresholds
**Contact Support** - Our team can guide you through the funding process and recommend the best approach for your use case.
# API Keys
Source: https://docs.zbdpay.com/get-started/api-keys
Generate and secure your keys to unlock Lightning-fast payments
API keys are your passport to the ZBD platform. With a single key, you can send payments globally, create invoices, manage wallets, and build the future of digital payments.
**Security First** - API keys are server-side only and grant full access to your project's wallet. Never expose them in client-side code, mobile apps, or public repositories.
## Your First API Key
Navigate to your project's **API** tab to view and manage your API keys.
### What You Can Do With API Keys
Pay any Lightning Address or invoice instantly
Generate invoices and process incoming payments
Check balances and transaction history
Issue redeemable payment links
## Quick Start Example
Once you have your API key, you're ready to send your first payment:
```bash cURL theme={null}
curl -X POST https://api.zbdpay.com/v0/payments \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": "1000",
"description": "First payment!",
"internalId": "test-001",
"callbackUrl": "https://myapp.com/webhook"
}'
```
```javascript Node.js theme={null}
const payment = await fetch('https://api.zbdpay.com/v0/payments', {
method: 'POST',
headers: {
'apikey': process.env.ZBD_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: '1000',
description: 'First payment!',
internalId: 'test-001'
})
});
```
## Security Best Practices
### 🔐 Secure Storage
```bash theme={null}
# .env file (never commit this!)
ZBD_API_KEY=your_api_key_here
# Access in code
const apiKey = process.env.ZBD_API_KEY;
```
**Best for**: Local development and deployment platforms
Use dedicated secret management services:
* **AWS Secrets Manager**
* **Google Secret Manager**
* **HashiCorp Vault**
* **Azure Key Vault**
**Best for**: Production environments
Configure secrets in your deployment pipeline:
* **GitHub Actions**: Repository secrets
* **Vercel**: Environment variables
* **Heroku**: Config vars
* **Docker**: Build secrets
**Best for**: Automated deployments
### 🛡️ IP Allowlisting
Restrict API access to specific IP addresses for maximum security:
**How to Configure:**
1. Navigate to your project's API tab
2. Click "API Access Controls"
3. Add your server's IP addresses
4. Save changes
**Dynamic IPs?** If your infrastructure uses dynamic IPs (like serverless functions), consider using a proxy service with static IPs or contact our team for alternative security options.
## Key Rotation & Regeneration
Regular key rotation is a security best practice. Here's when and how to do it:
### When to Rotate Keys
* ⏰ **Scheduled**: Every 90 days as a best practice
* 🚨 **Immediately if**:
* Key exposed in client code
* Committed to version control
* Employee with access leaves
* Suspicious activity detected
### How to Regenerate
**Important**: Regenerating creates a new key and immediately disables the old one. Update your applications before regenerating to avoid downtime.
### Zero-Downtime Rotation Strategy
Schedule during low-traffic period
Test new key in staging environment
Update production with new key
Once deployed, regenerate in dashboard
Watch logs for any failed authentications
## API Key Permissions (Coming Soon)
**Scoped Permissions** - Soon you'll be able to create keys with limited permissions:
* Read-only keys for analytics
* Payment-only keys for point-of-sale
* Receive-only keys for donation pages
## Testing Your API Key
Use this simple test to verify your key is working:
```bash cURL theme={null}
curl https://api.zbdpay.com/v0/wallet \
-H "apikey: YOUR_API_KEY"
```
```javascript Node.js theme={null}
// Quick test script
const testApiKey = async () => {
const response = await fetch('https://api.zbdpay.com/v0/wallet', {
headers: { 'apikey': process.env.ZBD_API_KEY }
});
if (response.ok) {
console.log('✅ API key is valid!');
const wallet = await response.json();
console.log('Balance:', wallet.data.balance, 'sats');
} else {
console.error('❌ API key test failed:', response.status);
}
};
testApiKey();
```
## Ready to Build?
You now have everything needed to start integrating ZBD payments into your application.
Use our SDKs to send your first Lightning payment
Explore all available endpoints
# Create Account
Source: https://docs.zbdpay.com/get-started/create-account
Get started with ZBD in minutes
Creating a ZBD account gives you access to the most advanced payment infrastructure in gaming. Here's how to get started.
## Before You Begin
**Business Account Required** - ZBD is designed for businesses, game studios, and professional developers. You'll need to complete business verification (KYB) to access production features.
### What You'll Need
* Company name and website
* Business registration details
* Tax ID / EIN (US) or equivalent
* UBO (if applicable)
* Your work email address
* Phone number
* Your role at the company
## Account Creation Process
### Step 1: Schedule Your Onboarding Call
**Required First Step** - Our team will guide you through the onboarding process and ensure ZBD is the right fit for your needs. Schedule a quick 15-minute call to get started.
During the call, we'll discuss:
* Your use case and integration needs
* Pricing based on your expected volume
* Compliance requirements for your region
* Timeline to get you live
### Step 2: Create Your Account
After your sales call, you'll receive an invitation to create your account.
1. **Access the Dashboard** - Use the link provided by our team
2. **Enter Your Information** - Fill in your user details
3. **Set a Strong Password** - Must include uppercase, lowercase, numbers, and symbols
4. **Accept Terms** - Review and accept our Terms of Service
### Step 3: Verify Your Email
Check your inbox for a 6-digit verification code.
Verification codes expire after 10 minutes. If yours expires, you can request a new one.
### Step 4: Complete Business Verification
After email verification, you'll be guided through our KYB (Know Your Business) process:
Provide company registration documents
Verify business ownership structure
Describe your intended use of ZBD
**Verification Timeline**: Most businesses are verified within 24 hours. Complex cases may take 2-3 business days.
## After Account Creation
Once verified, you'll have access to:
Set up your first project and get API keys
Fund your wallet to start processing payments
Start integrating with our quickstart guides
## Ready to Transform Your Payments?
**Schedule Your Onboarding Call** - Join thousands of developers building the future of digital payments. Our team is ready to help you get started.
# Create Project
Source: https://docs.zbdpay.com/get-started/create-project
Set up your first ZBD project and unlock the power of Lightning payments
Projects are your gateway to the future of payments. Each project gets its own Lightning wallet, API keys, and analytics – everything you need to integrate ZBD into your app or game.
**One Account, Multiple Projects** - Create separate projects for different apps, environments, or business units. Each project has isolated wallets and permissions.
## Why Projects Matter
Each project has its own Bitcoin Lightning wallet with separate balances
Get your API key per project with specific permissions
Track performance metrics per project independently
## Creating Your First Project
### Step 1: Navigate to Projects
From your dashboard, click **Projects** in the sidebar and then the **+ New Project** button.
### Step 2: Configure Your Project
Fill in your project details in the creation modal:
### Step 3: Create and Explore
Click **Create Project** and you will be redirected to your new project's wallet page.
## What Happens Next
Once your project is created, you instantly get:
A programmable Bitcoin Lightning wallet ready for instant global payments
Head to the API Keys tab to generate your first key
Use our SDKs to send your first payment in minutes
## Project Best Practices
### Environment Strategy
Create separate projects for each environment:
* **MyGame - Development**: Sandbox testing with test transactions
* **MyGame - Staging**: Pre-production testing with real money
* **MyGame - Production**: Live environment for real users
This separation ensures clean analytics and prevents accidental transactions.
Organize projects by application:
* **Mobile Game**: iOS and Android API keys sharing one wallet
* **Web Platform**: Separate wallet with frontend/backend keys
* **Tournament System**: Isolated wallet for prize pools
Each app gets its own analytics and wallet management.
### Common Use Cases
* **Separate projects per game** for isolated economies
* **Shared project for tournaments** across multiple games
* **Dev/staging/prod projects** for each game
* **API product project** for usage-based billing
* **Marketplace project** for user-to-user payments
* **Regional projects** for compliance separation
* **Client projects** with isolated wallets
* **Demo project** for POCs and sales
* **Template projects** for quick starts
## Quick Actions After Creation
Generate your first API key to start integrating
Add funds to start processing payments
Use our SDK to send your first Lightning payment
## Success! You have Created Your First Project 🎉
You are now ready to revolutionize payments in your application. Your Lightning wallet is active and waiting for its first transaction.
**Generate Your API Keys** - Get your API credentials and send your first payment in under 5 minutes.
***
Quick start guides for all languages
Explore all available endpoints
# Developer Dashboard
Source: https://docs.zbdpay.com/get-started/dev-dashboard
Your command center for global payments and real-money rewards
The ZBD Developer Dashboard is where you manage everything – from API keys to real-time analytics. One dashboard to power payments across your entire platform.
## What You Get
Create multiple projects with isolated wallets and API keys
Track transactions, volumes, and user activity live
Generate and manage API keys to control the Project Wallet
Programmable Lightning wallets with instant settlement
Sandbox environment and testing utilities
KYB verification and transaction monitoring included
## Dashboard Features
### 🚀 Quick Actions
* **Send Payments** - Pay any Lightning Address instantly
* **Create Charges** - Generate payment requests with QR codes
* **Issue Vouchers** - Create redeemable payment links
* **Download Reports** - Export transaction data
### 🔧 Developer Tools
* API playground for testing endpoints
* Webhook management and logs
* SDK quick-start guides
* Code examples in multiple languages
## Who Uses the Dashboard?
**Power Your Game Economy**
* Manage in-game currencies and rewards
* Track player transactions in real-time
* Set up tournament prize pools
* Monitor cross-game economies
**Scale Global Payments**
* Multi-project support for different products
* Compliance and regulatory tools built-in
* White-label payment solutions
* Enterprise-grade reliability
Perfect for payment providers serving multiple markets
**Monetize Anything**
* Add payments to any app in minutes
* Usage-based billing for APIs
* Creator monetization tools
* Micropayment capabilities
From social apps to productivity tools
## Getting Access
ZBD requires business verification to ensure platform security and compliance. Individual developers can explore our documentation while preparing for business onboarding.
[Talk to our sales team](https://zbd.one/sales) about your use case
Quick business verification process (usually same day)
Receive your credentials and start building
## What's Next?
Step-by-step account creation guide
Set up your first project and get API keys
**Schedule a Demo** - See the dashboard in action and get your access. Most businesses are verified within 24 hours.
# Login with ZBD
Source: https://docs.zbdpay.com/get-started/login-with-zbd
# Manage Project
Source: https://docs.zbdpay.com/get-started/manage-project
Edit project settings, manage access, and control your project lifecycle
Keep your projects organized and up-to-date. From updating branding to archiving completed projects, here's everything you need to know about project management in ZBD.
**Critical Actions**: Some project management actions (like archiving) are irreversible. Always ensure you understand the implications before proceeding.
## Editing Project Details
Your project's details appear in payment flows and help organize your dashboard. Keep them current and professional.
### What You Can Edit
Appears in payment notifications to users
Internal notes for your team's reference
Your logo shown during payment flows
### How to Edit
Editing a project details is simple:
1. Navigate to **Projects** page
2. Find your project card
3. Click the project card to enter project view
4. Select **Settings** tab
5. Edit the details you want to change
6. Click **Update**
## Archiving Projects
When a project is no longer needed, archiving keeps your dashboard clean while preserving records.
**Immediate Effects of Archiving**:
* API key is permanently disabled
* No new transactions possible
* Wallet funds auto-transfer to main wallet
* Action cannot be undone
### When to Archive
* Project development is cancelled
* App/game has been sunset
* Migrating to a new project
* Cleaning up test projects
### How to Archive
Navigate to the project you want to archive
Click the Settings tab on the top
Scroll down and choose **Archive Project** from advanced options
Read the warning and click **Archive** to confirm
## Next Steps
Secure your API keys and set up IP allowlisting
Track your project's financial activity
Discuss enterprise features for larger teams
***
**Pro Tip**: Set up a project naming convention early. As you scale, having organized projects with clear names like "AppName-Prod-US" and "AppName-Dev-EU" will save hours of confusion.
# Project Wallet
Source: https://docs.zbdpay.com/get-started/project-wallet
Understand how Bitcoin Lightning wallets power your projects
Every ZBD project comes with its own programmable Bitcoin Lightning wallet. This isolated wallet gives you complete control over your project's funds, transactions, and financial operations – all accessible via API.
**Core Architecture**: 1 Project = 1 Wallet = 1 API Key. This separation ensures clean accounting, isolated risk, and granular control.
## How Project Wallets Work
Each project has its own Bitcoin balance, completely separate from other projects
Every transaction through your API key affects only this wallet
Balance changes instantly with Lightning-speed settlements
### Wallet Architecture
```mermaid theme={null}
graph TB
A[Developer Account] --> B[Main Developer Wallet]
A --> C[Project 1]
A --> D[Project 2]
A --> E[Project 3]
C --> F[Project 1 Wallet]
D --> G[Project 2 Wallet]
E --> H[Project 3 Wallet]
F --> I[API Key 1]
G --> J[API Key 2]
H --> K[API Key 3]
style B fill:#f9f,stroke:#333,stroke-width:2px
style F fill:#bbf,stroke:#333,stroke-width:2px
style G fill:#bbf,stroke:#333,stroke-width:2px
style H fill:#bbf,stroke:#333,stroke-width:2px
```
## Wallet Dashboard
Navigate to your project's **Wallet** tab to access comprehensive financial data:
## Wallet Management Best Practices
**Buffer Recommendation**: Keep 1.5x your daily volume
* Monitor daily burn rate
* Automate top-ups if possible
* Plan for traffic spikes
**Protect Your Funds**
* Use IP allowlisting for API keys
* Enable 2FA on your account
* Regularly audit transactions
* Set up webhook notifications
**When to Use Multiple Projects**
* Different apps/games
* Staging vs production
* Regional separation
* Department budgets
**Financial Tracking**
* Export transactions monthly (talk to your Customer Success Manager)
* Use reference IDs for reconciliation
* Track by project for clean books
* Integrate with accounting software
## Common Wallet Operations
### Check Balance
```javascript Node.js theme={null}
const wallet = await zbd.getWallet();
console.log(`Balance: ${wallet.balance} sats`);
console.log(`USD Value: $${wallet.balanceUSD}`);
```
```bash cURL theme={null}
curl https://api.zbdpay.com/v0/wallet \
-H "apikey: YOUR_PROJECT_API_KEY"
```
### Transfer Between Projects
```javascript Node.js theme={null}
// Transfer funds between your projects
const result = await zbd.internalTransfer({
amount: 10000,
receiverWalletId: 'project_abc123',
reference: 'Budget reallocation'
});
```
```bash cURL theme={null}
curl -X POST https://api.zbdpay.com/v0/internal-transfer \
-H "apikey: YOUR_PROJECT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": "10000",
"receiverWalletId": "project_abc123"
}'
```
## Next Steps
Make your first Lightning payment
Monitor transaction updates in real-time
***
**Pro Tip**: Use project wallets to isolate financial risk. If one project has issues, your other projects remain unaffected. This is especially important for testing new features or running experiments.
# Identity Verification
Source: https://docs.zbdpay.com/get-started/verify-identity
Complete your profile to unlock production access and higher limits
Identity verification unlocks the full power of ZBD. As a regulated financial institution, we're required to verify all businesses before enabling production access – but we've made it as painless as possible.
**Why Verification Matters** - ZBD is a licensed money transmitter in the US (MSB/MTL) and an Electronic Money Institution (EMI) in the EU under MiCAR. This means your funds are protected and your business is compliant.
## Why We Verify
Get LIVE API keys to process real payments
Increase transaction and wallet balance limits
Operate legally and compliantly in Tier 1 global markets (US, EU, etc)
Your money is safeguarded by regulated entities
### Regulatory Framework
As a global payment provider, ZBD maintains licenses and registrations worldwide:
**Federal Registration**
* FinCEN registered Money Services Business (MSB)
* BSA/AML program in place
**State Licenses**
* Money Transmitter Licenses (MTL) in required states
* Compliance with state-specific regulations
**MiCAR Compliance**
* Electronic Money Institution (EMI) license
* Access to all EU member states
* Segregated customer funds
* Regular audits and reporting
**International Standards**
* FATF compliance guidelines
* Sanctions screening (OFAC, UN, EU)
* SOC 2 Type II
### Individual Verification (KYC)
For authorized representatives and beneficial owners:
* Passport (preferred)
* Driver's license
* National ID card
* Quick selfie
* Automated verification
* Instant results
## Complete Your Profile
Beyond regulatory requirements, a complete profile helps us serve you better:
### 1. Verify Email Address ✅
Already completed during signup, but ensure your business email is verified.
### 2. Choose Your Gamertag
Your ZBD Gamertag appears in payment notifications to users:
**Choose Wisely** - Your Gamertag is visible to anyone you pay. Use your business name or something professional like "AcmeGameStudio" rather than "xXx\_PayMaster\_xXx".
Good examples:
* `YourCompanyName`
* `StudioNameGames`
* `AppNameOfficial`
### 3. Upload Profile Image
Add your company logo for brand recognition in payment flows.
Requirements:
* Square image (1:1 ratio)
* PNG or JPG format
* Under 3MB
* Clear on small screens
### 4. Enable Two-Factor Authentication (2FA)
**Required for Production** - 2FA is mandatory for all accounts with production access. Protect your funds and API keys.
How to enable:
1. Navigate to **Account > Security**
2. Click **Enable 2FA**
3. Scan QR code with authenticator app
4. Enter verification code
5. Save backup codes securely
Recommended authenticator apps:
* Google Authenticator
* Authy
* 1Password
* Microsoft Authenticator
### 5. Complete Identity Verification
The final step to unlock production access:
Go to **Account > Verification** and click **Verify Now**
Take photo of passport or driver's license
Follow on-screen instructions for liveness check
Usually completed within minutes
## What Happens After Verification?
* ✅ **Production API Keys** - Start processing real payments
* ✅ **Increased Limits** - Higher transaction and balance limits
* ✅ **Full Dashboard Access** - All features unlocked
* ✅ **Priority Support** - Dedicated success manager
* 📋 **Transaction Monitoring** - Automated AML checks
* 📋 **Periodic Reviews** - Annual KYB refresh
* 📋 **Sanctions Screening** - Real-time checks
* 📋 **Regulatory Updates** - We handle compliance changes
## Common Verification Issues
Ensure photos are clear, uncropped, and all text is readable
Account name must match ID exactly
Utility bills must be recent (\< 3 months)
Ensure all pages are included and documents are current
## Need Help?
**Having Issues?** - Our compliance team can guide you through verification. Most issues are resolved in one call.
***
**Compliance = Trust** - Our regulatory compliance isn't red tape – it's your protection. It means your funds are safe, your business is legitimate, and you can scale globally without worry.
# Vouchers
Source: https://docs.zbdpay.com/get-started/vouchers
Create shareable Bitcoin gifts and promotional codes that drive engagement
Turn Bitcoin into shareable gift codes. Vouchers are redeemable payment links that let you distribute value without knowing recipients' payment details – perfect for promotions, rewards, and re-engagement campaigns.
Send Bitcoin without knowing Lightning addresses or gamertags
Create bulk codes for promotions, giveaways, and campaigns
Monitor redemption rates and campaign performance
## Why Use Vouchers?
### 🎁 User Acquisition & Retention
**The Problem**: Getting users to try your app is hard
**The Solution**: Give them immediate value
```javascript theme={null}
// Create welcome bonus vouchers
const voucher = await zbd.createVoucher({
amount: 1000, // sats (~$0.50)
description: "Welcome to GameApp! 🎮"
});
// Send via email/SMS
sendWelcomeEmail(user.email, voucher.code);
```
**Result**: 3x higher activation rates
**Re-engage Dormant Users**
Send personalized vouchers to users who haven't been active:
* "We miss you! Here's 2000 sats"
* "Complete your profile for 5000 sats"
* "Return bonus: 10,000 sats"
**Case Study**: Game studio saw 40% of churned users return
**Viral Growth Mechanics**
```javascript theme={null}
// Both referrer and referee get rewards
const referralVoucher = await createVoucher({
amount: 5000,
description: "Thanks for sharing!"
});
```
Users share more when they can give real value
### 🎯 Marketing & Promotions
* Twitter/X campaigns: "RT to win!"
* Discord events and contests
* Twitch stream rewards
* Community milestones
* Conference booth traffic
* QR code scavenger hunts
* Workshop attendance rewards
* Beta testing incentives
* Survey completion rewards
* Newsletter signup bonuses
* Tutorial completion gifts
* Review incentives
* Co-marketing vouchers
* Influencer distribution
* Cross-promotion codes
* Sponsor activations
## Creating Vouchers
### Dashboard Method
Navigate to **Vouchers** in your dashboard and click **Create Voucher**:
### API Method
```javascript Node.js theme={null}
// Single voucher
const voucher = await zbd.createVoucher({
amount: 1000, // satoshis
description: "Thanks for playing!"
});
console.log(`Share this code: ${voucher.code}`);
// Output: Share this code: ABC12345
// Bulk creation for campaigns
const campaign = await Promise.all(
Array(100).fill(null).map(() =>
zbd.createVoucher({
amount: 500,
description: "Launch week special"
})
)
);
```
```python Python theme={null}
# Create marketing voucher
voucher = zbd.create_voucher(
amount=1000,
description="Welcome bonus"
)
# Generate QR code for easy sharing
qr_url = f"https://zbd.gg/v/{voucher['code']}"
```
```bash cURL theme={null}
curl -X POST https://api.zbdpay.com/v0/vouchers \
-H "apikey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": "1000",
"description": "Conference giveaway"
}'
```
## Distribution Strategies
### 📧 Email Campaigns
```html theme={null}
You've received Bitcoin! 🎉
Redeem your gift with this code:
ABC12345
Redeem now!
```
### 🎮 In-App Distribution
```javascript theme={null}
// Trigger voucher creation on achievement
async function rewardAchievement(userId, achievement) {
const voucher = await zbd.createVoucher({
amount: achievement.rewardAmount,
description: `Achievement unlocked: ${achievement.name}`
});
// Show in-game notification
showNotification({
title: "Achievement Unlocked! 🏆",
message: `You earned ${achievement.rewardAmount} sats!`,
code: voucher.code,
action: "Tap to redeem"
});
}
```
## Redemption Process
### For End Users
**Quick Redemption** (anywhere in dashboard):
1. Open redemption modal inside Vouchers page
2. Enter 8-character code
3. Click "Redeem Voucher"
4. Funds instantly added to wallet
**Mobile Redemption**:
1. Tap wallet balance in navbar
2. Select "Redeem Voucher"
3. Enter voucher code
4. Confirm redemption
### API Redemption
```javascript theme={null}
// Programmatic redemption
const result = await zbd.redeemVoucher({
code: 'ABC12345',
});
if (result.success) {
console.log(`Redeemed ${result.amount} sats!`);
}
```
## Managing Vouchers
### Voucher Statuses
| Status | Description | Action Available |
| -------------- | --------------------- | ---------------- |
| 🟢 **Valid** | Active and redeemable | Share, Revoke |
| ✅ **Redeemed** | Successfully claimed | View details |
| ❌ **Revoked** | Cancelled by creator | None |
### Revoke Unused Vouchers
Cancel vouchers and reclaim funds:
```javascript Node.js theme={null}
// Revoke single voucher
await zbd.revokeVoucher(voucherId);
```
```bash cURL theme={null}
curl -X POST https://api.zbdpay.com/v0/vouchers/voucher_id/revoke \
-H "apikey: YOUR_API_KEY"
```
## Best Practices
Create urgency and prevent long-term liabilities
Track campaign performance with clear descriptions
## Advanced Use Cases
### 🎰 Gamified Redemption
```javascript theme={null}
// Mystery box vouchers with random amounts
function createMysteryVoucher() {
const amounts = [100, 500, 1000, 5000, 10000];
const random = amounts[Math.floor(Math.random() * amounts.length)];
return zbd.createVoucher({
amount: random,
description: "Mystery Box 📦"
});
}
```
## Common Questions
Yes, vouchers expire and are automatically revoked if not redeemed within 30 days. Unused funds are returned to your wallet.
No, each voucher is single-use only. For recurring rewards, create multiple vouchers.
## Start Your First Campaign
Define goals, audience, and budget
Use dashboard or API for bulk creation
Email, social media, or in-app
Monitor redemption rates and adjust
**Start Creating Vouchers** - Check out our API reference for programmatic voucher creation at scale.
# ZBD App
Source: https://docs.zbdpay.com/get-started/zbd-app
# ZBD Earn SDK
Source: https://docs.zbdpay.com/get-started/zbd-earn-sdk
# ZBD Payments API
Source: https://docs.zbdpay.com/get-started/zbd-payments-api
# ZBD Ramp
Source: https://docs.zbdpay.com/get-started/zbd-ramp
# ZBD Payments
Source: https://docs.zbdpay.com/payments
Global instant payments infrastructure for apps and games with Bitcoin, Lightning Network, and multi-currency support
Build global payment experiences that actually work. ZBD Payments provides instant, low-cost money movement across major Tier 1 markets (US, EU, etc) using Bitcoin, Lightning Network, and traditional currencies - all through a single API.
Sub-second global payments with Lightning Network. No waiting, no borders.
Accept and send USD, EUR, and BTC. One API, multiple currencies.
Built for millions of microtransactions. Handle millions of transactions with ease.
Simple APIs, comprehensive SDKs, and documentation that doesn't suck.
## Why ZBD Payments?
### The Problem with Traditional Payments
**Card Networks:**
* Minimum \~\$0.30 fee per transaction
* Can't send 0.10c when fees are 0.30c
* Chargebacks eat profits
* High decline rates
**ZBD Payments:**
* Send amounts as low as \$0.001
* Proportional fees (typically \< 1%)
* No chargebacks
* Near 100% success rate
**Legacy Providers:**
* Complex integration (weeks/months)
* Different APIs per country
* Compliance nightmares
* Poor documentation
**ZBD Payments:**
* Single API globally
* 5-minute quick start
* Compliance built-in
* Stripe-quality docs
**Traditional Systems:**
* 3-5 day settlement times
* \$25-45 fees per transaction
* Limited to banking hours
* Blocked in many countries
**ZBD Payments:**
* Instant settlement (\< 1 second)
* Fees from \$0.0001
* 24/7/365 availability
* Works in globally
## How It Works
```mermaid theme={null}
graph LR
A[Your App] -->|API Call| B[ZBD Platform]
B --> C{Payment Type}
C -->|Lightning| D[Instant Delivery]
C -->|On-chain| E[Bitcoin Network]
C -->|Fiat| F[Banking Rails]
D --> G[Recipient]
E --> G
F --> G
```
### Core Concepts
Bitcoin's Layer 2 scaling solution enabling instant, low-cost payments. Think of it as the Visa network for Bitcoin - same security, 1000x faster.
**Key Benefits:**
* Instant settlement (\< 1 second)
* Fees typically \< \$0.01
* Millions of TPS capacity
* Perfect for gaming microtransactions
Human-readable payment addresses like `user@zbd.gg`. No more copying long Bitcoin addresses. Works like email for money.
**Why It Matters:**
* Memorable usernames
* No QR codes needed
* Works across all Lightning wallets
* Perfect for in-game identities
## Products & Features
### 🚀 ZBD Ramp
Let users buy Bitcoin directly in your app. First widget to support Lightning Address delivery.
Embeddable widget • Built-in KYC • Multiple payment methods
### ⚡ Payments API
Send and receive payments globally via our REST API.
Instant settlements • Global reach • Bitcoin Lightning Network
### 🛠️ Developer SDKs
Production-ready SDKs for popular languages and frameworks. Get building in minutes, not weeks.
TypeScript • Go • Rust • C# • More coming
## Use Cases
### Gaming & Virtual Worlds
* Instant item purchases
* No minimum transaction
* Global player base
* Zero chargebacks
* P2P marketplaces
* Instant settlement
* Cross-border trades
* Low fees = more profit
* Instant winner payouts
* Any amount, any country
* No banking details needed
* Automated via API
* Pay mod creators
* Revenue sharing
* Micropayments work
* Global participation
### Apps & Platforms
Pay-per-article, pay-per-view, tips - amounts too small for cards
Instant payouts to workers globally without bank accounts
Send money home instantly with fees under \$0.01
Usage-based billing down to fractions of a cent
## Compliance & Security
### Built-in Compliance
* **KYC/AML**: Automated identity verification where required
* **Sanctions Screening**: Real-time OFAC and international lists
* **Transaction Monitoring**: AI-powered fraud detection
* **Regulatory Licenses**: Money transmission licenses in key markets
### Security First
* **End-to-end Encryption**: All data encrypted in transit and at rest
* **API Key Security**: Scoped permissions and IP allowlisting
* **Webhook Signatures**: Cryptographic verification of all events
* **SOC 2 Type II**: Annual security audits
## Pricing
**Custom Pricing** - We offer competitive rates based on your volume and use case. Schedule a call to discuss pricing that works for your business.
### What Affects Pricing
* Transaction volume
* Average transaction size
* Geographic distribution
* Settlement preferences
* Support level needed
## Start Building
[Schedule a call](https://zbd.one/sales) with our team to get access
Pick between Ramp, Payments API, or both
Use our quick start guides to integrate in minutes
Start processing real payments with production keys
Let users buy Bitcoin
TypeScript, Go, Rust & more
Complete API documentation
***
## Need Help?
Get API keys and discuss your use case
Technical help from our engineering team
# AI Ingestion
Source: https://docs.zbdpay.com/payments/ai-ingestion
Understand how to use ZBD Payments with LLMs.
[docs.zbdpay.com](/) documentation pages are content rich and can be a great source of information for LLMs for AI tools. You can use your documentation to fine-tune a chatbot, answer questions about your product, or use it to generate code.
## /llms.txt
An [industry standard](https://llmstxt.org) that helps general-purpose LLMs index more efficiently (e.g. a sitemap for AI).
Every documentation site automatically hosts a **/llms.txt** file at the root that lists all available pages in your documentation.
Open llms.txt for docs.zbdpay.com
## /llms-full.txt
A markdown file of all your content is automatically available at **/llms-full.txt**.
llms-full.txt contains the entire content of your docs, and is a great way to provide a complete context to AI tools.
Open llms-full.txt for docs.zbdpay.com
## .md extension
Add **.md** to an individual documentation page to see a markdown version of that page. Helps load individual pages into AI tools with better token efficiency & inference time.
Open get-started.md
# Payments API Reference
Source: https://docs.zbdpay.com/payments/api
Understand general API concepts and authentication strategies.
## Overview
ZBD offers a powerful REST API that supports Bitcoin Lightning Network transactions with various payout and payin methods. Our API uses JSON data structures and makes use of industry standard HTTP response codes.
## Base URL
The ZBD API is available on the following base URL:
```bash theme={null}
https://api.zbdpay.com
```
If you're looking for the Sandbox API, that's available at `https://sandbox-api.zbdpay.com`.
## Authentication
All ZBD endpoints are protected by an API Key. To make requests against these endpoints you must pass a header property called `apikey` with your [ZBD Project API Key](/get-started/api-keys).
```json theme={null}
apikey: "1PnXYRdcm13gJrHZVzctgCAUIEniVomQR"
```
## SSL / HTTPS Access
**ZBD only provides a secure interface over HTTPS with SSL certificate support**. Any requests that attempt to reach the ZBD API in an insecure fashion (plain-text over HTTP requests) will be rejected.
Secure Sockets Layer (SSL) is the standard security technology for establishing an encrypted link between a server and a client. SSL allows sensitive information such as credit card numbers, social security numbers, and login credentials to be transmitted securely.
## Resources
Links to help you get the most out of your ZBD development experience:
# Callbacks
Source: https://docs.zbdpay.com/payments/api/callbacks
Receive secure payment status updates from ZBD servers.
**Every payment in the Bitcoin Lightning Network is asynchronous.**
**Therefore, every payment inside of ZBD Payments API is asynchronous.**
## Payment Lifecycle
Although it may be that 99% of the time you use the ZBD Payments API to send a payment it settles immediately, this is NOT a certainty. All payments are asynchronous so there's still chances they will not succeed.
The Lightning Network is a decentralized organism / network and therefore there are many factors and circumstances that are outside of ZBD's control. Whether it is another provider going offline, or improper management of Bitcoin liquidity on the network, payments in Lightning can fail and you as a developer must understand how to react to these failures.
### Receiving Bitcoin
To receive payments, you normally create [Charges](/payments/api/lightning-charges/create) (or [Static Charges](/payments/api/lightning-charges/create-static)). These are created and remain in a `pending` status until someone successfully scans and pays the Charge, at which point it becomes `completed`. If enough time is elapsed, the Charge can also `expire` making it impossible to be paid.
### Sending Bitcoin
On the other hand, to send Bitcoin you must use one of the many [Payment APIs](/payments#instant-bitcoin-payouts). Payments through the Lightning Network can always fail, due to a myriad of reasons (e.g. network connectivity, size of payment, destination or receipient, etc). Because of that, every payment starts in a `processing` state, and only when it's settled or failed does it receive the `completed` or `failed` status' respectively.
As you can understand now, **it is important that you subscribe to updates on all your Charges and Payments when using the ZBD Payments API**.
**ZBD Payments API retains a 97% payment success rate for all time payments in the Lightning Network.**
## Callback URL
In order to properly receive updates to any Payments, Charges, and Withdrawals created through the ZBD Payments API, you should always pass along the `callbackUrl` property.
This `callbackUrl` should point to an HTTP server that you control/manage and should expose a POST HTTP call on this endpoint. It could look like this:
```bash theme={null}
https://yourserver.com/api/v1/zbd/callback
```
**Callback URLs MUST be HTTPS**. HTTP calls are ignored. The server must be reachable to the public internet and not require any additional means of authentication.
We are in the process of adding `retry` functionality for these callback payloads, in case your server happens to be offline when a payment settles.
### Payloads
Below is a set of example payloads for the main APIs available:
#### Charges
```json theme={null}
{
"amount":"1000",
"callbackUrl":"",
"internalId":null,
"status":"expired",
"unit":"msats"
}
```
#### Payments
```json theme={null}
{
"amount":"10000",
"confirmedAt":"2024-02-06T11:51:26.985Z",
"description":"Test payment",
"fee":"0",
"id":"",
"internalId":null,
"invoice":"",
"preimage":"",
"processedAt":"2024-02-06T11:51:26.985Z",
"status":"completed",
"unit":"msats"
}
```
#### Withdrawals
```json theme={null}
{
"amount":"10000",
"callbackUrl":"",
"createdAt":"2024-02-06T12:02:08.166Z",
"description":"Test withdrawal",
"expiresAt":"2024-02-06T12:05:08.164Z",
"fee":"0",
"id":"",
"internalId":null,
"invoice":
{
"fastRequest":"",
"fastUri":"",
"uri":""
},
"status":"completed",
"unit":"msats"
}
```
#### Lightning Address
```json theme={null}
{
"amount":"1000",
"callbackUrl":"",
"internalId":null,
"invoice":"",
"preimage":"",
"unit":"msats",
"walletId":""
}
```
## Security / Integrity
It is important that developers are able to validate the integrity of all API calls performed to their `callbackUrl` endpoints.
To ensure that calls are coming from trusted ZBD Payments API servers, please use the [ZBD IP Address API Endpoint](/payments/api/utils/ip).
**By checking the originating IP address** of the request received to your callback servers, **with the approved IP address** returned from this API endpoint, you are able to verify the authenticity of the requests.
We have plans to expose features to further harden this security by providing data-encryption capabilities. The idea here is to allow developers to enter a secret key in their ZBD Project's Settings and then require this key to decode the encrypted data payload.
## Testing Locally
When developing with the ZBD Payments API, it is imperative that developers can test full end-to-end functionality of payment flows, including the async updates received through the `callbackUrl`s.
In order to receive updates locally, we recommend using a proxy server such as [ngrok](https://ngrok.com).
* [Follow the installation steps](https://ngrok.com/docs/getting-started/)
* Run command to start ngrok tunnel `ngrok http 8000`
* ngrok URL (e.g. `https://84c5dfxx39d74.ngrok.io`) is provided
* This URL is accessible to the world --> expose an API endpoint here and use it as the `callbackUrl` (e.g. `https://84c5dfxx39d74.ngrok.io/api/zbd-callback`).
You will now be able to receive async updates about your ZBD Payments API transactions directly to your local environment.
# Errors
Source: https://docs.zbdpay.com/payments/api/errors
Troubleshoot problems with API calls.
The ZBD API follows standard HTTP response codes for handling success and error requests.
If you are unfamiliar with HTTP requests, [please read more here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
## HTTP status codes
Below is an overview of HTTP status codes available in the standard, which ZBD API adheres by:
| HTTP Response Group | Status Code Range |
| ------------------------ | :---------------: |
| Informational Responses | `100-199` |
| **Successful Responses** | `200-299` |
| Redirects | `300-399` |
| **Client Errors** | `400-499` |
| **Server Errors** | `500-599` |
## Common response codes
These are the HTTP status codes most often returned by the ZBD API.
| Status Code | Details | Response Description |
| :---------: | :---------------: | ---------------------------------------------------------------------------------------------------------- |
| `200` | Success | Request was successful. |
| `400` | Bad Request | Either incorrect or missing parameters provided for the Request. |
| `401` | Unauthorized | Request is not authorized. Make sure correct API Key is provided. |
| `403` | Forbidden | Request is forbidden. Make sure your IP is located in a region/country that ZBD services are available in. |
| `404` | Not Found | The requested endpoint/resource was not found. |
| `422` | Missing Parameter | The requested endpoint expected a specific parameter to be provided. |
| `429` | Rate Limited | Too many requests in short time-frame. |
| `500` | Server Error | Something went wrong in the ZBD API servers. |
## Error messages
To help identify the issue with your API requests, the error JSON response returned will often include a **message** property that aims to be descriptive.
Example of an error message from the API:
```json theme={null}
{
"success": false,
"message": "Error creating Withdrawal Request: The \"amount\" property (in millisatoshis) is required.",
}
```
# ZBD Gamertags
Source: https://docs.zbdpay.com/payments/api/gamertags
How to send instant payments to ZBD Gamertags using ZBD Payments APIs.
Section coming soon.
# Create Charge
Source: https://docs.zbdpay.com/payments/api/gamertags/create-charge
POST https://api.zbdpay.com/v0/gamertag/charges
Generate a payment request for a ZBD User.
## Description
While you can use the [Pay to ZBD Gamertag](/payments/api/gamertags/send) endpoint to make a direct Bitcoin payment to a given ZBD user, if for whatever reason you'd want to create a general Lightning Network Charge / Payment Request QR code, you can use this endpoint.
The response payload will include a `invoiceRequest` which is the contents of the Charge / Payment Request QR code. Do note that Charges have defined expiration times. After a Charge expires it cannot be paid, simply create another Charge.
**Important:** ZBD Gamertags are mutable and can be changed by users at any time. If you're implementing user-specific limits (e.g., 1 withdrawal per day) or tracking balances, **do not use Gamertags as identifiers**. Instead, use the [Get ID by ZBD Gamertag](/payments/api/gamertags/retrieve-userid) endpoint to retrieve the immutable User ID for each Gamertag, then track limits and balances using that User ID. Otherwise, users can bypass your limits simply by changing their Gamertag.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount for the Payment -> in millisatoshis
Destination ZBD Gamertag
Note or comment for this Payment (visible to recipient)
Time until Charge expiration -> in seconds
Open metadata string property
The endpoint ZBD will POST Charge updates to
```json Response theme={null}
{
"success": true,
"data": {
"unit": "msats",
"status": "CHARGE_PENDING",
"amount": "15000",
"createdAt": "2023-03-14T19:40:13.880Z",
"internalId": "test",
"callbackUrl": "https://my-website.ngrok.io/callback",
"description": "Requesting Charge for Gamertag",
"invoiceRequest": "lnbc10n1pjppnvapp5camc852ky0et9g46gyey9mnv5xgux6tnkkq5qc6cexrr65xw2j9sdps2fjhzat9wd6xjmn8yppksctjvajjqen0wgsywctdv4e8gct8cqzpgxqzjcsp5jgs84mxjwk8n9r7xmp7ulzycy7882f5m8zagk45s2qp23p7rprqq9qyyssq3ysvdsgg5qvx0nwtlz46hcrucs7m6nkvsffcze5nhes40hqrnnes3xjcq0a4wtpqvvrdqlyqy3sz5yhqh6944unan4d32py2azq38zgq4c5ysu",
"invoiceExpiresAt": "2023-03-14T19:50:13.859Z",
"invoiceDescriptionHash": null
}
}
```
# Get Gamertag By ZBD ID
Source: https://docs.zbdpay.com/payments/api/gamertags/retrieve-from-userid
GET https://api.zbdpay.com/v0/gamertag/user-id/{id}
Retrieve ZBD user ID from a Gamertag.
## Usage
This API endpoint is the reverse of the [Get User ID for ZBD Gamertag](/payments/api/gamertags/retrieve-userid) endpoint. Use this endpoint to get a given user's ZBD Gamertag.
If you've got a User ID and you wish to find out that user's ZBD Gamertag, perhaps to then [send that user payments](/payments/api/gamertags/send), you may use this endpoint.
## Configuration
### Path Parameters
User ID
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"data": {
"gamertag": "foxp2"
},
"message": "Fetched gamertag from uuid"
}
```
# Get Payment
Source: https://docs.zbdpay.com/payments/api/gamertags/retrieve-payment
GET https://api.zbdpay.com/v0/gamertag/transaction/{id}
Retrieve all data about a Payment sent to ZBD User.
## Description
In order to get data on payments sent to ZBD Gamertags, you can use this endpoint. The data payload returned will inform you of the `status` of that transaction as well as any associated `fees`.
## Usage
The idea here is to use the `transactionId` property returned from the [Pay to ZBD Gamertag](/payments/api/gamertags/send) response, and use that ID to fetch the latest details of the given Payment.
## Configuration
### Path Parameters
Payment Transaction ID
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"message": "Fetched charge.",
"success": true,
"data": {
"id": "903883f2-67d9-4707-a21b-ddff004fe041",
"receiverId": "ec9b38d5-b126-4307-9d1e-8aa0dfab5d7e",
"amount": "15000",
"fee": "1000",
"unit": "msats",
"processedAt": "2023-01-04T15:59:16.993Z",
"confirmedAt": "2023-01-04T15:59:16.989Z",
"comment": "Sending to ZBD Gamertag",
"status": "TRANSACTION_STATUS_COMPLETED"
}
}
```
# Get ID by ZBD Gamertag
Source: https://docs.zbdpay.com/payments/api/gamertags/retrieve-userid
GET https://api.zbdpay.com/v0/user-id/gamertag/{GAMERTAG}
Retrieve Gamertag from a ZBD user ID.
## Description
Make use of this endpoint to get a given User's ID when provided with a ZBD Gamertag.
## Usage
This is needed because ZBD Gamertags are akin to social media handles, they are swappable. In the scenario where a Developer is using a ZBD Gamertag as the identifier for transaction limits and/or thresholds (for example), a user could simply change their ZBD Gamertag and try to bypass those constraints. Using a truly unique and immutable ID like the `User ID` will provide Developers with the needed assurances.
## Configuration
### Path Parameters
ZBD Gamertag
### Header Parameters
ZBD Project API Key
```json 200 Response theme={null}
{
"success": true,
"data": {
"id": "0a59bf56-daa3-4888-8330-cbc02eba3a6e"
}
}
```
```json 400 Response theme={null}
{
"success": false,
"message": "No user found with this gamertag"
}
```
# Pay to ZBD Gamertag
Source: https://docs.zbdpay.com/payments/api/gamertags/send
POST https://api.zbdpay.com/v0/gamertag/send-payment
Send instant Bitcoin payments to ZBD Users.
Unlike other payout endpoints in the ZBD API, sending payments to ZBD Gamertags is a synchronous action -> this is why there is no `callbackUrl` property. The payment either succeeds or fails on the spot.
**Important:** ZBD Gamertags are mutable and can be changed by users at any time. If you're implementing user-specific limits (e.g., 1 withdrawal per day) or tracking balances, **do not use Gamertags as identifiers**. Instead, use the [Get ID by ZBD Gamertag](/payments/api/gamertags/retrieve-userid) endpoint to retrieve the immutable User ID for each Gamertag, then track limits and balances using that User ID. Otherwise, users can bypass your limits simply by changing their Gamertag.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount for the Payment -> in millisatoshis
Destination ZBD Gamertag
Note or comment for this Payment (visible to recipient)
```json Response theme={null}
{
"success": true,
"data": {
"id": "49cccd62-b686-4057-9f44-f492bd54ac39",
"status": "settled",
"transactionId": "78fb6474-d791-47a1-bda1-a4b9023898c0",
"receiverId": "ec9b38d5-b126-4307-9d1e-8aa0dfab5d7e",
"amount": "1000",
"comment": "Sent to ZBD Gamertag",
"settledAt": "2023-07-19T21:42:54.993Z"
},
"message": "Payment done."
}
```
# Keysend
Source: https://docs.zbdpay.com/payments/api/keysend
How to send Keysend payments using ZBD Payments APIs.
Section coming soon.
# Send Keysend Payment
Source: https://docs.zbdpay.com/payments/api/keysend/send
POST https://api.zbdpay.com/v0/keysend-payment
Start sending Keysend payments on the Lightning Network.
## Description
Every Lightning Network node has a public key identifying it to the wider network. While most payments in the Lightning Network require Payment Requests ([Charges](/payments/glossary#charges)) QR codes to be created and then paid for, there is another type of payment known as `Spontaneous Payment` or `Keysend Payment` on a more technical note.
This endpoint exposes the ability to make payment directly to a Lightning Network node Public Key, without the need for a Payment Request / Charge.
## Usage
If your system relies on sending Bitcoin over the Lightning Network to specific node Public Keys, this API is what you're looking for.
Additional metadata and TLV record data can be attached to this endpoint as well. Both of these properties/values will be returned on the `callbackUrl` POST call from ZBD.
As with all asynchronous payments in the Lightning Network, in order to receive updates about whether a payment settled, you must provide the `callbackUrl` property. As you will note from the response example below, if the Keysend Payment doesn't settle (almost) immediately, you will receive a `Payment Processing` response payload. Once it settles, you'll receive the update on the `callbackUrl`.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount for the Payment -> in millisatoshis
The Public Key for the destination Lightning node
The endpoint ZBD will POST Keysend Payment updates to
Open metadata object property
List of TLV records
type of the TLV record
value of the TLV record (hex encoded string)
```json Response theme={null}
{
"message": "Payment processing.",
"success": true,
"data": {
"keysendId": "0d54521c-f41c-4cec-8799-edf9d87cf6b5",
"paymentId": "276e6f54-65fb-4c30-9b86-b44659015cd6",
"transaction": {
"id": "a51bd8d3-1d65-4785-bfd2-3341dc696f84",
"walletId": "cce98a9b-c52a-427c-8cf5-d7ca39c5035e",
"type": "KEYSEND_PAYMENT",
"totalAmount": "3000",
"fee": "2000",
"amount": "1000",
"description": "Keysend Payment",
"status": "TRANSACTION_STATUS_PROCESSING",
"confirmedAt": null
}
}
}
```
# Lightning Address
Source: https://docs.zbdpay.com/payments/api/lightning-address
How to send instant payments to Lightning Addresses using ZBD Payments APIs.
## Description
A Lightning Address is an internet identifier (akin to an email address -- `andre@zbd.gg`) that anyone can use to send you Bitcoin Lightning Network payments.
Leverage this API to programmatically perform these types of payments.
A massively simpler way for anyone to send you Bitcoin instantly on the Lightning Network. Like an email address, but for your Bitcoin!
As creators of the [Lightning Address open source standard](https://github.com/andrerfneves/lightning-address), we believe this API to be the single most frictionless way of using Bitcoin today.
## APIs
Here are some Lightning Address APIs that you can use to programmatically help perform these types of payments.
Ensure destination is a valid Lightning Address.
Send a payment to a Lightning Address.
Create a charge QR code for a Lightning Address.
# Create Charge
Source: https://docs.zbdpay.com/payments/api/lightning-address/create-charge
POST https://api.zbdpay.com/v0/ln-address/fetch-charge
Generate a payment request for a Lightning Address.
## Description
If instead of sending Bitcoin payments directly to a given Lightning Address, you would rather create a Payment Request QR code for that Lightning Address, you can use this API.
## Usage
Depending on your system's configuration or your product's UX, you may need the ability to generate Charges for specific users. For ZBD users that's easy using the ZBD Gamertag endpoints. For any user that is using a different provider, you can use this endpoint.
The way to think of this is:
Given `user@domain.com` Lightning Address and an `amount` property, this endpoint generates a Charge.
If this new Charge is paid, the payment is received by `user@domain.com`.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The Lightning Address of the intended recipient
The amount for the Charge -> in millisatoshis
Note or comment of this Charge
```json Response theme={null}
{
"success": true,
"data": {
"lnaddress": "andre@zbd.gg",
"amount": "15000",
"invoice": {
"uri": "lightning:lnbc100n1p3mtxc3pp5tz4srtee9c4gsvlcqa6azu60a2ak2fvrnk7jv52j6n0rzp0musnqhp5xt5ts9t74akf67j59ynkr5qz8x3hs4g09d3dttmjrwwdhrxgc03qcqzpgxqzfvsp5529t5y03yaakumqrm9cwr5t6nysnr5cv93pnvw089a25aa7wszas9qyyssqalswdlc92983203l5azl43nksehadfy2uahc9v6qwg67xs52z02hg6vh7alrm3yx46ywdrl3dxey75t9l2ekmuwc3tu4ug03dy729fspdld2lj",
"request": "lnbc100n1p3mtxc3pp5tz4srtee9c4gsvlcqa6azu60a2ak2fvrnk7jv52j6n0rzp0musnqhp5xt5ts9t74akf67j59ynkr5qz8x3hs4g09d3dttmjrwwdhrxgc03qcqzpgxqzfvsp5529t5y03yaakumqrm9cwr5t6nysnr5cv93pnvw089a25aa7wszas9qyyssqalswdlc92983203l5azl43nksehadfy2uahc9v6qwg67xs52z02hg6vh7alrm3yx46ywdrl3dxey75t9l2ekmuwc3tu4ug03dy729fspdld2lj"
}
}
}
```
# Pay to Lightning Address
Source: https://docs.zbdpay.com/payments/api/lightning-address/send
POST https://api.zbdpay.com/v0/ln-address/send-payment
Send instant Bitcoin payments to any Lightning Address.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The Lightning Address of the intended recipient (e.g. [andre@zbd.gg](mailto:andre@zbd.gg))
The amount for the Payment -> in millisatoshis
Note or description of this Payment
Open metadata string property
The endpoint ZBD will POST Charge updates to
```json Response theme={null}
{
"success": true,
"data": {
"id": "db3e9e98-82c6-4ad5-acb8-900212d352aa",
"fee": "0",
"unit": "msats",
"amount": "10000",
"invoice": "lnbc100n1p3mtx6gpp5qpc7qvapr475jjazwkves7t7qdyq5njym52z5r6mg0a9d79w783shp5xt5ts9t74akf67j59ynkr5qz8x3hs4g09d3dttmjrwwdhrxgc03qcqzpgxqzfvsp59uasmyhqwfuek2dwyfla6dn7la5wxkwzmlvvhcuptxdxsxs8d24q9qyyssqslvgpll5cwtcmhr0ch607gg463xc3s2g7mfww2dr3l0f29czt7eq03rylyg5g09qz0w97qv87mmmcyj0ytfahhzc6y79je5vsf67tgcp8248ez",
"preimage": null,
"walletId": "2e686eed-82c6-4722-95bd-de1b23f27d44",
"transactionId": "2924bf31-96ba-4d26-80df-9e35c09a59cf",
"callbackUrl": "https://your-domain.com/zbd-callback",
"internalId": "uniqueIdFromYourSystem",
"comment": "Sending to a Lightning Address",
"processedAt": "2023-01-04T15:29:12.577Z",
"createdAt": "2023-01-04T15:29:12.514Z",
"status": "completed"
},
"message": "Payment done."
}
```
# Validate Lightning Address
Source: https://docs.zbdpay.com/payments/api/lightning-address/validate
GET https://api.zbdpay.com/v0/ln-address/validate/{address}
Verify the validity of a Lightning Address.
## Usage
Not all internet identifiers are Lightning Addresses. Make use of this API to validate whether a user's entered address is indeed a valid Lightning Address that can accept Bitcoin payments.
The idea behind this API endpoint is to verify whether an internet-indentifier (e.g. `user@domain.com`) is in fact a Lightning Address and NOT an email address. Once verified, use the [Send Lightning Address Payment](/payments/api/lightning-address/send) to perform the transaction.
## Configuration
### Path Parameters
Lightning Address to be verified
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"data": {
"valid": true,
"metadata": {
"minSendable": 10000,
"maxSendable": 150000000,
"commentAllowed": 150,
"tag": "payRequest",
"metadata": "[[\"text/plain\",\"andre - Welcome to ZBD! ;)\"],[\"text/identifier\",\"andre@zbd.gg\"],[\"image/png;base64\",\"/9j/2wBDAAYEBQ......IUeDcpP9akPkjm3XPid8/OmYZB//9k=\"]]",
"callback": "https://api.zbdpay.com/v0/process-static-charges/d0f2c3da-e836-480a-bf8c-f5d5b167d6f8",
"payerData": {
"name": {
"mandatory": false
},
"identifier": {
"mandatory": false
}
},
"disposable": false
}
}
}
```
# Overview
Source: https://docs.zbdpay.com/payments/api/lightning-charges
How to create and manage Lightning Charges.
## Introduction
Static Charges are a type of Payment Request QR code in the Bitcoin Lightning Network that has some incredible characteristics and capabiltiies. Whereas [Charges](/payments/api/lightning-charges/create) create `fixed-amount` and `single-use` Payment Requests that expire, [Static Charges](/payments/api/lightning-charges/create-static) provide you a lot more flexibility & capabilities, including:
Static Charges have both `minAmount` and `maxAmount` properties, allowing for the payer to define the amount.
By default Static Charges have **no expiration time**, making them usable for any N payers and payments.
Slots allow you to define that only N payments are to be accepted for this specific Static Charge QR.
When a payment is completed, a `Success Message` can be displayed to the payer (e.g. receipt, link).
## What is a Static Charge?
A Static Charge is a static QR code that can be used an unlimited number of times, does not expire, accepts various amounts, accepts attached messages, and allows for full configurability, **all while maintaining the same QR code**.
A Static Charge QR code looks like the one show below:
## Common use cases
There are many potential scenarios where Static Charges are very handy. Let's take a look at couple of them.
### User deposits
Static Charges are excellent for handling user deposits. You can generate a Static Charge for each unique users in your platform and provide that QR code to them. Whenever payments come in through that specific Static QR code, you will know it belongs to such user. Your users can now receive money from any Bitcoin Lightning wallet.
Static Charges can be set up such that they can be used an unlimited number of times and they do not expire. It makes receiving payments extremely easy.
\*Just like every user has a \$venmotag for Venmo, every ZBD user has an Static Charge. The only difference between the two is that there is interoperability between different providers since they understand the same money protocol.
### In-person fundraising
One crafty thing you can do for donations is throw a Static Charge QR code on a large screen and anyone who has a wallet can now pay you directly just by scanning and confirming a payment.
The ZBD API makes this incredibly easy. Since there are no limits to the number of Static Charges created, you could create one for each campaign and properly measure donation goal reach. Cool, right?
This is great for nonprofits!
### Remote fundraising / donations
Streamers can take their QR image and easily add it to any streaming software (e.g. OBS) to enable direct payments to them from their audience. Never has this been possible before.
Please check out [ZBD Streamer](https://streamer.zebedee.io) to view this live in a ZBD product.
### User tips / Zaps / User-to-user payments
Static Charges are great for tips or commonly referred to as "zaps". It can also be used for user-to-user payments, since they are a static QR code. Though the best user experience for these use cases is a [Lightning Address](/payments/api/lightning-address/send).
### Deposits
Users can attach Static QR codes to their blog posts, social media posts, images, live streams, videos, & art.
# Create Charge
Source: https://docs.zbdpay.com/payments/api/lightning-charges/create
POST https://api.zbdpay.com/v0/charges
Start receiving instant Bitcoin payments through the ZBD API.
## Description
Creates a new [Charge](/payments/glossary#charge) in the Bitcoin Lightning Network, payable by any Lightning-capable wallet.
These payment requests are single-use, fixed-amount QR codes. If you're looking for multi-use and multi-amount payment requests you want [Static Charges](/payments/api/lightning-charges/create-static).
## Usage
This API is used for `receiving` funds into your ZBD Project. The primary idea is to create one of these Charges anytime someone wishes to perform a payment **TO** you.
On a successful `200 HTTP response` from the ZBD API, you should render the contents of `data.invoice.uri` in a QR code. This QR code can be scanned by any Bitcoin Lightning wallet.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount for the Charge -> in millisatoshis
Note or comment for this Charge (visible to payer)
Time until Charge expiration -> in seconds
The endpoint ZBD will POST Charge updates to
Open metadata string property
```json Response theme={null}
{
"success": true,
"message": "Successfully created Charge.",
"data": {
"unit": "msats",
"amount": "10000",
"confirmedAt": null,
"status": "pending",
"description": "My Charge Description",
"createdAt": "2020-05-09T15:09:05.765Z",
"expiresAt": "2020-05-09T15:14:05.618Z",
"id": "1907b0fe-789b-4e25-b18a-0c4c0f5cced7",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"callbackUrl": "https://your-website.com/callback",
"invoice": {
"request": "lnbc100n1p0td3u3pp5z2ed9yjfrz0rgu0fzuc5cdwfu8dtjlgrfztz5uga8hakkjy2yzgsdpzf4ujqsmgv9exwefqg3jhxcmjd9c8g6t0dccqzpgxqzfvsp5q8z5mkghmuzrnusxdwtmls7x8vuy63j25rt4z55gj3s7340dv72q9qy9qsqz02rlmlzcvew3vk90c6l0369ewk7tkr2tx0yrk3qa235v07w6d3qeksk99wm7y8f8ug7zqy6yjudu4cs2f4umpey43cw7msyj7uqj2qq8x03te",
"uri": "lightning:lnbc100n1p0td3u3pp5z2ed9yjfrz0rgu0fzuc5cdwfu8dtjlgrfztz5uga8hakkjy2yzgsdpzf4ujqsmgv9exwefqg3jhxcmjd9c8g6t0dccqzpgxqzfvsp5q8z5mkghmuzrnusxdwtmls7x8vuy63j25rt4z55gj3s7340dv72q9qy9qsqz02rlmlzcvew3vk90c6l0369ewk7tkr2tx0yrk3qa235v07w6d3qeksk99wm7y8f8ug7zqy6yjudu4cs2f4umpey43cw7msyj7uqj2qq8x03te"
}
}
}
```
# Create Static Charge
Source: https://docs.zbdpay.com/payments/api/lightning-charges/create-static
POST https://api.zbdpay.com/v0/static-charges
Start accepting payments on Lightning with Static QR codes.
## Description
Static Charges are static Payment Requests in the Bitcoin Lightning Network. Whereas [Charges](/payments/api/lightning-charges/create) create fixed-amount and single-use Payment Requests that expire, Static Charges provide you a lot more flexibility & capabilities, including:
* **Variable Amounts** -> Static Charges have both `minAmount` and `maxAmount` properties, allowing for variable amounts set by the payer.
* **Multi-use** -> By default Static Charges have no expiration time, making them usable for any N payers/payments.
* **Success Message** -> When a payer completes the payment flow for this Static Charge, a Success Message is displayed to them.
* **Slots** -> Static Charges can also have the notion of `allowedSlots`. This means only N payments will be accepted at this Static Charge before disabling them.
Static Charges also have the same core properties of Charges such as `internalId` and `callbackUrl`.
## Usage
Use this API endpoint to create advanced Payment Requests on the Bitcoin Lightning Network. Enjoy static QR codes that can accept any number of payments, for various amounts, with additional metadata in the payment flow.
You can create a `multi-use` Static Charge with a fixed amount too, simply by setting `minAmount` and `maxAmount` to the same amount.
To understand more use cases for Static Charges, [check our in-depth guide](/payments/api/lightning-charges).
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
Minimum allowed amount for the Static Charge -> in millisatoshis
Maximum allowed amount for the Static Charge -> in millisatoshis
Note or comment for this Static Charge (visible to payer)
Message displayed to the payer AFTER payment settles. Maximum of 144 characters.
Number of payments this Static Charge can accept
Open metadata string property
The endpoint ZBD will POST Charge updates to
Used for Custom Lightning Addresses (see guide)
```json Response theme={null}
{
"message":"Successfully created Static Charge.",
"data":{
"id":"45c225b1-022b-4a37-98d6-5a5568f78d11",
"unit":"msats",
"slots":0,
"minAmount":"10000",
"maxAmount":"100000",
"createdAt":"2023-03-07T20:07:06.910Z",
"expiresAt":null,
"internalId":"myInternalId",
"description":"Static Charge API Ref",
"callbackUrl":"https://my-website/zbd-callback",
"allowedSlots":1000,
"successMessage":"Congratulations your payment was successful!",
"status":"active",
"invoice":{
"request":"lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9aex2ut4v4ehgttnw3shg6tr943ksctjvajhxte5x43nyv34vgcj6vpjxf3z6drpxvmj6wfcvsmz6dtpx56nvwrxxuuxgvf3uzvpfy",
"uri":"lightning:lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9aex2ut4v4ehgttnw3shg6tr943ksctjvajhxte5x43nyv34vgcj6vpjxf3z6drpxvmj6wfcvsmz6dtpx56nvwrxxuuxgvf3uzvpfy"
}
}
}
```
# Decode Charge
Source: https://docs.zbdpay.com/payments/api/lightning-charges/decode
POST https://api.zbdpay.com/v0/decode-invoice
Understand the inner properties of a Charge QR code.
## Usage
This API is used for further decyphering the details of a Charge. The idea is to use this API endpoint if you have to validate any of the specific properties of this Payment Request.
Any Lightning Network Charge can be used as a property here, even those not generated by the ZBD API.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The Charge or Invoice QR code contents
```json Response theme={null}
{
"success": true,
"data": {
"amount": "212325000",
"lnRequest": "lnbc2123250n1pjpr2qmpp526234tljpx5756pa2fyj2zrdmn2tnz9rhj54km2s7dv0pap3vtkqhp5extcuyp2x0ydfwnfhrc5cwx8azxeen2g7hxr29464ezvn3k6w2fqcqzpgxqzjcsp5xzelh2w3twt4ysvva2ugu2klurmrl7nk8h46x2hcthf9cvee24jq9qyyssq6an9tjftjymjeklerjmw8cv4ccpsvd2vzuzxn5upt9s37hnw2r0z0n5cd8cqq8jq5ems00tugt5jnw5jn03tr84945nd6j4hsfsu7kqp9hptk2",
"lnExpiresAt": "2023-03-15T11:22:27.000Z",
"network": "bitcoin",
"description": "Paying for Master Sword #5546",
"descriptionHash": "c9978e102a33c8d4ba69b8f14c38c7e88d9ccd48f5cc3516baae44c9c6da7292",
"paymentHash": "56951aaff209a9ea683d524925086ddcd4b988a3bca95b6d50f358f0f43162ec",
"paymentSecret": "30b3fba9d15b9752418ceab88e2adfe0f63ffa763deba32af85dd25c33395564",
"payee": "036ff83834666d3ebfe61c2a7d1f8fc5d6b339a26559a61819e2b0d1b5f540fdfc",
"signature": "d76655c92b91372cdbf91cb6e3e195c60306354c170469d38159611f5e6e50de27ce9869f0001e40a67707bd7c42e929ba929be2b19ea5ad26dd4ab78261cf58"
}
}
```
# Retrieve Charge
Source: https://docs.zbdpay.com/payments/api/lightning-charges/retrieve
GET https://api.zbdpay.com/v0/charges/{id}
Retrieve all data about a single Charge.
## Usage
While the best approach is to rely on the `callbackUrl` property and expect async Charge updates sent from ZBD servers, this API can be used to check any information about any Charge, specifically properties such as `status` and `internalId` which are likely useful for your application.
For most use cases it is unlikely you will hit a rate limit, however it is recommended to avoid practices such as "long polling" especially if your server collectively "long polls" for multiple clients as this could cumulatively cause a rate limit to be reached.
## Configuration
### Path Parameters
Charge ID
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"message": "Successfully retrieved Charge.",
"data": {
"unit": "msats",
"amount": "10000",
"confirmedAt": null,
"status": "pending",
"description": "My Charge Description",
"createdAt": "2020-05-09T15:09:05.765Z",
"expiresAt": "2020-05-09T15:14:05.618Z",
"id": "1907b0fe-789b-4e25-b18a-0c4c0f5cced7",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"callbackUrl": "https://your-website.com/callback",
"invoice": {
"request": "lnbc100n1p0td3u3pp5z2ed9yjfrz0rgu0fzuc5cdwfu8dtjlgrfztz5uga8hakkjy2yzgsdpzf4ujqsmgv9exwefqg3jhxcmjd9c8g6t0dccqzpgxqzfvsp5q8z5mkghmuzrnusxdwtmls7x8vuy63j25rt4z55gj3s7340dv72q9qy9qsqz02rlmlzcvew3vk90c6l0369ewk7tkr2tx0yrk3qa235v07w6d3qeksk99wm7y8f8ug7zqy6yjudu4cs2f4umpey43cw7msyj7uqj2qq8x03te",
"uri": "lightning:lnbc100n1p0td3u3pp5z2ed9yjfrz0rgu0fzuc5cdwfu8dtjlgrfztz5uga8hakkjy2yzgsdpzf4ujqsmgv9exwefqg3jhxcmjd9c8g6t0dccqzpgxqzfvsp5q8z5mkghmuzrnusxdwtmls7x8vuy63j25rt4z55gj3s7340dv72q9qy9qsqz02rlmlzcvew3vk90c6l0369ewk7tkr2tx0yrk3qa235v07w6d3qeksk99wm7y8f8ug7zqy6yjudu4cs2f4umpey43cw7msyj7uqj2qq8x03te"
}
}
}
```
# Get Static Charge
Source: https://docs.zbdpay.com/payments/api/lightning-charges/retrieve-static
GET https://api.zbdpay.com/v0/static-charges/{id}
Retrieve all data about a single Static Charge.
You should rely on `callbackUrl` property and expect async Static Charge updates sent from ZBD servers. However, this API can be used to check any information about any specific Static Charge, specifically properties such as `slots`, `successMessage`, and `status`.
## Configuration
### Path Parameters
Static Charge ID
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"message":"Successfully fetched Static Charge.",
"data":{
"id":"45c225b1-022b-4a37-98d6-5a5568f78d11",
"unit":"msats",
"slots":0,
"minAmount":"10000",
"maxAmount":"100000",
"createdAt":"2023-03-07T20:07:06.910Z",
"expiresAt":null,
"internalId":"myInternalId",
"description":"This is my static charge",
"callbackUrl":"https://my-website/zbd-callback",
"allowedSlots":1000,
"successMessage":"Congratulations your payment was successful!",
"status":"active",
"invoice":{
"request":"lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9aex2ut4v4ehgttnw3shg6tr943ksctjvajhxte5x43nyv34vgcj6vpjxf3z6drpxvmj6wfcvsmz6dtpx56nvwrxxuuxgvf3uzvpfy",
"uri":"lightning:lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9aex2ut4v4ehgttnw3shg6tr943ksctjvajhxte5x43nyv34vgcj6vpjxf3z6drpxvmj6wfcvsmz6dtpx56nvwrxxuuxgvf3uzvpfy"
}
}
}
```
# Update Static Charge
Source: https://docs.zbdpay.com/payments/api/lightning-charges/update-static
PATCH https://api.zbdpay.com/v0/static-charges/{id}
Change the configuration of a Static Charge QR code.
## Usage
Use this API endpoint with the specific Static Charge ID to update its properties. Usually you'd use this API for the purposes of `increasing slots` or `changing min/max amount` settings.
Updating a Static Charge **WILL NOT modify its QR code**. The point of a Static Charge is that it **does not change**, while its contents can remain dynamic.
## Configuration
### Path Parameters
Static Charge ID
### Header Parameters
ZBD Project API Key
Content Type
### Body
Minimum allowed amount for the Static Charge -> in millisatoshis
Maximum allowed amount for the Static Charge -> in millisatoshis
Note or comment for this Static Charge (visible to payer)
Message displayed to the payer AFTER payment settles
Number of payments this Static Charge can accept
Open metadata string property
The endpoint ZBD will POST Charge updates to
```json Response theme={null}
{
"message":"Successfully editted Static Charge.",
"data":{
"id":"45c225b1-022b-4a37-98d6-5a5568f78d11",
"unit":"msats",
"slots":0,
"minAmount":"10000",
"maxAmount":"100000",
"createdAt":"2023-03-07T20:07:06.910Z",
"expiresAt":null,
"internalId":"myInternalId",
"description":"This is my static charge",
"callbackUrl":"https://my-website/zbd-callback",
"allowedSlots":1000,
"successMessage":"Congratulations your payment was successful!",
"status":"active",
"invoice":{
"request":"lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9aex2ut4v4ehgttnw3shg6tr943ksctjvajhxte5x43nyv34vgcj6vpjxf3z6drpxvmj6wfcvsmz6dtpx56nvwrxxuuxgvf3uzvpfy",
"uri":"lightning:lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9aex2ut4v4ehgttnw3shg6tr943ksctjvajhxte5x43nyv34vgcj6vpjxf3z6drpxvmj6wfcvsmz6dtpx56nvwrxxuuxgvf3uzvpfy"
}
}
}
```
# Lightning Payments
Source: https://docs.zbdpay.com/payments/api/lightning-payments
How to send instant payments to Lightning Addresses using ZBD Payments APIs.
Section coming soon.
# Retrieve Payment
Source: https://docs.zbdpay.com/payments/api/lightning-payments/retrieve
GET https://api.zbdpay.com/v0/payments/{id}
Retrieve all data about a single Payment.
## Usage
Use this API endpoint to get all of the properties of a given Payment record, including its total fee, processing timestamp, and settlement status.
## Configuration
### Path Parameters
Payment ID
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"message": "Fetched Payment.",
"data": {
"id": "caafd318-527c-466b-81f2-441d3a092aae",
"fee": "2000",
"unit": "msats",
"amount": "101000",
"invoice": "lnbc1010n1p3mt8akpp5uyxhllflux2fvl36wjxh80wtqzdh2vjmu8cdyzuap578az80v74qdqcd3hzucmpwd5zqurp09kk2mn5cqzpgxqzjhsp550s770zy4puj76wqnua0hmym883gr07dhuast5ygcm44grl6z7ns9qyyssqgf7sumdmxwzgkq2m0h9lcv530sqs0m4t4shlu98djrrckrtulcmr8rear70dyftdm67jvgncxgz4jmd6ksx87jvnj88e39un48ssk4gp8vs4u5",
"preimage": "8a14f6da89d4a8ffd09677f585b7c377de72744b7c3713d3c115fa71ca4fc290",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"processedAt": "2023-01-04T15:48:29.805Z",
"confirmedAt": "2023-01-04T15:48:29.805Z",
"description": "Custom Payment Description",
"status": "completed"
}
}
```
# Send Payment
Source: https://docs.zbdpay.com/payments/api/lightning-payments/send
POST https://api.zbdpay.com/v0/payments
Start sending instant Bitcoin payments through the ZBD API.
## Description
This endpoint sends a payment on the Bitcoin Lightning Network. This is one of the main APIs which allow you to pay any [Charge](/payments/glossary#charge) in the network.
The words *Charge*, *Payment Request*, and *Invoice* can be seen as equivalent in the context of requesting funds in the Bitcoin Lightning Network.
## Usage
All payments in the Lightning Network are asynchronous. Though possible, most payments will not settle immediately on the API invocation. They do however tend to settle *immediately thereafter*, which means you **MUST** to provide the `callbackUrl` to receive updates about your app's payments.
If the Charge does not have a predefined amount (e.g. an `amountless invoice`), you can pass an `amount` property with a defined value to this API call.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
Lightning Network Payment Request / Charge
Note or comment for this Payment
Amount to be paid to this Charge/Invoice -> in millisatoshis *(only valid if Amountless Invoice)*
Open metadata string property
The endpoint ZBD will POST Payment updates to
```json Response theme={null}
{
"success": true,
"message": "Payment done.",
"data": {
"id": "caafd318-527c-466b-81f2-441d3a092aae",
"fee": "2000",
"unit": "msats",
"amount": "101000",
"invoice": "lnbc1010n1p3mt8akpp5uyxhllflux2fvl36wjxh80wtqzdh2vjmu8cdyzuap578az80v74qdqcd3hzucmpwd5zqurp09kk2mn5cqzpgxqzjhsp550s770zy4puj76wqnua0hmym883gr07dhuast5ygcm44grl6z7ns9qyyssqgf7sumdmxwzgkq2m0h9lcv530sqs0m4t4shlu98djrrckrtulcmr8rear70dyftdm67jvgncxgz4jmd6ksx87jvnj88e39un48ssk4gp8vs4u5",
"preimage": "8a14f6da89d4a8ffd09677f585b7c377de72744b7c3713d3c115fa71ca4fc290",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"status": "completed"
"processedAt": "2023-01-04T15:48:29.805Z",
"confirmedAt": "2023-01-04T15:48:29.805Z",
"description": "Custom Payment Description",
}
}
```
# OpenAPI
Source: https://docs.zbdpay.com/payments/api/resources/openapi
Explore the OpenAPI specification for the ZBD Payments API.
The official OpenAPI specification for the ZBD Payments API.
# Utilities
Source: https://docs.zbdpay.com/payments/api/utils
Utility APIs for developers integrating with ZBD Payments.
Section coming soon.
# BTC USD Price Feed
Source: https://docs.zbdpay.com/payments/api/utils/btc-usd
GET https://api.zbdpay.com/v0/btcusd
Get the latest price for Bitcoin in US Dollars.
## Description
The exchange rate feed is refreshed every 5 seconds and is based upon a combination of industry-leading partner exchange providers's price feeds.
## Usage
Use this API to show your users the correct USD value when paying any Satoshis/BTC Charges or Payment Requests. This API allows you to stay synced with ZBD on the `price of Bitcoin`.
```json Response theme={null}
{
"success": true,
"data": {
"btcUsdPrice": "16825",
"btcUsdTimestamp": "1672847113"
},
"message": "Successfully retrieved BTC USD price ticker information."
}
```
# ZBD IP Address
Source: https://docs.zbdpay.com/payments/api/utils/ip
GET https://api.zbdpay.com/v0/prod-ips
Get the official IP addresses of ZBD servers.
## Description
The ZBD API relies on callback URLs for keeping you informed about updates that occur to any Charges, Payments, or Withdrawals you've created. In order to ensure that any incoming callback message is indeed from a trusted ZBD API infrastructure server, we provide this API endpoint for you to know which IP addresses `real` requests come from.
## Usage
The idea is to use this API endpoint to fetch the production IP addresses for ZBD servers, such that when you receive a callback about a payment having settled, you can check the originating IP address and confirm it indeed came from ZBD.
ZBD has a static set of IP addresses so, though possible, it is unlikely we will be changing these IPs often.
## Configuration
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"data": {
"ips": [
"3.225.112.64"
]
}
}
```
# API Supported Regions
Source: https://docs.zbdpay.com/payments/api/utils/is-supported-region
GET https://api.zbdpay.com/v0/is-supported-region/{IP_ADDRESS}
Verify if a user is coming from a supported region.
## Description
The ZBD API is available in over 100 countries around the world, and we're always aiming to expand our reach.
If you wish to know whether the incoming user request is coming from a region where ZBD is supported or not, you can use this simple API endpoint and pass the target IP address as a parameter.
## Usage
The idea behind this endpoint is that in order to serve your users the best way possible, you should check where they are located and ensure that they can make use of ZBD services.
## Configuration
### Path Parameters
IP address to check
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"data": {
"ipAddress": "66.109.221.0",
"isSupported": true,
"ipCountry": "US",
"ipRegion": "CO"
}
}
```
# Vouchers
Source: https://docs.zbdpay.com/payments/api/vouchers
How to create and manage Vouchers using ZBD Payments APIs.
Section coming soon.
# Create Voucher
Source: https://docs.zbdpay.com/payments/api/vouchers/create
POST https://api.zbdpay.com/v1/create-voucher
## Description
Debits your Project wallet to create a single-time use [ZBD Voucher](/get-started/vouchers). Returns a valid 8-digit voucher Code which can be redeemed by any ZBD user to claim the sats (crediting their account). Creating a voucher takes either a fee of 1 sat or 1% of the voucher amount.
ZBD Vouchers are redeemable by any ZBD user, via the Developer Dashboard or ZBD App.
## Usage
You can create vouchers any time you want to send another ZBD user sats from a Project Wallet. For example, you could run a giveaway by programatically creating the required number of vouchers and distributing the Codes to users accordingly.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount for the Charge -> in millisatoshis
Note or comment for this Charge (visible to payer)
```json Response theme={null}
{
"success": true,
"data": {
"amount": "1000",
"code": "7EE15185",
"createdAt": "2023-08-24T15:01:56.408Z",
"createTransactionId": "0e11be7a-fd5e-48db-a0bb-54731681bc25",
"description": "Voucher for user.",
"fee": "1000",
"id": "a2eb43c4-af7f-4eb9-839c-ca31db34b3fc",
"unit": "msats",
"walletId": "4a4bd549-297e-4e67-a594-386200e1bc21"
},
"message": "Successfully created Voucher."
}
```
# Redeem Voucher
Source: https://docs.zbdpay.com/payments/api/vouchers/redeem
POST https://api.zbdpay.com/v0/redeem-voucher
## Description
Credits your Project wallet by claiming a single-time use [ZBD Voucher](/get-started/vouchers).
## Usage
Enter a valid 8-digit voucher Code to redeem the sats to your Project wallet.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
Valid 8-digit ZBD Voucher Code
```json Response theme={null}
{
"success": true,
"data": {
"amount": "1000",
"code": "7EE15185",
"createdAt": "2023-08-24T15:01:56.408Z",
"description": "Voucher for user.",
"id": "a2eb43c4-af7f-4eb9-839c-ca31db34b3fc",
"redeemedAt": "2023-08-24T15:03:43.333Z",
"redeemedById": "4a4bd549-297e-4e67-a594-386200e1bc21",
"redeemedTransactionId": "656695f9-36e3-4b9c-abfa-8c2e90f61b45",
"revokedAt": null,
"revokedById": null,
"revokedTransactionId": null,
"unit": "msats"
},
"message": "Successfully redeemed Voucher."
}
```
# Retrieve Voucher
Source: https://docs.zbdpay.com/payments/api/vouchers/retrieve
GET https://api.zbdpay.com/v0/vouchers/{VOUCHER_ID}
## Description
Retrieves details for a [ZBD Voucher](/get-started/vouchers). Returns whether the provided ID corresponds to a valid Voucher, and details about a valid Voucher.
## Usage
You can retrieve details about a voucher at any time, including whether it is valid, redeemed, or revoked.
## Configuration
### Path Parameters
ID of the Voucher
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"data": {
"amount": "1000",
"code": "7EE15185",
"createdAt": "2023-08-24T15:01:56.408Z",
"createTransactionId": "0e11be7a-fd5e-48db-a0bb-54731681bc25",
"description": "Voucher for user.",
"id": "a2eb43c4-af7f-4eb9-839c-ca31db34b3fc",
"redeemedAt": null,
"redeemedById": null,
"redeemedTransactionId": null,
"revokedAt": null,
"revokedById": null,
"revokedTransactionId": null,
"updatedAt": null,
"unit": "msats",
"walletId": "4a4bd549-297e-4e67-a594-386200e1bc21"
},
"message": "Successfully retrieved Voucher."
}
```
# Revoke Voucher
Source: https://docs.zbdpay.com/payments/api/vouchers/revoke
POST https://api.zbdpay.com/v0/revoke-voucher
## Description
Credits your Project wallet by revoking a valid (non-redeemed, non-revoked) single-time use [ZBD Voucher](/get-started/vouchers).
## Usage
Enter a valid 8-digit voucher Code to reclaim the sats to your Project wallet. Revoke a voucher if you don't want the Voucher to be redeemable by another user.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
Valid 8-digit ZBD Voucher Code
```json Response theme={null}
{
"success": true,
"data": {
"amount": "1000",
"code": "E044A15A",
"createdAt": "2023-08-24T15:04:19.927Z",
"description": "Voucher for user.",
"id": "8703d5da-6b38-499f-b543-c6e73543b371",
"redeemedAt": null,
"redeemedById": null,
"redeemedTransactionId": null,
"revokedAt": "2023-08-24T15:04:41.196Z",
"revokedById": "4a4bd549-297e-4e67-a594-386200e1bc21",
"revokedTransactionId": "34f5abab-3f36-4fb3-b25a-4d54b0ad0924",
"unit": "msats"
},
"message": "Successfully revoked Voucher."
}
```
# Wallet
Source: https://docs.zbdpay.com/payments/api/wallet
How to manage your ZBD Wallet using ZBD Payments APIs.
Section coming soon.
# Initiate Internal Transfer
Source: https://docs.zbdpay.com/payments/api/wallet/internal-transfer
POST https://api.zbdpay.com/v0/internal-transfer
Performs a transfer of funds between two Projects.
## Usage
The API Key used is the Project Wallet that is `SPENDING` the funds, so the `apikey` used in this request must be the `SENDER` Project Wallet.
In the body payload, the API also expects a `receiverWalletId`. This Project Wallet ID has to match the `RECEIVING` Project Wallet ID, which can be found in the ZBD Developer Dashboard under Project Details.
This API is primarily to be used for any programmatic movement of funds between any two of your Projects.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount to be transferred -> in millisatoshis
The Wallet ID of the recipient Project
```json Response theme={null}
{
"success": true,
"data": {
"id": "c8571a4c-3c34-47af-8ded-ebd476f519c1",
"senderWalletId": "b81fa874-ac60-4a08-84f2-0af79684c506",
"receiverWalletId": "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6",
"userId": "2470d896-9dc8-4d49-b18c-a4e83263e76d",
"sendTxId": "f532db20-2cfa-41b0-8c00-40cfbe124b54",
"receiveTxId": "4b4640e0-d8a2-4f1e-8973-d98196f79a88",
"status": "TRANSFER_STATUS_COMPLETED",
"amount": "1000",
"createdAt": "2023-02-16T02:28:32.754Z",
"updatedAt": "2023-02-16T02:28:32.777Z"
},
"message": "Internal Transfer done."
}
```
# Get Wallet
Source: https://docs.zbdpay.com/payments/api/wallet/retrieve-balance
GET https://api.zbdpay.com/v0/wallet
Retrieve all data about a ZBD Project's Wallet.
To retrieve the balance of the Wallet for a specific ZBD Project, just make sure to use that Project's API Key in the `apikey` header property in the API endpoint.
## Configuration
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"message": "Successfully retrieved Wallet.",
"data": {
"unit": "msats",
"balance": "384000"
}
}
```
# Withdrawal Requests
Source: https://docs.zbdpay.com/payments/api/withdrawal-requests
How to create and manage Withdrawal Requests using ZBD Payments APIs.
Section coming soon.
# Create Withdrawal Request
Source: https://docs.zbdpay.com/payments/api/withdrawal-requests/create
POST https://api.zbdpay.com/v0/withdrawal-requests
Start creating Bitcoin voucher QR codes.
## Description
Withdrawal Requests can be thought of as exact opposites to Charges. Charges in the ZBD API are QR codes that represent Payment Requests in the Bitcoin Lightning Network. These QR codes expect that a payer will scan and perform a **payment** against it.
A Withdrawal Request is the same in that it also is represented as a QR code. But unlike Charges, Withdrawal Requests are QR codes that someone scans to **receive** Bitcoin. You can read more about the LNURL Withdrawal specification [here](https://github.com/lnurl/luds/blob/luds/03.md).
Think of it like this:
* **Charges** -> Lightning QR codes that **YOU SPEND**
* **Withdrawal Requests** -> Lightning QR codes that **YOU RECEIVE**
## Usage
The most common use of this API endpoint are 1) Fintechs adding the ability for Withdrawals / Payouts through the Lightning Network, and 2) Apps and Games sending Bitcoin microrewards through Withdrawal QR codes / redeem codes.
Every Withdrawal Request will be in a `pending` state until someone scans the QR code and claims the funds.
Withdrawal Requests created by ZBD API are `single-use` and will not work if attempted again.
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body
The amount for the Withdrawal Request -> in millisatoshis
Note or comment for this Withdrawal Request
Time until Withdrawal Request expiration -> in seconds
Open metadata string property
The endpoint ZBD will POST Charge updates to
```json 200 Response theme={null}
{
"success": true,
"data": {
"id": "e54e62d4-9cfa-495d-abb9-9c9f4bc4f2cf",
"unit": "msats",
"amount": "15000",
"createdAt": "2023-04-27T22:15:54.258Z",
"expiresAt": "2023-04-27T22:20:54.252Z",
"internalId": "1c3b1-f61j2",
"description": "Withdraw QR!",
"callbackUrl": "https://your-website.com/zbd-callback",
"status": "pending",
"fee": null,
"invoice": {
"request": "lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apax5exxwpjx9jx2wf4xajnxc3sx4jrwcenv56nwdm9vg6kxwtrx9sk2dtzvsunxce3vymkxef4vycxvwpexd3kxcmpxcmk2d3n8yenswqph63m6",
"fastRequest": "lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7arpvu7hw6t5dpj8ycth2fjhzat9wd6zv6e3856nycecxgckgefex5mk2vmzxq6kgdmrxdjn2dehv43r2ceevvckzef4vfjrjvmrx9snwcm9x4snqe3c8yekxcmrvymrwefkxvunxwpcyekkjmjhd96xserjv9mkzcnvv57nzdfsxqczvmtp0ptkjargv3exzampvfkx20f3x5crqvpxv3jkvct4d36ygetnvdexjur5d9hku02hd96xserjv9mjq52jyynxxctvd33xzcmt8458garswvaz7tmpwp5ju7n9vfjkget99e5k7tmkxqhhqun0vdjhxuedwa5hg6rywfshwctv94ex2ut4v4ehg5thy6x",
"uri": "lightning:lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apax5exxwpjx9jx2wf4xajnxc3sx4jrwcenv56nwdm9vg6kxwtrx9sk2dtzvsunxce3vymkxef4vycxvwpexd3kxcmpxcmk2d3n8yenswqph63m6",
"fastUri": "lightning:lnurl1dp68gurn8ghj7ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7arpvu7hw6t5dpj8ycth2fjhzat9wd6zv6e3856nycecxgckgefex5mk2vmzxq6kgdmrxdjn2dehv43r2ceevvckzef4vfjrjvmrx9snwcm9x4snqe3c8yekxcmrvymrwefkxvunxwpcyekkjmjhd96xserjv9mkzcnvv57nzdfsxqczvmtp0ptkjargv3exzampvfkx20f3x5crqvpxv3jkvct4d36ygetnvdexjur5d9hku02hd96xserjv9mjq52jyynxxctvd33xzcmt8458garswvaz7tmpwp5ju7n9vfjkget99e5k7tmkxqhhqun0vdjhxuedwa5hg6rywfshwctv94ex2ut4v4ehg5thy6x"
}
},
"message": "Successfully created Withdrawal Request."
}
```
```json 400 Response theme={null}
{
"success": false,
"message": "The minimum Withdrawal amount supported is 10 satoshis."
}
```
# Retrieve Withdrawal Request
Source: https://docs.zbdpay.com/payments/api/withdrawal-requests/retrieve
GET https://api.zbdpay.com/v0/withdrawal-requests/{id}
Retrieve all data about a single Withdrawal Request.
## Configuration
### Path Parameters
Withdrawal Request ID
### Header Parameters
ZBD Project API Key
```json Response theme={null}
{
"success": true,
"message": "Successfully retrieved Withdrawal Request.",
"data": {
"unit": "msats",
"amount": "12000",
"status": "pending",
"createdAt": "2020-05-09T15:15:30.222Z",
"expiresAt": "2020-05-09T15:20:30.212Z",
"description": "My Withdrawal Description",
"id": "243ee7f6-a91b-4644-aa5f-ecc9c9fdd351",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"callbackUrl": "https://your-website.com/zbd-callback",
"invoice": {
"request": "lnurl1dp68gurn8ghj7er9wch85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apaxfsnqvmz8pjx2ephxucnzdphxa3xzd3kvfjk2vnyxejnzdf3x93n2e3evesnsetyxsenzvesvdjrxdtrv9jxxdnzxaskxvm9vscrzeg58h24k",
"fastRequest": "lnurl1dp68gurn8ghj7er9wch85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7arpvu7hw6t5dpj8ycth2fjhzat9wd6zv6e385exzvpnvguxgetyxumnzvf5xumkycfkxe3x2efjvsmx2vf4xyckxdtx89nxzwr9vs6rxvfnxp3kgve4vdskgcekvgmkzcenv4jrqvt9yekkjmjhd96xserjv9mkzcnvv57nzv3sxqczvmtp0ptkjargv3exzampvfkx20f3xgcrqvpxv3jkvct4d36ygetnvdexjur5d9hku02d0ys9w6t5dpj8ycthv9kzq3r9wd3hy6tsw35k7m3xvdskcmrzv93kk0tgw368que69uhkgetk9eax2cn9v3jk2tnfduhhvvp0wpex7cm9wdej6amfw35xgunpwaskcttjv4ch2etnwsvtdjtq",
"uri": "lightning:lnurl1dp68gurn8ghj7er9wch85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apaxfsnqvmz8pjx2ephxucnzdphxa3xzd3kvfjk2vnyxejnzdf3x93n2e3evesnsetyxsenzvesvdjrxdtrv9jxxdnzxaskxvm9vscrzeg58h24k",
"fastUri": "lightning:lnurl1dp68gurn8ghj7er9wch85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7arpvu7hw6t5dpj8ycth2fjhzat9wd6zv6e385exzvpnvguxgetyxumnzvf5xumkycfkxe3x2efjvsmx2vf4xyckxdtx89nxzwr9vs6rxvfnxp3kgve4vdskgcekvgmkzcenv4jrqvt9yekkjmjhd96xserjv9mkzcnvv57nzv3sxqczvmtp0ptkjargv3exzampvfkx20f3xgcrqvpxv3jkvct4d36ygetnvdexjur5d9hku02d0ys9w6t5dpj8ycthv9kzq3r9wd3hy6tsw35k7m3xvdskcmrzv93kk0tgw368que69uhkgetk9eax2cn9v3jk2tnfduhhvvp0wpex7cm9wdej6amfw35xgunpwaskcttjv4ch2etnwsvtdjtq"
}
}
}
```
# Global Support
Source: https://docs.zbdpay.com/payments/coverage
List of regions where ZBD Payments APIs, SDKs, and services are supported.
**This page lists region coverage for ZBD Payments products.** For ZBD Rewards product region coverage, please visit [Rewards Coverage](/earn/coverage).
### US States
The ZBD API is available in all US states, **except New York (NY)**.
***
### Countries
The ZBD API is **NOT YET** available in the following countries:
* Afghanistan
* Algeria
* Andorra
* Aruba
* Azerbaijan
* Bahamas
* Bangladesh
* Barbados
* Belarus
* Belize
* Benin
* Bolivia
* Bosnia-Herzegovina
* Botswana
* Burundi
* Cambodia
* Cayman Islands
* Central African Republic
* Chad
* China
* Comoros
* Congo (Brazzaville)
* Costa Rica
* Cuba
* Democratic People’s Republic of Korea (DPRK)
* Democratic Republic of the Congo
* Dominican Republic
* Ecuador
* Equatorial Guinea
* Falkland Islands
* Faroe Islands
* Fiji
* French Polynesia
* Ghana
* Gibraltar
* Greenland
* Guam
* Guatemala
* Guinea
* Guinea-Bissau
* Haiti
* Honduras
* Iran
* Iraq
* Jamaica
* Kiribati
* Kyrgyzstan
* Lao People’s Democratic Republic
* Lebanon
* Lesotho
* Liberia
* Libya
* Liechtenstein
* Macau
* Madagascar
* Maldives
* Mali
* Marshall Islands
* Martinique
* Mauritania
* Mauritius
* Monaco
* Mongolia
* Morocco
* Mozambique
* Myanmar (Burma)
* Nicaragua
* Niger
* Niue
* Norfolk Island
* Oman
* Pakistan
* Palau
* Palestine, State of
* Panama
* Pitcairn
* Russia
* Samoa
* San Marino
* Sao Tome & Prin.
* Saudi Arabia
* Senegal
* Seychelles
* Somalia
* South Sudan
* Sudan
* Syria
* Tanzania
* Timor-Leste
* Togo
* Trinidad and Tobago
* Turkmenistan
* Tuvalu
* Uganda
* Ukraine
* United States Virgin Islands
* Vanuatu
* Vatican City State
* Venezuela
* Vietnam
* Yemen
* Zimbabwe
# Glossary
Source: https://docs.zbdpay.com/payments/glossary
In this documentation portal you will encounter a handful of highly-specific technical terms that are used throughout the ZBD Platform and APIs. Below you will find a Glossary of the main terms used. This list is not exhaustive and is meant to help you understand the concepts and terminology used in the documentation.
## B[](#b "Direct link to heading")
### BOLTs[](#bolts "Direct link to heading")
The [Basis of Lightning Technology (BOLT)](https://github.com/lightning/bolts) are specifications that describe the rules and standards required for participants of the Lightning Network. The standards established by the BOLTs allow different Lightning implementation software to integrate with one another and form a network.
### BOLT11[](#bolt11 "Direct link to heading")
[BOLT11](https://bolt11.org) is the 11th specification document for the BOLTs (Basis of Lightning Technology), and it is the invoice protocol for Lightning Payments. It is a simple, extendable, QR-code-ready protocol for requesting payments over Lightning.
Learn more about BOLT11 on this [interactive visualizer](https://bolt11.org) as well as the core [RFC documentation](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md).
## C[](#c "Direct link to heading")
### Charge[](#charge "Direct link to heading")
A Charge is the name given inside of the ZBD Platform to a Lightning Network invoice (BOLT11) that is sent to a peer to request a Bitcoin payment.
## I[](#i "Direct link to heading")
### Invoice[](#invoice "Direct link to heading")
Invoices, charges, payment requests -- these are all terms for the same thing. Invoices are used to request payments from a peer on the Bitcoin Lightning Network.
## L[](#l "Direct link to heading")
### Lightning Address[](#lightning-address "Direct link to heading")
A [Lightning Address](https://lightningaddress.com) is a unique internet identifier that identifies a user inside of a given provider. It resembles an email address format with `username` @ `provider.com`. The ZBD API allows a developer to send payments to any user of a company, wallet provider, or self-hosted user software that supports the open source protocol.
By leveraging Lightning Addresses a developer is able to support sending payments to users of any provider, with frictionless user experience.
**It's like an email address, but for your Bitcoin.**
Every ZBD user has a unique Lightning Address based on their [ZBD Gamertag](https://zbd.gg) resembling **[satoshi@zbd.gg](mailto:satoshi@zbd.gg)**.
### LNURL[](#lnurl "Direct link to heading")
LNURL is a set of HTTP open API standards that aim to facilitate the interactions between service providers (stores, websites, apps) and wallets (users). The idea is to provide for standardized ways of performing Bitcoin Lightning Network invoice-orchestration and payment-requesting.
LNURL technologis are leveraged inside of the ZBD Platform in places such as Static Charges and Withdrawal Requests. LNURL is also the base protocol for the Lightning Address user standard.
## M[](#m "Direct link to heading")
### Millisatoshi[](#millisatoshi "Direct link to heading")
The ZBD API is built on millisatoshis. 1,000 millisatoshis make up 1 satoshi. And 100 million satoshis make up 1 Bitcoin. This is akin to 100 cents being equal to 1 dollar.
While the API is built with millisatoshis in mind, the currently-allowed minimum amount for transaction sizes is 1 satoshi, or 1,000 millisatoshis. 1 satoshi is currently valued at \$0.0005 USD, and the system was built with scalability in mind, both in amount size, and Bitcoin valuation.
**100,000,000 satoshis = 1 Bitcoin**
**1,000 millisatoshis = 1 satoshi**
## O[](#o "Direct link to heading")
### On-chain[](#on-chain "Direct link to heading")
On-chain is a term used to describe any data that is registered on the Bitcoin blockchain, in contrast with off-chain data, which is not stored on the blockchain. On-chain data are always Bitcoin transactions, while off-chain data can be an unconfirmed Bitcoin transaction or any other type of data.
### Off-chain[](#off-chain "Direct link to heading")
Off-chain is a term used to describe any data that is not registered on the Bitcoin blockchain. Off-chain data can be Bitcoin transactions that were not sent to the blockchain, data on the Lightning Network, or data on other blockchains, such as a sidechain.
## S[](#s "Direct link to heading")
### Satoshi[](#satoshi "Direct link to heading")
Satoshis, or “sats” for short, are the atomic unit of Bitcoin, named after Bitcoin’s creator, Satoshi Nakamoto. A Bitcoin is equal to 100 million satoshis (1 BTC = 100,000,000 sats).
**There will only ever be 21 million bitcoin, and there will only ever be 2.1 quadrillion sats.**
This makes Bitcoin more divisible, enabling payments smaller than $0.01 at current prices. 1 satoshi is currently valued at ~$0.0005 USD.
## V[](#v "Direct link to heading")
### Voucher[](#voucher "Direct link to heading")
A ZBD Voucher is an 8-digit code that can be used in any product in the ZBD suite to redeem for Bitcoin on the Lightning Network. It is usually used as a tool for onboarding new users to Bitcoin.
Learn more about the capabilities of ZBD Vouchers on [this thread](https://twitter.com/andreneves/status/1517572121609879552).
## W[](#w "Direct link to heading")
### Withdrawal Request[](#withdrawal-request "Direct link to heading")
A Withdrawal Request is the direct opposite of a Payment Request (or Charge). The Withdrawal Request is used to request a withdrawal **from** a user's wallet, whereas a Payment Request is used to request a payment **to** a user's wallet.
While both user flows are nearly identical -- scan QR code and press submit -- behind the scenes one flow is sending Bitcoin over Lightning while the other is **request Bitcoin to be sent over Lightning**. If you ever want to **receive Bitcoin by scanning a QR code**, then that's what a Withdrawal Request effectively enables.
# Lightning Address
Source: https://docs.zbdpay.com/payments/lightning-address
The human-readable payment protocol that transformed Bitcoin UX forever
Lightning Address is the protocol that made Bitcoin payments as simple as sending an email. Created by Andre Neves (CTO of ZBD) in 2021, it has become the standard for user-friendly Bitcoin payments, processing millions of transactions across hundreds of apps and services globally.
**Fun Fact**: Lightning Address was invented at ZBD to solve a real problem – our users were terrified of long Bitcoin Lightning invoices. Today, it's an open protocol used by the entire Lightning ecosystem.
[user@domain.com](mailto:user@domain.com) instead of lnbc1pvjluezpp5qqqsyq...
One address, unlimited payments. No more invoice generation.
Works across all supporting wallets and services globally.
## The UX Revolution
### Before Lightning Address (2009-2021)
```bash theme={null}
# Bitcoin address (hard to remember, changes each time)
bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh
# Lightning invoice (expires, single use, even longer)
lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w
```
**Problems:**
* 🤯 Impossible to memorize
* ⏱️ Invoices HAVE to expire at a certain time
* 🔄 New address / invoice needed for each payment
* 📱 Required QR codes or copy-paste
### After Lightning Address (2021-Present)
```bash theme={null}
# Lightning Address (simple, permanent, reusable)
andre@zbd.gg
```
**Solved:**
* ✅ Easy as email – memorizable and shareable
* ✅ Works 24/7 – receive payments while you sleep
* ✅ One address forever – put it in your bio
* ✅ No QR codes needed – just type it
## How Lightning Address Works
Sender enters `gamer@zbd.gg` in any Lightning wallet
Wallet looks up `https://zbd.gg/.well-known/lnurlp/gamer`
ZBD creates a fresh Lightning invoice for this payment
Standard Lightning payment flows to recipient
```mermaid theme={null}
sequenceDiagram
participant User
participant Wallet
participant ZBD Server
participant Recipient
User->>Wallet: Pay andre@zbd.gg
Wallet->>ZBD Server: GET /.well-known/lnurlp/andre
ZBD Server->>Wallet: Payment details + invoice
Wallet->>ZBD Server: Lightning payment
ZBD Server->>Recipient: Payment received!
```
## Real-World Impact
Since its creation in 2021, Lightning Address has transformed Bitcoin payments and ZBD is here to support it.
Maintaining the protocol specification, contributing improvements back to community, and advocating for widespread adoption.
### Success Stories
**🎮 Gaming Revolution**
* Players share addresses as gamertags
* Streamers receive tips without interruption
* Tournament payouts to `player@zbd.gg`
* Cross-game portable identity
**💸 Creator Economy**
* Artists put addresses in social bios
* Direct fan-to-creator payments
* No platform fees or restrictions
* Instant global monetization
**🌍 Global Remittances**
* Families share memorable addresses
* No bank account required
* Instant settlement, minimal fees
* Works on basic smartphones
## Why Lightning Address Matters
### 1. Mainstream-Ready UX
**Email Model**: Everyone understands email. Lightning Address uses the same mental model – user\@domain – making Bitcoin accessible to billions.
No technical knowledge required. No long strings. No QR codes. Just human-readable addresses.
**Set It and Forget It**: Unlike invoices that expire or addresses that change, your Lightning Address is permanent. Put it on business cards, social profiles, or billboards.
Receive payments 24/7/365 without generating new invoices.
**Universal Standard**: Send from any supporting wallet to any other supporting service. Like email, it just works across providers.
ZBD to Cash App – all seamless.
### 2. Enhanced Privacy
* No on-chain footprint for address lookups
* Rotating invoices prevent payment correlation
* Optional sender/receiver metadata
* No public address / invoice reuse
### 3. Developer Friendly
```javascript Node.js theme={null}
// Send to Lightning Address
const payment = await zbd.sendLightningAddress({
lnAddress: 'andre@zbd.gg',
amount: 1000, // sats
comment: 'Thanks for creating this!'
});
// Validate Lightning Address
const isValid = await zbd.validateLightningAddress({
lnAddress: 'user@domain.com'
});
```
```python Python theme={null}
# Create Lightning Address for user
address = zbd.create_lightning_address(
username="newuser",
user_id="usr_123"
)
# Returns: newuser@zbd.gg
# Receive notification on payment
@webhook_handler
def payment_received(data):
print(f"Received {data.amount} sats")
```
## Advanced Features
### Custom Domains
Run Lightning Address on your own domain:
```nginx theme={null}
# Nginx config for yourgame.com
location /.well-known/lnurlp/ {
proxy_pass https://api.zbdpay.com/lnurlp/;
proxy_set_header Host api.zbdpay.com;
}
```
Now users can have `player@yourgame.com` addresses!
## The Future of Lightning Address
ZBD continues to evolve the protocol:
* **🔜 Multi-Currency Support**: Send USD and receive BTC seamlessly
* **🔜 Cross-Currency Payments**: Automatic currency conversion on payment
* **🔜 Bitcoin Onchain**: Support for traditional Bitcoin addresses (fallback)
* **🔜 BOLT12 Integration**: Enhanced Lightning Network features
**Want to onramp users directly to Lightning Addresses?**
[ZBD Ramp](/payments/ramp) is the first and only fiat-to-crypto widget that supports Lightning Address delivery. Let your users buy Bitcoin and receive it instantly at their Lightning Address!
## Start Using Lightning Address
[Contact our team](https://zbd.one/sales) to get your API keys
Use our SDKs to create and manage Lightning Addresses
Help users understand their new superpower
Complete Lightning Address API docs
Quick integration with our SDKs
Ramp directly to Lightning Addresses
***
Lightning Address is an open protocol. While ZBD created and maintains it, it's free for anyone to implement. We're proud to have contributed this UX breakthrough to the Bitcoin ecosystem and continue supporting its growth.
# Lightning Network
Source: https://docs.zbdpay.com/payments/lightning-network
Instant global payments that unlock new business models impossible with traditional systems
The Lightning Network transforms Bitcoin from digital gold into a global payment rail capable of millions of transactions per second. It's not just faster Bitcoin – it's an entirely new paradigm for moving money.
Payments settle in milliseconds, not minutes or days
Send 1 cent for \$0.0001 in fees. Finally, micropayments that work.
Millions of TPS capacity. Built for the scale of the internet.
## What Makes Lightning Different
### Traditional Payments vs Lightning
**Credit Cards**: 2-3 business days to settle\
**Bank Transfers**: 1-5 business days\
**Bitcoin**: 10-60 minutes\
**Lightning**: \< 1 second ⚡
Lightning payments are literally faster than loading a webpage.
**Credit Cards**: `2.9% + $0.30`\
**International Wire**: `$25-50`\
**Bitcoin**: `$1-20` (varies)\
**Lightning**: `< $0.01` (typical)
Send 1 cent profitably.
## New Business Models Now Possible
Lightning enables entirely new ways to monetize and transfer value that were impossible before:
### 💰 True Micropayments
Finally, payments smaller than a dollar that actually make sense:
* \$0.01 to read an article
* \$0.001 per API call
* \$0.05 to skip ads
* Tips as small as \$0.0001
* Buy items for pennies
* Micro-wagers on matches
* Pay-to-play arcade style
* Fractional tournament fees
### 🌍 Instant Global Settlement
Send money anywhere, instantly, 24/7/365:
```javascript theme={null}
// Monday 3am in Tokyo → Sunday 2pm in New York
// Settlement: 847 milliseconds
// Fee: $0.003
// No banks involved
await zbd.send({
amount: 1000000, // sats (~$500)
receiver: 'business@tokyo.jp',
comment: 'Invoice #12345'
});
```
**Unlocked Use Cases:**
* Global gig economy payments
* Cross-border gaming economies
* International remittances
* 24/7 market settlement
### ⚡ Machine-to-Machine Payments
APIs and IoT devices that pay each other automatically:
```javascript theme={null}
// Car pays for parking by the second
while (parked) {
await payParkingMeter({
amount: 0.001, // $0.001 per second
meterId: 'meter_sf_123'
});
await sleep(1000);
}
```
**Future Applications:**
* Self-paying autonomous vehicles
* IoT device micropayments
* AI agents with wallets
* Automated supply chains
## How Lightning Actually Works
Think of Lightning like having bar tabs across the internet. Instead of settling every drink immediately, you keep a running tab and settle up later.
### The Bar Tab Analogy
You and the bartender each put \$100 in a lockbox (the channel)
Each drink updates the balance. You owe more, bartender owes less.
Your friend can pay through your tab if they know the bartender
Close the tab and take your remaining balance
### Technical Architecture
```mermaid theme={null}
graph TB
A[Your Wallet] ---|Payment Channel| B[ZBD Node]
B ---|Routing| C[Lightning Network]
C ---|Multiple Hops| D[Recipient]
style A fill:#f9f,stroke:#333,stroke-width:2px
style D fill:#9f9,stroke:#333,stroke-width:2px
```
**Key Concepts:**
Two-party Bitcoin smart contracts that enable unlimited off-chain transactions. Only opening and closing hit the blockchain.
Payments find the best path through multiple channels automatically. Like internet packet routing, but for money.
HTLCs (Hash Time-Locked Contracts) ensure payments either complete fully or fail completely. No money gets stuck.
Channels need Bitcoin on both sides to route payments. ZBD manages this complexity for you.
## Common Myths Debunked
**"Lightning is too complex for users"**
Reality: Users just see an email-like address ([user@zbd.gg](mailto:user@zbd.gg)). The complexity is abstracted away, just like email hides SMTP.
**"Lightning is centralized"**
Reality: 15,000+ nodes globally. More decentralized than traditional DNS or BGP internet routing.
**"Lightning is still experimental"**
Reality: \$400M+ total network capacity, processing millions of payments daily across major apps and games.
## Building on Lightning
### Quick Start Examples
```javascript Node.js theme={null}
// Receive streaming payments
const invoice = await zbd.createCharge({
amount: 1000, // sats
description: 'Power-up purchase'
});
// Send instant payment
await zbd.sendPayment({
receiver: 'gamer@zbd.gg',
amount: 500,
comment: 'GG! Nice win'
});
```
```python Python theme={null}
# Generate Lightning invoice
invoice = zbd.create_charge(
amount=1000,
description="API credits"
)
# Pay Lightning Address
payment = zbd.send_payment(
receiver="api@zbd.gg",
amount=100
)
```
### Best Practices
Begin with simple send/receive before complex flows
Use satoshis (1 BTC = 100M sats) for precision
## The Future is Streaming Money
Lightning isn't just an improvement to payments – it's a fundamental shift in how money moves. Just as the internet packetized information, Lightning packetizes value.
### What's Next
* **AI Agents**: LLMs with Lightning wallets paying for resources
* **Streaming Contracts**: Smart contracts that execute based on payment flows
* **Global Gaming Economies**: Truly borderless in-game currencies
* **Machine Economy**: Billions of devices transacting autonomously
Get your API keys and build the next generation of payment experiences. The internet of money is here.
## Resources
Human-readable payment addresses
Complete Lightning API docs
Step-by-step implementation
***
Lightning Network is open source and permissionless. While you can technically run your own node, ZBD handles all of the complexity of channel management, liquidity, and routing so you can focus on building great experiences.
# MCP Server
Source: https://docs.zbdpay.com/payments/mcp
Extend the capabilities of your AI Agents with ZBD Payments as an MCP Server
## What is MCP?
MCP is a protocol for integrating tools with AI Agents. It can greatly enhance the capabilities of your AI Agents by providing them with real-time data and context.
ZBD has MCP support built into the [ZBD Payments TypeScript SDK](/payments/sdk/typescript).
## Using ZBD Payments as an MCP server
You need a MCP-capable Agent environment to use ZBD Payments as an MCP server. A few of them are Claude and Cursor.
### Claude
Add the following server definition to your claude\_desktop\_config.json file:
```json theme={null}
{
"mcpServers": {
"zbd": {
"command": "npx",
"args": ["-y", "@zbdpay/payments-sdk-mcp", "--client=claude"],
"env": {
"ZBD_PAYMENTS_API_KEY": "YOUR_ZBD_API_KEY"
}
}
}
}
```
## Filtering tools
You can run the package on the command line to discover and filter the set of tools that are exposed by the ZBD MCP Server. This can be helpful for large APIs where including all endpoints at once is too much for your AI's
context window.
You can filter by multiple aspects:
* `--tool` includes a specific tool by name
* `--resource` includes all tools under a specific resource, and can have wildcards, e.g. `my.resource*`
* `--operation` includes just read (get/list) or just write operations
See more information with `--help`.
All of these command-line options can be repeated, combined together, and have corresponding exclusion versions (e.g. `--no-tool`).
Use `--list` to see the list of available tools, or see below.
### Specifying the MCP Client
Different clients have varying abilities to handle arbitrary tools and schemas.
You can specify the client you are using with the `--client` argument, and the MCP server will automatically
serve tools and schemas that are more compatible with that client.
* `--client=`: Set all capabilities based on a known MCP client
* Valid values: `openai-agents`, `claude`, `claude-code`, `cursor`
* Example: `--client=cursor`
Additionally, if you have a client not on the above list, or the client has gotten better
over time, you can manually enable or disable certain capabilities:
* `--capability=`: Specify individual client capabilities
* Available capabilities:
* `top-level-unions`: Enable support for top-level unions in tool schemas
* `valid-json`: Enable JSON string parsing for arguments
* `refs`: Enable support for \$ref pointers in schemas
* `unions`: Enable support for union types (anyOf) in schemas
* `formats`: Enable support for format validations in schemas (e.g. date-time, email)
* `tool-name-length=N`: Set maximum tool name length to N characters
* Example: `--capability=top-level-unions --capability=tool-name-length=40`
* Example: `--capability=top-level-unions,tool-name-length=40`
## Importing the tools and server individually
```js theme={null}
// Import the server, generated endpoints, or the init function
import { server, endpoints, init } from "@zbdpay/payments-sdk-mcp/server";
// import a specific tool
import createChargeGamertags from "@zbdpay/payments-sdk-mcp/tools/gamertags/create-charge-gamertags";
// initialize the server and all endpoints
init({ server, endpoints });
// manually start server
const transport = new StdioServerTransport();
await server.connect(transport);
// or initialize your own server with specific tools
const myServer = new McpServer(...);
// define your own endpoint
const myCustomEndpoint = {
tool: {
name: 'my_custom_tool',
description: 'My custom tool',
inputSchema: zodToJsonSchema(z.object({ a_property: z.string() })),
},
handler: async (client: client, args: any) => {
return { myResponse: 'Hello world!' };
})
};
// initialize the server with your custom endpoints
init({ server: myServer, endpoints: [createChargeGamertags, myCustomEndpoint] });
```
## Available Tools
The following tools are available in this MCP server.
### Resource `gamertags`:
* `create_charge_gamertags` (`write`): Generate a payment request for a ZBD User.
* `retrieve_by_gamertag_gamertags` (`read`): Retrieve Gamertag from a ZBD user ID.
* `retrieve_by_zbd_id_gamertags` (`read`): Retrieve ZBD user ID from a Gamertag.
* `retrieve_payment_gamertags` (`read`): Retrieve all data about a Payment sent to ZBD User.
* `send_payment_gamertags` (`write`): Send instant Bitcoin payments to ZBD Users.
### Resource `lightning_charges`:
* `create_lightning_charges` (`write`): Start receiving instant Bitcoin payments through the ZBD API.
* `retrieve_lightning_charges` (`read`): Retrieve all data about a single Charge.
### Resource `internal_transfer`:
* `initiate_internal_transfer` (`write`): Performs a transfer of funds between two Projects.
### Resource `lightning_address`:
* `create_charge_lightning_address` (`write`): Generate a payment request for a Lightning Address.
* `send_payment_lightning_address` (`write`): Send instant Bitcoin payments to any Lightning Address.
* `validate_lightning_address` (`read`): Verify the validity of a Lightning Address.
### Resource `lightning_static_charges`:
* `create_lightning_static_charges` (`write`): Start accepting payments on Lightning with Static QR codes.
* `retrieve_lightning_static_charges` (`read`): Retrieve all data about a single Static Charge.
* `update_lightning_static_charges` (`write`): Change the configuration of a Static Charge QR code.
### Resource `vouchers`:
* `create_vouchers` (`write`): Create Voucher
* `retrieve_vouchers` (`read`): Get Voucher
* `redeem_vouchers` (`write`): Redeem Voucher
* `revoke_vouchers` (`write`): Revoke Voucher
### Resource `withdrawal_requests`:
* `create_withdrawal_requests` (`write`): Start creating Bitcoin voucher QR codes.
* `retrieve_withdrawal_requests` (`read`): Retrieve all data about a single Withdrawal Request.
### Resource `lightning_payments`:
* `retrieve_lightning_payments` (`read`): Retrieve all data about a single Payment.
* `send_lightning_payments` (`write`): Start sending instant Bitcoin payments through the ZBD API.
### Resource `wallet`:
* `retrieve_balance_wallet` (`read`): Retrieve all data about a ZBD Project's Wallet.
### Resource `utils`:
* `check_ip_support_utils` (`read`): Verify if a user is coming from a supported region.
* `decode_lightning_charge_utils` (`write`): Understand the inner properties of a Charge QR code.
* `list_prod_ips_utils` (`read`): Get the official IP addresses of ZBD servers.
* `retrieve_btc_usd_utils` (`read`): Get the latest price for Bitcoin in US Dollars.
### Resource `oauth2`:
* `create_authorization_url_oauth2` (`read`): Create an authorization URL for ZBD Login.
* `refresh_token_oauth2` (`write`): Generate a new accessToken for a ZBD Login user.
* `retrieve_user_data_oauth2` (`read`): Fetch user-related information about a logged-in ZBD User.
* `retrieve_wallet_data_oauth2` (`read`): Fetch wallet-related information about a logged-in ZBD User.
### Resource `keysend_payments`:
* `send_keysend_payments` (`write`): Start sending Keysend payments on the Lightning Network.
# Request Charge for ZBD Gamertag
Source: https://docs.zbdpay.com/payments/payins/gamertags
Learn how to generate payment requests specifically for ZBD users.
## ZBD Gamertag Charge API
While you can use the [Send Bitcoin to ZBD Gamertag](/payments/api/gamertags/send) endpoint to make a direct payment to a ZBD user, if you want to create a regular Lightning Network payment request / Charge QR code for that given user, you can do so using the [Create Charge for ZBD Gamertag](/payments/api/gamertags/create-charge) endpoint.
In order to request Charges from a ZBD Gamertag you just need to make a simple API call with a payload like the example below.
```bash theme={null}
curl --location --request POST 'https://api.zbdpay.com/v0/gamertag/charges' \
--header 'Content-Type: application/json' \
--header 'apikey: API_KEY_HERE' \
--data-raw '{
"gamertag": "andre",
"amount": "15000",
"internalId": "12347ahk1n",
"description": "ZBD so fast!",
"callbackUrl": "https://your-app.com/zbd-callback"
}'
```
In order to receive updates about the status of this request, make sure to include a `callbackUrl` in the `data` portion of the request.
The response payload will include a **`invoiceRequest`** which is the contents of the payment request QR code.
```json theme={null}
{
"success": true,
"data": {
"status": "CHARGE_PENDING",
"amount": "15000",
"internalId": "12347ahk1n",
"description": "ZBD so fast!",
"invoiceRequest": "lnbc100n1pskq45xpp5q5rtpfzydndqk4fu2y4h64fdc284y6av0fn8gz4dmkq89xuxd28sdpvw3jhxarfdenjqctxw3jhygrjv4kk7anfdenjqmnpd4jscqzpgxqzjcsp59g6vgrss790zkwjqc3adndzt5tcq2ltaxynfstggjl6rre3kk6js9qyyssqfyan62pzsjsm62l6zq57jv9pmlpmycvqu649ccfjn7mar77awgykz2gft3fcgl9x5m4mz78nyng920uf6zwft5qnt2qjtqgpl7c72dgq4z7mgv",
"invoiceExpiresAt": "2021-10-08T14:42:38.759Z",
"unit": "msats",
"createdAt": "2022-02-08T14:32:38.793Z"
},
"message": "Successfully created charge request for gamertag"
}
```
Charges / Payment Requests have defined expiration times. After a Charge expires it cannot be paid, but you can simply create another one.
Once a payment is made and the Charge settles, the ZBD User will receive a Push Notification alerting them they've been sent some Bitcoin.
## Multiplayer Commerce through ZBD Gamertag Charges
For App or Game Developers that wish to provide a more robust commerce experience for their users and gamers, requesting an invoice from ZBD Gamertags can be one of the ways.
**Think of yourself, the Developer, as the Orchestrator of payments.**
By leveraging Lightning Network invoices tied to specific ZBD Gamertag, you can ensure that the payment is made to the correct user, and that the payment has truly settled.
### 1. Two-Step Payment Orchestration
Let's say **Alice** wants to buy a sword from **Bob** inside of the game. Well that's easy, and there's two ways:
### 2. ZBD Gamertag Charges
You can use the above endpoint to create a Charge from **Bob**'s ZBD Gamertag, and display it for **Alice** to pay. Pass a `callbackUrl` on the ZBD API request and when the payment settles, you will be alerted of it and can then transfer the sword asset inside the game.
**Yes, it's really that simple!**
### 3. Project Wallet as Escrow
Alternatively you could rely on the Project's own Wallet as a form of escrow. You can create a Charge using the `/charges` endpoint passing a `callbackUrl` to receive settlement updates, and have **Alice** pay it.
Alice will effectively be paying the Project Wallet in this scenario.
Once payment is settled, you can use the [Send Bitcoin to ZBD Gamertag](/payments/api/gamertags/send) endpoint and send the same amount to **Bob**. When this second payment settles you can then transfer the sword asset inside the game.
While this technically involves two transactions, it provides a bit more control to the Developer that wishes to manage the transfer of assets/in-game items a bit more closely and with more checks and balances in place. Both approaches are recommended.
# Receiving Lightning Payments
Source: https://docs.zbdpay.com/payments/payins/lightning-charges
Learn how to receive Lightning payments using the ZBD API.
## Charge API
In order to receive Bitcoin through the Lightning Network using the ZBD API, you must first create a **Charge**.
A Charge accepts the following attributes:
| Property | Description |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount` | The Charge amount (in millisatoshis --> 1 satoshi = 1,000 millisatoshi). |
| `description` | The Charge note or comment. |
| `internalId` | An optional free-use attribute. Usually used by setting the Player/User ID of your Game/Application in order to link specific Charges to specific Players. |
| `callbackUrl` | The URL ZBD API will make a POST HTTP request to with information about the Charges's status updates. See [Callbacks](/payments/api/callbacks) for more. |
| `expiresIn` | The desired expiration time for this Charge (in seconds). |
To create a Charge, use the [`/charges`](/payments/api/lightning-charges/create) API (or leverage one of our SDKs) by passing the correct attributes:
```js NodeJS theme={null}
// Using ZBD's NodeJS SDK
import { zbd } from '@zbdpay/payments-sdk';
// Instantiate ZBD client
const ZBD = new zbd(API_KEY_HERE);
// Set the payload
const payload = {
expiresIn: 300,
amount: '50000',
internalId: '118304b8',
description: 'My Charge Description',
callbackUrl: 'https://your-app.com/zbd-callback',
};
// Create Charge
try {
const response = await ZBD.createCharge(payload);
} catch(error) {
console.log({ error });
}
```
```bash cURL theme={null}
curl --location --request POST 'https://api.zbdpay.com/v0/charges' \
--header 'Content-Type: application/json' \
--header 'apikey: API_KEY_HERE' \
--data-raw '{
"expiresIn": 300,
"amount": "50000",
"internalId": "118304b8",
"description": "My Charge Description",
"callbackUrl": "https://your-app.com/zbd-callback"
}'
```
If the submitted request suceeds, you can expect a JSON API response that resembles the following:
```json theme={null}
{
"message": "Successfully created Charge.",
"data": {
"id": "c121356b-9671-4fbd-a751-987fb4b3d0b3",
"description": "My Charge Description",
"createdAt": "2022-12-23T03:58:17.993Z",
"callbackUrl": "https://your-app.com/zbd-callback",
"internalId": "118304b8",
"amount": "50000",
"status": "pending",
"invoice": {
"expiresAt": "2019-12-23T04:08:18.038Z",
"request": "lnbc20n1p0qqw66pp5lhjn2sshvh03h2lsxyzg5eyfwt0760207q3hake25fs7l3psegtqdpgg3jhxcmjd9c8g6t0dcsx7e3qw35x2gzrdpshyem9cqzpgxqzjcfppjramjf8sxnvy3k8dq84kv56dy5gq9mlqs9qy9qsqsp5jvf69w282jdxkyt824dn0crxdentx8nvncfdt0ulqp75lvkjpagqqwpgcttpmfzaxc3akfn85jlu8cmtv5l2hu8q3yqttru8vlryg3vnewssy8w00yyfsghzqj03j45kj3uhhjek6q6e8djfu5u4gna6wjcqdsdhwe"
}
}
}
```
## Receiving Funds
Now that you have created a Charge, you can allow anyone to pay this Payment Request in the Bitcoin Lightning Network. Depending on your use-case you may choose to display the `invoice.request` property as a QR Code that others can scan with their mobile apps, or you can put it under a button click.
**Any Bitcoin Lightning-capable wallets can read, decode, and effect payments against these Charges.**
## Charge Updates
All Charges will either **complete** or **expire**. If no payment is effected until the Charge's expiration time, the Charge (and underlying Bitcoin Lightning Network Invoice) will expire and will therefore no longer be payable. To know the status of your specific Charge, check the `status` attribute returned from the `/charges/create` or `/charges/get` API calls.
```json theme={null}
{
...
"status": "pending" // pending | completed | expired | error
...
}
```
To subscribe to updates on any given Charge object, the recommended approach is to provide a `callbackUrl` property when creating that Charge. Whenever there are updates to the Charge (a payment was made, or Charge expires) the ZBD API will make a POST request to the URL provided in `callbackUrl`, passing the Charge updates as data in the request.
# Send Bitcoin to ZBD Gamertag
Source: https://docs.zbdpay.com/payments/payouts/gamertags
Learn how to instantly send Bitcoin to a ZBD user.
## Introduction
The ZBD API allows for developers to create Charges, perform Payments, and process Withdrawal Requests for any user, wallet, or service that understands / speaks the Lightning Network protocol. These capabilities are possible because of the underlying `Lightning Charges / Payment Requests / Invoices`, the single-use payable QR codes the platform can create and handle.
While this Payment Request provides a truly interoperable experience for ZBD-powered apps, games, and services to interact with any type of Bitcoin Lightning wallet a user may use, it can at times provide for a much poorer user experience (UX). This is the case because it involves a switch of context, going in-and-out of the app / game and wallet applications to perform a simple payment or withdrawal. This is especially true for mobile devices (which comprises over 2/3 of the entire gaming market for example).
## Enter the ZBD Gamertag
**Every ZBD user has a ZBD Gamertag.** A ZBD Gamertag is a user's unique identifier that allows a developer to directly interact with the given user. This means you can directly send payments to users / gamers.
### Send Bitcoin to ZBD Gamertags
In order to send payments directly to a ZBD user you just need to make a simple API call with a payload similar to the example below.
```js NodeJS theme={null}
// Using ZBD's NodeJS SDK
import { zbd } from '@zbdpay/payments-sdk';
// Instantiate ZBD client
const ZBD = new zbd(API_KEY_HERE);
// Set the payload
const payload = {
amount: '50000',
gamertag: 'andre',
description: 'ZBD so fast!',
};
// Send Payment
try {
const response = await ZBD.sendGamertagPayment(payload);
} catch(error) {
console.log({ error });
}
```
```bash cURL theme={null}
curl --location --request POST 'https://api.zbdpay.com/v0/gamertag/send-payment' \
--header 'Content-Type: application/json' \
--header 'apikey: API_KEY_HERE' \
--data-raw '{
"gamertag": "andre",
"amount": "50000",
"description": "ZBD so fast!",
}'
```
If the ZBD Gamertag exists and is active, the ZBD API will perform the transaction and will return a 200 status code and a JSON response with the following:
```json theme={null}
{
"success": true,
"data": {
"status": "settled",
"settledAt": "2021-10-08T14:21:55.378Z",
"amount": "5000",
"receiverId": "3dde8e48-7c13-4db7-a0e5-caf2a48c002a",
"comment": "So fast!"
},
"message": "Payment done."
}
```
At this stage the user will receive a Push Notification alerting them they've been sent some Bitcoin.
## In-Game Bitcoin Rewards through ZBD Gamertag
One of the many benefits of the ZBD API is that it is flexible enough to allow for developers to create simple in-game / in-app reward systems for their users. This is shown to increase user retention and improve general KPIs around ROAS and CPI. This is done by asking the user to enter their ZBD Gamertag in the game, and whenever the user completes a level, or triggers an event (depends entirely on the game or app and the developer's needs), some Bitcoin is immediately streamed to the user's ZBD App.
# Send Bitcoin to Lightning Address
Source: https://docs.zbdpay.com/payments/payouts/lightning-address
Learn how to instantly send Bitcoin to any Lightning Address.
## Lightning Address API
To send Bitcoin to a given Lightning Address, all you need to do is call the [Send Lightning Address Payment API](/payments/api/lightning-address/send) with a POST call providing the following properties:
| Property | Description |
| ----------- | --------------------------------------------------------- |
| `lnAddress` | Recipient Lightning Address to send payment to. |
| `amount` | Total amount of satoshis to send (in millisatoshis). |
| `comment` | comment to be sent with the payment (max 150 characters). |
Example: If you wish to reward 20 satoshis to a user for their completion of a challenge, and you have the user's Lightning Address, you can use the information below to send it in 1 API call.
## Sending Transaction
```js NodeJS theme={null}
// Using ZBD's NodeJS SDK
import { zbd } from '@zbdpay/payments-sdk';
// Instantiate ZBD client
const ZBD = new zbd(API_KEY_HERE);
// Set the payload
const payload = {
amount: "20000",
lnAddress: "andre@zbd.gg",
comment: "Sending to a Lightning Address"
};
// Send Lightning Address payment
try {
const response = await ZBD.sendLightningAddressPayment(payload);
} catch(error) {
console.log({ error });
}
```
```bash cURL theme={null}
curl --location --request POST 'https://api.zbdpay.com/v0/ln-address/send-payment' \
--header 'Content-Type: application/json' \
--header 'apikey: API_KEY_HERE' \
--data-raw '{
"amount": "20000",
"lnAddress": "andre@zbd.gg",
"comment": "Sending to a Lightning Address"
}'
```
## API Response
Response payloads will usually look similar to this:
```json theme={null}
{
"success": true,
"data": {
"id": "795de178-573f-47dd-9535-a710cd9daf56",
"fee": "2000",
"unit": "msats",
"amount": "20000",
"preimage": "e2fb59fe93a2c63082be50f58f4f3e92841d436339fab93fdd67b1280650cf47",
"status": "completed",
"invoice": "lnbc200n1p3277jtpp5594ju6twysvqkqtus4l0pnawuum4w8l9x3ktz234pp93nfsdc5fshp574njlu3jdr3y2k3g4g9xcp323kgwh7n4v7n4yraakvwh7xmeyugqcqzpgxqyz5vqsp55ju2g2j06u8ua59kj80wqrpgsnkjclzdv28d0msgah90fcx9t9ds9qyyssqphhva4akne5hr0f6t3gmmdpllu00zxgvu70s0kp5g8wmg5vv26qygsearsyrcm4xjecttazfy3ul9lmcvas9ha24n9jtpc3ca9g2mqsppxzvdl",
"walletId": "73c1db10-d1f7-499f-bbbe-eea2f73bb27c",
"transactionId": "9ab28811-97d3-40d0-b603-50cfa00bba2d",
"createdAt": "2022-06-19T19:34:35.955Z",
"processedAt": "2022-06-19T19:34:36.936Z"
},
"message": "Payment done."
}
```
Wow that's easy. Welcome to instantaneous payments!
Fees are added post-send given that the routing fees for the Lightning Network are variable.(e.g if you send a 10,000 satoshi transaction to a Lightning Address and the fee ends up being 10 satoshis, the total paid by the API wallet is 10,010 satoshis).
# Pay Lightning Network Charges
Source: https://docs.zbdpay.com/payments/payouts/lightning-charges
Learn how to pay Lightning Network Charges using ZBD.
## Payment API
In order to make a payment against a Lightning Network Payment Request (a.k.a Lightning Invoices, or Charges), you simply have to use the [Send Payment API](/payments/api/lightning-payments/send) endpoint. A Payment accepts the following attributes:
| Property | Status | Description |
| ------------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invoice` | *String* | The Lightning payment request, or invoice, that is meant to be paid. |
| `description` | *String* | The Payment description (only used for internal record-keeping). |
| `internalId` | *String* | An optional free-use attribute. Usually used by setting the Player/User ID of your Game/Application in order to link specific Payments to specific users. |
| `callbackUrl` | *String* | The URL ZBD services will make a POST HTTP request to with information about the Payment's status updates. See [Callbacks](/payments/api/callbacks) for more. |
To perform the Payment, use the API (or leverage one of our SDKs) by passing the correct attributes:
```js NodeJS theme={null}
// Using ZBD's NodeJS SDK
import { zbd } from '@zbdpay/payments-sdk';
// Instantiate the client
const ZBD = new zbd('API_KEY_HERE');
// Set the payload
const payload = {
description: 'My Payment Description',
callbackUrl: 'https://your-app.com/zbd-callback',
internalId: '11af01d09a6b8304b8',
invoice: 'lnbc450n1p0yeytspp55yrs0j42wnkw0qutr8e0tgsf2yplxs9986t5gqmfpn7mfd0ckc8sdzq2pshjmt9de6zqen0wgsrgdfqwp5hsetvwvsxzapqwdshgmmndp5hxtnsd3skxefwxqzjccqp2sp5pyccqt6apxelz62d2ndrt0ssahndpcua4wklea80glaczx80t3wqrzjqfn4cln8jwe4dh4dmscddrmd6sdw6hzkn702l6ghwvr8lhad0ez5vzt8vyqqf2sqqqqqqqlgqqqqqqgq9q9qy9qsqqeft09gryr80aaghm7rmh7eeqfl7hxlcynp99730yk7qh534d9nyfwp0nc628rp8hpgp23fxzj5l2aet4y6sc4t79uj3wyjxffejmvgqrmxkvr',
};
// Make Payment
try {
const response = await ZBD.sendPayment(payload);
} catch(error) {
console.log({ error });
}
```
```bash cURL theme={null}
curl --location --request POST 'https://api.zbdpay.com/v0/payments' \
--header 'Content-Type: application/json' \
--header 'apikey: API_KEY' \
--data-raw '{
"invoice": "lnbc450n1p0yeytspp55yrs0j42wnkw0qutr8e0tgsf2yplxs9986t5gqmfpn7mfd0ckc8sdzq2pshjmt9de6zqen0wgsrgdfqwp5hsetvwvsxzapqwdshgmmndp5hxtnsd3skxefwxqzjccqp2sp5pyccqt6apxelz62d2ndrt0ssahndpcua4wklea80glaczx80t3wqrzjqfn4cln8jwe4dh4dmscddrmd6sdw6hzkn702l6ghwvr8lhad0ez5vzt8vyqqf2sqqqqqqqlgqqqqqqgq9q9qy9qsqqeft09gryr80aaghm7rmh7eeqfl7hxlcynp99730yk7qh534d9nyfwp0nc628rp8hpgp23fxzj5l2aet4y6sc4t79uj3wyjxffejmvgqrmxkvr",
"description": "My Payment Description",
"callbackUrl": "https://myapp.com/zbd-callback",
"internalId": "11af01d0cb33faa6b8304b8"
}'
```
If the submitted request suceeds, you can expect a JSON API response that resembles the following:
```json theme={null}
{
"message": "Successfully made Payment.",
"data": {
"id": "31d60de1-efe0-4e55-9942-910934efe7a3",
"fee": "1000",
"unit": "msats",
"amount": "10000",
"status": "completed",
"description": "My Payment Description",
"processedAt": "2020-01-01T19:34:42.794Z",
"invoice": "lnbc450n1p0yeytspp55yrs0j42wnkw0qutr8e0tgsf2yplxs9986t5gqmfpn7mfd0ckc8sdzq2pshjmt9de6zqen0wgsrgdfqwp5hsetvwvsxzapqwdshgmmndp5hxtnsd3skxefwxqzjccqp2sp5pyccqt6apxelz62d2ndrt0ssahndpcua4wklea80glaczx80t3wqrzjqfn4cln8jwe4dh4dmscddrmd6sdw6hzkn702l6ghwvr8lhad0ez5vzt8vyqqf2sqqqqqqqlgqqqqqqgq9q9qy9qsqqeft09gryr80aaghm7rmh7eeqfl7hxlcynp99730yk7qh534d9nyfwp0nc628rp8hpgp23fxzj5l2aet4y6sc4t79uj3wyjxffejmvgqrmxkvr"
}
}
```
## Payment Updates
There are cases where Lightning Payments can `get stuck` in transit (e.g. a network node on the path to the payment's destination suddenly goes offline). ZBD aims to provide cutting edge Lightning Network infrastructure with high availability and liquidity. That said, due to the possibility of running into stuck payment cases, the recommended method of getting Payment updates is through the `callbackUrl` attribute. By providing a `callbackUrl` when making the Payment, the [ZBD API](/payments/api) is able to make a POST request to that URL and pass along Payment updates as they happen.
# Using Withdrawal QR Codes
Source: https://docs.zbdpay.com/payments/payouts/withdrawal-requests
Understanding the Lightning Charge Workflow Problem
## Introduction
The Lightning Network is a push-based system: in order to receive payments, the payee must first create a Charge / Payment Request, which the payer can pay. This is a great workflow when users are making payments for goods and services. Usually this workflow is as follows:
User performs action that requires a Payment.
A Lightning Charge is created for the specified amount and displayed as QR.
User uses a Lightning Wallet (usually mobile app) to scan QR and decode payment.
User reviews and confirms request details and accepts the Payment.
You receive the Payment and unlock content/action for the user.
This is a great user experience between User and a Project (e.g. game or application). However, this user workflow is limited to **User paying Project**.
To perform the reverse (Project paying User), as with all Lightning payments, the Project must first ask for a Lightning Network Charge/Invoice from the User, for a specific amount. This provides for subpar UX because the User is now an active participant when receiving funds.
## Withdrawal Request API
Withdrawal Requests are the exact opposite of a Charge. Whereas a Charge is a payment from a User to a Project, a Withdrawal Request can be understood as a payment from a Project to a User. In other words, a Charge is a QR code that accepts a Bitcoin payment while **a Withdrawal Request is a QR code that allows a User to claim Bitcoin**.
ZBD's Withdrawal Request capability is based on the [LNURL open-source specification](https://github.com/fiatjaf/lnurl-rfc), which provides a standard for easier communication between Wallets (users) and Projects, through the use of HTTP requests. A developer building upon ZBD's Withdrawal Requests functionality does not need to understand the underlying methodology and workflow of LNURL - the [ZBD API](/payments/api) abstracts away any complexities. Let's see how to do it.
If you've been able to create a ZBD Charge, then you will be able to create a ZBD Withdrawal Request easily.
### Creating a Withdrawal Request
When creating a Withdrawal Request code to allow Lightning Wallets to withdraw funds from the Project (game or application) you must provide the following attributes to the [`/withdrawal-requests`](/payments/api/withdrawal-requests/create) endpoint:
| Property | Status | Description |
| ------------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amount` | *String* | The Withdrawal Request amount (in millisatoshis). |
| `description` | *String* | The Withdrawal Request description. |
| `internalId` | *String* | An optional free-use attribute. Usually used by setting the Player/User ID of your Game/Application in order to link specific Withdrawal Requests to specific Players. |
| `callbackUrl` | *String* | The URL ZBD services will make a POST HTTP request to with information about the Withdrawal Requests's status updates. See [Callbacks](/payments/api/callbacks) for more. |
| `expiresIn` | *Number* | The desired expiration time for this Withdrawal Request (in seconds). |
To create the Withdrawal Request, use the ZBD API (or leverage one of our SDKs) by passing the correct attributes:
```js NodeJS theme={null}
// Using ZBD's NodeJS SDK
import { zbd } from '@zbdpay/payments-sdk';
// Instantiate the client
const ZBD = new zbd('API_KEY_HERE');
// Set the payload
const payload = {
expiresIn: 300,
amount: '50000',
internalId: '11af01d0924aa6b8304b8',
description: 'My Custom Withdrawal Request',
callbackUrl: 'https://yourapp.com/zbd-callback',
};
// Create Withdrawal Request
try {
const response = await ZBD.createWithdrawalRequest(payload);
} catch(error) {
console.log({ error });
}
```
```bash cURL theme={null}
curl --location --request POST 'https://api.zbdpay.com/v0/withdrawal-requests' \
--header 'Content-Type: application/json' \
--header 'apikey: API_KEY' \
--data-raw '{
"expiresIn": 300,
"amount": "50000",
"internalId": "11af01d0926b8304b8",
"description": "My Custom Withdrawal Description",
"callbackUrl": "https://example.com/zbd-callback"
}'
```
If the submitted request suceeds, you can expect a JSON API response that resembles the following:
```json theme={null}
{
"message": "Successfully created Withdrawal Request.",
"data": {
"id": "c121356b-9671-4fbd-a751-987fb4b3d0b3",
"unit": "msats",
"amount": "50000",
"status": "pending",
"description": "Description of the Withdrawal Request",
"createdAt": "2019-12-23T03:58:17.993Z",
"callbackUrl": "https://example.com/zbd-callback",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"invoice": {
"expiresAt": "2019-12-23T04:08:18.038Z",
"request": "lnurl1dp68gurn8ghj7cn9w3sj6ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apav3skxdfev93rwvm9x43nwcf5vvekgdmpxq6rgvrrxumnxdp3vserqe35v4jr2efs8y6k2epkxf3rxc35vg6nwdrpx9jrqv3kxfjxxwqxmuhcd"
}
}
}
```
### Displaying as QR Code
In order to display the Withdrawal Request as a QR code, simple use the `data.invoice.request` attribute returned from the API response and pass it to your QR code generator of choice. The QR code should look something like this:
## Request Updates
Note that the Withdrawal Request is created in a `pending` state as it still hasn't *been claimed*. All Withdrawal Requests will either **complete** or **expire**. If no User is able to Withdraw the funds on time before the Withdrawal Request's expiration time, the Request will expire and will therefore no longer be valid. To know the status of your specific Withdrawal Request, check the `status` attribute returned from the `CreateWithdrawalRequest` or `GetWithdrawalRequestDetails` API calls.
```json theme={null}
{
...
"status": "expired" // pending | completed | expired | error
...
}
```
To subscribe to updates on a specific Withdrawal Request, the recommended approach is to provide a `callbackUrl` property when creating that Withdrawal Request. Whenever there are updates to the Withdrawal Request (a payment was made, or it has expired) the [ZBD API](/payments/api) will make a POST request to the URL provided in `callbackUrl`, passing the Withdrawal Request updates as data in the request.
# ZBD Ramp
Source: https://docs.zbdpay.com/payments/ramp
Enable Bitcoin purchases directly in your app with our embeddable ramp widget
Enable your users to buy Bitcoin directly within your app or game. ZBD Ramp is the first widget to support Lightning Address delivery, providing instant Bitcoin access for gaming and interactive entertainment.
First-in-market Lightning Address support for instant Bitcoin delivery
Built for high-throughput gaming transactions and in-app purchases
Integrated KYC/AML with gaming-friendly risk assessment
## How It Works
Your backend creates a secure session with our API
Users verify identity and purchase Bitcoin through the widget
Funds are delivered via Lightning Address or onchain to your users
## Perfect for Gaming Use Cases
### 🎮 In-Game Wallet Top-ups
Let players add funds to their game wallets for purchasing skins, items, or premium content. With Lightning-fast delivery, they're back in the game in seconds.
### 🏆 Tournament Entry Fees
Enable players to fund tournament entries directly. Our high-throughput system handles peak tournament registration periods without breaking a sweat.
### 💰 Play-to-Earn Onboarding
Onboard new players into your crypto-powered game economy. They can purchase their first Bitcoin and start earning immediately.
## Integration at a Glance
```typescript theme={null}
// 1. Initialize session (backend)
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
const response = await initRampSession({
apikey: process.env.ZBD_API_KEY,
email: "player@game.com",
webhook_url: "https://yourgame.com/webhooks/zbd",
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
destination: "spiderman@zbd.gg",
reference_id: "player_123"
});
const sessionToken = response.data.session_token;
// 2. Embed widget (frontend)
import { ZBDRamp } from '@zbdpay/ramp-react';
console.log('Purchase completed:', data)}
/>
// 3. Handle webhooks
app.post('/webhooks/zbd', (req, res) => {
if (req.body.event === 'purchase.completed') {
// Credit user's game wallet
}
});
```
That's it. One backend endpoint, one iframe, one webhook handler.
## Key Features
### Available Now
* **Pay by Bank** - ACH transfers via Plaid for US users
* Low fees and high success rates
Coming soon: Credit/Debit cards, Apple Pay, Google Pay, and Stablecoin payments
### Bitcoin Delivery
* **Lightning Address** - Instant delivery (industry first!)
* **Onchain Bitcoin** - Standard Bitcoin addresses
### Built-in Protection
* Advanced AI-native fraud detection
* Automated KYC/AML processes
* Gaming-optimized risk scoring
* Bot/VPN/Emulator detection
## Why ZBD Ramp?
### For Developers
* Simple 3-step integration
* No crypto complexity
* Comprehensive webhook events
* White-label customization
### For Your Users
* Seamless in-app experience
* Fast KYC process
* Competitive rates
* Multiple payment options
## Ready to Get Started?
Schedule a 15-minute demo to see ZBD Ramp in action and get your API keys.
Get up and running in minutes with our integration guide
Explore the API endpoints and webhook events
***
ZBD Ramp requires a business account and KYB verification. Individual developers can explore our Rewards products while preparing for business verification.
# AI-Generated Themes
Source: https://docs.zbdpay.com/payments/ramp/ai-themes
Use AI to instantly generate custom themes that match your brand
ZBD Ramp features an innovative AI-powered theme generator that can create a custom theme from your existing brand materials in seconds.
## How It Works
Our AI theme generator analyzes your uploaded images and automatically maps your brand colors and design patterns to create a perfectly matched widget theme.
Upload a screenshot, logo, or any image that represents your brand's visual identity
Select whether to start from a light or dark theme foundation
Optionally provide guidance like "focus on blue and green colors" or "make it vibrant"
Click generate and watch AI create your custom theme in seconds
Edit any element using the Live Preview editor to perfect your theme
## Support
Need help with AI theme generation?
* Access the generator in your [ZBD Developer Dashboard](https://dashboard.zebedee.io)
* Contact your account manager for guidance
* Review generated theme examples in the dashboard
# Email Receipts
Source: https://docs.zbdpay.com/payments/ramp/emails
Email notifications and receipts for ZBD Ramp transactions
Email receipt functionality is coming soon. This feature will provide ability for you to customize email notifications and transaction receipts to users.
# Frequently Asked Questions
Source: https://docs.zbdpay.com/payments/ramp/faq
Onboard into Bitcoin with ZBD Ramp.
ZBD Ramp currently supports:
* Bitcoin (BTC)
Users can withdraw their funds to:
* Bitcoin on-chain addresses
* Lightning Network addresses
Currently, ZBD Ramp supports:
* Pay by Bank with ACH
Coming soon:
* Google Pay
* Apple Pay
* Credit Cards
* Debit Cards
The ZBD Ramp widget is designed as an embeddable web view, making it compatible with virtually any development environment. The ZBD team is actively working on wrapper SDKs and libraries for popular development environments to make integration even easier.
For detailed pricing information and fee structures, please speak with your ZBD customer success manager or [connect with our sales team](https://zbd.one/sales).
Customer support is handled internally by the ZBD team. The ZBD Ramp widget includes a built-in chatbot that can handle a wide range of user inquiries, create support tickets directly, and even provide guides and detailed walkthroughs to help assist users.
ZBD Ramp implements multiple layers of security:
* Secure API endpoints
* Encrypted data transmission and webhook payloads
* Compliance with financial regulations (KYC, AML, etc.)
* Real-time AI-based transaction monitoring and fraud detection
To integrate ZBD Ramp, you need:
1. A ZBD developer account
2. API credentials
3. A secure backend environment
4. Compliance with our integration guidelines
Transaction limits vary based on your specific needs. Contact your ZBD Customer Success Manager for specific limit details.
# Platform Details
Source: https://docs.zbdpay.com/payments/ramp/platform
Configure your platform branding and identity in ZBD Ramp
Configure your platform's branding elements to ensure a seamless, cohesive experience for your users throughout the ZBD Ramp widget.
## Platform Configuration
Your platform details appear throughout the widget experience, providing users with confidence and brand continuity. All platform details can be configured through the ZBD Developer Dashboard.
### Available Settings
Your platform or application name that appears in the widget header and throughout the user journey
Your platform logo displayed prominently in the widget. Recommended: SVG or PNG with transparent background, minimum 200x200px
Optional wordmark/text logo for extended branding opportunities. Used in specific widget layouts where horizontal space allows
Brief description of your platform that helps users understand the context of their transaction. Maximum 160 characters
Your platform's website URL for additional credibility and user reference
## Best Practices
### Logo Guidelines
* **Format**: Use SVG for best quality across all screen sizes
* **Size**: Minimum 200x200px, maximum 1000x1000px
* **Background**: Transparent background recommended
* **Color**: Ensure logo works on your chosen theme backgrounds
### Platform Name
* Keep it concise and recognizable
* Use the name your users know you by
* Avoid special characters that might not render properly
* Consider international users if applicable
### Description Tips
* Be clear and concise (160 characters max)
* Focus on what your platform does
* Build trust with professional language
* Avoid marketing jargon
## Configuration Steps
Log into your [ZBD Developer Dashboard](https://dashboard.zbdpay.com)
Select your project and go to Ramp → Platform Details
Upload your logo and wordmark using the provided upload fields
Fill in your platform name, description, and website URL
Use the Live Preview to see how your platform details appear in the widget
Save your configuration to apply changes immediately
# Integration Guide
Source: https://docs.zbdpay.com/payments/ramp/quickstart
Complete guide to integrating ZBD Ramp into your application
Get ZBD Ramp integrated into your application in minutes using our official SDKs. This guide covers session initialization, widget rendering, and webhook handling.
## Choose Your SDK
Select the SDK that best fits your application:
Core SDK for Node.js, browsers, and JavaScript frameworks
React components and hooks for web applications
Native components for iOS and Android apps
Flutter plugin for cross-platform mobile apps
## Integration Flow
Add the appropriate ZBD Ramp SDK to your project
Create a session token from your backend using the SDK
Display the Ramp widget using SDK components
Process webhooks and widget callbacks
## Quick Start
### 1. Install the SDK
```bash theme={null}
npm install @zbdpay/ramp-ts
```
```bash theme={null}
npm install @zbdpay/ramp-react
```
```bash theme={null}
npm install @zbdpay/ramp-react-native react-native-webview
```
### 2. Initialize Session (Backend)
Create a session token from your backend to keep your API key secure:
```typescript theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
const response = await initRampSession({
apikey: process.env.ZBD_API_KEY,
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://yourapp.com/webhooks/zbd',
reference_id: 'user_123_purchase_456',
metadata: {
user_id: '123',
session_id: 'abc'
}
});
const sessionToken = response.data.session_token;
```
```javascript theme={null}
const { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } = require('@zbdpay/ramp-ts');
const response = await initRampSession({
apikey: process.env.ZBD_API_KEY,
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://yourapp.com/webhooks/zbd'
});
const sessionToken = response.data.session_token;
```
```bash theme={null}
curl -X POST https://api.zbdpay.com/api/v1/ramp-widget \
-H "Content-Type: application/json" \
-H "apikey: YOUR_API_KEY" \
-d '{
"email": "user@example.com",
"webhook_url": "https://yourapp.com/webhooks/zbd",
"quote_currency": "USD",
"base_currency": "BTC",
"destination": "lightning-address@zbd.gg"
}'
```
### 3. Render Widget (Frontend)
Display the Ramp widget in your application:
```tsx theme={null}
import { ZBDRamp } from '@zbdpay/ramp-react';
function PaymentPage({ sessionToken }) {
return (
{
console.log('Payment successful:', data);
// Handle successful payment
}}
onError={(error) => {
console.error('Payment error:', error);
// Handle error
}}
onClose={() => {
console.log('Widget closed');
// Handle close
}}
style={{ width: '100%', height: '600px' }}
/>
);
}
```
```javascript theme={null}
import { createRamp } from '@zbdpay/ramp-ts';
const ramp = createRamp({
sessionToken: 'your-session-token',
container: '#ramp-container',
onSuccess: (data) => {
console.log('Payment successful:', data);
},
onError: (error) => {
console.error('Payment error:', error);
},
onClose: () => {
console.log('Widget closed');
}
});
ramp.mount();
```
```tsx theme={null}
import { ZBDRamp } from '@zbdpay/ramp-react-native';
import { View, StyleSheet } from 'react-native';
function PaymentScreen({ sessionToken }) {
return (
{
console.log('Payment successful:', data);
}}
onError={(error) => {
console.error('Payment error:', error);
}}
style={styles.webview}
/>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
webview: { flex: 1 }
});
```
### 4. Handle Webhooks
Process webhook events on your backend:
```javascript theme={null}
app.post('/webhooks/zbd', (req, res) => {
const event = req.body;
switch(event.type) {
case 'ramp.purchase.completed':
// Payment successful - credit user account
const { amount, currency, reference_id } = event.data;
creditUserAccount(reference_id, amount);
break;
case 'ramp.purchase.failed':
// Payment failed - notify user
notifyUserOfFailure(event.data.reference_id);
break;
case 'ramp.kyc.completed':
// KYC completed - update user status
updateUserKYCStatus(event.data.user_id);
break;
}
res.status(200).send('OK');
});
```
## Complete Example
Here's a full implementation using React and Node.js:
### Backend (Node.js + Express)
```javascript theme={null}
import express from 'express';
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
const app = express();
app.use(express.json());
// Create session endpoint
app.post('/api/ramp/session', async (req, res) => {
try {
const response = await initRampSession({
apikey: process.env.ZBD_API_KEY,
email: req.body.email,
destination: req.body.destination,
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: `${process.env.BASE_URL}/webhooks/zbd`,
reference_id: req.user.id,
metadata: {
user_id: req.user.id,
session_id: req.session.id
}
});
res.json({ sessionToken: response.data.session_token });
} catch (error) {
res.status(500).json({ error: 'Failed to create session' });
}
});
// Webhook handler
app.post('/webhooks/zbd', async (req, res) => {
const event = req.body;
if (event.type === 'ramp.purchase.completed') {
// Credit user's account
await creditUserBalance(
event.data.reference_id,
event.data.amount,
event.data.currency
);
}
res.status(200).send('OK');
});
```
### Frontend (React)
```tsx theme={null}
import React, { useState, useEffect } from 'react';
import { ZBDRamp } from '@zbdpay/ramp-react';
function BuyBitcoin() {
const [sessionToken, setSessionToken] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Fetch session token from backend
fetch('/api/ramp/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: user.email,
destination: user.lightningAddress
})
})
.then(res => res.json())
.then(data => {
setSessionToken(data.sessionToken);
setLoading(false);
});
}, []);
if (loading) return Loading...;
return (
Buy Bitcoin
{
alert('Payment successful!');
window.location.href = '/wallet';
}}
onError={(error) => {
alert(`Payment failed: ${error.message}`);
}}
style={{ width: '100%', height: '600px' }}
/>
);
}
```
## Session Parameters
When initializing a session, you can configure various parameters:
| Parameter | Type | Required | Description |
| ---------------- | ------ | -------- | -------------------------------- |
| `apikey` | string | Yes | Your ZBD API key |
| `email` | string | Yes | User's email address |
| `webhook_url` | string | Yes | URL for webhook notifications |
| `destination` | string | No | Lightning or Bitcoin address |
| `quote_currency` | enum | No | Source currency (USD, EUR, etc.) |
| `base_currency` | enum | No | Target currency (BTC) |
| `reference_id` | string | No | Your internal reference ID |
| `metadata` | object | No | Additional data to attach |
Sessions expire after 15 minutes. Create a new session if the user needs more time.
## Security Best Practices
* Never expose API keys in frontend code
* Always create sessions from your backend
* Use environment variables
* Rotate keys regularly
* Use HTTPS endpoints only
* Implement idempotency
* Verify webhook signatures
* Log all events for audit
## Demo Applications
To help you get started quickly, we've created example applications showing ZBD Ramp integration across different platforms. These demos showcase best practices and real-world implementation patterns.
**Features:**
* Clean TypeScript implementation
* Session management
* Webhook handling
* Error handling examples
Perfect for web applications and Node.js backends. See the [TypeScript SDK documentation](/payments/ramp/sdks/typescript) for more details.
**Features:**
* Native mobile integration
* WebView implementation
* iOS and Android support
* Navigation patterns
Ideal for cross-platform mobile apps. See the [React Native SDK documentation](/payments/ramp/sdks/react-native) for implementation details.
**Features:**
* Flutter widget integration
* Platform-specific handling
* Material Design patterns
* State management
Flutter widget integration for iOS and Android. See the [Flutter SDK documentation](/payments/ramp/sdks/flutter) for implementation details.
These example applications demonstrate production-ready patterns for integrating ZBD Ramp. Use them as a starting point for your own implementation.
***
## Next Steps
See a complete walkthrough of the user experience
Learn how to customize the widget to match your brand
Explore all available webhook events and payloads
View the complete API documentation
Schedule a technical support session with our team
# Flutter SDK
Source: https://docs.zbdpay.com/payments/ramp/sdks/flutter
Flutter plugin for ZBD Ramp - Enable Bitcoin purchases in your Flutter apps
The `zbd_ramp` package provides a native Flutter widget for integrating ZBD Ramp into your iOS, Android, and Web applications.
## Features
Built specifically for Flutter with native WebView integration
Works seamlessly on iOS, Android, and Web
Full Dart type safety with comprehensive type definitions
PostMessage communication for error handling, logging, and step tracking
## Installation
Add the package to your `pubspec.yaml`:
```yaml theme={null}
dependencies:
zbd_ramp: ^1.0.0
http: ^1.1.0
```
Then run:
```bash theme={null}
flutter pub get
```
## Quick Start
### 1. Create Session Token
First, initialize a ramp session from your backend or directly in your Flutter app:
```dart theme={null}
import 'package:zbd_ramp/zbd_ramp.dart';
final response = await initRampSession(InitRampSessionConfig(
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quoteCurrency: QuoteCurrency.USD,
baseCurrency: BaseCurrency.BTC,
webhookUrl: 'https://your-webhook-url.com',
referenceId: 'order-123',
metadata: {'userId': '456', 'plan': 'premium'},
));
if (response.success) {
final sessionToken = response.data.sessionToken;
// Use sessionToken with ZBDRampWidget
} else {
print('Failed to create session: ${response.error}');
}
```
```dart theme={null}
import 'package:zbd_ramp/zbd_ramp.dart';
final response = await initRampSession(InitRampSessionConfig(
apikey: 'your-zbd-api-key',
accessToken: 'user-access-token',
destination: 'lightning-address@zbd.gg',
quoteCurrency: QuoteCurrency.USD,
baseCurrency: BaseCurrency.BTC,
webhookUrl: 'https://your-webhook-url.com',
));
if (response.success) {
final sessionToken = response.data.sessionToken;
// Use sessionToken with ZBDRampWidget
}
```
### 2. Display the Ramp Widget
Add the widget to your Flutter app:
```dart theme={null}
import 'package:flutter/material.dart';
import 'package:zbd_ramp/zbd_ramp.dart';
class PaymentScreen extends StatelessWidget {
final String sessionToken;
const PaymentScreen({Key? key, required this.sessionToken}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Buy Bitcoin')),
body: ZBDRampWidget(
config: RampConfig(sessionToken: sessionToken),
callbacks: RampCallbacks(
onSuccess: (data) {
print('Payment successful: $data');
// Handle successful payment
},
onError: (error) {
print('Payment error: ${error.message}');
// Handle error
},
onStepChange: (step) {
print('Current step: $step');
// Track user progress
},
),
height: 600,
),
);
}
}
```
## API Reference
### initRampSession()
Creates a new session token for the ZBD Ramp widget.
#### Parameters
```dart theme={null}
class InitRampSessionConfig {
final String apikey; // Required: Your ZBD API key
final String? email; // Email authentication
final String? accessToken; // Access token authentication
final String destination; // Required: Lightning address or username
final QuoteCurrency quoteCurrency; // Required: Quote currency (USD)
final BaseCurrency baseCurrency; // Required: Base currency (BTC)
final String? webhookUrl; // Optional: Webhook URL
final String? referenceId; // Optional: Your reference ID
final Map? metadata; // Optional: Additional metadata
}
```
Either `email` OR `accessToken` must be provided for authentication.
#### Returns
```dart theme={null}
class InitRampSessionResponse {
final InitRampSessionData data;
final String? error;
final bool success;
final String message;
}
class InitRampSessionData {
final String sessionToken; // Session token for widget
final String expiresAt; // Token expiration time
final String widgetUrl; // Direct widget URL
}
```
### refreshAccessToken()
Refreshes an expired access token using a refresh token.
**Token Lifecycle:**
* Access tokens expire after 30 days
* Refresh tokens expire after 90 days
* Both tokens are received via webhook after user completes OTP login with email
#### Parameters
```dart theme={null}
class RefreshAccessTokenConfig {
final String apikey; // Required: Your ZBD API key
final String accessTokenId; // Required: ID of access token to refresh
final String refreshToken; // Required: Refresh token
}
```
#### Returns
```dart theme={null}
class RefreshAccessTokenResponse {
final RefreshAccessTokenData data;
final String? error;
final bool success;
final String message;
}
class RefreshAccessTokenData {
final String accessTokenId;
final String accessToken; // New access token
final String refreshToken; // New refresh token
final String accessTokenExpiresAt;
final String refreshTokenExpiresAt;
}
```
#### Example
```dart theme={null}
try {
final response = await refreshAccessToken(RefreshAccessTokenConfig(
apikey: 'your-zbd-api-key',
accessTokenId: '7b585ffa-9473-43ca-ba1d-56e9e7e2263b',
refreshToken: 'user-refresh-token',
));
if (response.success) {
final newAccessToken = response.data.accessToken;
final newRefreshToken = response.data.refreshToken;
// Store the new tokens securely
}
} catch (error) {
print('Token refresh error: $error');
}
```
### ZBDRampWidget
Main Flutter widget that renders the ZBD Ramp interface.
#### Constructor
```dart theme={null}
ZBDRampWidget({
Key? key,
required RampConfig config,
required RampCallbacks callbacks,
double? width,
double? height,
})
```
#### RampConfig
Configuration for the widget:
```dart theme={null}
class RampConfig {
final String sessionToken; // Required: Session token
final String? secret; // Optional: Widget secret
}
```
#### RampCallbacks
Event handlers for widget lifecycle:
```dart theme={null}
class RampCallbacks {
final OnSuccessCallback? onSuccess; // Payment successful
final OnErrorCallback? onError; // Error occurred
final OnStepChangeCallback? onStepChange; // User navigated to new step
final OnLogCallback? onLog; // Debug/info logging
final OnReadyCallback? onReady; // Widget fully loaded
final OnCloseCallback? onClose; // User closed widget
}
```
## Complete Example
Here's a full implementation with all callbacks:
```dart theme={null}
import 'package:flutter/material.dart';
import 'package:zbd_ramp/zbd_ramp.dart';
class BuyBitcoinScreen extends StatefulWidget {
@override
_BuyBitcoinScreenState createState() => _BuyBitcoinScreenState();
}
class _BuyBitcoinScreenState extends State {
String? sessionToken;
bool isLoading = true;
String? error;
@override
void initState() {
super.initState();
_createSession();
}
Future _createSession() async {
try {
final response = await initRampSession(InitRampSessionConfig(
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning@zbd.gg',
quoteCurrency: QuoteCurrency.USD,
baseCurrency: BaseCurrency.BTC,
webhookUrl: 'https://your-webhook.com',
referenceId: 'user_123',
));
if (response.success) {
setState(() {
sessionToken = response.data.sessionToken;
isLoading = false;
});
} else {
setState(() {
error = response.error;
isLoading = false;
});
}
} catch (e) {
setState(() {
error = e.toString();
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Buy Bitcoin')),
body: isLoading
? Center(child: CircularProgressIndicator())
: error != null
? Center(child: Text('Error: $error'))
: ZBDRampWidget(
config: RampConfig(sessionToken: sessionToken!),
callbacks: RampCallbacks(
onSuccess: (data) {
print('✅ Payment successful: $data');
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Payment successful!')),
);
},
onError: (error) {
print('❌ Error: ${error.message}');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${error.message}'),
backgroundColor: Colors.red,
),
);
},
onStepChange: (step) {
print('📍 Step changed: $step');
},
onReady: () {
print('✅ Widget ready');
},
onClose: () {
print('👋 Widget closed');
Navigator.of(context).pop();
},
onLog: (log) {
print('📝 Log: $log');
},
),
height: 600,
),
);
}
}
```
## Error Handling
Handle errors gracefully in your application:
```dart theme={null}
void _handleError(RampError error) {
// Error structure: { code: string, message: string, details?: any }
print('Error Code: ${error.code}');
print('Error Message: ${error.message}');
if (error.details != null) {
print('Error Details: ${error.details}');
}
// Show user-friendly message
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Payment Error'),
content: Text(error.message),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
),
);
}
```
## Platform Setup
### iOS Configuration
Add the following to your `ios/Runner/Info.plist`:
```xml theme={null}
NSAppTransportSecurity
NSAllowsArbitraryLoads
NSCameraUsageDescription
Camera access is required for KYC verification
```
### Android Configuration
Add permissions to your `android/app/src/main/AndroidManifest.xml`:
```xml theme={null}
```
## Try the Example App
The quickest way to see the SDK in action:
```bash theme={null}
git clone https://github.com/zbdpay/ramp-flutter.git
cd ramp-flutter/example
```
```bash theme={null}
flutter pub get
```
```bash theme={null}
flutter run
```
* Enter your ZBD API Key
* Fill in email and Lightning destination
* Tap "Create Session & Load Ramp"
## Resources
View the official Flutter package
View source code and example app
Complete API documentation
Handle webhook notifications
## Other SDKs
Core TypeScript/JavaScript package for web applications.
[View TypeScript SDK →](/payments/ramp/sdks/typescript)
React components for web applications.
[View React SDK →](/payments/ramp/sdks/react)
Native components for iOS and Android apps.
[View React Native SDK →](/payments/ramp/sdks/react-native)
***
## Support
Need help? Create an issue on [GitHub](https://github.com/zbdpay/ramp-flutter/issues) or reach out to our [support team](https://zbd.one/sales).
# React SDK
Source: https://docs.zbdpay.com/payments/ramp/sdks/react
React wrapper for ZBD Ramp
The `@zbdpay/ramp-react` package is a React wrapper for the ZBD Ramp widget that enables Buying Bitcoin with USD directly to the Lightning Network.
## Features
* **React Optimized**: Built specifically for React with hooks and components
* **TypeScript Support**: Full type safety with comprehensive TypeScript definitions
* **Ref API**: Access to underlying ramp instance methods via React refs
* **Hook Support**: `useZBDRamp` hook for programmatic usage
* **Session Token Based**: Uses secure session tokens for authentication
## Installation
```bash theme={null}
npm install @zbdpay/ramp-react
```
```bash theme={null}
yarn add @zbdpay/ramp-react
```
```bash theme={null}
pnpm add @zbdpay/ramp-react
```
## Quick Start
### 1. Create Session Token
First, create a session token using the ZBD API:
```tsx theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-react';
const response = await initRampSession({
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://your-webhook-url.com',
});
const sessionToken = response.data.session_token;
```
### 2. Use ZBDRamp Component
```tsx theme={null}
import { ZBDRamp } from '@zbdpay/ramp-react';
function App() {
const handleSuccess = (data) => {
console.log('Payment successful:', data);
};
const handleError = (error) => {
console.error('Payment error:', error);
};
return (
);
}
```
## API Reference
### initRampSession
Creates a new session token for the ZBD Ramp widget.
Configuration object for creating a session
#### Configuration Parameters
Your ZBD API key
User's email address
Lightning address or Bitcoin address
Quote currency (e.g., USD)
Base currency (e.g., BTC)
Webhook URL for notifications
Your internal reference ID
Additional metadata to attach to the session
### ZBDRamp Component
React component that renders the ZBD Ramp widget.
#### Props
Session token from ZBD API
Widget width
Widget height (minimum 600px recommended)
CSS class for container
Inline styles for container
#### Callback Props
Called when payment is successful
Called when an error occurs
Called when user navigates to a different step
Debug/info logging callback
Called when widget is fully loaded
Called when user closes the widget
#### Ref API
```typescript theme={null}
interface ZBDRampRef {
mount: (container?: HTMLElement | string) => void;
unmount: () => void;
destroy: () => void;
}
```
### useZBDRamp Hook
Hook for creating and managing ZBD Ramp instances programmatically.
```tsx theme={null}
const { createInstance, destroyInstance, instance } = useZBDRamp(options);
```
## Usage Examples
### Basic Component
```tsx theme={null}
import React from 'react';
import { ZBDRamp } from '@zbdpay/ramp-react';
function PaymentWidget({ sessionToken }) {
const handleSuccess = (data: any) => {
console.log('Payment successful:', data);
// Handle successful payment
};
const handleError = (error: any) => {
console.error('Payment error:', error);
// Handle error
};
return (
Make a Payment
);
}
```
### With Ref for Control
```tsx theme={null}
import React, { useRef } from 'react';
import { ZBDRamp } from '@zbdpay/ramp-react';
import type { ZBDRampRef } from '@zbdpay/ramp-react';
function ControlledPayment({ sessionToken }) {
const rampRef = useRef(null);
const closeWidget = () => {
rampRef.current?.unmount();
};
const destroyWidget = () => {
rampRef.current?.destroy();
};
return (
console.log('Success:', data)}
onError={(error) => console.error('Error:', error)}
/>
);
}
```
### Using the Hook
```tsx theme={null}
import React, { useState } from 'react';
import { useZBDRamp } from '@zbdpay/ramp-react';
function HookExample({ sessionToken }) {
const [isOpen, setIsOpen] = useState(false);
const { createInstance, destroyInstance } = useZBDRamp({
sessionToken,
container: '#ramp-container',
onSuccess: (data) => {
console.log('Payment successful:', data);
setIsOpen(false);
},
onClose: () => {
setIsOpen(false);
},
});
const openRamp = () => {
setIsOpen(true);
createInstance();
};
const closeRamp = () => {
setIsOpen(false);
destroyInstance();
};
return (
{isOpen && (
)}
);
}
```
### Error Handling
```tsx theme={null}
import React, { useState } from 'react';
import { ZBDRamp } from '@zbdpay/ramp-react';
import type { RampError } from '@zbdpay/ramp-react';
function PaymentWithErrorHandling({ sessionToken }) {
const [error, setError] = useState(null);
const handleError = (error: RampError) => {
switch (error.code) {
case 'INVALID_CONFIG':
setError('Configuration error. Please check your settings.');
break;
case 'NETWORK_ERROR':
setError('Network error. Please check your connection.');
break;
case 'PAYMENT_FAILED':
setError('Payment failed. Please try again.');
break;
default:
setError('An unexpected error occurred.');
}
};
const clearError = () => setError(null);
return (
{error && (
Error: {error}
)}
setError(null)}
onError={handleError}
/>
);
}
```
### Session Token Creation
```tsx theme={null}
import React, { useState } from 'react';
import { ZBDRamp, initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-react';
function SessionTokenExample() {
const [sessionToken, setSessionToken] = useState('');
const [isLoading, setIsLoading] = useState(false);
const createSession = async () => {
setIsLoading(true);
try {
const response = await initRampSession({
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://your-webhook.com',
});
if (response.success) {
setSessionToken(response.data.session_token);
} else {
console.error('Failed to create session:', response.error);
}
} catch (error) {
console.error('Error creating session:', error);
} finally {
setIsLoading(false);
}
};
return (
{!sessionToken ? (
) : (
console.log('Success:', data)}
/>
)}
);
}
```
### Modal Integration
```tsx theme={null}
import React, { useState } from 'react';
import { ZBDRamp } from '@zbdpay/ramp-react';
function ModalExample({ sessionToken }) {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
{isModalOpen && (
setIsModalOpen(false)}>
e.stopPropagation()}>
{
console.log('Payment successful:', data);
setIsModalOpen(false);
}}
onClose={() => setIsModalOpen(false)}
style={{ width: '100%', height: '600px' }}
/>
)}
>
);
}
```
## TypeScript Support
The package includes comprehensive TypeScript definitions:
```typescript theme={null}
import type {
ZBDRampProps,
ZBDRampRef,
RampConfig,
RampCallbacks,
RampOptions,
RampError,
RampLog,
RampInstance,
PostMessageData,
InitRampSessionConfig,
InitRampSessionData,
InitRampSessionResponse,
QuoteCurrencyEnum,
BaseCurrencyEnum,
} from '@zbdpay/ramp-react';
```
### Type Examples
```typescript theme={null}
// Define typed configuration
const config: InitRampSessionConfig = {
apikey: process.env.REACT_APP_ZBD_API_KEY!,
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
};
// Handle typed responses
const handleSuccess = (data: any): void => {
console.log('Payment completed:', data);
};
const handleError = (error: RampError): void => {
console.error(`Error ${error.code}: ${error.message}`);
};
// Create typed ref
const rampRef = useRef(null);
```
## Complete Example App
The repository includes a complete example application:
```bash theme={null}
# Clone and run example
git clone https://github.com/zbdpay/ramp-react.git
cd ramp-react/example
npm install
npm run dev
```
The example includes:
* Session token creation form
* Complete ZBD Ramp integration
* Error handling and callbacks
* TypeScript implementation
## Related Packages
Core TypeScript/JavaScript SDK
React Native components
Flutter plugin
## Resources
* [GitHub Repository](https://github.com/zbdpay/ramp-react)
* [NPM Package](https://www.npmjs.com/package/@zbdpay/ramp-react)
* [API Documentation](/payments/ramp/session)
* [Webhook Events](/payments/ramp/webhooks)
## Support
For support and questions:
* GitHub Issues: [Create an issue](https://github.com/zbdpay/ramp-react/issues)
# React Native SDK
Source: https://docs.zbdpay.com/payments/ramp/sdks/react-native
React Native wrapper for ZBD Ramp
The `@zbdpay/ramp-react-native` package is a React Native wrapper for the ZBD Ramp widget that enables Buying Bitcoin with USD directly to the Lightning Network.
## Features
* **React Native Optimized**: Built specifically for React Native with WebView
* **TypeScript Support**: Full type safety with comprehensive TypeScript definitions
* **Cross-Platform**: Works on iOS and Android
* **Ref API**: Access to WebView methods and ramp instance
* **Hook Support**: `useZBDRamp` hook for programmatic usage
## Installation
```bash theme={null}
npm install @zbdpay/ramp-react-native react-native-webview
```
```bash theme={null}
yarn add @zbdpay/ramp-react-native react-native-webview
```
```bash theme={null}
pnpm add @zbdpay/ramp-react-native react-native-webview
```
### iOS Setup
#### 1. Install CocoaPods dependencies
```bash theme={null}
cd ios && pod install
```
#### 2. Add Privacy Permissions
Add the following entries to your `ios/{YourAppName}/Info.plist`:
```xml theme={null}
NSCameraUsageDescription
ZBD Ramp needs camera access for document verification and identity verification processes.
NSMicrophoneUsageDescription
ZBD Ramp needs microphone access for liveness detection during identity verification.
NSPhotoLibraryUsageDescription
ZBD Ramp needs photo library access to upload documents for verification purposes.
NSPhotoLibraryAddUsageDescription
ZBD Ramp may save verification photos to your photo library.
```
These permissions are required for the ZBD Ramp widget to access device features like camera (document verification) and microphone (liveness detection) within the WebView context.
### Android Setup
Add the following permissions to your `android/app/src/main/AndroidManifest.xml`:
```xml theme={null}
```
These permissions prevent `permissions_unavailable` errors when the ZBD Ramp widget tries to access device features.
## Quick Start
### 1. Create Session Token
First, create a session token using the ZBD API:
```tsx theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-react-native';
const response = await initRampSession({
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://your-webhook-url.com',
});
const sessionToken = response.data.session_token;
```
### 2. Use ZBDRamp Component
```tsx theme={null}
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { ZBDRamp } from '@zbdpay/ramp-react-native';
function App() {
return (
console.log('Success:', data)}
onError={(error) => console.error('Error:', error)}
onStepChange={(step) => console.log('Step:', step)}
style={styles.webview}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
flex: 1,
},
});
```
## API Reference
### initRampSession
Creates a new session token for the ZBD Ramp widget.
Configuration object for creating a session
#### Configuration Parameters
Your ZBD API key
User's email address
Lightning address or Bitcoin address
Quote currency (e.g., USD)
Base currency (e.g., BTC)
Webhook URL for notifications
Your internal reference ID
Additional metadata to attach to the session
### ZBDRamp Component
React Native component that renders the ZBD Ramp widget using WebView.
#### Props
Session token from ZBD API
WebView style
Additional WebView props
#### Callback Props
Called when payment is successful
Called when an error occurs
Called when user navigates to a different step
Debug/info logging callback
Called when widget is fully loaded
Called when user closes the widget
#### Ref API
```typescript theme={null}
interface ZBDRampRef {
mount: (container?: HTMLElement | string) => void;
unmount: () => void;
destroy: () => void;
}
```
### useZBDRamp Hook
Hook for managing ZBD Ramp instances programmatically.
```tsx theme={null}
const { rampRef, sendMessage, updateConfig, reload } = useZBDRamp(options);
```
## Usage Examples
### Basic Component
```tsx theme={null}
import React from 'react';
import { View, StyleSheet, Alert } from 'react-native';
import { ZBDRamp } from '@zbdpay/ramp-react-native';
function PaymentScreen() {
const handleSuccess = (data: any) => {
Alert.alert('Success', 'Payment completed successfully!');
console.log('Payment data:', data);
};
const handleError = (error: any) => {
Alert.alert('Error', error.message);
console.error('Payment error:', error);
};
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
webview: {
flex: 1,
backgroundColor: 'transparent',
},
});
```
### With Ref for Control
```tsx theme={null}
import React, { useRef } from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { ZBDRamp } from '@zbdpay/ramp-react-native';
import type { ZBDRampRef } from '@zbdpay/ramp-react-native';
function ControlledPayment() {
const rampRef = useRef(null);
const unmountWidget = () => {
rampRef.current?.unmount();
};
const destroyWidget = () => {
rampRef.current?.destroy();
};
return (
Unmount
Destroy
console.log('Success:', data)}
onError={(error) => console.error('Error:', error)}
style={styles.webview}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
controls: {
flexDirection: 'row',
justifyContent: 'space-around',
padding: 10,
backgroundColor: '#fff',
},
button: {
backgroundColor: '#ff6b35',
paddingHorizontal: 15,
paddingVertical: 8,
borderRadius: 4,
},
buttonText: {
color: 'white',
fontSize: 12,
fontWeight: 'bold',
},
webview: {
flex: 1,
},
});
```
### Using the Hook
```tsx theme={null}
import React, { useState } from 'react';
import { View, TouchableOpacity, Text, StyleSheet, Modal } from 'react-native';
import { ZBDRamp, useZBDRamp } from '@zbdpay/ramp-react-native';
function HookExample() {
const [isVisible, setIsVisible] = useState(false);
const { rampRef, sendMessage, updateConfig, reload } = useZBDRamp({
sessionToken: 'your-session-token',
onSuccess: (data) => {
console.log('Payment successful:', data);
setIsVisible(false);
},
onClose: () => {
setIsVisible(false);
},
});
const openPayment = () => {
setIsVisible(true);
};
const closePayment = () => {
setIsVisible(false);
};
return (
Open Payment
Close
{
console.log('Success:', data);
setIsVisible(false);
}}
style={styles.webview}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
openButton: {
backgroundColor: '#ff6b35',
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 8,
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
modalContainer: {
flex: 1,
},
modalHeader: {
flexDirection: 'row',
justifyContent: 'flex-end',
padding: 15,
backgroundColor: '#f8f8f8',
},
closeButton: {
fontSize: 16,
color: '#007AFF',
},
webview: {
flex: 1,
},
});
```
### Custom WebView Configuration
```tsx theme={null}
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { ZBDRamp } from '@zbdpay/ramp-react-native';
function CustomWebViewRamp() {
return (
console.log('Success:', data)}
onError={(error) => console.error('Error:', error)}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
flex: 1,
backgroundColor: '#ffffff',
},
});
```
### Error Handling
```tsx theme={null}
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Alert } from 'react-native';
import { ZBDRamp } from '@zbdpay/ramp-react-native';
import type { RampError } from '@zbdpay/ramp-react-native';
function PaymentWithErrorHandling() {
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const handleError = (error: RampError) => {
setIsLoading(false);
let errorMessage = 'An unexpected error occurred.';
switch (error.code) {
case 'INVALID_CONFIG':
errorMessage = 'Configuration error. Please check your settings.';
break;
case 'NETWORK_ERROR':
errorMessage = 'Network error. Please check your connection.';
break;
case 'PAYMENT_FAILED':
errorMessage = 'Payment failed. Please try again.';
break;
}
setError(errorMessage);
Alert.alert('Payment Error', errorMessage);
};
const handleReady = () => {
setIsLoading(false);
setError(null);
};
const retry = () => {
setError(null);
setIsLoading(true);
};
return (
{isLoading && (
Loading payment widget...
)}
{error && (
{error}
Retry
)}
{!error && (
{
setError(null);
Alert.alert('Success', 'Payment completed!');
}}
style={styles.webview}
/>
)}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
errorText: {
color: 'red',
textAlign: 'center',
marginBottom: 20,
fontSize: 16,
},
retryButton: {
backgroundColor: '#ff6b35',
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 8,
},
retryButtonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
webview: {
flex: 1,
},
});
```
## TypeScript Support
The package includes comprehensive TypeScript definitions:
```typescript theme={null}
import type {
ZBDRampProps,
ZBDRampRef,
RampConfig,
RampCallbacks,
RampOptions,
RampError,
RampLog,
PostMessageData,
InitRampSessionConfig,
InitRampSessionData,
InitRampSessionResponse,
QuoteCurrencyEnum,
BaseCurrencyEnum,
} from '@zbdpay/ramp-react-native';
```
### Type Examples
```typescript theme={null}
// Define typed configuration
const config: InitRampSessionConfig = {
apikey: process.env.ZBD_API_KEY!,
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
};
// Handle typed responses
const handleSuccess = (data: any): void => {
console.log('Payment completed:', data);
};
const handleError = (error: RampError): void => {
console.error(`Error ${error.code}: ${error.message}`);
};
// Create typed instance
const ramp: ZBDRampRef = useRef(null);
```
## Development Setup
### Running the Example App
The repository includes a complete React Native example app:
```bash theme={null}
# Clone the repository
git clone https://github.com/zbdpay/ramp-react-native.git
cd ramp-react-native
# Install dependencies
npm install
# Navigate to example app
cd example
npm install
# For iOS
cd ios && pod install && cd ..
npm run ios
# For Android
npm run android
```
The example app includes:
* Session token creation
* Debug logging
* Full integration with all event handlers
* Error handling examples
## Related Packages
Core TypeScript/JavaScript SDK
React components and hooks
Flutter plugin
## Resources
* [GitHub Repository](https://github.com/zbdpay/ramp-react-native)
* [NPM Package](https://www.npmjs.com/package/@zbdpay/ramp-react-native)
* [API Documentation](/payments/ramp/session)
* [Webhook Events](/payments/ramp/webhooks)
## Support
For support and questions:
* GitHub Issues: [Create an issue](https://github.com/zbdpay/ramp-react-native/issues)
# TypeScript SDK
Source: https://docs.zbdpay.com/payments/ramp/sdks/typescript
Core TypeScript/JavaScript SDK for ZBD Ramp integration
The `@zbdpay/ramp-ts` package is the core TypeScript/JavaScript iframe wrapper for the ZBD Ramp widget that enables Bitcoin purchase interface for web applications.
## Features
* **TypeScript First**: Full type safety with comprehensive TypeScript definitions
* **PostMessage Communication**: Real-time error handling, logging, and step tracking
* **Lightweight**: No dependencies, tree-shakeable
* **Framework Agnostic**: Works with any JavaScript framework or vanilla JS
## Installation
```bash theme={null}
npm install @zbdpay/ramp-ts
```
```bash theme={null}
yarn add @zbdpay/ramp-ts
```
```bash theme={null}
pnpm add @zbdpay/ramp-ts
```
```html theme={null}
```
## Quick Start
### 1. Create Session Token
First, create a session token using the ZBD API:
```typescript theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
const response = await initRampSession({
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://your-webhook-url.com',
});
const sessionToken = response.data.session_token;
```
### 2. Create and Mount Widget
```typescript theme={null}
import { createRamp } from '@zbdpay/ramp-ts';
const ramp = createRamp({
sessionToken,
container: '#ramp-container',
onSuccess: (data) => console.log('Success:', data),
onError: (error) => console.error('Error:', error),
onStepChange: (step) => console.log('Step:', step),
});
ramp.mount();
```
## API Reference
### initRampSession
Creates a new session token for the ZBD Ramp widget.
Configuration object for creating a session
#### Configuration Parameters
Your ZBD API key
User's email address
Lightning address or Bitcoin address
Quote currency (e.g., USD)
Base currency (e.g., BTC)
Webhook URL for notifications
Your internal reference ID
Additional metadata to attach to the session
#### Response
```typescript theme={null}
interface InitRampSessionResponse {
data: {
session_token: string; // Session token for widget
expires_at: string; // Token expiration time
widget_url: string; // Direct widget URL
};
error: string | null; // Error message if failed
success: boolean; // Success status
message: string; // Response message
}
```
#### Example
```typescript Async/Await theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
try {
const response = await initRampSession({
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://your-webhook.com',
reference_id: 'order-123',
metadata: {
userId: '456',
plan: 'premium'
},
});
if (response.success) {
const sessionToken = response.data.session_token;
console.log('Session created:', sessionToken);
} else {
console.error('Failed to create session:', response.error);
}
} catch (error) {
console.error('Session creation error:', error);
}
```
```typescript Promise theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
initRampSession({
apikey: 'your-zbd-api-key',
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
})
.then(response => {
if (response.success) {
console.log('Session token:', response.data.session_token);
}
})
.catch(error => {
console.error('Error:', error);
});
```
### createRamp
Creates a new ZBD Ramp widget instance.
Configuration options for the widget
#### Options
Session token from initRampSession
Container element or CSS selector
Widget width
Widget height (minimum 600px recommended)
#### Callback Options
Called when payment is successful
Called when an error occurs
Called when user navigates to a different step
Debug/info logging callback
Called when widget is fully loaded
Called when user closes the widget
#### Returns
```typescript theme={null}
interface RampInstance {
mount: (container?: HTMLElement | string) => void;
unmount: () => void;
destroy: () => void;
}
```
## Usage Examples
### Basic Implementation
```typescript theme={null}
import { createRamp } from '@zbdpay/ramp-ts';
const ramp = createRamp({
sessionToken: 'your-session-token',
container: document.getElementById('ramp-container'),
});
ramp.mount();
```
### With Event Handlers
```typescript theme={null}
const ramp = createRamp({
sessionToken: 'your-session-token',
onSuccess: (data) => {
console.log('Payment successful:', data);
// Update UI, redirect, etc.
window.location.href = '/success';
},
onError: (error) => {
console.error('Payment error:', error);
// Show error message to user
alert(`Error: ${error.message}`);
},
onStepChange: (step) => {
console.log('Current step:', step);
// Track user progress
analytics.track('Ramp Step', { step });
},
onReady: () => {
console.log('Widget ready');
// Hide loading spinner
},
onClose: () => {
console.log('Widget closed');
// Handle user closing widget
}
});
```
### Custom Dimensions
```typescript theme={null}
const ramp = createRamp({
sessionToken: 'your-session-token',
width: '400px',
height: '700px',
});
// Default iframe styles applied:
// - border: none
// - border-radius: 8px
// - allow: payment
// - allowtransparency: true
// - min-height: 600px
```
### Programmatic Control
```typescript theme={null}
const ramp = createRamp({
sessionToken: 'your-session-token',
});
// Mount to specific container
ramp.mount('#my-container');
// Unmount iframe (keeps instance alive)
ramp.unmount();
// Remount to different container
ramp.mount('#another-container');
// Clean up completely
ramp.destroy();
```
### Error Handling
```typescript theme={null}
const ramp = createRamp({
sessionToken: 'your-session-token',
onError: (error) => {
// Error structure
console.error('Error Code:', error.code);
console.error('Error Message:', error.message);
if (error.details) {
console.error('Error Details:', error.details);
}
// Handle specific error codes
switch(error.code) {
case 'SESSION_EXPIRED':
// Create new session
createNewSession();
break;
case 'KYC_REQUIRED':
// Inform user about KYC
showKYCMessage();
break;
default:
// Generic error handling
showErrorMessage(error.message);
}
},
});
```
## TypeScript Support
The package includes comprehensive TypeScript definitions:
```typescript theme={null}
import type {
RampConfig,
RampCallbacks,
RampOptions,
RampError,
RampLog,
RampInstance,
PostMessageData,
InitRampSessionConfig,
InitRampSessionData,
InitRampSessionResponse,
QuoteCurrencyEnum,
BaseCurrencyEnum,
} from '@zbdpay/ramp-ts';
```
### Type Examples
```typescript theme={null}
// Define typed configuration
const config: InitRampSessionConfig = {
apikey: process.env.ZBD_API_KEY!,
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
};
// Handle typed responses
const handleSuccess = (data: any): void => {
console.log('Payment completed:', data);
};
const handleError = (error: RampError): void => {
console.error(`Error ${error.code}: ${error.message}`);
};
// Create typed instance
const ramp: RampInstance = createRamp({
sessionToken: 'token',
onSuccess: handleSuccess,
onError: handleError,
});
```
## Simple Iframe Alternative
If you don't need JavaScript callbacks, you can use a simple iframe:
```html theme={null}
```
## Framework Integrations
This is the core package. For framework-specific integrations, see:
React components and hooks
React Native components
Flutter plugin
## Try It Out
### Interactive Example
To try the interactive example locally:
1. Clone the repository:
```bash theme={null}
git clone https://github.com/zbdpay/ramp-ts.git
cd ramp-ts
```
2. Start a local server:
```bash theme={null}
npx http-server . -p 8000 -o /example/js.html
```
3. Fill the form with your API key and user details
4. Click "Create Session & Load Ramp" to see it in action
### CodeSandbox Example
Try it online: [CodeSandbox Demo](https://codesandbox.io/s/zbd-ramp-example)
## Resources
* [GitHub Repository](https://github.com/zbdpay/ramp-ts)
* [NPM Package](https://www.npmjs.com/package/@zbdpay/ramp-ts)
* [API Documentation](/payments/ramp/session)
* [Webhook Events](/payments/ramp/webhooks)
## Support
For support and questions:
* GitHub Issues: [Create an issue](https://github.com/zbdpay/ramp-ts/issues)
# Create Ramp Session
Source: https://docs.zbdpay.com/payments/ramp/session
POST https://api.zbdpay.com/api/v1/ramp-widget
Initialize a new ramp widget session for a user
## API Overview
### Base URL
All API requests should be made to:
```
https://api.zbdpay.com
```
### Authentication
All ZBD endpoints are protected by an API Key. To make requests against these endpoints you must pass a header property called `apikey` with your [ZBD Project API Key](/get-started/api-keys).
```json theme={null}
apikey: "your-api-key-here"
```
Get your API keys by [scheduling a call](https://zbd.one/sales) with our sales team.
### SSL / HTTPS Access
**ZBD only provides a secure interface over HTTPS with SSL certificate support**. Any requests that attempt to reach the ZBD API in an insecure fashion (plain-text over HTTP requests) will be rejected.
## Description
This endpoint creates a session token and widget URL that can be used to embed the ZBD Ramp widget in your game or application.
## Usage
The ramp widget allows your users to purchase Bitcoin using their preferred fiat currency. The session creation process involves:
Create a session with user details and configuration options
Receive a widget URL and session token to embed in your application
## Configuration
### Header Parameters
ZBD Project API Key
Content Type
### Body Parameters
Email address of the user launching the Ramp
URL to receive webhook notifications
Existing user session token (for returning users)
Currency to convert from (e.g., USD)
Currency to convert to (e.g., BTC)
Destination address for the funds (Lightning Address or onchain address)
Your internal reference ID for this transaction
Additional metadata for the transaction
```bash cURL theme={null}
curl -X POST https://api.zbdpay.com/api/v1/ramp-widget \
-H "Content-Type: application/json" \
-H "apikey: YOUR_API_KEY" \
-d '{
"email": "user@example.com",
"webhook_url": "https://yourapp.com/webhooks/zbd"
}'
```
```javascript Node.js theme={null}
const response = await fetch('https://api.zbdpay.com/api/v1/ramp-widget', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': process.env.ZBD_API_KEY
},
body: JSON.stringify({
email: 'user@example.com',
webhook_url: 'https://yourapp.com/webhooks/zbd'
})
});
const data = await response.json();
```
```json Response theme={null}
{
"success": true,
"data": {
"session_token": "eyJraWQiOiJzLWE1OWNkMjc4...",
"widget_url": "https://ramp.zbdpay.com/?session=eyJraWQiOiJzLWE1OWNkMjc4...",
"session_id": "ses_9n3f7h2u4b",
"expires_at": "2025-06-09T12:00:00Z"
}
}
```
### Error Responses
```json theme={null}
{
"success": false,
"error": {
"code": "INVALID_EMAIL",
"message": "Please provide a valid email address"
}
}
```
Common error codes:
* `INVALID_EMAIL` - Email format is invalid
* `INVALID_WEBHOOK_URL` - Webhook URL is not accessible
* `UNAUTHORIZED` - Invalid API key
* `RATE_LIMITED` - Too many requests
## Webhook Events
Webhooks are sent as POST requests to your specified `webhook_url`.
### Event Structure
All webhook events follow this structure:
```json theme={null}
{
"id": "evt_2n4f8gu3nf",
"type": "ramp.purchase.completed",
"created_at": "2025-06-09T10:30:00Z",
"livemode": true,
"data": {
// Event-specific data
}
}
```
# Themes Customization
Source: https://docs.zbdpay.com/payments/ramp/themes
Customize every visual element of ZBD Ramp to match your brand
ZBD Ramp provides complete control over the widget's appearance through an advanced theming system. Customize every visual element to create a seamless brand experience.
## Theme Options
### Pre-built Themes
Start with our professionally designed themes:
Clean, bright interface perfect for daytime use and professional applications
Modern dark interface that reduces eye strain and saves battery on OLED screens
## Live Preview Editor
The ZBD Developer Dashboard features a powerful Live Preview editor that makes customization intuitive and immediate.
### How It Works
Navigate to Ramp → Theme in your ZBD Developer Dashboard
Click directly on any element in the preview to select it
Adjust the element's properties in the side panel
Watch your changes apply in real-time
Save your custom theme when satisfied
### Customizable Properties
For every element in the widget, you can customize:
* **Background Color**: Primary background color
* **Text Color**: Primary text color
* **Border Color**: Element border color
* **Border Radius**: Corner rounding
* **Hover Background**: Background color on hover
* **Hover Text**: Text color on hover
* **Active Background**: Background when clicked/active
* **Active Text**: Text color when active
* **Disabled State**: Appearance when disabled
* **Shadow**: Box shadow effects
* **Padding & Margins**: Spacing adjustments
## Custom Theme JSON
Every theme configuration is exportable as JSON, allowing you to:
* Version control your theme
* Share themes across projects
* Backup theme configurations
* Programmatically apply themes
### Example Theme JSON
```json theme={null}
{
"name": "My Custom Theme",
"base": "light",
"variables": {
"--primary": "210 100% 50%",
"--primary-foreground": "0 0% 100%",
"--secondary": "210 40% 96%",
"--secondary-foreground": "222 47% 11%",
"--accent": "210 40% 90%",
"--accent-foreground": "222 47% 11%",
"--destructive": "0 84% 60%",
"--destructive-foreground": "0 0% 100%",
"--border": "214 32% 91%",
"--input": "214 32% 91%",
"--ring": "210 100% 50%",
"--radius": "0.5rem",
"--widget-background": "#FFFFFF",
"--widget-card-background": "#FAFAFA",
"--amount-input-display-text": "#000000",
"--amount-input-display-error": "#ef4444",
"--amount-input-quick-amount-bg": "#F5F5F5",
"--amount-input-quick-amount-text": "#000000",
"--amount-input-quick-amount-border": "#E0E0E0",
"--amount-input-quick-amount-hover-bg": "#EEEEEE",
"--amount-input-quick-amount-active-bg": "#E0E0E0",
"--amount-input-numpad-bg": "transparent",
"--amount-input-numpad-text": "#000000",
"--amount-input-numpad-hover-bg": "#F5F5F5",
"--amount-input-numpad-active-bg": "#EEEEEE",
"--button-primary-bg": "210 100% 50%",
"--button-primary-text": "0 0% 100%",
"--button-primary-hover-bg": "210 100% 45%",
"--button-primary-active-bg": "210 100% 40%",
"--button-secondary-bg": "210 40% 96%",
"--button-secondary-text": "222 47% 11%",
"--button-secondary-hover-bg": "210 40% 92%",
"--button-secondary-active-bg": "210 40% 88%"
}
}
```
### Importing/Exporting Themes
#### Export Your Theme
1. Open the Theme editor in your dashboard
2. Click "Export Theme" button
3. Copy the JSON or download as a file
#### Import a Theme
1. Open the Theme editor
2. Click "Import Theme"
3. Paste your JSON or upload a file
4. Preview and apply
## Version Control Integration
### Best Practices
1. **Store in Repository**: Keep your theme JSON in your project repository
2. **Use Environment Configs**: Different themes for dev/staging/production
3. **Document Changes**: Comment significant theme updates
4. **Test Across Devices**: Ensure theme works on all screen sizes
## Testing Your Theme
Always test your custom theme across different devices and browsers to ensure a consistent experience.
## Support
Need help with theme customization?
* Use the Live Preview in your [ZBD Developer Dashboard](https://dashboard.zbdpay.com)
* Contact your ZBD account manager for advanced customization
* Review our example themes in the dashboard
# User Flow Walkthrough
Source: https://docs.zbdpay.com/payments/ramp/user-flow
Visual walkthrough of the complete ZBD Ramp user experience
This guide walks through the complete user journey in the ZBD Ramp widget, from initial screen to completed purchase. Use this reference to understand what your users will experience when buying Bitcoin through your app.
## 1. Initial Screen
When users first launch the ramp widget, they're greeted with a clean, intuitive interface to begin their purchase journey.
The initial screen presents the core functionality and guides users to begin the purchase process.
***
## 2. Email Verification
To ensure account security and compliance, users must verify their email address before proceeding.
Users receive a verification code via email and enter it to confirm their identity and proceed to KYC.
***
## 3. KYC Flow
The Know Your Customer (KYC) process is streamlined into clear steps. This is required for regulatory compliance and fraud prevention.
### Step 1: Getting Started
Users are introduced to the KYC process and what information they'll need to provide.
### Step 2: Country Selection
Users select their country of residence. This determines available payment methods and compliance requirements.
### Step 3: Personal Information
Users provide basic personal information including full name, date of birth, and other required details.
### Step 4: Address
Users enter their residential address for identity verification purposes.
### Step 5: Document Selection
Users choose which type of government-issued ID they'll upload (passport, driver's license, etc.).
### Step 6: Document Upload
Users can upload documents directly or receive a secure link to complete the upload on their phone.
Users can scan a QR code or receive a link to upload from their mobile device.
A secure, one-time link is generated for mobile document uploads.
Confirmation that the mobile device is connected and ready for upload.
***
## 4. KYC Processing
After submitting KYC information, users enter the verification stage.
Users see a processing screen while their information is being verified. This typically takes just a few moments.
Upon successful verification, users are cleared to proceed with their purchase.
If verification fails, users receive clear guidance on next steps or alternative options.
***
## 5. Payment Method Selection
Once KYC is approved, users choose how they want to pay for their Bitcoin.
Users can connect their bank account via Plaid for ACH payments. Additional payment methods are coming soon.
If a user hasn't linked a bank account yet, they'll see an option to connect via Plaid.
***
## 6. Plaid Bank Connection
To enable bank payments, users securely connect their bank account through Plaid.
### Plaid Flow Steps
Users are introduced to the secure Plaid connection process.
Users search for and select their bank from thousands of supported institutions.
Users log into their bank account securely through Plaid's interface.
Confirmation that the bank account is successfully connected and ready for payments.
***
## 7. Payment Confirmation
After payment method setup, users confirm their purchase details.
Users see a success screen confirming their Bitcoin purchase and delivery details.
If the payment fails, users receive clear error messages and options to retry.
***
## 8. Transaction Management
Users can view their transaction history and details at any time.
### Transaction History
A comprehensive list of all past and pending transactions, with status indicators for easy tracking.
### Transaction Details
Detailed view of individual transactions including amounts, timestamps, fees, and destination addresses.
***
## Integration Tips
Design your app to seamlessly transition users into the ramp widget. Consider the context and timing of when you present the purchase option.
Implement webhook handlers to process purchase events and update your app state in real-time as users progress through the flow.
***
## Next Steps
Learn how to integrate the ZBD Ramp widget into your application
Customize the widget's theme to match your brand
Handle webhook events to track user progress and purchases
Explore the complete API documentation
# Webhook Events
Source: https://docs.zbdpay.com/payments/ramp/webhooks
Complete reference for ZBD Ramp webhook events
## Overview
Webhooks allow you to receive real-time notifications about events that occur during the ZBD Ramp lifecycle. From session initialization to payment completion, webhooks provide crucial updates about your users' transactions.
ZBD Ramp sends webhook events to your specified endpoint as HTTP POST requests. Each event contains detailed information about what occurred, allowing you to update your systems accordingly.
### Webhook URL Setup
Configure your webhook URL when creating a session:
```typescript @zbdpay/ramp-ts theme={null}
import { initRampSession, QuoteCurrencyEnum, BaseCurrencyEnum } from '@zbdpay/ramp-ts';
const response = await initRampSession({
apikey: process.env.ZBD_API_KEY,
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: QuoteCurrencyEnum.USD,
base_currency: BaseCurrencyEnum.BTC,
webhook_url: 'https://app.xyz/webhooks/zbd', // <---- YOUR WEBHOOK URL HERE
reference_id: 'order-123',
metadata: {
userId: 'user-456',
plan: 'premium'
}
});
const sessionToken = response.data.session_token;
```
```typescript Fetch theme={null}
const response = await fetch('https://api.zbdpay.com/api/v1/ramp-widget', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': process.env.ZBD_API_KEY
},
body: JSON.stringify({
email: 'user@example.com',
destination: 'lightning-address@zbd.gg',
quote_currency: 'USD',
base_currency: 'BTC',
webhook_url: 'https://app.xyz/webhooks/zbd', // <---- YOUR WEBHOOK URL HERE
reference_id: 'order-123',
metadata: {
userId: 'user-456',
plan: 'premium'
}
})
});
const data = await response.json();
const sessionToken = data.data.session_token;
```
## Event Categories
Webhook events are organized into six main categories:
Widget lifecycle events
User verification events
Identity verification events
Bank connection events
Transaction events
Crypto delivery events
## Event Structure
All webhook events follow a consistent structure:
```json theme={null}
{
"event": "RAMP_WIDGET.V1.EVENT_NAME",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
// Event-specific data
"metadata": {
// Your custom metadata
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:30:00Z"
}
```
## Complete Event Reference
### Session Events
**Event:** `RAMP_WIDGET.V1.SESSION.INITIATED`
Triggered when a Ramp session is successfully initiated.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.SESSION.INITIATED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789"
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:30:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.SESSION.CLOSED`
Fired when a Ramp session is closed, either by unmount, user action, or completion.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.SESSION.CLOSED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789"
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T11:15:00Z"
}
```
### Authentication Events
**Event:** `RAMP_WIDGET.V1.CODE_VERIFICATION.SUCCEEDED`
Sent when a user successfully verifies their 6-digit code.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.CODE_VERIFICATION.SUCCEEDED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789"
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:32:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.CODE_VERIFICATION.FAILED`
Triggered when a 6-digit code verification attempt fails.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.CODE_VERIFICATION.FAILED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789"
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:33:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.USER_ACCESS_TOKEN.CREATED`
Fired when user access and refresh tokens are generated.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.USER_ACCESS_TOKEN.CREATED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"access_token_id": "tok_abc123",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"access_token_expires_at": "2025-01-18T11:45:00Z",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token_expires_at": "2025-02-18T10:45:00Z",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:45:00Z"
}
```
### KYC Events
**Event:** `RAMP_WIDGET.V1.KYC.INITIATED`
Fired when KYC (Know Your Customer) verification process is initiated.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.KYC.INITIATED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:35:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.KYC.PROCESSING`
Indicates that KYC verification is being processed.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.KYC.PROCESSING",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:36:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.KYC.COMPLETED`
Sent when KYC verification is successfully completed.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.KYC.COMPLETED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:40:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.KYC.REJECTED`
Triggered when KYC verification is rejected or fails.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.KYC.REJECTED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:41:00Z"
}
```
### Bank Connection Events
**Event:** `RAMP_WIDGET.V1.BANK_CONNECTION.INITIATED`
Triggered when bank connection flow is initiated.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.BANK_CONNECTION.INITIATED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:50:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.BANK_CONNECTION.COMPLETED`
Sent when bank connection is successfully established.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.BANK_CONNECTION.COMPLETED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:55:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.BANK_CONNECTION.FAILED`
Fired when bank connection attempt fails.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.BANK_CONNECTION.FAILED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T10:56:00Z"
}
```
### Payment Events
**Event:** `RAMP_WIDGET.V1.PAYMENT.INITIATED`
Triggered when a payment transaction is initiated.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.PAYMENT.INITIATED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"base_amount": "100.00",
"base_currency": "USD",
"quote_amount": "0.0025",
"quote_currency": "BTC",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T11:00:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.PAYMENT.SETTLED`
Sent when a payment transaction is successfully settled.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.PAYMENT.SETTLED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"base_amount": "100.00",
"base_currency": "USD",
"quote_amount": "0.0025",
"quote_currency": "BTC",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T11:05:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.PAYMENT.FAILED`
Fired when a payment transaction fails.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.PAYMENT.FAILED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"base_amount": "100.00",
"base_currency": "USD",
"quote_amount": "0.0025",
"quote_currency": "BTC",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T11:06:00Z"
}
```
### Withdrawal Events
**Event:** `RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED`
Triggered when a withdrawal is successfully completed.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"base_amount": "100.00",
"base_currency": "USD",
"quote_amount": "0.0025",
"quote_currency": "BTC",
"destination": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payment_hash": "c0ff35a42445041592aa5ff982606971ae46b3f9df0a100cb15f05f61718f223",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T11:10:00Z"
}
```
**Event:** `RAMP_WIDGET.V1.WITHDRAWAL.FAILED`
Sent when a withdrawal attempt fails.
```json theme={null}
{
"event": "RAMP_WIDGET.V1.WITHDRAWAL.FAILED",
"data": {
"email": "user@example.com",
"session_id": "sess_abc123xyz789",
"base_amount": "100.00",
"base_currency": "USD",
"quote_amount": "0.0025",
"quote_currency": "BTC",
"destination": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"metadata": {
"customer_id": "cust_123",
"source": "widget"
}
},
"url": "https://partner.com/webhooks",
"created_at": "2025-01-18T11:11:00Z"
}
```
## Webhook Implementation
### Basic Handler Examples
Here are webhook handler implementations in popular frameworks:
```typescript Next.js theme={null}
// app/api/webhooks/zbd/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const event = await request.json();
// Log the event
console.log(`Received webhook: ${event.event}`);
// Handle different event types
switch(event.event) {
case 'RAMP_WIDGET.V1.PAYMENT.SETTLED':
// Update user balance, send confirmation, etc.
await handlePaymentSettled(event.data);
break;
case 'RAMP_WIDGET.V1.KYC.COMPLETED':
// Update user verification status
await handleKYCCompleted(event.data);
break;
case 'RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED':
// Log successful withdrawal
await handleWithdrawalSuccess(event.data);
break;
default:
console.log(`Unhandled event type: ${event.event}`);
}
// Always respond with 200 OK
return NextResponse.json({ received: true }, { status: 200 });
}
async function handlePaymentSettled(data: any) {
// Your payment processing logic
console.log('Payment settled:', data);
}
async function handleKYCCompleted(data: any) {
// Your KYC completion logic
console.log('KYC completed:', data);
}
async function handleWithdrawalSuccess(data: any) {
// Your withdrawal success logic
console.log('Withdrawal succeeded:', data);
}
```
```go Go theme={null}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type WebhookEvent struct {
Event string `json:"event"`
Data map[string]interface{} `json:"data"`
URL string `json:"url"`
CreatedAt string `json:"created_at"`
}
func webhookHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading body", http.StatusBadRequest)
return
}
var event WebhookEvent
err = json.Unmarshal(body, &event)
if err != nil {
http.Error(w, "Error parsing JSON", http.StatusBadRequest)
return
}
// Log the event
log.Printf("Received webhook: %s", event.Event)
// Handle different event types
switch event.Event {
case "RAMP_WIDGET.V1.PAYMENT.SETTLED":
handlePaymentSettled(event.Data)
case "RAMP_WIDGET.V1.KYC.COMPLETED":
handleKYCCompleted(event.Data)
case "RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED":
handleWithdrawalSuccess(event.Data)
default:
log.Printf("Unhandled event type: %s", event.Event)
}
// Always respond with 200 OK
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "OK")
}
func handlePaymentSettled(data map[string]interface{}) {
// Your payment processing logic
log.Printf("Payment settled: %v", data)
}
func handleKYCCompleted(data map[string]interface{}) {
// Your KYC completion logic
log.Printf("KYC completed: %v", data)
}
func handleWithdrawalSuccess(data map[string]interface{}) {
// Your withdrawal success logic
log.Printf("Withdrawal succeeded: %v", data)
}
func main() {
http.HandleFunc("/webhooks/zbd", webhookHandler)
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
```
```rust Rust theme={null}
use actix_web::{web, App, HttpResponse, HttpServer, Result};
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Deserialize, Serialize)]
struct WebhookEvent {
event: String,
data: Value,
url: String,
created_at: String,
}
async fn webhook_handler(event: web::Json) -> Result {
// Log the event
println!("Received webhook: {}", event.event);
// Handle different event types
match event.event.as_str() {
"RAMP_WIDGET.V1.PAYMENT.SETTLED" => {
handle_payment_settled(&event.data).await;
}
"RAMP_WIDGET.V1.KYC.COMPLETED" => {
handle_kyc_completed(&event.data).await;
}
"RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED" => {
handle_withdrawal_success(&event.data).await;
}
_ => {
println!("Unhandled event type: {}", event.event);
}
}
// Always respond with 200 OK
Ok(HttpResponse::Ok().body("OK"))
}
async fn handle_payment_settled(data: &Value) {
// Your payment processing logic
println!("Payment settled: {:?}", data);
}
async fn handle_kyc_completed(data: &Value) {
// Your KYC completion logic
println!("KYC completed: {:?}", data);
}
async fn handle_withdrawal_success(data: &Value) {
// Your withdrawal success logic
println!("Withdrawal succeeded: {:?}", data);
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Server starting on http://127.0.0.1:8080");
HttpServer::new(|| {
App::new()
.route("/webhooks/zbd", web::post().to(webhook_handler))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
```
```javascript Node.js/Express theme={null}
app.post('/webhooks/zbd', (req, res) => {
const event = req.body;
// Log the event
console.log(`Received webhook: ${event.event}`);
// Handle different event types
switch(event.event) {
case 'RAMP_WIDGET.V1.PAYMENT.SETTLED':
// Update user balance, send confirmation, etc.
handlePaymentSettled(event.data);
break;
case 'RAMP_WIDGET.V1.KYC.COMPLETED':
// Update user verification status
handleKYCCompleted(event.data);
break;
case 'RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED':
// Log successful withdrawal
handleWithdrawalSuccess(event.data);
break;
default:
console.log(`Unhandled event type: ${event.event}`);
}
// Always respond with 200 OK
res.status(200).send('OK');
});
function handlePaymentSettled(data) {
// Your payment processing logic
console.log('Payment settled:', data);
}
function handleKYCCompleted(data) {
// Your KYC completion logic
console.log('KYC completed:', data);
}
function handleWithdrawalSuccess(data) {
// Your withdrawal success logic
console.log('Withdrawal succeeded:', data);
}
```
```python Python/Flask theme={null}
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhooks/zbd', methods=['POST'])
def handle_webhook():
event = request.json
# Log the event
print(f"Received webhook: {event['event']}")
# Handle different event types
if event['event'] == 'RAMP_WIDGET.V1.PAYMENT.SETTLED':
handle_payment_settled(event['data'])
elif event['event'] == 'RAMP_WIDGET.V1.KYC.COMPLETED':
handle_kyc_completed(event['data'])
elif event['event'] == 'RAMP_WIDGET.V1.WITHDRAWAL.SUCCEEDED':
handle_withdrawal_success(event['data'])
else:
print(f"Unhandled event type: {event['event']}")
# Always respond with 200 OK
return 'OK', 200
def handle_payment_settled(data):
# Your payment processing logic
print(f"Payment settled: {data}")
def handle_kyc_completed(data):
# Your KYC completion logic
print(f"KYC completed: {data}")
def handle_withdrawal_success(data):
# Your withdrawal success logic
print(f"Withdrawal succeeded: {data}")
if __name__ == '__main__':
app.run(port=8080)
```
## Security Best Practices
**Important:** Always validate webhook authenticity before processing events.
### Webhook Verification
1. **Use HTTPS Only** - Always use HTTPS endpoints for webhooks
2. **Verify Signatures** - Validate webhook signatures when provided
3. **IP Allowlisting** - Restrict webhook access to ZBD IP addresses
4. **Idempotency** - Handle duplicate events gracefully
5. **Timeout Handling** - Respond quickly (within 5 seconds)
### Error Handling
* Always respond with `200 OK` status, even if processing fails
* Log all webhook events for debugging
* Implement retry logic for critical operations
* Use message queues for asynchronous processing
## Testing Webhooks
### Local Development
Use tools like [ngrok](https://ngrok.com) to expose your local webhook endpoint:
```bash theme={null}
ngrok http 3000
```
Then use the ngrok URL as your webhook endpoint during development.
### Webhook Testing Checklist
Essential events to handle:
* ✅ PAYMENT.SETTLED
* ✅ WITHDRAWAL.SUCCEEDED
* ✅ PAYMENT.FAILED
* ✅ WITHDRAWAL.FAILED
Improve user experience:
* ✅ KYC.COMPLETED
* ✅ KYC.REJECTED
* ✅ BANK\_CONNECTION.COMPLETED
* ✅ SESSION.CLOSED
For advanced integrations:
* ⚪ SESSION.INITIATED
* ⚪ CODE\_VERIFICATION.SUCCEEDED
* ⚪ KYC.INITIATED
* ⚪ PAYMENT.INITIATED
## Troubleshooting
### Common Issues
* Verify your webhook URL is publicly accessible
* Check for firewall or security rules blocking requests
* Ensure your endpoint responds with 200 status
* Confirm webhook URL was correctly set during session creation
* Implement idempotency using the session\_id
* Store processed event IDs to prevent reprocessing
* Use database transactions for critical operations
* Process webhooks asynchronously using queues
* Respond immediately with 200 OK
* Move heavy processing to background jobs
## Next Steps
Learn how to create widget sessions
Complete integration walkthrough
# ZBD Payments SDK
Source: https://docs.zbdpay.com/payments/sdk
Use ZBD Payments in your preferred development environment.
## Official SDKs
The following SDKs are maintained by the ZBD Payments core team.
Easiest way to interact with the ZBD Payments APIs. Quickstart guides and source code for Next.js, Node.js, and Express applications.
Python SDK for ZBD Payments APIs. Includes support for Django, Flask and FastAPI frameworks.
## Community SDKs
Supported by the ZBD open source developer community.
Rust SDK for ZBD Payments APIs
Go SDK for ZBD Payments APIs
C# SDK for ZBD Payments APIs
# C# SDK
Source: https://docs.zbdpay.com/payments/sdk/csharp
Learn how to send and receive instant Bitcoin payments with C# and ZBD.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* [Visual Studio](https://visualstudio.microsoft.com/downloads/)
## 1. Create project
Create a new project or open an existing project in Visual Studio.
## 2. Install the ZBD NuGet package
NuGet package name: `dev.zbd.csharp`
```bash Package Manager theme={null}
NuGet\Install-Package dev.zbd.csharp
```
```bash .NET CLI theme={null}
dotnet add package dev.zbd.csharp
```
```xml Package Reference theme={null}
```
## 3. Send and receive Bitcoin
The below code is an example of how you can create a charge.
```csharp theme={null}
using ZebedeeAPI;
var handler = new ZebedeeHandler("");
var charge =
await handler.CreateCharge(
expiresIn: "10000",
amount: "100000",
description: "A Charge Created with ZBD!"
);
Console.WriteLine(charge.data.invoice.request);
```
You're looking for the `data.invoice.request` property in the JSON response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
```
lnbc1u1pjdlax9pp5t7jhkd7h2wntd4f2v7xp22dknmjxp0q8nm7hfcny4p7a5mr7x3rsdp9f4hkueteypshggrfde6x2unwv46zqumsv4jkgcqzzsxqzjcsp5dsayu6m6632p28rnkeeqsr7d54amrkv6wh46yrv42gdgca8xl8gs9qyyssqgj2zrkax733rzulfkzc5mqsr8fpwrva82stpa7e0frw32722trv37jlq8mvlqfp8y75lr6mz63zd7qnxar8hhsehuy22pvfq6wjxwqqqa60lx3
```
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
# Go SDK
Source: https://docs.zbdpay.com/payments/sdk/go
Learn how to use the Go SDK to send Bitcoin to any Email.
This guide is coming soon. Until then you can check the [Go SDK repository](https://github.com/zebedeeio/go-sdk).
# Python SDK
Source: https://docs.zbdpay.com/payments/sdk/python
Learn how to send and receive instant Bitcoin payments with Python and ZBD.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* Python 3.8 or higher
## 1. Install the ZBD Python package
Install the official ZBD Python SDK from PyPI:
```bash theme={null}
pip install zbdpay
```
## 2. Send and receive Bitcoin
Get started with just a few lines of code. Here's how to send a payment to any Lightning Address:
```python theme={null}
import os
from zbdpay import ZbdPayments
# Initialize the client
client = ZbdPayments(
apikey=os.environ.get("ZBD_PAYMENTS_API_KEY")
)
# Send instant Bitcoin payment
response = client.lightning_address.send_payment(
amount="500000", # Amount in millisatoshis
comment="Instant global payments",
ln_address="andre@zbd.gg"
)
print(f"Payment sent! Transaction ID: {response.data.id}")
```
## 3. Create a payment request
Accept Bitcoin payments by creating a charge:
```python theme={null}
# Create a charge (payment request)
charge = client.lightning_charges.create(
amount="100000", # 100 satoshis
description="Payment for your product",
expires_in=300 # Expires in 5 minutes
)
print(f"Payment Request: {charge.data.invoice.request}")
print(f"QR Code: {charge.data.invoice.uri}")
```
You're looking for the `data.invoice.request` property in the response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
Payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payments asynchronously.
## Async Support
The SDK also supports async operations for better performance:
```python theme={null}
import asyncio
from zbdpay import AsyncZbdPayments
async def main():
client = AsyncZbdPayments(
apikey=os.environ.get("ZBD_PAYMENTS_API_KEY")
)
# Send payment asynchronously
await client.lightning_address.send_payment(
amount="500000",
comment="Async payment",
ln_address="andre@zbd.gg"
)
asyncio.run(main())
```
## Next Steps
Ready to dive deeper? Check out these resources:
Explore the source code and contribute to the SDK
View the official Python package on PyPI with full documentation
## Advanced Usage
For more advanced features like custom timeouts, retries, and raw response access, check out the [full documentation on PyPI](https://pypi.org/project/zbdpay).
# Rust SDK
Source: https://docs.zbdpay.com/payments/sdk/rust
Learn how to send and receive instant Bitcoin payments with Rust and ZBD.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* [Rust](https://www.rust-lang.org/tools/install) and [cargo](https://www.rust-lang.org/tools/install) installed
## 1. Create a Rust project
```bash theme={null}
cargo new
cd
```
## 2. Install dependencies
Add both the `zebedee-rust` and `tokio` crates to your project:
```bash theme={null}
cargo add zebedee-rust tokio
```
## 3. Update your Cargo.toml
Update your `Cargo.toml` file to use full features in tokio.
```yaml theme={null}
[package]
name = "zbd-rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.29.1", features = ['full']}
zebedee-rust = "0.4.4"
```
## 4. Create a Charge
Open your project's `main.rs` file and add the following code:
```rust theme={null}
use std::env;
use zebedee_rust::{charges::*, ZebedeeClient};
#[tokio::main]
async fn main(){
let apikey: String = env::var("ZBD_API_KEY").unwrap();
let zbd_client = ZebedeeClient::new().apikey(apikey).build();
let charge = Charge{
amount: String::from("5000"),
..Default::default()
};
let charges_res = zbd_client.create_charge(&charge).await.unwrap();
println!("{:?}", charge_res);
}
```
Make sure to create an environment variable called **ZBD\_API\_KEY** in your Rust project. This is the API key you get from your ZBD Project.
Run the following command to create your charge:
```bash theme={null}
cargo run
```
You can now create charges using the ZBD and Rust!
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
## 5. Try it yourself
You can now begin receiving instant Bitcoin payments with Rust + ZBD!
See the full source code.
# TypeScript SDK
Source: https://docs.zbdpay.com/payments/sdk/typescript
ZBD is your one-stop shop API for all things instant payments in TypeScript.
## Installation
```bash theme={null}
pnpm install @zbdpay/payments-sdk
```
## Quickstart
Use the following guides to get started with the TypeScript SDK for ZBD Payments:
} href="/payments/sdk/typescript/next">
Application codebase that allows you to quickly get started with ZBD and Next.js -- ZBD API Playground and a Starter Kit for ZBD-powered Next.js apps.
} href="/payments/sdk/typescript/vercel/send" />
} href="/payments/sdk/typescript/supabase/send" />
# Express
Source: https://docs.zbdpay.com/payments/sdk/typescript/express
Learn how to send and receive instant Bitcoin payments with Express and ZBD.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
## 1. Create a Node.js project
Start with a brand new empty directory called `express-example` and run the following command to initiate a Node.js project:
```bash theme={null}
npm init -y
```
## 2. Install Express.js
Inside your project directory, run the following command to install Express.js:
```bash yarn theme={null}
yarn add express
```
```bash npm theme={null}
npm install express
```
```bash pnpm theme={null}
pnpm add express
```
## 3. Install @zbdpay/payments-sdk Node.js SDK
Inside your Express.js
```bash yarn theme={null}
yarn add @zbdpay/payments-sdk
```
```bash npm theme={null}
npm install @zbdpay/payments-sdk
```
```bash pnpm theme={null}
pnpm add @zbdpay/payments-sdk
```
## 4. Send and receive Bitcoin
Create a new file called `index.js` and add the following code:
```js theme={null}
import express from "express";
import ZbdPayments from '@zbdpay/payments-sdk';
const ZBD_API_KEY = 'b7YW3s2JzZKGcXjIf5Dqof8wjKT2RuWr8'; // dummy key
const client = new ZbdPayments({
apikey: ZBD_API_KEY,
});
// Create Express app
const app = express();
// Creating a Bitcoin Lightning payment request
app.get("/request", async (req, res) => {
try {
const data = await client.lightningCharges.create({
amount: '100000',
callbackUrl: 'https://your-app.com/zbd-callback',
description: 'Express + ZBD!',
});
res.status(200).json({ data });
} catch (error) {
res.status(500).json({ error });
}
});
// Send a payment to a Bitcoin Lightning Address
app.get("/send", async (req, res) => {
try {
const data = await client.lightningAddress.sendPayment({
lnAddress: "andreneves@zbd.gg", // Who is the recipient?
amount: "100000", // 100 satoshis (100,000 msats)
comment: "Express + ZBD!",
});
res.status(200).json({ data });
} catch (error) {
res.status(500).json({ error });
}
});
app.listen(3000, () => {
console.log("Express server w/ ZBD listening on https://example.com");
});
```
Run the following command to start your Express.js server:
```bash yarn theme={null}
yarn start
```
```bash npm theme={null}
npm start
```
Opening your browser to the following URL: `https://example.com/request` should return a JSON response with a payment request.
You can also test this using curl command:
```bash theme={null}
curl https://example.com/request
```
You're looking for the `data.invoice.request` property in the JSON response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
```
lnbc1u1pjdlax9pp5t7jhkd7h2wntd4f2v7xp22dknmjxp0q8nm7hfcny4p7a5mr7x3rsdp9f4hkueteypshggrfde6x2unwv46zqumsv4jkgcqzzsxqzjcsp5dsayu6m6632p28rnkeeqsr7d54amrkv6wh46yrv42gdgca8xl8gs9qyyssqgj2zrkax733rzulfkzc5mqsr8fpwrva82stpa7e0frw32722trv37jlq8mvlqfp8y75lr6mz63zd7qnxar8hhsehuy22pvfq6wjxwqqqa60lx3
```
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
Opening your browser to the following URL: `https://example.com/send` should return a JSON response with the payment sent message.
You can also test this using curl command:
```bash theme={null}
curl https://example.com/send
```
You're looking for the `status` of `completed` to know that the payment settled successfully.
Payments in the Lightning Network are asynchronous so you may see a response stating the payment is `processing`. This is expected -- use the `callbackUrl` property to receive updates about your payments.
## 3. Try it yourself
You can now send and receive instant Bitcoin payments using Express.js + ZBD!
See the full source code.
# Next.js
Source: https://docs.zbdpay.com/payments/sdk/typescript/next
Learn how to use the ZBD with Next.js and our Playground Starter Kit.
## Playground Starter Kit
The ZBD + Next.js Playground Starter Kit is an application codebase that allows you to quickly get started with ZBD and Next.js. It includes two main sections: a ZBD API Playground and a Starter Kit for ZBD-powered Next.js applications.
Open the ZBD + Next.js Playground
View the source code.
} href="https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fzebedeeio%2Fnextjs-zebedee-starter&env=ZBD_API_KEY&envDescription=Your%20ZBD%20project%20API%20key&demo-title=ZBD%20%2B%20Next.js%20Starter&demo-description=Starter%20kit%20for%20using%20ZBD%20API%20with%20Next.js%20fullstack%20applications&demo-url=https%3A%2F%2Fnextjs-zebedee-starter.vercel.app%2F&demo-image=https%3A%2F%2Fi.imgur.com%2FNf8wRgv.png">
1-click deploy your own instance.
## Next.js
To use ZBD with Next.js and complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
### 1. Create a Next.js project
Start with a brand new Next.js project. To begin run the following command and walk through the initializing steps:
```bash theme={null}
npx create-next-app@latest
```
### 2. Install @zbdpay/payments-sdk Node.js SDK
Install ZBD:
```bash yarn theme={null}
yarn add @zbdpay/payments-sdk
```
```bash npm theme={null}
npm install @zbdpay/payments-sdk
```
```bash pnpm theme={null}
pnpm add @zbdpay/payments-sdk
```
### 3. Create Send and Receive API routes
Create a new file `/app/api/receive/route.ts` and add the following code to create an API route that will receive instant Bitcoin payments:
```js theme={null}
import { NextResponse } from 'next/server';
import ZbdPayments from '@zbdpay/payments-sdk';
const ZBD_API_KEY = 'b7YW3s2JzZKGcXjIf5Dqof8wjKT2RuWr8'; // dummy key
const client = new ZbdPayments({
apikey: ZBD_API_KEY,
});
export async function POST() {
try {
const data = await client.lightningCharges.create({
amount: '100000',
callbackUrl: 'https://your-app.com/zbd-callback',
description: 'Next.js + ZBD!',
});
return NextResponse.json(data);
} catch (error) {
return NextResponse.json({ error });
}
}
```
Then create a new file `/app/api/send/route.ts` and add the following code to create an API route that will send Bitcoin Lightning Address payments:
```js theme={null}
import { NextResponse } from 'next/server';
import ZbdPayments from '@zbdpay/payments-sdk';
const ZBD_API_KEY = 'b7YW3s2JzZKGcXjIf5Dqof8wjKT2RuWr8';
const client = new ZbdPayments({
apikey: ZBD_API_KEY,
});
export async function POST() {
try {
const data = await client.lightningAddress.sendPayment({
lnAddress: "andreneves@zbd.gg", // Who is the recipient?
amount: "100000", // 100 satoshis (100,000 msats)
comment: "Next.js + ZBD!",
});
return NextResponse.json(data);
} catch (error) {
return NextResponse.json({ error });
}
}
```
### 4. Run your Next.js server
Run the following command to start your Next.js server:
```bash yarn theme={null}
yarn dev
```
```bash npm theme={null}
npm run dev
```
Using an API tool like [Postman](https://postman.com), you should be able to make a POST call to this endpoint and receive a JSON response with a payment request:
```bash theme={null}
https://example.com/api/request
```
You're looking for the `data.invoice.request` property in the JSON response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
```
lnbc1u1pjdlax9pp5t7jhkd7h2wntd4f2v7xp22dknmjxp0q8nm7hfcny4p7a5mr7x3rsdp9f4hkueteypshggrfde6x2unwv46zqumsv4jkgcqzzsxqzjcsp5dsayu6m6632p28rnkeeqsr7d54amrkv6wh46yrv42gdgca8xl8gs9qyyssqgj2zrkax733rzulfkzc5mqsr8fpwrva82stpa7e0frw32722trv37jlq8mvlqfp8y75lr6mz63zd7qnxar8hhsehuy22pvfq6wjxwqqqa60lx3
```
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
Using an API tool like [Postman](https://postman.com), you should be able to make a POST call to this endpoint and receive a JSON response with the payment success message:
```bash theme={null}
https://example.com/api/send
```
You're looking for the `status` of `completed` to know that the payment settled successfully.
Payments in the Lightning Network are asynchronous so you may see a response stating the payment is `processing`. This is expected -- use the `callbackUrl` property to receive updates about your payments.
### 5. Try it yourself
You can now send and receive instant Bitcoin payments using Next.js + ZBD!
See the full source code.
# Node.js
Source: https://docs.zbdpay.com/payments/sdk/typescript/node
Learn how to send and receive instant Bitcoin payments with Node.js and ZBD.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
## 1. Create a Node.js project
Start with a brand new empty directory called `node-example` and run the following command to initiate a Node.js project:
```bash theme={null}
npm init -y
```
## 2. Install @zbdpay/payments-sdk Node.js SDK
Install ZBD:
```bash yarn theme={null}
yarn add @zbdpay/payments-sdk
```
```bash npm theme={null}
npm install @zbdpay/payments-sdk
```
```bash pnpm theme={null}
pnpm add @zbdpay/payments-sdk
```
## 3. Send and receive Bitcoin
Create a new file called `index.js` and add the following code:
```js theme={null}
import ZbdPayments from '@zbdpay/payments-sdk';
const ZBD_API_KEY = 'b7YW3s2JzZKGcXjIf5Dqof8wjKT2RuWr8'; // dummy key
const client = new ZbdPayments({
apikey: ZBD_API_KEY,
});
(async function () {
try {
const data = await client.lightningCharges.create({
amount: '100000',
callbackUrl: 'https://your-app.com/zbd-callback',
description: 'Node.js + ZBD!',
});
console.log(data);
} catch (error) {
console.error(error);
}
})();
```
Run the following command to start your Node.js server:
```bash yarn theme={null}
yarn start
```
```bash npm theme={null}
npm start
```
You may need to add a `start` script to your `package.json` file such as `node index.js`.
You're looking for the `data.invoice.request` property in the JSON response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
```
lnbc1u1pjdlax9pp5t7jhkd7h2wntd4f2v7xp22dknmjxp0q8nm7hfcny4p7a5mr7x3rsdp9f4hkueteypshggrfde6x2unwv46zqumsv4jkgcqzzsxqzjcsp5dsayu6m6632p28rnkeeqsr7d54amrkv6wh46yrv42gdgca8xl8gs9qyyssqgj2zrkax733rzulfkzc5mqsr8fpwrva82stpa7e0frw32722trv37jlq8mvlqfp8y75lr6mz63zd7qnxar8hhsehuy22pvfq6wjxwqqqa60lx3
```
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
## 3. Try it yourself
You can now send and receive instant Bitcoin payments using Express.js + ZBD!
See the full source code.
# Receiving instant Bitcoin payments with Supabase
Source: https://docs.zbdpay.com/payments/sdk/typescript/supabase/receive
Learn how to receive Bitcoin using Supabase Edge Functions.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* [Supabase account](https://supabase.com/) + [Supabase CLI installed](https://supabase.com/docs/guides/cli#installation)
## 1. Create a Supabase Function
To create a Supabase Edge Function you must run the following command locally:
```bash theme={null}
supabase functions new zbd-receive
```
This will create a `/supabase/functions/zbd-receive` folder structure in your project.
## 2. Write the Edge Function
Use the code below as a starting point for your handler function. You will need to replace the `ZBD_API_KEY` with your own ZBD Project's API key.
```typescript theme={null}
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
const ZBD_API_KEY = "b7Ya3s2JZKZcXXX2Dqf8wjKTZZZRuWr8";
const zbdReceive = async (_request: Request): Promise => {
const res = await fetch("https://api.zbdpay.com/v0/charges", {
method: "POST",
headers: {
"Content-Type": "application/json",
"apikey": `${ZBD_API_KEY}`,
},
body: JSON.stringify({
amount: '100000', // 100 satoshis (100,000 msats) -- ~$0.03
description: 'Money at internet speed', // What is this payment request for?
}),
});
const data = await res.json();
return new Response(JSON.stringify(data), {
status: 200,
headers: {
"Content-Type": "application/json",
},
});
};
serve(zbdReceive);
```
## 3. Receive payment locally
To run this Supabase Edge Function locally you can spin up your Supabase instance using the following command. *You may already have this running at this stage.*
```bash theme={null}
supabase functions start
```
Then you can run the following command to start your serverless function:
```bash theme={null}
supabase functions serve zbd-receive --no-verify-jwt
```
Note that we add the `--no-verify-jwt` flag to the command to disable JWT verification. This is because we are not passing a JWT token to the function when we call it. **This is not recommended for production use.**
Supabase CLI will output a HTTP URL endpoint that you can use to test your function by issuing a POST request to that resource.
## 4. Deploying to Supabase Edge
After testing it locally, you can deploy your function to Supabase Edge using the following command. *You will need to enter your Supabase project ID to deploy.*
```bash theme={null}
supabase functions deploy zbd-receive
```
Once you deploy you will receive a URL that you can use to view that function in production on Supabase's Web Dashboard:
Opening your browser (or another HTTP client) to the URL provided by Supabase: `https://xxxxxxxxxxxxx.supabase.co/functions/v1/zbd-receive` should return a JSON response with the payment request details.
You can also test this using curl command:
```bash theme={null}
curl https://xxxxxxxxxxxxx.supabase.co/functions/v1/zbd-receive
```
You're looking for the `data.invoice.request` property in the JSON response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
```
lnbc1u1pjdlax9pp5t7jhkd7h2wntd4f2v7xp22dknmjxp0q8nm7hfcny4p7a5mr7x3rsdp9f4hkueteypshggrfde6x2unwv46zqumsv4jkgcqzzsxqzjcsp5dsayu6m6632p28rnkeeqsr7d54amrkv6wh46yrv42gdgca8xl8gs9qyyssqgj2zrkax733rzulfkzc5mqsr8fpwrva82stpa7e0frw32722trv37jlq8mvlqfp8y75lr6mz63zd7qnxar8hhsehuy22pvfq6wjxwqqqa60lx3
```
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
## 5. Try it yourself
You can now begin receiving instant Bitcoin payments on the edge with Supabase + ZBD!
See the full source code.
# Sending instant Bitcoin payments with Supabase
Source: https://docs.zbdpay.com/payments/sdk/typescript/supabase/send
Learn how to send Bitcoin using Supabase Edge Functions.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* [Supabase account](https://supabase.com/) + [Supabase CLI installed](https://supabase.com/docs/guides/cli#installation)
## 1. Create a Supabase Function
To create a Supabase Edge Function you must run the following command locally:
```bash theme={null}
supabase functions new zbd-send
```
This will create a `/supabase/functions/zbd-send` folder structure in your project.
## 2. Write the Edge Function
Use the code below as a starting point for your handler function. You will need to replace the `ZBD_API_KEY` with your own ZBD Project's API key.
```typescript theme={null}
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
const ZBD_API_KEY = "b7Ya3s2JZKZcXXX2Dqf8wjKTZZZRuWr8";
const zbdSend = async (_request: Request): Promise => {
const res = await fetch("https://api.zbdpay.com/v0/ln-address/send-payment", {
method: "POST",
headers: {
"Content-Type": "application/json",
"apikey": `${ZBD_API_KEY}`,
},
body: JSON.stringify({
lnAddress: 'andre@zbd.gg', // Who is the recipient of the payment?
amount: '100000', // 100 satoshis (100,000 msats) -- ~$0.03
comment: 'Money at internet speed', // What is this payment for?
}),
});
const data = await res.json();
return new Response(JSON.stringify(data), {
status: 200,
headers: {
"Content-Type": "application/json",
},
});
};
serve(zbdSend);
```
## 3. Send payment locally
In order to successfully send payments through the API, you must have an active balance in the ZBD Project you are using. [Learn more about depositing funds into a ZBD Project wallet](/get-started/add-funds).
If you do not have funds in the ZBD Project you are using, you will receive a 4xx error from the API stating insufficient funds.
To run this Supabase Edge Function locally you can spin up your Supabase instance using the following command. *You may already have this running at this stage.*
```bash theme={null}
supabase functions start
```
Then you can run the following command to start your serverless function:
```bash theme={null}
supabase functions serve zbd-send --no-verify-jwt
```
Note that we add the `--no-verify-jwt` flag to the command to disable JWT verification. This is because we are not passing a JWT token to the function when we call it. **This is not recommended for production use.**
Supabase CLI will output a HTTP URL endpoint that you can use to test your function by issuing a POST request to that resource.
## 4. Deploying to Supabase Edge
After testing it locally, you can deploy your function to Supabase Edge using the following command. *You will need to enter your Supabase project ID to deploy.*
```bash theme={null}
supabase functions deploy zbd-send
```
Once you deploy you will receive a URL that you can use to view that function in production on Supabase's Web Dashboard:
Opening your browser (or another HTTP client) to the URL provided by Supabase: `https://xxxxxxxxxxxxx.supabase.co/functions/v1/zbd-send` should return a JSON response with the payment sent message.
You can also test this using curl command:
```bash theme={null}
curl https://xxxxxxxxxxxxx.supabase.co/functions/v1/zbd-send
```
You're looking for the `status` of `completed` to know that the payment settled successfully.
Payments in the Lightning Network are asynchronous so you may see a response stating the payment is `processing`. This is expected -- use the `callbackUrl` property to receive updates about your payments.
## 5. Try it yourself
You can now begin sending instant Bitcoin payments on the edge with Supabase + ZBD!
See the full source code.
# Receiving instant Bitcoin payments on Vercel
Source: https://docs.zbdpay.com/payments/sdk/typescript/vercel/receive
Learn how to receive Bitcoin using Vercel Edge Functions.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* [Vercel account](https://vercel.com/signup) + [Vercel CLI installed](https://vercel.com/docs/cli#installing-vercel-cli)
## 1. Create a Next.js Project
Follow the prompts on the create-next-app CLI to create a new project, and then change into the directory of your project.
```bash theme={null}
yarn create next-app
```
```bash theme={null}
cd
```
## 2. Write an Edge Function
For this guide we will be making use of the [App Router](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) inside of Next.js.
Create a new file in the `app/api/request/route.ts` that creates a Bitcoin Lightning Charge (payment request) with the following code:
```javascript app/api/request/route.ts theme={null}
import { NextResponse } from 'next/server';
export const runtime = 'edge';
export const dynamic = 'force-dynamic';
const ZBD_BASE_URL = 'https://api.zbdpay.com';
const ZBD_API_KEY = 'b7YW3s2JzZKGcXjIf5Dqof8wjKT2RuWr8';
export async function GET() {
const res = await fetch(`${ZBD_BASE_URL}/v0/charges`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': `${ZBD_API_KEY}`,
},
body: JSON.stringify({
amount: '100000', // 100 satoshis (100,000 msats) -- ~$0.03
description: 'Money at internet speed', // What is this payment request for?
}),
});
if (res.ok) {
const data = await res.json();
return NextResponse.json(data);
}
}
```
## 3. Create payment request locally
Run function locally:
```bash theme={null}
npx next dev
```
Opening your browser to the following URL: `https://example.com/api/request` should return a JSON response with a payment request.
You can also test this using curl command:
```bash theme={null}
curl https://example.com/api/request
```
You're looking for the `data.invoice.request` property in the JSON response. It starts with `lnbc1` and is the payment request anyone in the Bitcoin Lightning Network can use to pay you.
```
lnbc1u1pjdlax9pp5t7jhkd7h2wntd4f2v7xp22dknmjxp0q8nm7hfcny4p7a5mr7x3rsdp9f4hkueteypshggrfde6x2unwv46zqumsv4jkgcqzzsxqzjcsp5dsayu6m6632p28rnkeeqsr7d54amrkv6wh46yrv42gdgca8xl8gs9qyyssqgj2zrkax733rzulfkzc5mqsr8fpwrva82stpa7e0frw32722trv37jlq8mvlqfp8y75lr6mz63zd7qnxar8hhsehuy22pvfq6wjxwqqqa60lx3
```
Charges and payment requests are usually shown to users as QR codes that can be scanned by mobile apps (e.g. [ZBD](https://zbd.one/download)). Read [Callbacks](/payments/api/callbacks) to understand how to receive updates about your payment asynchronously.
## 4. Create payment request in production
Deploy your project to Vercel:
```bash theme={null}
vercel
```
Opening your browser to the following URL: `https://project-name.vercel.app/api/request` should now return this in production.
You can also test this using curl command:
```bash theme={null}
curl https://project-name.vercel.app/api/request
```
## 5. Try it yourself
You can now begin receiving instant Bitcoin payments on the edge with Vercel + ZBD!
See the full source code.
# Sending instant Bitcoin payments on Vercel
Source: https://docs.zbdpay.com/payments/sdk/typescript/vercel/send
Learn how to send Bitcoin using Vercel Edge Functions.
## Prerequisites
To complete this guide, you will need the following:
* [ZBD Project with a Live API key](/get-started/api-keys)
* [Vercel account](https://vercel.com/signup) + [Vercel CLI installed](https://vercel.com/docs/cli#installing-vercel-cli)
## 1. Create a Next.js Project
Follow the prompts on the create-next-app CLI to create a new project, and then change into the directory of your project.
```bash theme={null}
yarn create next-app
```
```bash theme={null}
cd
```
## 2. Write an Edge Function
For this guide we will be making use of the [App Router](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) inside of Next.js.
Create a new file in the `app/api/send/route.ts` that makes a payment to a [Lightning Address](/payments/glossary#lightning-address) (e.g. [andre@zbd.gg](mailto:andre@zbd.gg)) with the following code:
```javascript app/api/send/route.ts theme={null}
import { NextResponse } from 'next/server';
export const runtime = 'edge';
export const dynamic = 'force-dynamic';
const ZBD_BASE_URL = 'https://api.zbdpay.com';
const ZBD_API_KEY = 'b7YW3s2JzZKGcXjIf5Dqof8wjKT2RuWr8';
export async function GET() {
const res = await fetch(`${ZBD_BASE_URL}/v0/ln-address/send-payment`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': `${ZBD_API_KEY}`,
},
body: JSON.stringify({
lnAddress: 'andre@zbd.gg', // Who is the recipient of the payment?
amount: '100000', // 100 satoshis (100,000 msats) -- ~$0.03
comment: 'Money at internet speed', // What is this payment for?
}),
});
if (res.ok) {
const data = await res.json();
return NextResponse.json(data);
}
}
```
## 3. Send payment locally
In order to successfully send payments through the API, you must have an active balance in the ZBD Project you are using. [Learn more about depositing funds into a ZBD Project wallet](/get-started/add-funds).
If you do not have funds in the ZBD Project you are using, you will receive a 4xx error from the API.
Run function locally:
```bash theme={null}
npx next dev
```
Opening your browser to the following URL: `https://example.com/api/send` should return a JSON response with the payment sent message.
You can also test this using curl command:
```bash theme={null}
curl https://example.com/api/send
```
You're looking for the `status` of `completed` to know that the payment settled successfully.
Payments in the Lightning Network are asynchronous so you may see a response stating the payment is `processing`. This is expected -- use the `callbackUrl` property to receive updates about your payments.
## 4. Send payment in production
Deploy your project to Vercel:
```bash theme={null}
vercel
```
Opening your browser to the following URL: `https://project-name.vercel.app/api/send` should now return this in production.
You can also test this using curl command:
```bash theme={null}
curl https://project-name.vercel.app/api/send
```
## 5. Try it yourself
You can now begin sending instant Bitcoin payments on the edge with Vercel + ZBD!
See the full source code.