Paystack setup
24 AI agent skills for Paystack API integration — automate payment workflows with TypeScript, Node.js, and Next.js
npx -y skills add rexedge/paystack --skill paystack-setupAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up the Paystack API client, environment variables, and TypeScript helpers for server-side payment integration. Use this skill whenever starting a new Paystack integration, configuring API keys, creating a reusable fetch wrapper for the Paystack REST API, or setting up the foundation for any Paystack feature. Also use when you see errors related to missing PAYSTACK_SECRET_KEY, authentication failures, or need to understand Paystack's base URL, response format, pagination, currencies, or amount subunit conversion.
SKILL.md
6.1 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
Paystack Setup
Set up the foundational Paystack API client and environment configuration for TypeScript/JavaScript server-side applications.
API Fundamentals
| Property | Value |
|---|---|
| Base URL | https://api.paystack.co |
| Auth Header | Authorization: Bearer SECRET_KEY |
| Content Type | application/json |
| Response Format | { status: boolean, message: string, data: object } |
| Amount Unit | Subunit of currency (multiply display amount × 100) |
| Transaction ID | Unsigned 64-bit integer — use string in TypeScript |
Supported Currencies & Subunits
| Currency | Code | Subunit | Multiplier |
|---|---|---|---|
| Nigerian Naira | NGN | kobo | ×100 |
| US Dollar | USD | cent | ×100 |
| Ghanaian Cedi | GHS | pesewa | ×100 |
| South African Rand | ZAR | cent | ×100 |
| Kenyan Shilling | KES | cent | ×100 |
| West African CFA | XOF | — | ×100 |
| Egyptian Pound | EGP | piaster | ×100 |
| Rwandan Franc | RWF | — | ×100 |
Environment Variables
Create a .env file (or .env.local for Next.js):
PAYSTACK_SECRET_KEY=sk_test_xxxxx # Server-side only, NEVER expose to client
NEXT_PUBLIC_PAYSTACK_PUBLIC_KEY=pk_test_xxxxx # Safe for client-side (Popup/InlineJS)
The secret key (sk_*) must NEVER appear in client-side code, browser bundles, or public repositories. The public key (pk_*) is safe for front-end use with Paystack Popup/InlineJS only.
Test keys start with sk_test_ / pk_test_. Live keys start with sk_live_ / pk_live_. Get them from the Paystack Dashboard under Settings → API Keys & Webhooks.
Install Dependencies
# For client-side Popup/InlineJS checkout
npm install @paystack/inline-js
# Or with pnpm / yarn
pnpm add @paystack/inline-js
yarn add @paystack/inline-js
No server-side SDK is needed — use the built-in fetch API with the helper below.
TypeScript API Client Helper
Create a reusable, type-safe Paystack client. Every other Paystack skill depends on this pattern:
// lib/paystack.ts
const PAYSTACK_SECRET_KEY = process.env.PAYSTACK_SECRET_KEY;
if (!PAYSTACK_SECRET_KEY) {
throw new Error("PAYSTACK_SECRET_KEY is not set in environment variables");
}
export interface PaystackResponse<T = unknown> {
status: boolean;
message: string;
data: T;
}
export interface PaystackListResponse<T = unknown> {
status: boolean;
message: string;
data: T[];
meta: {
total: number;
skipped: number;
perPage: number;
page: number;
pageCount: number;
};
}
export class PaystackError extends Error {
constructor(
message: string,
public statusCode: number,
public response?: unknown
) {
super(message);
this.name = "PaystackError";
}
}
export async function paystackRequest<T>(
endpoint: string,
options: RequestInit = {}
): Promise<PaystackResponse<T>> {
const url = `https://api.paystack.co${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
Authorization: `Bearer ${PAYSTACK_SECRET_KEY}`,
"Content-Type": "application/json",
...options.headers,
},
});
const data = await response.json();
if (!response.ok) {
throw new PaystackError(
data.message || `Paystack API error: ${response.status}`,
response.status,
data
);
}
return data as PaystackResponse<T>;
}
Pagination
All list endpoints accept perPage (default: 50, max: 100) and page (default: 1) as query parameters. The response includes a meta object:
{
"meta": {
"total": 243,
"skipped": 0,
"perPage": 50,
"page": 1,
"pageCount": 5
}
}
Build paginated queries like so:
const params = new URLSearchParams({
perPage: "20",
page: "2",
from: "2024-01-01T00:00:00.000Z",
to: "2024-12-31T23:59:59.000Z",
});
const result = await paystackRequest<Transaction[]>(`/transaction?${params}`);
Amount Conversion
Always convert display amounts to subunits before sending to Paystack, and convert back when displaying:
// Display → Paystack (multiply by 100)
const amountInKobo = Math.round(amountInNaira * 100);
// Paystack → Display (divide by 100)
const amountInNaira = amountInKobo / 100;
Use Math.round() to avoid floating-point issues like 19.99 * 100 = 1998.9999999999998.
HTTP Methods
| Method | Usage |
|---|---|
| POST | Create resources, initiate actions |
| GET | Fetch, list, verify resources |
| PUT | Update resources |
| DELETE | Deactivate or remove resources |
Error Handling
Wrap Paystack calls in try/catch and handle the PaystackError class:
import { paystackRequest, PaystackError } from "@/lib/paystack";
try {
const result = await paystackRequest<Transaction>("/transaction/verify/ref_123");
} catch (error) {
if (error instanceof PaystackError) {
console.error(`Paystack error ${error.statusCode}: ${error.message}`);
// Handle specific status codes
if (error.statusCode === 400) { /* bad request / validation error */ }
if (error.statusCode === 401) { /* invalid secret key */ }
if (error.statusCode === 404) { /* resource not found */ }
}
throw error;
}
Security Checklist
- Store
PAYSTACK_SECRET_KEYin environment variables only, never in code - Add
.envand.env.localto.gitignore - All Paystack API calls must run server-side (API routes, server actions, backend)
- Use HTTPS for all callback and webhook URLs
- Validate amounts server-side before initializing transactions
- Always verify transaction status server-side after payment, never trust client-side callbacks alone
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most project setup skills give in ~1.4k tokens
Counted across 999 of the 1,637 authors here whose files we hold, read 2026-08-07
- Ask one question at a timein 29 of 999, across 28 files
- Detect the package manager from lockfilesin 28 of 999, across 9 files
- Present findings to the userin 26 of 999, across 5 files
- Explore current repo statein 24 of 999, across 3 files
- Update the agent skills block in place if it existsin 24 of 999, across 3 files
- Install husky lint-staged and prettierin 23 of 999, across 4 files
- Create the lintstagedrc filein 22 of 999, across 3 files
- Commit all changed filesin 22 of 999, across 3 files
- Run lint-staged to verify it worksin 22 of 999, across 3 files
- Create the husky pre-commit filein 21 of 999, across 2 files
- Create a prettierrc file if missingin 21 of 999, across 2 files
- Initialize huskyin 21 of 999, across 2 files
Said here and by no other author read
- throw an error if the secret key is missing
- use the built-in fetch api for requests
- create a reusable typescript client helper
- convert display amounts to subunits before sending
- use Math.round for amount conversion
- use string for transaction ids in typescript
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.