Authentication
Learn about supported modes and how to connect to Flutterwave.
There are two modes of operation on your Flutterwave account:
-
Test Mode: This mode does not require the use of real money and designed exclusively for testing purposes. You can simulate data to replicate real-world scenarios using our test cards and bank accounts without any financial impact. It lets you test and validate your integration before going live.
-
Live Mode: This mode is the production environment where real money, real transactions, and real operations take place. It handles actual customer data and financial transactions. Only switch to this after you've tested your integrations thoroughly on test mode.
You can easily switch between Live and Test modes, by using the toggle button in the menu sidebar on your settings page. When you switch between modes, we'll also switch the API keys shown. Test keys will always have _TEST as prefix (for example, FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXX-X)

Get your API Keys
When you create a Flutterwave account, you receive three types of API keys:
-
Secret key: Grants full access to your account. Use it only in secure server-side environments. Never expose it publicly.
-
Public key: Safe for client-side use (e.g., Flutterwave Inline).
-
Encryption key: Required for encrypting payloads when using the direct card charge endpoints. See the encryption guide for more details.
Your API keys are essential for authenticating requests to our servers. To get your API keys:
- Log into your Flutterwave account
- Go to your dashboard.
- Navigate to Settings
- Select the API Keys menu under the
DEVELOPERSsection and copy your keys.

In the live environment, API key management is slightly different. To enhance the security of your live transactions, we mask the keys to prevent unauthorized access.
Don't Take Any ChancesIf you think your keys may have been compromised (for instance, you accidentally committed them to Git), you should immediately generate new ones using the Generate new keys button on the Settings > API page on your dashboard.
This will invalidate all existing keys and give you a new set, and you can then update your app to use the new ones.
Authorizing API calls
All API calls on Flutterwave are protected by default. Any API requests made without proper authorization will result in the status code 401: Unauthorized.
Safeguard your API KeyYour secret key can perform any actions on your Flutterwave account without restriction. It should be kept confidential and only stored on your servers, preferably as an environment variable.
It should not be included in your Git repository or front-end JavaScript code.
To authorize API calls from your server, pass your secret key as a bearer token. This means passing an Authorization header with a value of Bearer: YOUR_SECRET_KEY.
For example, an API call in Node.js would look like the following:
const response = await fetch("https://api.flutterwave.com/v3/payments", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FLW_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tx_ref: 'titanic-48981487343MDI0NzMx',
amount: 54600,
currency: 'NGN',
payment_options: 'card, mobilemoneyghana, ussd',
redirect_url: 'https://glaciers.titanic.com/handle-flutterwave-payment',
meta: {
consumer_id: 23,
consumer_mac: '92a3-912ba-1192a',
},
customer: {
email: '[email protected]',
phone_number: '08102909304',
name: 'Rose DeWitt Bukater',
},
customizations: {
title: 'The Titanic Store',
description: 'Payment for an awesome cruise',
logo: 'https://www.logolynx.com/images/logolynx/22/2239ca38f5505fbfce7e55bbc0604386.jpeg',
},
}),
});
const body = await response.json();If you're using one of our backend SDKs, you don't need to pass the header manually; instead, you'll provide your keys when initializing the library.
// Install with: npm i flutterwave-node-v3
const Flutterwave = require("flutterwave-node-v3");
const flw = new Flutterwave(
process.env.FLW_PUBLIC_KEY,
process.env.FLW_SECRET_KEY
);
// Subsequent calls will automatically have the header added
flw.Misc.bvn({ bvn: "22222223883" }).then((response) => console.log(response));# Install with: gem install flutterwave_sdk
require "flutterwave_sdk"
flw = Flutterwave.new(ENV["FLW_PUBLIC_KEY"], ENV["FLW_SECRET_KEY"], ENV["FLW_ENCRYPTION_KEY"])
# Subsequent calls will automatically have the header added
misc = Misc.new(flw)
response = misc.resolve_bvn "22222223883"<?php
declare(strict_types=1);
// Install with: composer require flutterwavedev/flutterwave-v3
require __DIR__ . '/vendor/autoload.php';
use Flutterwave\Flutterwave;
use Flutterwave\Helper\Config;
use Flutterwave\Service\Misc;
// By default the package reads the Flutterwave environment variables.
// You can also pass them explicitly:
$config = Config::setUp(
(string) getenv('FLW_SECRET_KEY'),
(string) getenv('FLW_PUBLIC_KEY'),
(string) getenv('FLW_ENCRYPTION_KEY'),
'staging' // or 'production'
);
Flutterwave::bootstrap($config);
$service = new Misc();
$response = $service->resolveBvn('22222223883');
print_r($response);Troubleshooting authentication errors
A request that fails authentication returns HTTP 401 Unauthorized
{
"status": "error",
"message": "Authorization required",
"data": null
}Check these, in order:
| Cause | Fix |
|---|---|
No Authorization header | Add Authorization: Bearer <secret key> to every request. |
Wrong format, e.g. Bearer: KEY, bearer KEY, or no Bearer | Use exactly Bearer, one space, then the key. |
| Public or encryption key sent instead of secret key | Use the key starting with FLWSECK. |
| Key copied with whitespace, quotes, or a newline | Trim the value, and check how your env file is loaded. |
| Environment variable is empty at runtime | Log whether FLW_SECRET_KEY is set (never log the value itself). |
| Keys were regenerated | Copy the new keys from the dashboard and redeploy. |
| Test key used for a live-only resource, or vice versa | Make sure the key's mode matches the data you're accessing. |
Updated 5 days ago
