# Directory Structure
```
├── .github
│   └── workflows
│       └── publish.yml
├── .gitignore
├── .idx
│   └── dev.nix
├── .vscode
│   ├── extensions.json
│   └── settings.json
├── bin
│   └── generate-openapi-typescript
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── server.json
├── src
│   ├── client
│   │   ├── client.ts
│   │   ├── http
│   │   │   └── index.ts
│   │   ├── index.ts
│   │   ├── lib
│   │   │   ├── checkout.ts
│   │   │   ├── plan.ts
│   │   │   └── transactions.ts
│   │   ├── middleware
│   │   │   └── authMiddlewareV3.ts
│   │   ├── schema.ts
│   │   ├── specs
│   │   │   └── v3
│   │   │       ├── checkout.yaml
│   │   │       ├── plan.yaml
│   │   │       └── transactions.yaml
│   │   └── types
│   │       ├── v3
│   │       │   ├── checkout.d.ts
│   │       │   ├── plans.d.ts
│   │       │   └── transactions.d.ts
│   │       └── v3.d.ts
│   ├── config
│   │   └── index.ts
│   ├── index.ts
│   ├── prompts
│   │   ├── index.ts
│   │   └── transactions.ts
│   ├── server.ts
│   ├── tools
│   │   ├── checkout.ts
│   │   ├── get_transaction_timeline.ts
│   │   ├── index.ts
│   │   ├── plan.ts
│   │   ├── required.ts
│   │   ├── retry_transaction.ts
│   │   └── transaction.ts
│   └── types
│       ├── checkout
│       │   ├── index.ts
│       │   └── schema.ts
│       ├── index.ts
│       ├── plan
│       │   └── schema.ts
│       └── transaction
│           └── schema.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | /node_modules
2 | /build
3 | src/example.ts
4 | .mcpre*
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
  1 | # mcp-flutterwave
  2 | An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that enables AI assistants to interact with Flutterwave, providing tools for confirming transactions, send failed hooks, and more.
  3 | 
  4 | ## Warning!!!
  5 | This MCP is in active development.
  6 | 
  7 | ## Features
  8 | 
  9 | - Confirm Transactions (Already included)
 10 | - Retry Failed Transactions (Automatically retry transactions with recoverable errors) [✓]
 11 | - Retrieve Transaction History (Fetch and analyze past transactions) [✓]
 12 | - Send Failed Hooks (Already included)
 13 | - Generate Payment Links [✓]
 14 | - Automated Customer Support (AI chatbot integrated with Flutterwave for transaction inquiries) [✓]
 15 | 
 16 | ## Available Tools
 17 | 
 18 | - `get-transactions`: Get the final status of a transaction with a transaction ID
 19 | - `resent-failed-webhook`: Resend failed webhook for a transaction
 20 | - `create-checkout`: Create a payment link for customers
 21 | - `disable-checkout`: Disable a checkout transaction link
 22 | - `retry-transaction`: Analyze and provide guidance for retrying a failed transaction
 23 | - `get-transaction-timeline`: Get the timeline/history of events for a transaction
 24 | 
 25 | ## Installation
 26 | 
 27 | ### Via npm (Recommended)
 28 | ```bash
 29 | npm install -g mcp-flutterwave
 30 | ```
 31 | 
 32 | ### Via GitHub
 33 | ```bash
 34 | git clone https://github.com/bajoski34/mcp-flutterwave.git
 35 | cd mcp-flutterwave
 36 | npm install
 37 | npm run build
 38 | ```
 39 | 
 40 | ## Usage with Claude Desktop
 41 | Add the following to your `claude_desktop_config.json`. See [here](https://modelcontextprotocol.io/quickstart/user) for more details.
 42 | 
 43 | ### Using npm installation
 44 | ```json
 45 | {
 46 |   "mcpServers": {
 47 |     "flutterwave": {
 48 |       "command": "mcp-flutterwave",
 49 |       "args": [
 50 |         "--tools=create_checkout,disable_checkout,read_transaction,resend_transaction_webhook"
 51 |       ],
 52 |       "env": {
 53 |         "FLW_SECRET_KEY": "YOUR_SECRET_KEY"
 54 |       }
 55 |     }
 56 |   }
 57 | }
 58 | ```
 59 | 
 60 | ### Using local build
 61 | ```json
 62 | {
 63 |   "mcpServers": {
 64 |     "flutterwave": {
 65 |       "command": "node",
 66 |       "args": [
 67 |         "/path/to/mcp-flutterwave/build/index.js",
 68 |         "--tools=create_checkout,disable_checkout,read_transaction,resend_transaction_webhook"
 69 |       ],
 70 |       "env": {
 71 |         "FLW_SECRET_KEY": "YOUR_SECRET_KEY"
 72 |       }
 73 |     }
 74 |   }
 75 | }
 76 | ```
 77 | 
 78 | ## Setup Steps
 79 | 
 80 | 1. **Install the package**
 81 |    ```bash
 82 |    npm install -g mcp-flutterwave
 83 |    ```
 84 | 
 85 | 2. **Get your Flutterwave secret key**
 86 |    - Log into your Flutterwave dashboard
 87 |    - Go to Settings > API Keys
 88 |    - Copy your Secret Key
 89 | 
 90 | 3. **Configure Claude Desktop**
 91 |    - Add the configuration to your `claude_desktop_config.json`
 92 |    - Replace `YOUR_SECRET_KEY` with your actual Flutterwave secret key
 93 | 
 94 | 4. **Start using with Claude**
 95 |    - Open Claude Desktop
 96 |    - Ask questions related to Flutterwave transactions, payments, etc.
 97 | 
 98 | ## Contributing
 99 | 
100 | We welcome contributions! Please read our [Contributing Guide](./CONTRIBUTING.md) for details on how to get started, development guidelines, and how to submit changes.
101 | 
102 | 
```
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
```markdown
  1 | # Contributing to mcp-flutterwave
  2 | 
  3 | Thank you for your interest in contributing to mcp-flutterwave! This document provides guidelines and information for contributors.
  4 | 
  5 | ## Getting Started
  6 | 
  7 | ### Prerequisites
  8 | 
  9 | - Node.js (v18 or higher)
 10 | - npm or yarn
 11 | - A Flutterwave account with API access
 12 | - Basic knowledge of TypeScript and the Model Context Protocol (MCP)
 13 | 
 14 | ### Development Setup
 15 | 
 16 | 1. **Fork and clone the repository**
 17 |    ```bash
 18 |    git clone https://github.com/your-username/mcp-flutterwave.git
 19 |    cd mcp-flutterwave
 20 |    ```
 21 | 
 22 | 2. **Install dependencies**
 23 |    ```bash
 24 |    npm install
 25 |    ```
 26 | 
 27 | 3. **Set up environment variables**
 28 |    ```bash
 29 |    cp .env.example .env
 30 |    # Add your Flutterwave secret key
 31 |    echo "FLW_SECRET_KEY=your_secret_key_here" >> .env
 32 |    ```
 33 | 
 34 | 4. **Build the project**
 35 |    ```bash
 36 |    npm run build
 37 |    ```
 38 | 
 39 | 5. **Test the MCP server**
 40 |    ```bash
 41 |    node build/index.js --tools=all
 42 |    ```
 43 | 
 44 | ## Development Guidelines
 45 | 
 46 | ### Code Style
 47 | 
 48 | - Use TypeScript for all new code
 49 | - Follow the existing code style and formatting
 50 | - Use meaningful variable and function names
 51 | - Add JSDoc comments for public APIs
 52 | - Ensure proper error handling
 53 | 
 54 | ### Project Structure
 55 | 
 56 | ```
 57 | src/
 58 | ├── client/           # Flutterwave API client
 59 | │   ├── http/        # HTTP client configuration
 60 | │   ├── lib/         # API endpoint implementations
 61 | │   ├── specs/       # OpenAPI specifications
 62 | │   └── types/       # Generated TypeScript types
 63 | ├── config/          # Configuration files
 64 | ├── tools/           # MCP tool implementations
 65 | ├── types/           # Type definitions and schemas
 66 | └── server.ts        # MCP server setup
 67 | ```
 68 | 
 69 | ### Adding New Tools
 70 | 
 71 | 1. **Create the tool implementation** in `src/tools/`
 72 |    ```typescript
 73 |    // src/tools/your-tool.ts
 74 |    import { server } from "../server.js";
 75 |    import { z } from "zod";
 76 | 
 77 |    export async function yourToolFunction(params: YourParams) {
 78 |      // Implementation
 79 |      return {
 80 |        content: [{ type: "text" as const, text: "Result" }]
 81 |      };
 82 |    }
 83 | 
 84 |    export function registerYourTool() {
 85 |      server.tool(
 86 |        "your.tool.name",
 87 |        "Description of your tool",
 88 |        YourParamsSchema.shape,
 89 |        async (args) => {
 90 |          return await yourToolFunction(args);
 91 |        }
 92 |      );
 93 |    }
 94 |    ```
 95 | 
 96 | 2. **Add the schema** in `src/types/your-tool/schema.ts`
 97 |    ```typescript
 98 |    import { z } from "zod";
 99 | 
100 |    export const YourParamsSchema = z.object({
101 |      param1: z.string().min(1, "Required parameter"),
102 |      param2: z.number().optional()
103 |    });
104 |    ```
105 | 
106 | 3. **Register the tool** in `src/registered-tools.ts`
107 | 
108 | 4. **Update documentation** and tool lists in relevant files
109 | 
110 | ### API Client Development
111 | 
112 | When adding new Flutterwave API endpoints:
113 | 
114 | 1. **Add OpenAPI spec** in `src/client/specs/v3/`
115 | 2. **Generate types** using `npm run build:types`
116 | 3. **Implement client class** in `src/client/lib/`
117 | 4. **Export from main client** in `src/client/index.ts`
118 | 
119 | ### Testing
120 | 
121 | - Write unit tests for new functionality
122 | - Test with actual Flutterwave API when possible
123 | - Ensure error handling works correctly
124 | - Test MCP tool integration with Claude Desktop
125 | 
126 | ### Commit Guidelines
127 | 
128 | - Use conventional commit messages:
129 |   - `feat:` for new features
130 |   - `fix:` for bug fixes
131 |   - `docs:` for documentation changes
132 |   - `refactor:` for code refactoring
133 |   - `test:` for adding tests
134 |   - `chore:` for maintenance tasks
135 | 
136 | Example:
137 | ```
138 | feat: add subscription management tools
139 | fix: handle null responses in checkout creation
140 | docs: update README with new tool examples
141 | ```
142 | 
143 | ## Supported Tools
144 | 
145 | Current tools that can be extended or improved:
146 | 
147 | - **Transactions**: Get transaction details, resend webhooks
148 | - **Checkout**: Create payment links, disable links
149 | - **Plans**: Create and retrieve subscription plans
150 | - **Refunds**: Process transaction refunds
151 | - **Subscriptions**: Manage customer subscriptions
152 | 
153 | ## Common Issues and Solutions
154 | 
155 | ### TypeScript Errors
156 | 
157 | - Ensure all types are properly imported
158 | - Use `as const` for literal types in MCP responses
159 | - Check that Zod schemas match the expected API parameters
160 | 
161 | ### MCP Integration Issues
162 | 
163 | - Verify tool schemas use `.shape` property for registration
164 | - Ensure return objects match MCP content format
165 | - Check that all async functions properly handle errors
166 | 
167 | ### API Client Issues
168 | 
169 | - Verify OpenAPI specifications are accurate
170 | - Regenerate types after spec changes: `npm run build:types`
171 | - Check HTTP client configuration in `src/client/http/`
172 | 
173 | ## Submitting Changes
174 | 
175 | 1. **Create a feature branch**
176 |    ```bash
177 |    git checkout -b feature/your-feature-name
178 |    ```
179 | 
180 | 2. **Make your changes** following the guidelines above
181 | 
182 | 3. **Test your changes**
183 |    ```bash
184 |    npm run build
185 |    npm test # if tests are available
186 |    ```
187 | 
188 | 4. **Commit your changes**
189 |    ```bash
190 |    git add .
191 |    git commit -m "feat: describe your changes"
192 |    ```
193 | 
194 | 5. **Push and create a pull request**
195 |    ```bash
196 |    git push origin feature/your-feature-name
197 |    ```
198 | 
199 | 6. **Fill out the PR template** with:
200 |    - Description of changes
201 |    - Testing performed
202 |    - Any breaking changes
203 |    - Screenshots if applicable
204 | 
205 | ## Code Review Process
206 | 
207 | - All contributions require review
208 | - Address feedback promptly
209 | - Ensure CI checks pass
210 | - Maintain backward compatibility when possible
211 | 
212 | ## Getting Help
213 | 
214 | - Open an issue for bugs or feature requests
215 | - Join discussions in existing issues
216 | - Check the [MCP documentation](https://modelcontextprotocol.io) for protocol details
217 | - Review [Flutterwave API docs](https://developer.flutterwave.com) for API details
218 | 
219 | ## License
220 | 
221 | By contributing, you agree that your contributions will be licensed under the same license as the project.
222 | 
```
--------------------------------------------------------------------------------
/src/client/schema.ts:
--------------------------------------------------------------------------------
```typescript
1 | 
```
--------------------------------------------------------------------------------
/src/types/checkout/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | export * from "./schema.js"; 
```
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
```json
1 | {
2 |     "recommendations": [
3 |         "github.vscode-github-actions"
4 |     ]
5 | }
```
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
```json
1 | {
2 |     "IDX.aI.enableInlineCompletion": true,
3 |     "IDX.aI.enableCodebaseIndexing": true
4 | }
```
--------------------------------------------------------------------------------
/src/prompts/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { registerTransactionsPrompts } from './transactions.js';
2 | 
3 | export function registerPrompts() {
4 |   registerTransactionsPrompts();
5 | }
```
--------------------------------------------------------------------------------
/src/types/transaction/schema.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { z } from 'zod';
2 | 
3 | export const TransactionSchema = {
4 |     tx_id: z.string().min(1, 'Transaction ID is required').describe('Transaction ID'),
5 | }
```
--------------------------------------------------------------------------------
/src/client/middleware/authMiddlewareV3.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { Middleware } from "openapi-fetch";
 2 | 
 3 | export const authMiddlewareV3: Middleware = {
 4 |     async onRequest({ request }) {
 5 |       request.headers.set("Authorization", "Bearer " + process.env.FLW_SECRET_KEY);
 6 |       return request;
 7 |     }
 8 | };
 9 | 
10 | export default authMiddlewareV3;
```
--------------------------------------------------------------------------------
/src/client/index.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import transactions from "./lib/transactions.js"
 2 | import checkout from "./lib/checkout.js";
 3 | import plans from "./lib/plan.js";
 4 | 
 5 | 
 6 | export default class Flutterwave {
 7 |     static transactions() {
 8 |         return transactions;
 9 |     }
10 | 
11 |     static checkout() {
12 |         return checkout;
13 |     }
14 | 
15 | 
16 |     static plans() {
17 |         return new plans;
18 |     }
19 | }
```
--------------------------------------------------------------------------------
/src/tools/index.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import {registerCheckoutTools} from './checkout.js';
 2 | import { registerTransactionTools } from './transaction.js';
 3 | import { registerRequiredTools } from './required.js';
 4 | import { registerPlanTools } from './plan.js';
 5 | 
 6 | export function registerTools() {
 7 |   registerRequiredTools();
 8 |   registerTransactionTools();
 9 |   registerCheckoutTools();
10 |   registerPlanTools();
11 | }
```
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { registerTools } from "./tools/index.js";
 3 | import { registerPrompts } from "./prompts/index.js";
 4 | 
 5 | // Create server instance.
 6 | export const server = new McpServer({
 7 |     name: "flutterwave",
 8 |     version: "1.2.2",
 9 | });
10 | 
11 | // Register tools with the server.
12 | registerTools();
13 | registerPrompts();
14 | 
15 | export default server;
16 | 
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |     "compilerOptions": {
 3 |         "target": "ES2022",
 4 |         "module": "Node16",
 5 |         "moduleResolution": "Node16",
 6 |         "outDir": "./build",
 7 |         "rootDir": "./src",
 8 |         "strict": true,
 9 |         "esModuleInterop": true,
10 |         "skipLibCheck": true,
11 |         "forceConsistentCasingInFileNames": true
12 |     },
13 |     "include": [
14 |         "src/**/*"
15 |     ],
16 |     "exclude": [
17 |         "node_modules"
18 |     ]
19 | }
```
--------------------------------------------------------------------------------
/src/types/index.ts:
--------------------------------------------------------------------------------
```typescript
 1 | export type Options = {
 2 |     tools?: string[];
 3 |     apiKey?: string;
 4 | };
 5 | 
 6 | export type CheckoutPayload = {
 7 |     tx_ref: string,
 8 |     amount: string,
 9 |     currency: string,
10 |     redirect_url: string,
11 |     customer: {
12 |         email: string,
13 |         name: string,
14 |         phonenumber: string,
15 |     },
16 |     customizations: {
17 |         title: string,
18 |     },
19 |     configurations: {
20 |         session_duration: number,
21 |         max_retry_attempt: number
22 |     },
23 | }
```
--------------------------------------------------------------------------------
/src/client/client.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import createClient, { Middleware } from "openapi-fetch";
 2 | import type { paths } from "./types/v3.js";
 3 | import authMiddlewareV3 from "./middleware/authMiddlewareV3.js";
 4 | 
 5 | const FLW_API_VERSION = process.env.FLW_VERSION || 'v3';
 6 | const FLW_API_BASE = "https://api.flutterwave.com/" + FLW_API_VERSION;
 7 | const USER_AGENT = "flutterwave-mcp/0.1.0";
 8 |  
 9 | const client = createClient<paths>({ baseUrl: FLW_API_BASE, headers: { "User-Agent": USER_AGENT } });
10 | client.use(authMiddlewareV3);
11 | 
12 | export default client
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
 1 | FROM node:20.19.5-alpine3.22 AS builder
 2 | 
 3 | WORKDIR /app
 4 | 
 5 | ENV DOCKER=true
 6 | 
 7 | # Copy package files and install dependencies
 8 | COPY package*.json ./
 9 | RUN npm ci
10 | 
11 | # Copy source code
12 | COPY tsconfig.json ./
13 | COPY src/ ./src/
14 | 
15 | # Build the application
16 | RUN npm run build
17 | 
18 | # Start a new stage for a smaller production image
19 | FROM node:20.19.5-alpine3.22
20 | 
21 | WORKDIR /app
22 | 
23 | # Set environment variables
24 | ENV DOCKER=true
25 | ENV NODE_ENV=production
26 | ENV FLW_SECRET_KEY=${FLW_SECRET_KEY}
27 | 
28 | # Copy package files and install production dependencies only
29 | COPY package*.json ./
30 | RUN npm ci --omit=dev
31 | 
32 | # Copy the built application from the builder stage
33 | COPY --from=builder /app/build ./build
34 | 
35 | # Run the application
36 | CMD ["node", "build/index.js"] 
```
--------------------------------------------------------------------------------
/src/types/plan/schema.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { z } from 'zod';
 2 | 
 3 | export const CreatePlanPayloadSchema = {
 4 |     name: z.string().min(1, "Name is required"),
 5 |     amount: z.number().positive("Amount must be a positive number"),
 6 |     interval: z.enum(['daily', 'weekly', 'monthly', 'yearly']).refine(val => ['daily', 'weekly', 'monthly', 'yearly'].includes(val), { message: "Interval must be one of 'daily', 'weekly', 'monthly', 'yearly'" }),
 7 |     duration: z.number().int().positive("Duration must be a positive integer"),
 8 | };
 9 | 
10 | export const GetPlansFiltersSchema = {
11 |     name: z.string().min(1).optional(),
12 |     amount: z.number().positive().optional(),
13 |     interval: z.enum(['daily', 'weekly', 'monthly', 'yearly']).optional(),
14 |     status: z.enum(['active', 'inactive']).optional(),
15 |     from: z.string().optional(),
16 |     to: z.string().optional(),
17 | };
```
--------------------------------------------------------------------------------
/server.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |   "$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
 3 |   "name": "io.github.bajoski34/mcp-flutterwave",
 4 |   "description": "MCP Server to interact with Flutterwave APIs.",
 5 |   "repository": {
 6 |     "url": "https://github.com/bajoski34/mcp-flutterwave",
 7 |     "source": "github"
 8 |   },
 9 |   "version": "1.2.2",
10 |   "packages": [
11 |     {
12 |       "registryType": "npm",
13 |       "registryBaseUrl": "https://registry.npmjs.org",
14 |       "identifier": "mcp-flutterwave",
15 |       "version": "1.2.2",
16 |       "transport": {
17 |         "type": "stdio"
18 |       },
19 |       "environmentVariables": [
20 |         {
21 |           "description": "Your SECRET API key for the service",
22 |           "isRequired": true,
23 |           "format": "string",
24 |           "isSecret": true,
25 |           "name": "FLW_SECRET_KEY"
26 |         }
27 |       ]
28 |     }
29 |   ]
30 | }
```
--------------------------------------------------------------------------------
/src/config/index.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { version } from 'os';
 2 | import {z} from 'zod';
 3 | 
 4 | // environment variable schema for validation
 5 | const envSchema = z.object({
 6 |   FLW_SECRET_KEY: z.string().min(1, 'Flutterwave Secret Key is required'),
 7 |   NODE_ENV: z
 8 |     .enum(['development', 'production', 'test'])
 9 |     .optional()
10 |     .default('development'),
11 | });
12 | 
13 | // Parse and validate environment variables
14 | const envParse = envSchema.safeParse(process.env);
15 | 
16 | if (!envParse.success) {
17 |   console.error('❌ Invalid environment variables:', envParse.error.format());
18 |   throw new Error('Invalid environment variables');
19 | }
20 | 
21 | // Export validated config
22 | export const config = {
23 |   flutterwave: {
24 |     secretKey: envParse.data.FLW_SECRET_KEY,
25 |     apiUrl: 'https://api.flutterwave.com',
26 |     version: 'v3',
27 |   },
28 |   server: {
29 |     environment: envParse.data.NODE_ENV,
30 |   },
31 | } as const;
32 | 
```
--------------------------------------------------------------------------------
/src/tools/required.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { type Tool } from "@modelcontextprotocol/sdk/types.js";
 3 | import { z } from "zod";
 4 | import { server } from "../server.js";
 5 | 
 6 | const tools:any[] = [];
 7 | 
 8 | /**
 9 |  * Register tool for the Flutterwave MCP Server to function
10 |  */
11 | 
12 | // tools.push({
13 | //     name: "sample",
14 | //     description: "Sample Tool",
15 | //     inputSchema: { sample: z.string().min(1, "Sample is required").describe("Sample") },
16 | //     cb: ((args: any) => {
17 | //         return {
18 | //             content: [{ type: "text", text: `Sample Tool Executed with args: ${JSON.stringify(args)}` }] };
19 | //     }),
20 | // });
21 | 
22 | export async function registerRequiredTools() {
23 | 
24 |     // Register required tools with the server.
25 |     for (const tool of tools) {
26 |         server.tool(tool.name, tool.description, tool.inputSchema, tool.cb);
27 |     }
28 | 
29 | }
30 | 
```
--------------------------------------------------------------------------------
/src/types/checkout/schema.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { z } from 'zod';
 2 | 
 3 | export const CheckoutPayloadSchema = {
 4 |     tx_ref: z.string().min(1, "Transaction reference is required"),
 5 |     amount: z.string().min(1, "Amount is required"),
 6 |     currency: z.string().min(1, "Currency is required"),
 7 |     redirect_url: z.string().url("Redirect URL must be a valid URL"),
 8 |     customer: z.object({
 9 |         email: z.string().email("Invalid email address"),
10 |         name: z.string().min(1, "Customer name is required"),
11 |         phonenumber: z.string().min(1, "Customer phone number is required"),
12 |     }),
13 |     customizations: z.object({
14 |         title: z.string().min(1, "Title is required"),
15 |     }),
16 |     configurations: z.object({
17 |         session_duration: z.number().int().positive("Session duration must be a positive integer"),
18 |         max_retry_attempt: z.number().int().nonnegative("Max retry attempt must be a non-negative integer")
19 |     }),
20 | };
21 | 
22 | export const DisableCheckoutSchema = {
23 |     link: z.string().url("Checkout link must be a valid URL"),
24 | };
```
--------------------------------------------------------------------------------
/src/client/http/index.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import createClient from "openapi-fetch";
 2 | import type { paths as checkoutPaths } from "../types/v3/checkout.js";
 3 | import type { paths as transactionPaths } from "../types/v3/transactions.js";
 4 | import type { paths as planPaths } from "../types/v3/plans.js";
 5 | import authMiddlewareV3 from "../middleware/authMiddlewareV3.js";
 6 | import { config } from "../../config/index.js";
 7 | 
 8 | const FLW_API_VERSION = process.env.FLW_VERSION || config.flutterwave.version;
 9 | const FLW_API_BASE = config.flutterwave.apiUrl + '/' + FLW_API_VERSION;
10 | const USER_AGENT = "flutterwave-mcp/0.1.0";
11 |  
12 | const transactionClient = createClient<transactionPaths>({ baseUrl: FLW_API_BASE, headers: { "User-Agent": USER_AGENT } });
13 | transactionClient.use(authMiddlewareV3);
14 | const checkoutClient = createClient<checkoutPaths>({ baseUrl: FLW_API_BASE, headers: { "User-Agent": USER_AGENT } });
15 | checkoutClient.use(authMiddlewareV3);
16 | const planClient = createClient<planPaths>({ baseUrl: FLW_API_BASE, headers: { "User-Agent": USER_AGENT } });
17 | planClient.use(authMiddlewareV3);
18 | 
19 | export {
20 |     transactionClient,
21 |     checkoutClient,
22 |     planClient
23 | }
24 | 
25 | 
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |   "name": "mcp-flutterwave",
 3 |   "type": "module",
 4 |   "bin": {
 5 |     "mcp-flutterwave": "build/index.js"
 6 |   },
 7 |   "version": "1.2.2",
 8 |   "mcpName": "io.github.bajoski34/mcp-flutterwave",
 9 |   "repository": {
10 |     "type": "git",
11 |     "url": "https://github.com/bajoski34/mcp-flutterwave.git"
12 |   },
13 |   "description": "MCP Server to interact with Flutterwave APIs.",
14 |   "main": "build/index.js",
15 |   "scripts": {
16 |     "build": "npm run build:types &&tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
17 |     "clean": "rm -rf build",
18 |     "build:types": "./bin/generate-openapi-typescript"
19 |   },
20 |   "files": [
21 |     "build"
22 |   ],
23 |   "keywords": [
24 |     "mcp",
25 |     "model-context-protocol",
26 |     "flutterwave",
27 |     "payment",
28 |     "fintech",
29 |     "ai"
30 |   ],
31 |   "author": "Abraham Olaobaju <[email protected]>",
32 |   "license": "MIT",
33 |   "dependencies": {
34 |     "@modelcontextprotocol/sdk": "^1.18.2",
35 |     "colors": "^1.4.0",
36 |     "flutterwave-node-v3": "^1.1.15",
37 |     "openapi-fetch": "^0.14.0",
38 |     "ts-node": "^10.9.2",
39 |     "zod": "^3.24.2"
40 |   },
41 |   "devDependencies": {
42 |     "@types/node": "^22.13.10",
43 |     "nodemon": "^3.1.9",
44 |     "openapi-typescript": "^7.6.1",
45 |     "typescript": "^5.8.2",
46 |     "zod-to-json-schema": "^3.24.6"
47 |   }
48 | }
49 | 
```
--------------------------------------------------------------------------------
/src/client/lib/plan.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { planClient as client } from "../http/index.js";
 2 | import type { paths } from "../types/v3/plans.js";
 3 | 
 4 | type CreatePlanPayload = (
 5 |   paths["/plans"]["post"]["requestBody"]
 6 |   & { content: { "application/json": unknown } }
 7 | )["content"]["application/json"];
 8 | type CreatePlanResponse = paths["/plans"]["post"]["responses"]["200"]["content"]["application/json"];
 9 | 
10 | type GetPlanResponse = paths["/plans"]["get"]["responses"]["200"]["content"]["application/json"];
11 | type GetPlanParams = paths["/plans"]["get"]["parameters"]["query"];
12 | 
13 | export default class Plan {
14 |     async create(payload: CreatePlanPayload): Promise<{ status: number; data: CreatePlanResponse | string | null }> {
15 |         try {
16 |         const response = await client.POST("/plans", { body: payload });
17 |         return { 
18 |             status: response.response?.status ?? 500, 
19 |             data: response.data ?? null 
20 |         };
21 |         } catch (error) {
22 |         return { status: 500, data: (error as any)?.message || 'An error occurred'};
23 |         }
24 |     }
25 | 
26 |     async get(params?: GetPlanParams): Promise<{ status: number; data: GetPlanResponse | null }> {
27 |         try {
28 |         const response = await client.GET("/plans", { 
29 |             query: params || {
30 |                 page: 1,
31 |                 status: "active",
32 |                 from: "",
33 |                 to: "",
34 |                 amount: 0,
35 |                 interval: ""
36 |             }
37 |         });
38 |         return { 
39 |             status: response.response?.status ?? 500, 
40 |             data: response.data ?? null 
41 |         };
42 |         } catch (error) {
43 |         return { status: 500, data: null };
44 |         }
45 |     }
46 | }
47 | 
```
--------------------------------------------------------------------------------
/src/client/lib/checkout.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import { checkoutClient as client } from "../http/index.js";
 2 | 
 3 | type CheckoutPayload = {
 4 |     tx_ref: string,
 5 |     amount: string,
 6 |     currency: string,
 7 |     redirect_url: string,
 8 |     customer: {
 9 |         email: string,
10 |         name: string,
11 |         phonenumber: string,
12 |     },
13 |     customizations: {
14 |         title: string,
15 |     },
16 |     configurations: {
17 |         session_duration: number,
18 |         max_retry_attempt: number
19 |     },
20 | }
21 | 
22 | /**
23 |  * This checkout create paymrnt.
24 |  * https://developer.flutterwave.com/docs/flutterwave-standard-1
25 |  * 
26 | */
27 | async function create(payment_data: CheckoutPayload) : Promise<{ data: {
28 |     data: any; link: string 
29 | }, status: number } | undefined> {
30 |     const { data, error } = await client.POST("/payments", {
31 |         body: {
32 |             ...payment_data
33 |         }
34 |     });
35 | 
36 |     if (error) {
37 |         console.error(error);
38 |         return;
39 |     }
40 | 
41 |     return data;
42 | }
43 | 
44 | // {
45 | //     "status": "success",
46 | //     "message": "LINK DISABLED",
47 | //     "data": true
48 | // }
49 | 
50 | /**
51 |  * Disable a checkout link.
52 |  * https://developer.flutterwave.com/v3.0.0/docs/flutterwave-standard-1#how-to-disable-a-payment-link-via-api
53 |  * @param payment_link 
54 |  * @returns 
55 |  */
56 | async function disable(payment_link: string): Promise<{
57 |     status: string;
58 |     message: string;
59 |     data: null;
60 | } | undefined> {
61 |     const { data, error } = await client.POST("/payments/link/disable", {
62 |         body:{
63 |             link: payment_link
64 |         }
65 |     });
66 | 
67 |     if (error) {
68 |         console.error(error);
69 |         throw new Error('Failed to disable checkout link', { cause: error });
70 |     }
71 | 
72 |     // Ensure returned object always has data: null
73 |     return {
74 |         status: data?.status || 'error',
75 |         message: data?.message || 'An error occurred',
76 |         data: null
77 |     };
78 | }
79 | 
80 | export default {
81 |     create,
82 |     disable_link: disable
83 | }
```
--------------------------------------------------------------------------------
/src/tools/retry_transaction.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import Flutterwave from "../client/index.js";
 2 | 
 3 | export default async ({ tx_id }: { tx_id: string }) => {
 4 |     if (!process.env.FLW_SECRET_KEY) {
 5 |         return {
 6 |             content: [{ type: "text", text: "API key is missing. Please check configuration." }],
 7 |         };
 8 |     }
 9 | 
10 |     const transactions = Flutterwave.transactions();
11 | 
12 |     try {
13 |         const response = await transactions.retry_transaction(tx_id);
14 | 
15 |         if (!response || response.status === 'error') {
16 |             return {
17 |                 content: [{ 
18 |                     type: "text", 
19 |                     text: response?.message || `Unable to retry transaction ${tx_id}` 
20 |                 }],
21 |             };
22 |         }
23 | 
24 |         if (response.status === 'info' && response.data) {
25 |             const data = response.data;
26 |             return {
27 |                 content: [
28 |                     {
29 |                         type: "text",
30 |                         text: `Transaction retry analysis completed for ${tx_id}:\n` +
31 |                               `Status: ${data.status}\n` +
32 |                               `Original Reference: ${data.original_tx_ref}\n` +
33 |                               `Amount: ${data.amount} ${data.currency}\n` +
34 |                               `Customer: ${data.customer_email}\n\n` +
35 |                               `${response.message}`
36 |                     },
37 |                 ],
38 |             };
39 |         }
40 | 
41 |         return {
42 |             content: [
43 |                 {
44 |                     type: "text",
45 |                     text: `Transaction retry completed: ${response.message}`,
46 |                 },
47 |             ],
48 |         };
49 |     } catch (error) {
50 |         console.error(`Error retrying transaction ${tx_id}:`, error);
51 |         return {
52 |             content: [{ type: "text", text: `Error retrying transaction ${tx_id}` }],
53 |         };
54 |     }
55 | };
```
--------------------------------------------------------------------------------
/src/prompts/transactions.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import {server} from '../server.js';
 2 | 
 3 | const transactionInsightsPrompt = `
 4 | You are a helpful assistant connecting to Flutterwave Server. Your goal is to provide the user with actionable insights into transactions, including revenue, volume, success/failure rates, and trends.
 5 | 
 6 | Available Tools:
 7 | 1. \`list_transactions\`: Fetches detailed transaction records (amount, currency, status, customer, etc.).
 8 | 2. \`get_transaction_totals\`: Returns aggregated metrics such as total revenue, transaction count, success rate, and failure rate.
 9 | 3. \`list_customers\`: Provides information about customers to segment transactions and identify top spenders.
10 | 
11 | Workflow:
12 | 1. When a user asks about transaction insights (e.g., "How are my transactions this month?"), call \`get_transaction_totals\` with appropriate date filters.
13 | 2. Use \`list_transactions\` for deeper analysis like top payment methods, currencies, or customer segments.
14 | 3. Highlight key metrics:
15 |    - Total revenue
16 |    - Number of successful vs failed transactions
17 |    - Average transaction value
18 |    - Top payment methods and currencies
19 |    - Top customers by volume or value
20 | 4. Identify trends such as:
21 |    - Day with highest sales
22 |    - Increase/decrease compared to previous period
23 |    - Most common reasons for failed transactions (if available)
24 | 5. Present the insights in a concise, structured way (tables, bullet points, percentages).
25 | 6. Offer follow-up insights (e.g., "Would you like to see a breakdown by country or payment method?").
26 | 7. Focus on turning raw transaction data into clear business insights.
27 | `;
28 | 
29 | export function registerTransactionsPrompts() {
30 |   server.prompt(
31 |     'show-transaction-insights',
32 |     'Give me insights into my transactions this month',
33 |     {},
34 |     async () => ({
35 |       messages: [
36 |         {
37 |           role: 'assistant',
38 |           content: {
39 |             type: 'text',
40 |             text: transactionInsightsPrompt,
41 |           },
42 |         },
43 |       ],
44 |     })
45 |   );
46 | }
47 | 
48 | 
```
--------------------------------------------------------------------------------
/src/tools/get_transaction_timeline.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import Flutterwave from "../client/index.js";
 2 | 
 3 | export default async ({ tx_id }: { tx_id: string }) => {
 4 |     if (!process.env.FLW_SECRET_KEY) {
 5 |         return {
 6 |             content: [{ type: "text", text: "API key is missing. Please check configuration." }],
 7 |         };
 8 |     }
 9 | 
10 |     const transactions = Flutterwave.transactions();
11 | 
12 |     try {
13 |         const { status, data } = await transactions.timeline(tx_id) || { status: null, data: null };
14 | 
15 |         if(typeof status == 'number' && status >= 400) {
16 |             return {
17 |                 content: [{ type: "text", text: `Unable to retrieve timeline for ${tx_id}` }],
18 |             };
19 |         }
20 |         
21 |         if(!data) {
22 |             return {
23 |                 content: [{ type: "text", text: `Unable to retrieve timeline for ${tx_id}` }],
24 |             };
25 |         }
26 | 
27 |         if(!(data as any)?.status) {
28 |             return {
29 |                 content: [{ type: "text", text: `Unable to retrieve timeline for ${tx_id}` }],
30 |             };
31 |         }
32 | 
33 |         // Format the timeline data for display
34 |         let timelineText = `Transaction Timeline for ${tx_id}:\n\n`;
35 |         
36 |         if ((data as any).data && Array.isArray((data as any).data)) {
37 |             (data as any).data.forEach((event: any, index: number) => {
38 |                 timelineText += `${index + 1}. ${event.event || 'Event'}: ${event.description || 'No description'}\n`;
39 |                 if (event.created_at) {
40 |                     timelineText += `   Time: ${event.created_at}\n`;
41 |                 }
42 |                 timelineText += '\n';
43 |             });
44 |         } else {
45 |             timelineText += 'No timeline events available for this transaction.';
46 |         }
47 | 
48 |         return {
49 |             content: [
50 |                 {
51 |                     type: "text",
52 |                     text: timelineText,
53 |                 },
54 |             ],
55 |         };
56 |     } catch (error) {
57 |         console.error(`Error fetching timeline for ${tx_id}:`, error);
58 |         return {
59 |             content: [{ type: "text", text: `Error retrieving timeline for ${tx_id}` }],
60 |         };
61 |     }
62 | };
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
  1 | #!/usr/bin/env node
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import server from "./server.js";
  4 | import { Options } from "./types/index.js";
  5 | import { config } from "./config/index.js";
  6 | 
  7 | const ACCEPTED_ARGS = ['tools'];
  8 | 
  9 | const ACCEPTED_TOOLS = [
 10 |     'create_checkout',
 11 |     'disable_checkout',
 12 |     'create_refund',
 13 |     'read_transactions',
 14 |     'read_transaction',
 15 |     'read_transaction_timeline',
 16 |     'resend_transaction_webhook',
 17 |     'create_plan',
 18 |     'read_plan',
 19 |     'read_subscription'
 20 | ];
 21 | 
 22 | export function parseArgs(args: string[]): Options {
 23 |     const options: Options = {};
 24 | 
 25 |     args.forEach((arg) => {
 26 |         if (arg.startsWith('--')) {
 27 |             const [key, value] = arg.slice(2).split('=');
 28 | 
 29 |             if (key == 'tools') {
 30 |                 options.tools = value.split(',');
 31 |             } else {
 32 |                 throw new Error(
 33 |                     `Invalid argument: ${key}. Accepted arguments are: ${ACCEPTED_ARGS.join(
 34 |                         ', '
 35 |                     )}`
 36 |                 );
 37 |             }
 38 |         }
 39 |     });
 40 | 
 41 |     // Check if required tools arguments is present.
 42 |     if (!options.tools) {
 43 |         throw new Error('The --tools arguments must be provided.');
 44 |     }
 45 | 
 46 |     // Validate tools against accepted enum values.
 47 |     options.tools.forEach((tool: string) => {
 48 |         if (tool == 'all') {
 49 |             return;
 50 |         }
 51 |         if (!ACCEPTED_TOOLS.includes(tool.trim())) {
 52 |             throw new Error(
 53 |                 `Invalid tool: ${tool}. Accepted tools are: ${ACCEPTED_TOOLS.join(
 54 |                     ', '
 55 |                 )}`
 56 |             );
 57 |         }
 58 |     });
 59 | 
 60 |     // Check if API key is either provided in args or set in environment variables
 61 |     const apiKey = process.env.FLW_SECRET_KEY;
 62 | 
 63 |     if (!apiKey) {
 64 |         throw new Error(
 65 |             'Flutterwave Secret key not provided. Please either pass it as an argument --secret-key=$KEY or set the FLW_SECRET_KEY environment variable.'
 66 |         );
 67 |     }
 68 | 
 69 |     options.apiKey = apiKey;
 70 | 
 71 |     return options;
 72 | }
 73 | 
 74 | async function main() {
 75 |     const options = parseArgs(process.argv.slice(2));
 76 |     const transport = new StdioServerTransport();
 77 | 
 78 |     // Handle process termination
 79 |     process.on('SIGINT', async () => {
 80 |       console.error('Shutting down Flutterwave MCP Server...');
 81 |       await server.close();
 82 |       process.exit(0);
 83 |     });
 84 | 
 85 |     process.on('SIGTERM', async () => {
 86 |       console.error('Shutting down Flutterwave MCP Server...');
 87 |       await server.close();
 88 |       process.exit(0);
 89 |     });
 90 | 
 91 |     await server.connect(transport);
 92 |     console.error("Flutterwave MCP Server running on stdio");
 93 | }
 94 | 
 95 | main().catch((error) => {
 96 |     console.error("Fatal error in main():", error);
 97 |     process.exit(1);
 98 | });
 99 | 
100 | 
```
--------------------------------------------------------------------------------
/src/tools/plan.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import Flutterwave from "../client/index.js";
 2 | import { CheckoutPayload } from "../types/index.js";
 3 | import { server } from "../server.js";
 4 | import { CreatePlanPayloadSchema, GetPlansFiltersSchema } from "../types/plan/schema.js";
 5 | 
 6 | export async function createPlan(payload: { name: string; amount: number; interval: string; duration?: number; currency?: string; description?: string; }) {
 7 |     const plans = Flutterwave.plans();
 8 |      
 9 |     try {
10 |         const { status, data } = await plans.create({
11 |             ...payload,
12 |             duration: payload.duration ?? 0, // Provide a default value if undefined
13 |         }) || { status: null, data: null };
14 |         if(typeof status == 'number' && status >= 400)
15 |             return {
16 |                 content: [{ type: "text" as const, text: `Unable to create plan ${ payload.name } json: ${ JSON.stringify(data) }` }],
17 |             };
18 |         
19 |         if(!data)
20 |             return {
21 |                 content: [{ type: "text" as const, text: `Unable to create plan ${ payload.name } json: {message: "No response from server"}` }],
22 |             };
23 | 
24 |         return {
25 |             content: [
26 |                 {
27 |                     type: "text" as const,
28 |                     text: `Plan created with ID: ${ (data as { data?: { id?: string } }).data?.id }`,
29 |                 },
30 |             ],
31 |         };
32 |     } catch (error) {
33 |         return {
34 |             content: [{ type: "text" as const, text: `Error Occured on creating plan ${ payload.name } json: ${ JSON.stringify(error) }` }],
35 |         };
36 |     }
37 | }
38 | 
39 | export async function getPlans(filters?: { name?: string; amount?: number; interval?: string; status?: string; from?: string; to?: string; }) {
40 |     const plans = Flutterwave.plans();
41 |     
42 |     try {
43 |         const { status, data } = await plans.get({
44 |             ...filters
45 |         }) || { status: null, data: null };
46 |         if(typeof status == 'number' && status >= 400)
47 |             return {
48 |                 content: [{ type: "text" as const, text: `Unable to retrieve plans` }],
49 |             };
50 |         
51 |         if(!data)
52 |             return {
53 |                 content: [{ type: "text" as const, text: `Unable to retrieve plans` }],
54 |             };
55 | 
56 |         if(!data?.status)
57 |             return {
58 |                 content: [{ type: "text" as const, text: `Error Occured on retrieving plans json: ${ JSON.stringify(data) }` }],
59 |             };
60 | 
61 |         return {
62 |             content: [
63 |                 {
64 |                     type: "text" as const,
65 |                     text: `Plans retrieved: ${ JSON.stringify(data.data) }`,
66 |                 },
67 |             ],
68 |         };
69 |     } catch (error) {
70 |         return {
71 |             content: [{ type: "text" as const, text: `Error Occured on retrieving plans json: ${ JSON.stringify(error) }` }],
72 |         };
73 |     }
74 | }
75 | 
76 | export async function registerPlanTools() {
77 |     server.tool(
78 |         "create_payment_plan",
79 |         "Create a payment plan with Flutterwave.",
80 |         CreatePlanPayloadSchema,
81 |         async (input) => await createPlan(input)
82 |     )
83 | 
84 |     server.tool(
85 |         "get_payment_plans",
86 |         "Get payment plans with optional filters",
87 |         GetPlansFiltersSchema,
88 |         async (input) => await getPlans(input)
89 |     )
90 | }
```
--------------------------------------------------------------------------------
/src/tools/checkout.ts:
--------------------------------------------------------------------------------
```typescript
 1 | import Flutterwave from "../client/index.js";
 2 | import { CheckoutPayload } from "../types/index.js";
 3 | import { server } from "../server.js";
 4 | import { CheckoutPayloadSchema, DisableCheckoutSchema } from "../types/checkout/index.js";
 5 | 
 6 | export async function createCheckout(payload: CheckoutPayload) {
 7 |     const transactions = Flutterwave.checkout();
 8 | 
 9 |     try {
10 |         const { status, data } = await transactions.create(payload) || { status: null, data: null };
11 | 
12 |         if(typeof status == 'number' && status >= 400)
13 |             return {
14 |                 content: [{ type: "text" as const, text: `Unable to create a checkout url for ${ payload.customer.name }` }],
15 |             };
16 |         
17 |         if(!data)
18 |             return {
19 |                 content: [{ type: "text" as const, text: `Unable to create a checkout url for ${ payload.customer.name }` }],
20 |             };
21 | 
22 |         if(!data?.data?.status)
23 |             return {
24 |                 content: [{ type: "text" as const, text: `Error Occured on creating checkout url for ${ payload.customer.name } json: ${ JSON.stringify(data) }` }],
25 |             };
26 | 
27 |         return {
28 |             content: [
29 |                 {
30 |                     type: "text" as const,
31 |                     text: `Checkout link at: ${ data.data?.link }`,
32 |                 },
33 |             ],
34 |         };
35 |     } catch (error) {
36 |         return {
37 |             content: [{ type: "text" as const, text: `Error Occured on creating checkout url for ${ payload.customer.name } json: ${ JSON.stringify(error) }` }],
38 |         };
39 |     }
40 | }
41 | 
42 | export async function disableCheckout(link: string) {
43 |     const transactions = Flutterwave.checkout();
44 | 
45 |     try {
46 |         const { status, data } = await transactions.disable_link(link) || { status: null, data: null };
47 | 
48 |         if(typeof status == 'number' && status >= 400)
49 |             return {
50 |                 content: [{ type: "text" as const, text: `Unable to disable checkout link ${ link } json: ${ JSON.stringify(data) }` }],
51 |             };
52 |         
53 |         if(!data)
54 |             return {
55 |                 content: [{ type: "text" as const, text: `Unable to disable checkout link ${ link }` }],
56 |             };
57 | 
58 |         return {
59 |             content: [
60 |                 {
61 |                     type: "text" as const,
62 |                     text: `Successfully disabled the link.`,
63 |                 },
64 |             ],
65 |         };
66 |     } catch (error) {
67 |         return {
68 |             content: [{ type: "text" as const, text: `Error Occured on diabling the checkout: ${ link } json: ${ JSON.stringify(error) }` }],
69 |         };
70 |     }
71 | }
72 | 
73 | export function registerCheckoutTools() {
74 |     server.tool(
75 |         "create_checkout",
76 |         "Create a checkout link with Flutterwave.",
77 |         CheckoutPayloadSchema,
78 |         async (args) => {
79 |             try {
80 |                 return await createCheckout(args);
81 |             } catch (error) {
82 |                 return {
83 |                     content: [{ type: "text" as const, text: `Error Occured on creating checkout url for ${ args.customer.name }` }],
84 |                 };
85 |             }
86 |         }
87 |     );
88 | 
89 |     server.tool(
90 |         "disable_checkout",
91 |         "Disable a checkout link on Flutterwave.",
92 |         DisableCheckoutSchema,
93 |         async (args) => {
94 |             return await disableCheckout(args.link);
95 |         }
96 |     );
97 | }
```
--------------------------------------------------------------------------------
/src/client/specs/v3/checkout.yaml:
--------------------------------------------------------------------------------
```yaml
  1 | openapi: 3.0.3
  2 | info:
  3 |   title: Flutterwave Transactions API
  4 |   description: API for managing and retrieving transaction details via Flutterwave.
  5 |   version: 1.0.0
  6 | servers:
  7 |   - url: https://api.flutterwave.com/v3
  8 | paths:
  9 |   /payments:
 10 |       post:
 11 |         summary: Process a payment through Flutterwave
 12 |         description: Initiates a payment process through Flutterwave using a unique transaction reference.
 13 |         operationId: createPayment
 14 |         requestBody:
 15 |           description: Payment data for the transaction
 16 |           content:
 17 |             application/json:
 18 |               schema:
 19 |                 type: object
 20 |                 properties:
 21 |                   tx_ref:
 22 |                     type: string
 23 |                     example: 'txnref_djsdkjsnkdjvnsdfj'
 24 |                   amount:
 25 |                     type: string
 26 |                     example: '7500'
 27 |                   currency:
 28 |                     type: string
 29 |                     example: 'NGN'
 30 |                   redirect_url:
 31 |                     type: string
 32 |                     example: 'https://example_company.com/success'
 33 |                   customer:
 34 |                     type: object
 35 |                     properties:
 36 |                       email:
 37 |                         type: string
 38 |                         example: '[email protected]'
 39 |                       name:
 40 |                         type: string
 41 |                         example: 'Flutterwave Developers'
 42 |                       phonenumber:
 43 |                         type: string
 44 |                         example: '09012345678'
 45 |                   customizations:
 46 |                     type: object
 47 |                     properties:
 48 |                       title:
 49 |                         type: string
 50 |                         example: 'Flutterwave Standard Payment'
 51 |                 required:
 52 |                   - tx_ref
 53 |                   - amount
 54 |                   - currency
 55 |                   - redirect_url
 56 |                   - customer
 57 |                   - customizations
 58 | 
 59 |   /payments/link/disable:
 60 |     post:
 61 |       summary: Disable a Flutterwave payment link
 62 |       description: Disables a specific payment link for the given URL.
 63 |       operationId: disablePaymentLink
 64 |       requestBody:
 65 |         description: Payment link data to disable
 66 |         content:
 67 |           application/json:
 68 |             schema:
 69 |               type: object
 70 |               properties:
 71 |                 link:
 72 |                   type: string
 73 |                   example: 'https://checkout.flutterwave.com/v3/hosted/pay/flwlnk-01j8hkejppgm821xv8mfxfpgrb'
 74 |               required:
 75 |                 - link
 76 |       responses:
 77 |         '200':
 78 |           description: Payment link disabled successfully
 79 |           content:
 80 |             application/json:
 81 |               schema:
 82 |                 type: object
 83 |                 properties:
 84 |                   status:
 85 |                     type: string
 86 |                     example: 'success'
 87 |                   message:
 88 |                     type: string
 89 |                     example: 'Payment link has been disabled successfully'
 90 |         '400':
 91 |           description: Bad request, invalid data
 92 |         '401':
 93 |           description: Unauthorized, invalid API key
 94 |         '404':
 95 |           description: Payment link not found
 96 |         '500':
 97 |           description: Internal server error
 98 | components:
 99 |   schemas:
100 |     Transaction:
101 |       type: object
102 |   securitySchemes:
103 |     bearerAuth:
104 |       type: http
105 |       scheme: bearer
106 |       bearerFormat: JWT
```
--------------------------------------------------------------------------------
/src/client/lib/transactions.ts:
--------------------------------------------------------------------------------
```typescript
  1 | import { transactionClient as client } from "../http/index.js";
  2 | 
  3 | /**
  4 |  * This endpoint helps you query the details of a transaction.
  5 |  * https://developer.flutterwave.com/reference/verify-transaction.
  6 |  * @param tx_id 
  7 |  * @returns 
  8 |  */
  9 | async function get(tx_id: string) {
 10 |     const { data, error } = await client.GET("/transactions/{id}/verify", {
 11 |         params: {
 12 |             path: { id: tx_id },
 13 |         },
 14 |     });
 15 | 
 16 |     if (error) {
 17 |         console.error(error);
 18 |         return;
 19 |     }
 20 | 
 21 |     return data;
 22 | }
 23 | 
 24 | /**
 25 |  * This endpoint helps you query the details of a transaction using the transaction reference.
 26 |  * https://developer.flutterwave.com/reference/verify-transaction-with-tx_ref
 27 |  * @param tx_ref 
 28 |  * @returns 
 29 |  */
 30 | async function get_with_reference(tx_ref: string) {
 31 |     const { data, error } = await client.GET("/transactions/verify_by_reference", {
 32 |         params: {
 33 |             query: { tx_ref },
 34 |         },
 35 |     });
 36 | 
 37 |     if (error) {
 38 |         console.error(error);
 39 |         return;
 40 |     }
 41 | 
 42 |     return data;
 43 | }
 44 | 
 45 | /**
 46 |  * This endpoint helps you resend webhooks from failed sending queues to your server.
 47 |  * https://developer.flutterwave.com/reference/resend-transaction-webhook
 48 |  */
 49 | async function send_failed_webhook(tx_id: string) {
 50 |     const { data, error } = await client.POST("/transactions/{id}/resend-hook", {
 51 |         params: {
 52 |             path: { id: tx_id },
 53 |         },
 54 |     });
 55 | 
 56 |     if (error) {
 57 |         console.error(error);
 58 |         return;
 59 |     }
 60 | 
 61 |     return data;
 62 | }
 63 | 
 64 | /**
 65 |  * Review the timeline for a transaction from initiation to completion.
 66 |  * https://developer.flutterwave.com/reference/get-transaction-events
 67 |  */
 68 | async function timeline(tx_id: string) {
 69 |     const { data, error } = await client.POST("/transactions/{id}/events", {
 70 |         params: {
 71 |             path: { id: tx_id },
 72 |         },
 73 |     });
 74 | 
 75 |     if (error) {
 76 |         console.error(error);
 77 |         return;
 78 |     }
 79 | 
 80 |     return data;
 81 | }
 82 | 
 83 | /**
 84 |  * Retry a failed transaction by creating a new transaction with the same details
 85 |  * This is a wrapper function that gets the original transaction and recreates it
 86 |  */
 87 | async function retry_transaction(tx_id: string) {
 88 |     try {
 89 |         // First get the original transaction details
 90 |         const original = await get(tx_id);
 91 |         
 92 |         if (!original || !original.data) {
 93 |             return {
 94 |                 status: 'error',
 95 |                 message: 'Could not retrieve original transaction details',
 96 |                 data: null
 97 |             };
 98 |         }
 99 | 
100 |         const txData = original.data;
101 |         
102 |         // Check if transaction is in a retriable state
103 |         if (txData.status === 'successful') {
104 |             return {
105 |                 status: 'error',
106 |                 message: 'Transaction is already successful, cannot retry',
107 |                 data: null
108 |             };
109 |         }
110 | 
111 |         return {
112 |             status: 'info',
113 |             message: 'Transaction retry initiated. Please create a new transaction with the same details.',
114 |             data: {
115 |                 original_tx_ref: txData.tx_ref,
116 |                 amount: txData.amount,
117 |                 currency: txData.currency,
118 |                 customer_email: (txData as any).customer?.email,
119 |                 status: txData.status
120 |             }
121 |         };
122 |         
123 |     } catch (error) {
124 |         console.error('Error retrying transaction:', error);
125 |         return {
126 |             status: 'error',
127 |             message: 'Failed to retry transaction',
128 |             data: null
129 |         };
130 |     }
131 | }
132 | 
133 | export default {
134 |     get,
135 |     get_with_reference,
136 |     timeline,
137 |     send_failed_webhook,
138 |     retry_transaction
139 | }
```
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
```yaml
  1 | name: Publish Package
  2 | 
  3 | on:
  4 |   release:
  5 |     types: [published]
  6 |   workflow_dispatch:
  7 |     inputs:
  8 |       version:
  9 |         description: 'Version to publish'
 10 |         required: true
 11 |         default: 'patch'
 12 |         type: choice
 13 |         options:
 14 |         - patch
 15 |         - minor
 16 |         - major
 17 | 
 18 | jobs:
 19 |   publish:
 20 |     runs-on: ubuntu-latest
 21 |     permissions:
 22 |       contents: write
 23 |       id-token: write
 24 |     
 25 |     steps:
 26 |       - name: Checkout code
 27 |         uses: actions/checkout@v4
 28 |         with:
 29 |           fetch-depth: 0
 30 |           token: ${{ secrets.GITHUB_TOKEN }}
 31 | 
 32 |       - name: Setup Node.js
 33 |         uses: actions/setup-node@v4
 34 |         with:
 35 |           node-version: '18'
 36 |           registry-url: 'https://registry.npmjs.org'
 37 | 
 38 |       - name: Install dependencies
 39 |         run: npm ci
 40 | 
 41 |       - name: Run tests
 42 |         run: npm test --if-present
 43 | 
 44 |       - name: Build project
 45 |         run: npm run build
 46 | 
 47 |       - name: Configure Git
 48 |         run: |
 49 |           git config --local user.email "[email protected]"
 50 |           git config --local user.name "GitHub Action"
 51 | 
 52 |       - name: Bump version (manual trigger)
 53 |         if: github.event_name == 'workflow_dispatch'
 54 |         run: |
 55 |           npm version ${{ github.event.inputs.version }} --no-git-tag-version
 56 |           # Update server.json version to match package.json
 57 |           VERSION=$(node -p "require('./package.json').version")
 58 |           jq --arg v "$VERSION" '.version = $v' server.json > tmp && mv tmp server.json
 59 |           git add package.json package-lock.json server.json
 60 |           git commit -m "chore: bump version to $VERSION"
 61 |           git push
 62 | 
 63 |       - name: Create tag (manual trigger)
 64 |         if: github.event_name == 'workflow_dispatch'
 65 |         run: |
 66 |           VERSION=$(node -p "require('./package.json').version")
 67 |           git tag "v$VERSION"
 68 |           git push origin "v$VERSION"
 69 | 
 70 |       - name: Update server.json version on release
 71 |         if: github.event_name == 'release'
 72 |         run: |
 73 |           VERSION=$(echo "${{ github.ref }}" | sed 's/refs\/tags\/v//')
 74 |           jq --arg v "$VERSION" '.version = $v' server.json > tmp && mv tmp server.json
 75 |           jq --arg v "$VERSION" '.packages[0].version = $v' server.json > tmp && mv tmp server.json
 76 | 
 77 |       - name: Publish to npm
 78 |         run: npm publish --provenance --access public
 79 |         env:
 80 |           NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
 81 | 
 82 |       - name: Create GitHub Release (manual trigger)
 83 |         if: github.event_name == 'workflow_dispatch'
 84 |         uses: actions/create-release@v1
 85 |         env:
 86 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 87 |         with:
 88 |           tag_name: v${{ steps.version.outputs.version }}
 89 |           release_name: Release v${{ steps.version.outputs.version }}
 90 |           body: |
 91 |             Release notes for version ${{ steps.version.outputs.version }}
 92 |             
 93 |             ## Changes
 94 |             - Updated MCP Flutterwave integration
 95 |             
 96 |             ## Installation
 97 |             ```bash
 98 |             npm install -g mcp-flutterwave
 99 |             ```
100 |             
101 |             ## Usage with Claude Desktop
102 |             ```json
103 |             {
104 |               "mcpServers": {
105 |                 "flutterwave": {
106 |                   "command": "mcp-flutterwave",
107 |                   "env": {
108 |                     "FLW_SECRET_KEY": "YOUR_SECRET_KEY"
109 |                   }
110 |                 }
111 |               }
112 |             }
113 |             ```
114 |           draft: false
115 |           prerelease: false
116 | 
117 |       - name: Install MCP Publisher
118 |         run: |
119 |           curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.0.0/mcp-publisher_1.0.0_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
120 | 
121 |       - name: Login to MCP Registry
122 |         run: ./mcp-publisher login github-oidc
123 | 
124 |       - name: Publish to MCP Registry
125 |         run: ./mcp-publisher publish
126 | 
```
--------------------------------------------------------------------------------
/src/tools/transaction.ts:
--------------------------------------------------------------------------------
```typescript
  1 | import Flutterwave from "../client/index.js";
  2 | import { server } from "../server.js";
  3 | import { TransactionSchema } from "../types/transaction/schema.js";
  4 | 
  5 | export async function getTransaction({ tx_id }: { tx_id: string }) {
  6 |     const transactions = Flutterwave.transactions();
  7 | 
  8 |     try {
  9 |         const { status, data } = await transactions.get(tx_id) || { status: null, data: null };
 10 | 
 11 |         if(typeof status == 'number' && status >= 400)
 12 |             return {
 13 |                 content: [{ type: "text" as const, text: `Unable to retrive ${tx_id}` }],
 14 |             };
 15 |         
 16 |         if(!data)
 17 |             return {
 18 |                 content: [{ type: "text" as const, text: `Unable to retrive ${tx_id}` }],
 19 |             };
 20 | 
 21 |         if(!data.status)
 22 |             return {
 23 |                 content: [{ type: "text" as const, text: `Unable to retrive ${tx_id}` }],
 24 |             };
 25 | 
 26 |         return {
 27 |             content: [
 28 |                 {
 29 |                     type: "text" as const,
 30 |                     text: `Transaction Status: ${data.status}\nAmount: ${data.amount}\nCurrency: ${data.currency}`,
 31 |                 },
 32 |             ],
 33 |         };
 34 |     } catch (error) {
 35 |         return {
 36 |             content: [{ type: "text" as const, text: `Unable to retrive ${tx_id}` }],
 37 |         };
 38 |     }
 39 | }
 40 | 
 41 | export async function getTransactionTimeline({ tx_id }: { tx_id: string }) {
 42 |     const transactions = Flutterwave.transactions();
 43 | 
 44 |     try {
 45 |         const { status, data } = await transactions.timeline(tx_id) || { status: null, data: null };
 46 | 
 47 |         if(typeof status == 'number' && status >= 400)
 48 |             return {
 49 |                 content: [{ type: "text" as const, text: `Unable to retrive timeline for ${tx_id}` }],
 50 |             };
 51 |         
 52 |         if(!data)
 53 |             return {
 54 |                 content: [{ type: "text" as const, text: `Unable to retrive timeline for ${tx_id}` }],
 55 |             };
 56 | 
 57 |         return {
 58 |             content: [
 59 |                 {
 60 |                     type: "text" as const,
 61 |                     text: `Transaction Timeline: ${JSON.stringify(data)}`,
 62 |                 },
 63 |             ],
 64 |         };
 65 |     } catch (error) {
 66 |         return {
 67 |             content: [{ type: "text" as const, text: `Unable to retrive timeline for ${tx_id}` }],
 68 |         };
 69 |     }
 70 | }
 71 | 
 72 | export async function resendFailedWebhook({ tx_id }: { tx_id: string }) {
 73 |     const transactions = Flutterwave.transactions();
 74 | 
 75 |     try {
 76 |         const response = await transactions.send_failed_webhook(tx_id);
 77 |         const { status, data } = response || { status: 200, data: { status: "successful" }};
 78 | 
 79 |         if (!data || !data.status) {
 80 |             return {
 81 |                 content: [{ type: "text" as const, text: `Unable to retrieve ${tx_id}` }],
 82 |             };
 83 |         }
 84 | 
 85 |         if (typeof status === "number" && status >= 400) {
 86 |             return {
 87 |                 content: [{ type: "text" as const, text: `Unable to retrieve ${tx_id}` }],
 88 |             };
 89 |         }
 90 | 
 91 |         return {
 92 |             content: [
 93 |                 {
 94 |                     type: "text" as const,
 95 |                     text: `webhook Sent`,
 96 |                 },
 97 |             ],
 98 |         };
 99 |     } catch (error) {
100 |         console.error(`Error fetching transaction ${tx_id}:`, error);
101 |         return {
102 |             content: [{ type: "text" as const, text: `Error retrieving ${tx_id}` }],
103 |         };
104 |     }
105 | };
106 | 
107 | export async function registerTransactionTools() {
108 |     server.tool(
109 |         "read_transaction",
110 |         "Get Transaction Details",
111 |         TransactionSchema,
112 |         async (args) => {
113 |             return await getTransaction(args);
114 |         }
115 |     );
116 | 
117 |     server.tool(
118 |         "read_transaction_timeline",
119 |         "Get Transaction Timeline",
120 |         TransactionSchema,
121 |         async (args) => {
122 |             return await getTransactionTimeline(args);
123 |         }
124 |     );
125 | 
126 |     server.tool(
127 |         "resend_transaction_webhook",
128 |         "Resend Failed Webhook",
129 |         TransactionSchema,
130 |         async (args) => {
131 |             return await resendFailedWebhook(args);
132 |         }
133 |     ); 
134 | }
```
--------------------------------------------------------------------------------
/src/client/types/v3/checkout.d.ts:
--------------------------------------------------------------------------------
```typescript
  1 | /**
  2 |  * This file was auto-generated by openapi-typescript.
  3 |  * Do not make direct changes to the file.
  4 |  */
  5 | 
  6 | export interface paths {
  7 |     "/payments": {
  8 |         parameters: {
  9 |             query?: never;
 10 |             header?: never;
 11 |             path?: never;
 12 |             cookie?: never;
 13 |         };
 14 |         get?: never;
 15 |         put?: never;
 16 |         /**
 17 |          * Process a payment through Flutterwave
 18 |          * @description Initiates a payment process through Flutterwave using a unique transaction reference.
 19 |          */
 20 |         post: operations["createPayment"];
 21 |         delete?: never;
 22 |         options?: never;
 23 |         head?: never;
 24 |         patch?: never;
 25 |         trace?: never;
 26 |     };
 27 |     "/payments/link/disable": {
 28 |         parameters: {
 29 |             query?: never;
 30 |             header?: never;
 31 |             path?: never;
 32 |             cookie?: never;
 33 |         };
 34 |         get?: never;
 35 |         put?: never;
 36 |         /**
 37 |          * Disable a Flutterwave payment link
 38 |          * @description Disables a specific payment link for the given URL.
 39 |          */
 40 |         post: operations["disablePaymentLink"];
 41 |         delete?: never;
 42 |         options?: never;
 43 |         head?: never;
 44 |         patch?: never;
 45 |         trace?: never;
 46 |     };
 47 | }
 48 | export type webhooks = Record<string, never>;
 49 | export interface components {
 50 |     schemas: {
 51 |         Transaction: Record<string, never>;
 52 |     };
 53 |     responses: never;
 54 |     parameters: never;
 55 |     requestBodies: never;
 56 |     headers: never;
 57 |     pathItems: never;
 58 | }
 59 | export type $defs = Record<string, never>;
 60 | export interface operations {
 61 |     createPayment: {
 62 |         parameters: {
 63 |             query?: never;
 64 |             header?: never;
 65 |             path?: never;
 66 |             cookie?: never;
 67 |         };
 68 |         /** @description Payment data for the transaction */
 69 |         requestBody?: {
 70 |             content: {
 71 |                 "application/json": {
 72 |                     /** @example txnref_djsdkjsnkdjvnsdfj */
 73 |                     tx_ref: string;
 74 |                     /** @example 7500 */
 75 |                     amount: string;
 76 |                     /** @example NGN */
 77 |                     currency: string;
 78 |                     /** @example https://example_company.com/success */
 79 |                     redirect_url: string;
 80 |                     customer: {
 81 |                         /** @example [email protected] */
 82 |                         email?: string;
 83 |                         /** @example Flutterwave Developers */
 84 |                         name?: string;
 85 |                         /** @example 09012345678 */
 86 |                         phonenumber?: string;
 87 |                     };
 88 |                     customizations: {
 89 |                         /** @example Flutterwave Standard Payment */
 90 |                         title?: string;
 91 |                     };
 92 |                 };
 93 |             };
 94 |         };
 95 |         responses: never;
 96 |     };
 97 |     disablePaymentLink: {
 98 |         parameters: {
 99 |             query?: never;
100 |             header?: never;
101 |             path?: never;
102 |             cookie?: never;
103 |         };
104 |         /** @description Payment link data to disable */
105 |         requestBody?: {
106 |             content: {
107 |                 "application/json": {
108 |                     /** @example https://checkout.flutterwave.com/v3/hosted/pay/flwlnk-01j8hkejppgm821xv8mfxfpgrb */
109 |                     link: string;
110 |                 };
111 |             };
112 |         };
113 |         responses: {
114 |             /** @description Payment link disabled successfully */
115 |             200: {
116 |                 headers: {
117 |                     [name: string]: unknown;
118 |                 };
119 |                 content: {
120 |                     "application/json": {
121 |                         /** @example success */
122 |                         status?: string;
123 |                         /** @example Payment link has been disabled successfully */
124 |                         message?: string;
125 |                     };
126 |                 };
127 |             };
128 |             /** @description Bad request, invalid data */
129 |             400: {
130 |                 headers: {
131 |                     [name: string]: unknown;
132 |                 };
133 |                 content?: never;
134 |             };
135 |             /** @description Unauthorized, invalid API key */
136 |             401: {
137 |                 headers: {
138 |                     [name: string]: unknown;
139 |                 };
140 |                 content?: never;
141 |             };
142 |             /** @description Payment link not found */
143 |             404: {
144 |                 headers: {
145 |                     [name: string]: unknown;
146 |                 };
147 |                 content?: never;
148 |             };
149 |             /** @description Internal server error */
150 |             500: {
151 |                 headers: {
152 |                     [name: string]: unknown;
153 |                 };
154 |                 content?: never;
155 |             };
156 |         };
157 |     };
158 | }
159 | 
```
--------------------------------------------------------------------------------
/src/client/types/v3/plans.d.ts:
--------------------------------------------------------------------------------
```typescript
  1 | /**
  2 |  * This file was auto-generated by openapi-typescript.
  3 |  * Do not make direct changes to the file.
  4 |  */
  5 | 
  6 | export interface paths {
  7 |     "/plans": {
  8 |         parameters: {
  9 |             query?: never;
 10 |             header?: never;
 11 |             path?: never;
 12 |             cookie?: never;
 13 |         };
 14 |         /**
 15 |          * Retrieve all subscription plans
 16 |          * @description Fetch a list of all subscription plans.
 17 |          */
 18 |         get: operations["getPlans"];
 19 |         put?: never;
 20 |         /**
 21 |          * Create a new subscription plan
 22 |          * @description Create a new subscription plan with specified details.
 23 |          */
 24 |         post: operations["createPlan"];
 25 |         delete?: never;
 26 |         options?: never;
 27 |         head?: never;
 28 |         patch?: never;
 29 |         trace?: never;
 30 |     };
 31 | }
 32 | export type webhooks = Record<string, never>;
 33 | export interface components {
 34 |     schemas: never;
 35 |     responses: never;
 36 |     parameters: never;
 37 |     requestBodies: never;
 38 |     headers: never;
 39 |     pathItems: never;
 40 | }
 41 | export type $defs = Record<string, never>;
 42 | export interface operations {
 43 |     getPlans: {
 44 |         parameters: {
 45 |             query?: {
 46 |                 /** @description Page number for pagination */
 47 |                 page?: number;
 48 |                 /** @description This is the exact amount set when creating the payment plan */
 49 |                 amount?: number;
 50 |                 /** @description This is the currency used for the payment plan */
 51 |                 currency?: string;
 52 |                 /** @description This is the status of the payment plan */
 53 |                 status?: string;
 54 |                 /** @description This is the interval of the payment plan */
 55 |                 interval?: string;
 56 |                 /** @description This is the start date for the payment plan */
 57 |                 from?: string;
 58 |                 /** @description This is the end date for the payment plan */
 59 |                 to?: string;
 60 |             };
 61 |             header?: never;
 62 |             path?: never;
 63 |             cookie?: never;
 64 |         };
 65 |         requestBody?: never;
 66 |         responses: {
 67 |             /** @description A list of subscription plans */
 68 |             200: {
 69 |                 headers: {
 70 |                     [name: string]: unknown;
 71 |                 };
 72 |                 content: {
 73 |                     "application/json": {
 74 |                         /** @example success */
 75 |                         status?: string;
 76 |                         /** @example Payment plans fetched */
 77 |                         message?: string;
 78 |                         meta?: {
 79 |                             page_info?: {
 80 |                                 /** @example 10 */
 81 |                                 current_page?: number;
 82 |                                 /** @example 1 */
 83 |                                 total_pages?: number;
 84 |                             };
 85 |                         };
 86 |                         data?: {
 87 |                             /** @example pln_123456789 */
 88 |                             id?: string;
 89 |                             /** @example Premium Plan */
 90 |                             name?: string;
 91 |                             /** @example 5000 */
 92 |                             amount?: number;
 93 |                             /** @example monthly */
 94 |                             interval?: string;
 95 |                             /** @example 12 */
 96 |                             duration?: number;
 97 |                             /** @example NGN */
 98 |                             currency?: string;
 99 |                             /** @example active */
100 |                             status?: string;
101 |                             /**
102 |                              * Format: date-time
103 |                              * @example 2023-01-01T00:00:00Z
104 |                              */
105 |                             created_at?: string;
106 |                         }[];
107 |                     };
108 |                 };
109 |             };
110 |         };
111 |     };
112 |     createPlan: {
113 |         parameters: {
114 |             query?: never;
115 |             header?: never;
116 |             path?: never;
117 |             cookie?: never;
118 |         };
119 |         /** @description Plan data for the new subscription plan */
120 |         requestBody?: {
121 |             content: {
122 |                 "application/json": {
123 |                     /** @example Premium Plan */
124 |                     name: string;
125 |                     /** @example 5000 */
126 |                     amount: number;
127 |                     /** @example monthly */
128 |                     interval: string;
129 |                     /** @example 12 */
130 |                     duration: number;
131 |                     /** @example NGN */
132 |                     currency?: string;
133 |                 };
134 |             };
135 |         };
136 |         responses: {
137 |             /** @description Subscription plan created successfully */
138 |             200: {
139 |                 headers: {
140 |                     [name: string]: unknown;
141 |                 };
142 |                 content: {
143 |                     "application/json": {
144 |                         /** @example success */
145 |                         status?: string;
146 |                         /** @example Payment plan created */
147 |                         message?: string;
148 |                         data?: {
149 |                             /** @example pln_123456789 */
150 |                             id?: string;
151 |                             /** @example Premium Plan */
152 |                             name?: string;
153 |                             /** @example 5000 */
154 |                             amount?: number;
155 |                             /** @example monthly */
156 |                             interval?: string;
157 |                             /** @example 12 */
158 |                             duration?: number;
159 |                             /** @example NGN */
160 |                             currency?: string;
161 |                             /** @example active */
162 |                             status?: string;
163 |                             /** @example pln_tok_abcdef123456 */
164 |                             plan_token?: string;
165 |                             /**
166 |                              * Format: date-time
167 |                              * @example 2023-01-01T00:00:00Z
168 |                              */
169 |                             created_at?: string;
170 |                         };
171 |                     };
172 |                 };
173 |             };
174 |         };
175 |     };
176 | }
177 | 
```
--------------------------------------------------------------------------------
/src/client/specs/v3/plan.yaml:
--------------------------------------------------------------------------------
```yaml
  1 | openapi: 3.0.3
  2 | info:
  3 |   title: Flutterwave Transactions API
  4 |   description: API for managing and retrieving transaction details via Flutterwave.
  5 |   version: 1.0.0
  6 | servers:
  7 |   - url: https://api.flutterwave.com/v3
  8 | paths:
  9 |   /plans:
 10 |     post:
 11 |       summary: Create a new subscription plan
 12 |       description: Create a new subscription plan with specified details.
 13 |       operationId: createPlan
 14 |       requestBody:
 15 |         description: Plan data for the new subscription plan
 16 |         content:
 17 |           application/json:
 18 |             schema:
 19 |               type: object
 20 |               properties:
 21 |                 name:
 22 |                   type: string
 23 |                   example: 'Premium Plan'
 24 |                 amount:
 25 |                   type: integer
 26 |                   example: 5000
 27 |                 interval:
 28 |                   type: string
 29 |                   example: 'monthly'
 30 |                 duration:
 31 |                   type: integer
 32 |                   example: 12
 33 |                 currency:
 34 |                   type: string
 35 |                   example: 'NGN'
 36 |               required:
 37 |                 - name
 38 |                 - amount
 39 |                 - interval
 40 |                 - duration
 41 |       responses:
 42 |         '200':
 43 |           description: Subscription plan created successfully
 44 |           content:
 45 |             application/json:
 46 |               schema:
 47 |                 type: object
 48 |                 properties:
 49 |                   status:
 50 |                     type: string
 51 |                     example: 'success'
 52 |                   message:
 53 |                     type: string
 54 |                     example: 'Payment plan created'
 55 |                   data:
 56 |                     type: object
 57 |                     properties:
 58 |                       id:
 59 |                         type: string
 60 |                         example: 'pln_123456789'
 61 |                       name:
 62 |                         type: string
 63 |                         example: 'Premium Plan'
 64 |                       amount:
 65 |                         type: integer
 66 |                         example: 5000
 67 |                       interval:
 68 |                         type: string
 69 |                         example: 'monthly'
 70 |                       duration:
 71 |                         type: integer
 72 |                         example: 12
 73 |                       currency:
 74 |                         type: string
 75 |                         example: 'NGN'
 76 |                       status:
 77 |                         type: string
 78 |                         example: 'active'
 79 |                       plan_token:
 80 |                         type: string
 81 |                         example: 'pln_tok_abcdef123456'
 82 |                       created_at:
 83 |                         type: string
 84 |                         format: date-time
 85 |                         example: '2023-01-01T00:00:00Z'
 86 |     get:
 87 |       summary: Retrieve all subscription plans
 88 |       description: Fetch a list of all subscription plans.
 89 |       operationId: getPlans
 90 |       parameters:
 91 |         - in: query
 92 |           name: page
 93 |           schema:
 94 |             type: integer
 95 |             example: 1
 96 |           description: Page number for pagination
 97 |         - in: query
 98 |           name: amount
 99 |           schema:
100 |             type: integer
101 |             example: 10
102 |           description: This is the exact amount set when creating the payment plan
103 |         - in: query
104 |           name: currency
105 |           schema:
106 |             type: string
107 |             example: 'NGN'
108 |           description: This is the currency used for the payment plan
109 |         - in: query
110 |           name: status
111 |           schema:
112 |             type: string
113 |             example: 'active'
114 |           description: This is the status of the payment plan
115 |         - in: query
116 |           name: interval
117 |           schema:
118 |             type: string
119 |             example: 'monthly'
120 |           description: This is the interval of the payment plan
121 |         - in: query
122 |           name: from
123 |           schema:
124 |             type: string
125 |             example: '2023-01-01'
126 |           description: This is the start date for the payment plan
127 |         - in: query
128 |           name: to
129 |           schema:
130 |             type: string
131 |             example: '2023-12-31'
132 |           description: This is the end date for the payment plan
133 |       responses:
134 |         '200':
135 |           description: A list of subscription plans
136 |           content:
137 |             application/json:
138 |               schema:
139 |                 type: object
140 |                 properties:
141 |                   status:
142 |                     type: string
143 |                     example: 'success'
144 |                   message:
145 |                     type: string
146 |                     example: 'Payment plans fetched'
147 |                   meta:
148 |                     type: object
149 |                     properties:
150 |                       page_info:
151 |                         type: object
152 |                         properties:
153 |                           current_page:
154 |                             type: integer
155 |                             example: 10
156 |                           total_pages:
157 |                             type: integer
158 |                             example: 1 
159 |                   data:
160 |                     type: array
161 |                     items:
162 |                       type: object
163 |                       properties:
164 |                         id:
165 |                           type: string
166 |                           example: 'pln_123456789'
167 |                         name:
168 |                           type: string
169 |                           example: 'Premium Plan'
170 |                         amount:
171 |                           type: integer
172 |                           example: 5000
173 |                         interval:
174 |                           type: string
175 |                           example: 'monthly'
176 |                         duration:
177 |                           type: integer
178 |                           example: 12
179 |                         currency:
180 |                           type: string
181 |                           example: 'NGN'
182 |                         status:
183 |                           type: string
184 |                           example: 'active'
185 |                         created_at:
186 |                           type: string
187 |                           format: date-time
188 |                           example: '2023-01-01T00:00:00Z'
189 | components:
190 |   securitySchemes:
191 |     bearerAuth:
192 |       type: http
193 |       scheme: bearer
194 |       bearerFormat: JWT
```
--------------------------------------------------------------------------------
/src/client/specs/v3/transactions.yaml:
--------------------------------------------------------------------------------
```yaml
  1 | openapi: 3.0.3
  2 | info:
  3 |   title: Flutterwave Transactions API
  4 |   description: API for managing and retrieving transaction details via Flutterwave.
  5 |   version: 1.0.0
  6 | servers:
  7 |   - url: https://api.flutterwave.com/v3
  8 | paths:
  9 |   /payments:
 10 |       post:
 11 |         summary: Process a payment through Flutterwave
 12 |         description: Initiates a payment process through Flutterwave using a unique transaction reference.
 13 |         operationId: createPayment
 14 |         requestBody:
 15 |           description: Payment data for the transaction
 16 |           content:
 17 |             application/json:
 18 |               schema:
 19 |                 type: object
 20 |                 properties:
 21 |                   tx_ref:
 22 |                     type: string
 23 |                     example: 'txnref_djsdkjsnkdjvnsdfj'
 24 |                   amount:
 25 |                     type: string
 26 |                     example: '7500'
 27 |                   currency:
 28 |                     type: string
 29 |                     example: 'NGN'
 30 |                   redirect_url:
 31 |                     type: string
 32 |                     example: 'https://example_company.com/success'
 33 |                   customer:
 34 |                     type: object
 35 |                     properties:
 36 |                       email:
 37 |                         type: string
 38 |                         example: '[email protected]'
 39 |                       name:
 40 |                         type: string
 41 |                         example: 'Flutterwave Developers'
 42 |                       phonenumber:
 43 |                         type: string
 44 |                         example: '09012345678'
 45 |                   customizations:
 46 |                     type: object
 47 |                     properties:
 48 |                       title:
 49 |                         type: string
 50 |                         example: 'Flutterwave Standard Payment'
 51 |                 required:
 52 |                   - tx_ref
 53 |                   - amount
 54 |                   - currency
 55 |                   - redirect_url
 56 |                   - customer
 57 |                   - customizations
 58 |   /transactions/{id}/verify:
 59 |     get:
 60 |       summary: Retrieve transaction details
 61 |       description: Fetch the final status of a transaction using its transaction ID.
 62 |       parameters:
 63 |         - name: id
 64 |           in: path
 65 |           required: true
 66 |           schema:
 67 |             type: string
 68 |           description: The unique transaction ID.
 69 |       responses:
 70 |         "200":
 71 |           description: Successfully retrieved transaction details.
 72 |           content:
 73 |             application/json:
 74 |               schema:
 75 |                 type: object
 76 |                 properties:
 77 |                   status:
 78 |                     type: string
 79 |                     example: success
 80 |                   message:
 81 |                     type: string
 82 |                     example: Transaction fetched successfully
 83 |                   data:
 84 |                     type: object
 85 |                     properties:
 86 |                       id:
 87 |                         type: integer
 88 |                         example: 4975363
 89 |                       tx_ref:
 90 |                         type: string
 91 |                         example: "1710840858755-RND_83"
 92 |                       amount:
 93 |                         type: number
 94 |                         format: float
 95 |                         example: 1000
 96 |                       currency:
 97 |                         type: string
 98 |                         example: NGN
 99 |                       status:
100 |                         type: string
101 |                         example: successful
102 |                       created_at:
103 |                         type: string
104 |                         format: date-time
105 |                         example: "2024-03-19T09:34:27.000Z"
106 |         "400":
107 |           description: Bad request, invalid transaction ID.
108 |           content:
109 |             application/json:
110 |               schema:
111 |                 type: object
112 |                 properties:
113 |                   status:
114 |                     type: string
115 |                     example: error
116 |                   message:
117 |                     type: string
118 |                     example: "Invalid Transaction ID"
119 |                   data:
120 |                     type: object
121 |                     nullable: true
122 |         "404":
123 |           description: Transaction not found.
124 |           content:
125 |             application/json:
126 |               schema:
127 |                 type: object
128 |                 properties:
129 |                   status:
130 |                     type: string
131 |                     example: error
132 |                   message:
133 |                     type: string
134 |                     example: "Transaction not found"
135 |                   data:
136 |                     type: object
137 |                     nullable: true
138 |   /transactions/verify_by_reference:
139 |     get:
140 |       summary: Retrieve transaction details
141 |       description: Fetch the final status of a transaction using its transaction ID.
142 |       parameters:
143 |         - name: tx_ref
144 |           in: query
145 |           required: true
146 |           schema:
147 |             type: string
148 |           description: The unique transaction ID.
149 |       responses:
150 |         "200":
151 |           description: Successfully retrieved transaction details.
152 |           content:
153 |             application/json:
154 |               schema:
155 |                 type: object
156 |                 properties:
157 |                   status:
158 |                     type: string
159 |                     example: success
160 |                   message:
161 |                     type: string
162 |                     example: Transaction fetched successfully
163 |                   data:
164 |                     type: object
165 |                     properties:
166 |                       id:
167 |                         type: integer
168 |                         example: 4975363
169 |                       tx_ref:
170 |                         type: string
171 |                         example: "1710840858755-RND_83"
172 |                       amount:
173 |                         type: number
174 |                         format: float
175 |                         example: 1000
176 |                       currency:
177 |                         type: string
178 |                         example: NGN
179 |                       status:
180 |                         type: string
181 |                         example: successful
182 |                       created_at:
183 |                         type: string
184 |                         format: date-time
185 |                         example: "2024-03-19T09:34:27.000Z"
186 |         "400":
187 |           description: Bad request, invalid transaction ID.
188 |           content:
189 |             application/json:
190 |               schema:
191 |                 type: object
192 |                 properties:
193 |                   status:
194 |                     type: string
195 |                     example: error
196 |                   message:
197 |                     type: string
198 |                     example: "Invalid Transaction ID"
199 |                   data:
200 |                     type: object
201 |                     nullable: true
202 |         "404":
203 |           description: Transaction not found.
204 |           content:
205 |             application/json:
206 |               schema:
207 |                 type: object
208 |                 properties:
209 |                   status:
210 |                     type: string
211 |                     example: error
212 |                   message:
213 |                     type: string
214 |                     example: "Transaction not found"
215 |                   data:
216 |                     type: object
217 |                     nullable: true
218 |   /transactions/{id}/resend-hook:
219 |     post:
220 |       summary: Resend failed webhook
221 |       description: Resend failed webhook
222 |       parameters:
223 |         - name: id
224 |           in: path
225 |           required: true
226 |           schema:
227 |             type: string
228 |           description: The unique transaction ID.
229 |   /transactions/{id}/events:
230 |       post:
231 |         summary: Resend failed webhook.
232 |         description: Resend failed webhook.
233 |         parameters:
234 |           - name: id
235 |             in: path
236 |             required: true
237 |             schema:
238 |               type: string
239 |             description: The unique transaction ID.
240 |       security:
241 |         - bearerAuth: []
242 | components:
243 |   schemas:
244 |     Transaction:
245 |       type: object
246 |   securitySchemes:
247 |     bearerAuth:
248 |       type: http
249 |       scheme: bearer
250 |       bearerFormat: JWT
```
--------------------------------------------------------------------------------
/src/client/types/v3.d.ts:
--------------------------------------------------------------------------------
```typescript
  1 | /**
  2 |  * This file was auto-generated by openapi-typescript.
  3 |  * Do not make direct changes to the file.
  4 |  */
  5 | 
  6 | export interface paths {
  7 |     "/payments": {
  8 |         parameters: {
  9 |             query?: never;
 10 |             header?: never;
 11 |             path?: never;
 12 |             cookie?: never;
 13 |         };
 14 |         get?: never;
 15 |         put?: never;
 16 |         /**
 17 |          * Process a payment through Flutterwave
 18 |          * @description Initiates a payment process through Flutterwave using a unique transaction reference.
 19 |          */
 20 |         post: operations["createPayment"];
 21 |         delete?: never;
 22 |         options?: never;
 23 |         head?: never;
 24 |         patch?: never;
 25 |         trace?: never;
 26 |     };
 27 |     "/transactions/{id}/verify": {
 28 |         parameters: {
 29 |             query?: never;
 30 |             header?: never;
 31 |             path?: never;
 32 |             cookie?: never;
 33 |         };
 34 |         /**
 35 |          * Retrieve transaction details
 36 |          * @description Fetch the final status of a transaction using its transaction ID.
 37 |          */
 38 |         get: {
 39 |             parameters: {
 40 |                 query?: never;
 41 |                 header?: never;
 42 |                 path: {
 43 |                     /** @description The unique transaction ID. */
 44 |                     id: string;
 45 |                 };
 46 |                 cookie?: never;
 47 |             };
 48 |             requestBody?: never;
 49 |             responses: {
 50 |                 /** @description Successfully retrieved transaction details. */
 51 |                 200: {
 52 |                     headers: {
 53 |                         [name: string]: unknown;
 54 |                     };
 55 |                     content: {
 56 |                         "application/json": {
 57 |                             /** @example success */
 58 |                             status?: string;
 59 |                             /** @example Transaction fetched successfully */
 60 |                             message?: string;
 61 |                             data?: {
 62 |                                 /** @example 4975363 */
 63 |                                 id?: number;
 64 |                                 /** @example 1710840858755-RND_83 */
 65 |                                 tx_ref?: string;
 66 |                                 /**
 67 |                                  * Format: float
 68 |                                  * @example 1000
 69 |                                  */
 70 |                                 amount?: number;
 71 |                                 /** @example NGN */
 72 |                                 currency?: string;
 73 |                                 /** @example successful */
 74 |                                 status?: string;
 75 |                                 /**
 76 |                                  * Format: date-time
 77 |                                  * @example 2024-03-19T09:34:27.000Z
 78 |                                  */
 79 |                                 created_at?: string;
 80 |                             };
 81 |                         };
 82 |                     };
 83 |                 };
 84 |                 /** @description Bad request, invalid transaction ID. */
 85 |                 400: {
 86 |                     headers: {
 87 |                         [name: string]: unknown;
 88 |                     };
 89 |                     content: {
 90 |                         "application/json": {
 91 |                             /** @example error */
 92 |                             status?: string;
 93 |                             /** @example Invalid Transaction ID */
 94 |                             message?: string;
 95 |                             data?: Record<string, never> | null;
 96 |                         };
 97 |                     };
 98 |                 };
 99 |                 /** @description Transaction not found. */
100 |                 404: {
101 |                     headers: {
102 |                         [name: string]: unknown;
103 |                     };
104 |                     content: {
105 |                         "application/json": {
106 |                             /** @example error */
107 |                             status?: string;
108 |                             /** @example Transaction not found */
109 |                             message?: string;
110 |                             data?: Record<string, never> | null;
111 |                         };
112 |                     };
113 |                 };
114 |             };
115 |         };
116 |         put?: never;
117 |         post?: never;
118 |         delete?: never;
119 |         options?: never;
120 |         head?: never;
121 |         patch?: never;
122 |         trace?: never;
123 |     };
124 |     "/transactions/verify_by_reference": {
125 |         parameters: {
126 |             query?: never;
127 |             header?: never;
128 |             path?: never;
129 |             cookie?: never;
130 |         };
131 |         /**
132 |          * Retrieve transaction details
133 |          * @description Fetch the final status of a transaction using its transaction ID.
134 |          */
135 |         get: {
136 |             parameters: {
137 |                 query: {
138 |                     /** @description The unique transaction ID. */
139 |                     tx_ref: string;
140 |                 };
141 |                 header?: never;
142 |                 path?: never;
143 |                 cookie?: never;
144 |             };
145 |             requestBody?: never;
146 |             responses: {
147 |                 /** @description Successfully retrieved transaction details. */
148 |                 200: {
149 |                     headers: {
150 |                         [name: string]: unknown;
151 |                     };
152 |                     content: {
153 |                         "application/json": {
154 |                             /** @example success */
155 |                             status?: string;
156 |                             /** @example Transaction fetched successfully */
157 |                             message?: string;
158 |                             data?: {
159 |                                 /** @example 4975363 */
160 |                                 id?: number;
161 |                                 /** @example 1710840858755-RND_83 */
162 |                                 tx_ref?: string;
163 |                                 /**
164 |                                  * Format: float
165 |                                  * @example 1000
166 |                                  */
167 |                                 amount?: number;
168 |                                 /** @example NGN */
169 |                                 currency?: string;
170 |                                 /** @example successful */
171 |                                 status?: string;
172 |                                 /**
173 |                                  * Format: date-time
174 |                                  * @example 2024-03-19T09:34:27.000Z
175 |                                  */
176 |                                 created_at?: string;
177 |                             };
178 |                         };
179 |                     };
180 |                 };
181 |                 /** @description Bad request, invalid transaction ID. */
182 |                 400: {
183 |                     headers: {
184 |                         [name: string]: unknown;
185 |                     };
186 |                     content: {
187 |                         "application/json": {
188 |                             /** @example error */
189 |                             status?: string;
190 |                             /** @example Invalid Transaction ID */
191 |                             message?: string;
192 |                             data?: Record<string, never> | null;
193 |                         };
194 |                     };
195 |                 };
196 |                 /** @description Transaction not found. */
197 |                 404: {
198 |                     headers: {
199 |                         [name: string]: unknown;
200 |                     };
201 |                     content: {
202 |                         "application/json": {
203 |                             /** @example error */
204 |                             status?: string;
205 |                             /** @example Transaction not found */
206 |                             message?: string;
207 |                             data?: Record<string, never> | null;
208 |                         };
209 |                     };
210 |                 };
211 |             };
212 |         };
213 |         put?: never;
214 |         post?: never;
215 |         delete?: never;
216 |         options?: never;
217 |         head?: never;
218 |         patch?: never;
219 |         trace?: never;
220 |     };
221 |     "/transactions/{id}/resend-hook": {
222 |         parameters: {
223 |             query?: never;
224 |             header?: never;
225 |             path?: never;
226 |             cookie?: never;
227 |         };
228 |         get?: never;
229 |         put?: never;
230 |         /**
231 |          * Resend failed webhook
232 |          * @description Resend failed webhook
233 |          */
234 |         post: {
235 |             parameters: {
236 |                 query?: never;
237 |                 header?: never;
238 |                 path: {
239 |                     /** @description The unique transaction ID. */
240 |                     id: string;
241 |                 };
242 |                 cookie?: never;
243 |             };
244 |             requestBody?: never;
245 |             responses: never;
246 |         };
247 |         delete?: never;
248 |         options?: never;
249 |         head?: never;
250 |         patch?: never;
251 |         trace?: never;
252 |     };
253 |     "/transactions/{id}/events": {
254 |         parameters: {
255 |             query?: never;
256 |             header?: never;
257 |             path?: never;
258 |             cookie?: never;
259 |         };
260 |         get?: never;
261 |         put?: never;
262 |         /**
263 |          * Resend failed webhook.
264 |          * @description Resend failed webhook.
265 |          */
266 |         post: {
267 |             parameters: {
268 |                 query?: never;
269 |                 header?: never;
270 |                 path: {
271 |                     /** @description The unique transaction ID. */
272 |                     id: string;
273 |                 };
274 |                 cookie?: never;
275 |             };
276 |             requestBody?: never;
277 |             responses: never;
278 |         };
279 |         delete?: never;
280 |         options?: never;
281 |         head?: never;
282 |         patch?: never;
283 |         trace?: never;
284 |     };
285 | }
286 | export type webhooks = Record<string, never>;
287 | export interface components {
288 |     schemas: {
289 |         Transaction: Record<string, never>;
290 |     };
291 |     responses: never;
292 |     parameters: never;
293 |     requestBodies: never;
294 |     headers: never;
295 |     pathItems: never;
296 | }
297 | export type $defs = Record<string, never>;
298 | export interface operations {
299 |     createPayment: {
300 |         parameters: {
301 |             query?: never;
302 |             header?: never;
303 |             path?: never;
304 |             cookie?: never;
305 |         };
306 |         /** @description Payment data for the transaction */
307 |         requestBody?: {
308 |             content: {
309 |                 "application/json": {
310 |                     /** @example txnref_djsdkjsnkdjvnsdfj */
311 |                     tx_ref: string;
312 |                     /** @example 7500 */
313 |                     amount: string;
314 |                     /** @example NGN */
315 |                     currency: string;
316 |                     /** @example https://example_company.com/success */
317 |                     redirect_url: string;
318 |                     customer: {
319 |                         /** @example [email protected] */
320 |                         email?: string;
321 |                         /** @example Flutterwave Developers */
322 |                         name?: string;
323 |                         /** @example 09012345678 */
324 |                         phonenumber?: string;
325 |                     };
326 |                     customizations: {
327 |                         /** @example Flutterwave Standard Payment */
328 |                         title?: string;
329 |                     };
330 |                 };
331 |             };
332 |         };
333 |         responses: never;
334 |     };
335 | }
336 | 
```
--------------------------------------------------------------------------------
/src/client/types/v3/transactions.d.ts:
--------------------------------------------------------------------------------
```typescript
  1 | /**
  2 |  * This file was auto-generated by openapi-typescript.
  3 |  * Do not make direct changes to the file.
  4 |  */
  5 | 
  6 | export interface paths {
  7 |     "/payments": {
  8 |         parameters: {
  9 |             query?: never;
 10 |             header?: never;
 11 |             path?: never;
 12 |             cookie?: never;
 13 |         };
 14 |         get?: never;
 15 |         put?: never;
 16 |         /**
 17 |          * Process a payment through Flutterwave
 18 |          * @description Initiates a payment process through Flutterwave using a unique transaction reference.
 19 |          */
 20 |         post: operations["createPayment"];
 21 |         delete?: never;
 22 |         options?: never;
 23 |         head?: never;
 24 |         patch?: never;
 25 |         trace?: never;
 26 |     };
 27 |     "/transactions/{id}/verify": {
 28 |         parameters: {
 29 |             query?: never;
 30 |             header?: never;
 31 |             path?: never;
 32 |             cookie?: never;
 33 |         };
 34 |         /**
 35 |          * Retrieve transaction details
 36 |          * @description Fetch the final status of a transaction using its transaction ID.
 37 |          */
 38 |         get: {
 39 |             parameters: {
 40 |                 query?: never;
 41 |                 header?: never;
 42 |                 path: {
 43 |                     /** @description The unique transaction ID. */
 44 |                     id: string;
 45 |                 };
 46 |                 cookie?: never;
 47 |             };
 48 |             requestBody?: never;
 49 |             responses: {
 50 |                 /** @description Successfully retrieved transaction details. */
 51 |                 200: {
 52 |                     headers: {
 53 |                         [name: string]: unknown;
 54 |                     };
 55 |                     content: {
 56 |                         "application/json": {
 57 |                             /** @example success */
 58 |                             status?: string;
 59 |                             /** @example Transaction fetched successfully */
 60 |                             message?: string;
 61 |                             data?: {
 62 |                                 /** @example 4975363 */
 63 |                                 id?: number;
 64 |                                 /** @example 1710840858755-RND_83 */
 65 |                                 tx_ref?: string;
 66 |                                 /**
 67 |                                  * Format: float
 68 |                                  * @example 1000
 69 |                                  */
 70 |                                 amount?: number;
 71 |                                 /** @example NGN */
 72 |                                 currency?: string;
 73 |                                 /** @example successful */
 74 |                                 status?: string;
 75 |                                 /**
 76 |                                  * Format: date-time
 77 |                                  * @example 2024-03-19T09:34:27.000Z
 78 |                                  */
 79 |                                 created_at?: string;
 80 |                             };
 81 |                         };
 82 |                     };
 83 |                 };
 84 |                 /** @description Bad request, invalid transaction ID. */
 85 |                 400: {
 86 |                     headers: {
 87 |                         [name: string]: unknown;
 88 |                     };
 89 |                     content: {
 90 |                         "application/json": {
 91 |                             /** @example error */
 92 |                             status?: string;
 93 |                             /** @example Invalid Transaction ID */
 94 |                             message?: string;
 95 |                             data?: Record<string, never> | null;
 96 |                         };
 97 |                     };
 98 |                 };
 99 |                 /** @description Transaction not found. */
100 |                 404: {
101 |                     headers: {
102 |                         [name: string]: unknown;
103 |                     };
104 |                     content: {
105 |                         "application/json": {
106 |                             /** @example error */
107 |                             status?: string;
108 |                             /** @example Transaction not found */
109 |                             message?: string;
110 |                             data?: Record<string, never> | null;
111 |                         };
112 |                     };
113 |                 };
114 |             };
115 |         };
116 |         put?: never;
117 |         post?: never;
118 |         delete?: never;
119 |         options?: never;
120 |         head?: never;
121 |         patch?: never;
122 |         trace?: never;
123 |     };
124 |     "/transactions/verify_by_reference": {
125 |         parameters: {
126 |             query?: never;
127 |             header?: never;
128 |             path?: never;
129 |             cookie?: never;
130 |         };
131 |         /**
132 |          * Retrieve transaction details
133 |          * @description Fetch the final status of a transaction using its transaction ID.
134 |          */
135 |         get: {
136 |             parameters: {
137 |                 query: {
138 |                     /** @description The unique transaction ID. */
139 |                     tx_ref: string;
140 |                 };
141 |                 header?: never;
142 |                 path?: never;
143 |                 cookie?: never;
144 |             };
145 |             requestBody?: never;
146 |             responses: {
147 |                 /** @description Successfully retrieved transaction details. */
148 |                 200: {
149 |                     headers: {
150 |                         [name: string]: unknown;
151 |                     };
152 |                     content: {
153 |                         "application/json": {
154 |                             /** @example success */
155 |                             status?: string;
156 |                             /** @example Transaction fetched successfully */
157 |                             message?: string;
158 |                             data?: {
159 |                                 /** @example 4975363 */
160 |                                 id?: number;
161 |                                 /** @example 1710840858755-RND_83 */
162 |                                 tx_ref?: string;
163 |                                 /**
164 |                                  * Format: float
165 |                                  * @example 1000
166 |                                  */
167 |                                 amount?: number;
168 |                                 /** @example NGN */
169 |                                 currency?: string;
170 |                                 /** @example successful */
171 |                                 status?: string;
172 |                                 /**
173 |                                  * Format: date-time
174 |                                  * @example 2024-03-19T09:34:27.000Z
175 |                                  */
176 |                                 created_at?: string;
177 |                             };
178 |                         };
179 |                     };
180 |                 };
181 |                 /** @description Bad request, invalid transaction ID. */
182 |                 400: {
183 |                     headers: {
184 |                         [name: string]: unknown;
185 |                     };
186 |                     content: {
187 |                         "application/json": {
188 |                             /** @example error */
189 |                             status?: string;
190 |                             /** @example Invalid Transaction ID */
191 |                             message?: string;
192 |                             data?: Record<string, never> | null;
193 |                         };
194 |                     };
195 |                 };
196 |                 /** @description Transaction not found. */
197 |                 404: {
198 |                     headers: {
199 |                         [name: string]: unknown;
200 |                     };
201 |                     content: {
202 |                         "application/json": {
203 |                             /** @example error */
204 |                             status?: string;
205 |                             /** @example Transaction not found */
206 |                             message?: string;
207 |                             data?: Record<string, never> | null;
208 |                         };
209 |                     };
210 |                 };
211 |             };
212 |         };
213 |         put?: never;
214 |         post?: never;
215 |         delete?: never;
216 |         options?: never;
217 |         head?: never;
218 |         patch?: never;
219 |         trace?: never;
220 |     };
221 |     "/transactions/{id}/resend-hook": {
222 |         parameters: {
223 |             query?: never;
224 |             header?: never;
225 |             path?: never;
226 |             cookie?: never;
227 |         };
228 |         get?: never;
229 |         put?: never;
230 |         /**
231 |          * Resend failed webhook
232 |          * @description Resend failed webhook
233 |          */
234 |         post: {
235 |             parameters: {
236 |                 query?: never;
237 |                 header?: never;
238 |                 path: {
239 |                     /** @description The unique transaction ID. */
240 |                     id: string;
241 |                 };
242 |                 cookie?: never;
243 |             };
244 |             requestBody?: never;
245 |             responses: never;
246 |         };
247 |         delete?: never;
248 |         options?: never;
249 |         head?: never;
250 |         patch?: never;
251 |         trace?: never;
252 |     };
253 |     "/transactions/{id}/events": {
254 |         parameters: {
255 |             query?: never;
256 |             header?: never;
257 |             path?: never;
258 |             cookie?: never;
259 |         };
260 |         get?: never;
261 |         put?: never;
262 |         /**
263 |          * Resend failed webhook.
264 |          * @description Resend failed webhook.
265 |          */
266 |         post: {
267 |             parameters: {
268 |                 query?: never;
269 |                 header?: never;
270 |                 path: {
271 |                     /** @description The unique transaction ID. */
272 |                     id: string;
273 |                 };
274 |                 cookie?: never;
275 |             };
276 |             requestBody?: never;
277 |             responses: never;
278 |         };
279 |         delete?: never;
280 |         options?: never;
281 |         head?: never;
282 |         patch?: never;
283 |         trace?: never;
284 |     };
285 | }
286 | export type webhooks = Record<string, never>;
287 | export interface components {
288 |     schemas: {
289 |         Transaction: Record<string, never>;
290 |     };
291 |     responses: never;
292 |     parameters: never;
293 |     requestBodies: never;
294 |     headers: never;
295 |     pathItems: never;
296 | }
297 | export type $defs = Record<string, never>;
298 | export interface operations {
299 |     createPayment: {
300 |         parameters: {
301 |             query?: never;
302 |             header?: never;
303 |             path?: never;
304 |             cookie?: never;
305 |         };
306 |         /** @description Payment data for the transaction */
307 |         requestBody?: {
308 |             content: {
309 |                 "application/json": {
310 |                     /** @example txnref_djsdkjsnkdjvnsdfj */
311 |                     tx_ref: string;
312 |                     /** @example 7500 */
313 |                     amount: string;
314 |                     /** @example NGN */
315 |                     currency: string;
316 |                     /** @example https://example_company.com/success */
317 |                     redirect_url: string;
318 |                     customer: {
319 |                         /** @example [email protected] */
320 |                         email?: string;
321 |                         /** @example Flutterwave Developers */
322 |                         name?: string;
323 |                         /** @example 09012345678 */
324 |                         phonenumber?: string;
325 |                     };
326 |                     customizations: {
327 |                         /** @example Flutterwave Standard Payment */
328 |                         title?: string;
329 |                     };
330 |                 };
331 |             };
332 |         };
333 |         responses: never;
334 |     };
335 | }
336 | 
```