API Keys
In a nutshell
Paystack has three types of API keys. Public keys initiate payments from your frontend, secret keys call the full API from your backend, and restricted keys call only the endpoints you grant them.
Key types
Every integration has a public key and a secret key for test mode and for live mode. Test keys start with pk_test_ or sk_test_, and live keys start with pk_live_ or sk_live_. Restricted keys are optional, and you create them on the dashboard when you need them.
| Type | Prefix | Where you use it | What it can do |
|---|---|---|---|
| Public key | pk_ | Frontend | Initiate transactions with Paystack Inline and the Mobile SDKs |
| Secret key | sk_ | Backend | Call every endpoint in the Paystack API and verify webhook signatures |
| Restricted key | rk_ | Backend | Call only the endpoints covered by its scopes |
You use your public key in code that runs on your customer's device, so it's the only key that's safe to expose. Your secret key gives full access to the API. You also need it to verify webhook signatures, since Paystack signs webhook events with your secret key and not a restricted key. If your integration computes checkout hashes for Paystack Inline, or calls an endpoint that doesn't have a scope yet, you need your secret key for that too.
A restricted key is useful when a service only needs part of the API. For example, a reporting job that reads transactions only needs transactions:read. It's also the safer way to give a third party access to your account: you can scope the key to what their tool does, and revoke it when you stop working with them. If a restricted key leaks, it can only call the endpoints its scopes cover.
Keep secret and restricted keys on your server
Don't put a secret key or a restricted key in frontend code, a mobile app, or a code repository.
To learn how to send your key with a request, how test and live modes work, and how to set up IP allowlisting, check out the Authentication page.
Rotate your secret keys
You should rotate your secret keys on a regular schedule, and right away if you suspect one has leaked. You generate new keys on the dashboard, then choose how long your current keys keep working while you move your systems over to the new ones.
Before you begin!
Generating new keys replaces your live and test secret keys together. Before you start, find every place that uses either key: your production and staging servers, background workers and scheduled jobs, CI/CD secrets and your secrets manager, and your webhook verification code. Each of these needs the new key before your current key expires.
Generate new secret keys
- Open the Developers overview page on your dashboard.
- Click Generate new secret keys.
- Under How soon should your old keys expire?, choose an expiry time.
- Confirm, then copy your new live and test secret keys.
When your current keys expire, Paystack sends you an email to let you know. The email doesn't contain your key values.
Choose an expiry time
Your new keys work from the moment you confirm, and your current keys keep working until the expiry time you choose. The table below shows each option and when to use it:
| Option | When to use it |
|---|---|
| Immediately | You suspect a secret key has been exposed |
| 30 minutes | You can update every system that uses the key within 30 minutes |
| 2 hours | You're doing a planned rotation with one deployment |
| 6 hours | You're doing a planned rotation across several services or teams |
| 12 hours | Some systems need a manual change or an approval before you can deploy |
| Never | Your current keys keep working with no expiry. Don't choose this if a key has leaked. |
If a key has been exposed
Choose Immediately. Every request made with the exposed key fails from that moment, including requests from your own servers, so have the new key ready to deploy.
Update your servers
Replace the secret key in each environment, then deploy or restart every service that reads it. We recommend reading the key from an environment variable or your secrets manager rather than from source code, so the next rotation is a configuration change and not a code change.
To confirm a server is using the new key, call the Check BalanceAPI endpoint from that server. A 200 response with "status": true means the key works:
1curl https://api.paystack.co/balance \2 -H "Authorization: Bearer $PAYSTACK_SECRET_KEY"
Repeat the check with your test secret key in your test environments. Once your current key expires, any server still using it gets a 401 response with the message Invalid key. If you see this, make sure live systems have the new sk_live_ key and test systems have the new sk_test_ key, then redeploy.
Update your webhook signature validation
Paystack signs webhook events with your secret key, so your signature validation code needs the new key after you rotate. Until your current key expires, check each event's signature against both keys and accept it if either one matches. Once the current key expires, remove it from your configuration.
Restricted keys
Invite-only pilot
Restricted keys are available to integrations enrolled in the pilot. Integrations that connect to Paystack through a plugin aren't included in the pilot.
A restricted key authenticates requests the same way a secret key does, with Authorization: Bearer rk_..., but it can only call the endpoints its scopes allow. Every restricted key has a label that describes what it's for and at least one scope, such as transactions:read. You can also give it an expiry date, after which the key stops working.
You can change a key's label and scopes after you create it, and an integration can have up to 50 active restricted keys. Because restricted keys grant access to the API, Paystack asks for your dashboard password whenever you create, update, rotate, or revoke one.
Create a restricted key
Before you create a key, decide which scopes the service needs and grant only those. Switch your dashboard to test or live mode first: a key created in test mode starts with rk_test_ and only works with test data.
- Open the restricted keys section of the Developers overview page on your dashboard.
- Enter a label that describes what the key is for, such as
Reporting service. - Select the scopes the key needs.
- Optionally, set an expiry date.
- Enter your dashboard password to confirm.
- Copy the key and store it in your secrets manager. After you leave the page, the dashboard only shows the key's last 4 characters.
Make a request with a restricted key
You send a restricted key in the Authorization header, just as you would a secret key. This request calls the List TransactionsAPI endpoint with a key that has the transactions:read scope:
1curl "https://api.paystack.co/transaction?perPage=1" \2 -H "Authorization: Bearer $PAYSTACK_RESTRICTED_KEY"
If you've set up the key and scope correctly, you get a 200 response:
1{2 "status": true,3 "message": "Transactions retrieved",4 "data": [5 {6 "id": 4099260516,7 "domain": "test",8 "status": "success",9 "reference": "re4lyvq3s3",10 "amount": 40333,11 "currency": "NGN",12 "paid_at": "2024-08-22T09:15:02.000Z"13 }14 ],15 "meta": {16 "next": "dW5kZWZpbmVkOjQwMTM3MDk2MzU=",17 "previous": null,18 "perPage": 119 }20}
If you get an error instead, see Restricted key errors.
Rotate or revoke a restricted key
Rotating a restricted key replaces that one key, and the new key keeps the same label and scopes. The current key stops working immediately, or after a grace window of up to 24 hours, and you can't rotate it again while it's in its grace window. Only the service that uses the key needs updating.
Revoke a restricted key when nothing should use it again, such as when you stop working with the third party that held it. The key stops working on the next request.
Scopes
A scope grants a restricted key access to one resource at one level, and it's written as resource:level, for example transactions:read. The read level grants the endpoints that retrieve a resource, and write grants the endpoints that create, update, or delete it.
The table below lists the levels each resource supports:
| Resource | Levels |
|---|---|
apple_pay | write |
balance | read |
bank_accounts | read, write |
banks | read, write |
bulk_charges | read, write |
connect | write |
customer_insights | read |
customers | read, write |
direct_debit | read, write |
disputes_refunds | read, write |
metrics | read, write |
payment_pages | read, write |
payment_requests | read, write |
payouts | write |
plans | read, write |
preauthorizations | read, write |
products | read, write |
settlements | read, write |
subaccounts | read, write |
terminals | read, write |
transactions | read, write |
transfers | read, write |
verification | write |
virtual_accounts | read, write |
webhooks | read, write |
What restricted keys can't do
Restricted keys can't manage API keys or change your integration settings, and some endpoints don't have a scope yet. Use the dashboard or your secret key for those.
Restricted key errors
Paystack checks the key first, then the key's scopes, then the request itself. This means a request with a missing scope gets a 403 response even if its body is also invalid. The table below shows each error a restricted key can get:
| Status | Meaning |
|---|---|
401 | The key is unknown, malformed, revoked, expired, or you replaced it when you rotated it. The message is Invalid key, the same as for an invalid secret key. |
403 | The key is valid but doesn't have the scope the endpoint requires. Add the scope to the key on the dashboard, or use a key that has it. |
400 | The key has the required scope, but the request is invalid. This is the same validation error a secret key gets. |