Set up your account, test mode and an API key
An account, a wallet to be paid in, a key for your server, and a client that proves the key works.
Create your account
Sign up. Your account comes with an organization: where your products, payments, keys and webhook endpoints live. Nothing to deposit: payments go wallet to wallet (how the money moves).
Switch to test mode
Pick Test in the dashboard's mode switch. Test mode has its own networks, faucet tokens, keys, wallets, products and endpoints, and a test checkout is at most $5, fees included (test mode). Nothing carries over to live: the guide's last step redoes what matters.
Add a wallet
In Dashboard/Settings/Wallets, add a wallet you own and choose the currencies it accepts. Payments land there.
Watch out
Add it before your first checkout. A space (your organization's data in one mode:
spaces) whose wallets accept nothing can't open one: the API
answers 409 merchant_not_ready.
Create an API key
In Dashboard/Settings/API keys, choose Create an API
key. It's shown once: store it as QBITFLOW_API_KEY, which every example reads. A test key
(sk_test_…) only ever sees test data.
It acts as an admin of your organization: keep it on your server, in an environment variable, never in a browser, an app or a repository. Leaked? Revoke it on the same page: it stops working at once.
Install the SDK
terminal
# Nothing to install: cURL comes with macOS, Linux and Windows.curl --versionnpm install qbitflowpip install "qbitflow>=3,<4"go get github.com/QBitFlow/qbitflow-go-sdk/v3composer require qbitflow/qbitflow-php:^3.0Create a client
One client per key, shared by your whole program. Its first call asks what the key is: a good start-up check.
client-init.sh
# Every request sends your API key. The start-up check: what is this key, and which mode is it in?curl https://api.qbitflow.app/v2/me \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: { "credential": "apiKey", "role": "admin", "space": { "test": true, … }, … }// One client per API key, shared by the whole program. A blank key, one not starting with// sk_, or one with a space or a control character, throws a ValidationError (nothing is sent).const client = new QBitFlow( process. env. QBITFLOW_API_KEY ?? ''); // The recommended start-up check: what is this key, and which mode is it in? An// AuthenticationError for an unknown or revoked key.const me = await client.me();console.log(`${me.role} key, test mode: ${me.space?.test}`);# One client per API key, shared by the whole program. ValidationError: not an sk_… key.client = qbitflow. QBitFlow( os. environ["QBITFLOW_API_KEY"]) # The recommended start-up check: what is this key, and which mode is it in?me = client.me() # AuthenticationError for an unknown or revoked keyif me.space is not None: print( f"{me. space. organization_name}, role {me.role}, test mode {me.space.test}")// One client per API key, shared by the whole program: it is safe for concurrent use.client, err := qbitflow. NewClient( os. Getenv( "QBITFLOW_API_KEY"))if err != nil { log.Fatal(err) // a *qbitflow.ValidationError: no key, or not an sk_… key} // The recommended start-up check: what is this key, and which mode is it in?me, err := client.Me(ctx)if err != nil { log.Fatal(err) // a *qbitflow.AuthenticationError for an unknown or revoked key}if me.Space != nil { fmt.Printf("%s, role %s, test mode %v\n", me.Space.OrganizationName, me.Role, me.Space.Test)}// One client per API key, shared by the whole application.$client = new \QBitFlow\QBitFlow(apiKey: (string) getenv('QBITFLOW_API_KEY')); // The recommended start-up check: which space and mode is this key in?$me = $client->me(); // an AuthenticationException for an unknown or revoked keyprintf("%s, role %s, %s mode\n", $me->space?->organizationName ?? '?', $me->role ?? '?', $me->space?->test ? 'test' : 'live');Or read everything from the environment
The SDKs can build the client from QBITFLOW_API_KEY alone, plus the optional settings each one
names below. Explicit options win.
// QBITFLOW_API_KEY (required), and QBITFLOW_BASE_URL and QBITFLOW_ON_BEHALF_OF when set.const client = QBitFlow.fromEnv(); // Explicit options override the environment and add the others.const patient = QBitFlow.fromEnv({ timeout: 60_000, maxRetries: 5 });# QBITFLOW_API_KEY (required), QBITFLOW_BASE_URL and QBITFLOW_ON_BEHALF_OF when set.client = qbitflow. QBitFlow. from_env( timeout=10) # explicit options override the environment// QBITFLOW_API_KEY (required), QBITFLOW_BASE_URL and QBITFLOW_ON_BEHALF_OF (when set);// the options given here override them.client, err := qbitflow. NewClientFromEnv( qbitflow. WithTimeout( 10 * time.Second))if err != nil { log.Fatal(err) // a *qbitflow.ValidationError naming QBITFLOW_API_KEY when it is not set}// QBITFLOW_API_KEY (required), and QBITFLOW_BASE_URL and QBITFLOW_ON_BEHALF_OF when set, read from// getenv(), $_ENV or $_SERVER (a .env loaded by phpdotenv works).$client = \QBitFlow\QBitFlow::fromEnv(); // Named arguments override the environment and set the other options.$client = \QBitFlow\QBitFlow::fromEnv( timeout: 10.0, maxRetries: 5);Check it
The client's first call prints the key's role (admin for an organization key) and test mode
(space.test is true). A 401 (AuthenticationError) means a mistyped, revoked or expired key.