# Directory Structure
```
├── .eslintrc.json
├── .github
│ └── workflows
│ ├── publish-mcp.yml
│ └── publish.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── scripts
│ └── copy-openapi-json.cjs
├── server.json
├── smithery.yaml
├── src
│ ├── cashien.ts
│ ├── config.readonly.ts
│ ├── config.ts
│ ├── connect.ts
│ ├── index.ts
│ ├── initialize.ts
│ ├── input-source-help.ts
│ ├── openapi
│ │ ├── helpers.ts
│ │ ├── index.ts
│ │ ├── openapi-PG.json
│ │ ├── openapi-PO.json
│ │ ├── openapi-VRS.json
│ │ └── zod.ts
│ ├── search.ts
│ ├── settings.ts
│ ├── types.ts
│ └── utils.ts
├── THIRD_PARTY_LICENSES
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
```json
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": ["plugin:@typescript-eslint/recommended"]
}
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
# These are some examples of commonly ignored file patterns.
# You should customize this list as applicable to your project.
# Learn more about .gitignore:
# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
# Node artifact files
node_modules/
dist/
# Compiled Java class files
*.class
# Compiled Python bytecode
*.py[cod]
# Log files
*.log
# Package files
*.jar
# Maven
target/
dist/
# JetBrains IDE
.idea/
# Unit test reports
TEST*.xml
# Generated by MacOS
.DS_Store
# Generated by Windows
Thumbs.db
# Applications
*.app
*.exe
*.war
# Large media files
*.mp4
*.tiff
*.avi
*.flv
*.mov
*.wmv
# env files
.env.json
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
[](https://mseep.ai/app/cashfree-cashfree-mcp)
# Cashfree MCP Server
Cashfree MCP server allows AI tools and agents to integrate with [Cashfree](https://www.cashfree.com/) APIs (Payment Gateway, Payouts, and SecureID) using the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction).
## Setup
### Clone the Repository
```bash
git clone https://github.com/cashfree/cashfree-mcp.git
cd cashfree-mcp
```
### Install Dependencies
Before installing, ensure you have **Node.js v14.x or higher** installed. If you're using `nvm` or `brew`, make sure the correct version is active:
```bash
node -v
# Should output v14.x or higher
```
#### Step 1: Install project dependencies
```bash
npm install
```
This will install all required packages listed in `package.json`.
> 💡 If you're using `Node.js >=18`, you might face peer dependency issues with packages like `undici`. In that case, upgrade Node.js to `>=20.18.1` or adjust the package version if needed.
#### Step 2: Build the project
```bash
npm run build
```
This compiles the source files to the `dist/` directory, which is required to run the MCP server.
> 🛠️ If you see errors related to missing files in `/dist`, ensure you've run the build step successfully.
## Configuration
You will need a Cashfree account with API credentials (we support both sandbox and production keys). You can use Cashfree MCP in your favorite client, some sample configurations are shown below:
### Claude
Add the following configuration block to your `claude_desktop_config.json`
```json
{
"mcpServers": {
"cashfree": {
"command": "node",
"args": ["/path/to/cashfree-mcp/dist/index.js"],
"env": {
"PAYMENTS_APP_ID": "YOUR_PG_CLIENT_ID",
"PAYMENTS_APP_SECRET": "YOUR_PG_CLIENT_SECRET",
"PAYOUTS_APP_ID": "YOUR_PAYOUTS_CLIENT_ID",
"PAYOUTS_APP_SECRET": "YOUR_PAYOUTS_CLIENT_SECRET",
"TWO_FA_PUBLIC_KEY_PEM_PATH": "/path/to/public_key.pem",
"SECUREID_APP_ID": "YOUR_SECUREID_CLIENT_ID",
"SECUREID_APP_SECRET": "YOUR_SECUREID_CLIENT_SECRET",
"TOOLS": "pg,payouts,secureid",
"ENV": "sandbox",
"ELICITATION_ENABLED": "true"
}
}
}
}
```
### VS Code
Add the following configuration block to your VS Code settings
```json
{
"mcp": {
"inputs": [],
"servers": {
"cashfree": {
"command": "node",
"args": ["/path/to/cashfree-mcp/dist/index.js"],
"env": {
"PAYMENTS_APP_ID": "YOUR_PG_CLIENT_ID",
"PAYMENTS_APP_SECRET": "YOUR_PG_CLIENT_SECRET",
"PAYOUTS_APP_ID": "YOUR_PAYOUTS_CLIENT_ID",
"PAYOUTS_APP_SECRET": "YOUR_PAYOUTS_CLIENT_SECRET",
"TWO_FA_PUBLIC_KEY_PEM_PATH": "/path/to/public_key.pem",
"SECUREID_APP_ID": "YOUR_SECUREID_CLIENT_ID",
"SECUREID_APP_SECRET": "YOUR_SECUREID_CLIENT_SECRET",
"TOOLS": "pg,payouts,secureid",
"ENV": "sandbox",
"ELICITATION_ENABLED": "true"
}
}
}
}
}
```
### API Credentials
Set the following environment variables for each service:
**Payment Gateway:**
- `PAYMENTS_APP_ID`: Your Payment Gateway client ID
- `PAYMENTS_APP_SECRET`: Your Payment Gateway client secret
**Payouts:**
- `PAYOUTS_APP_ID`: Your Payouts client ID
- `PAYOUTS_APP_SECRET`: Your Payouts client secret
- `TWO_FA_PUBLIC_KEY_PEM_PATH`: Path to your 2FA public key (required only if 2FA is enabled)
**SecureID:**
- `SECUREID_APP_ID`: Your SecureID client ID
- `SECUREID_APP_SECRET`: Your SecureID client secret
- `TWO_FA_PUBLIC_KEY_PEM_PATH`: Path to your 2FA public key (required only if 2FA is enabled)
### Environment
`ENV`: Set to `production` for production environment, `sandbox` for sandbox (default: `sandbox`)
### Tools Configuration
`TOOLS`: Comma-separated list of modules to enable. Available options:
- `pg`: Payment Gateway APIs
- `payouts`: Payouts APIs
- `secureid`: SecureID APIs
### Elicitation Configuration
`ELICITATION_ENABLED`: Set to `true` to enable interactive parameter elicitation, `false` to disable (default: `false`)
When enabled, the MCP server will prompt users for missing required parameters instead of failing with validation errors. This provides a more interactive experience by asking users to provide values for required fields that weren't initially supplied.
## Tools
Cashfree MCP has the following tools available, grouped by the product category
### Payment Gateway (PG)
| Tool Name | Description |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| **search** | Search across the Cashfree Payments Developer Documentation. |
| **get-input-source-help** | Get comprehensive instructions for handling input source variable errors. |
| **create-payment-link** | Create a new payment link. |
| **fetch-payment-link-details** | View all details and status of a payment link. |
| **cancel-payment-link** | Cancel an active payment link. No further payments can be done against cancelled links |
| **get-orders-for-a-payment-link** | View all order details for a payment link. |
| **create-order** | Create orders with Cashfree to get a payment_sessions_id for transactions |
| **get-order** | Fetch order details using order_id |
| **get-order-extended** | Get extended order data like address, cart, offers, customer details etc |
| **get-eligible-payment-methods** | Get eligible payment methods for a given order amount and ID |
| **get-payments-for-an-order** | View all payment details for an order. |
| **get-payment-by-id** | View payment details of an order for a Payment ID. |
| **create-refund** | Initiate refunds. |
| **get-all-refunds-for-an-order** | Fetch all refunds processed against an order. |
| **get-refund** | Fetch a specific refund processed on your Cashfree Account. |
| **get-all-settlements** | Get all settlement details by specifying the settlement ID, settlement UTR, or date range. |
| **get-split-and-settlement-details-by-order-id-v2-0** | Get split and settlement details, including settled/unsettled transactions for vendors in an order |
| **get-settlements-by-order-id** | View all the settlements of a particular order. |
| **get-disputes-by-order-id** | Get all dispute details by Order ID |
| **get-disputes-by-payment-id** | Get all dispute details by Payment ID |
| **get-disputes-by-dispute-id** | Get dispute details by Dispute ID |
| **accept-dispute-by-dispute-id** | Accept a dispute by its Dispute ID |
| **submit-evidence-to-contest-the-dispute-by-dispute-id** | Submit evidence to contest a dispute |
| **simulate-payment** | Simulate payment for testing. Requires prior order creation |
| **fetch-simulation** | Fetch simulated payment details |
### Payouts
| Tool Name | Description |
| -------------------------------- | -------------------------------------------------------------------------------- |
| **standard-transfer-v2** | Initiate an amount transfer at Cashfree Payments. |
| **get-transfer-status-v2** | Get the status of an initiated transfer. |
| **batch-transfer-v2** | Initiate a batch transfer request at Cashfree Payments. |
| **get-batch-transfer-status-v2** | Get the status of an initiated batch transfer. |
| **authorize** | Authenticate with the Cashfree system and obtain the authorization bearer token. |
| **create-cashgram** | Create a Cashgram. |
| **deactivate-cashgram** | Deactivate a Cashgram. |
| **get-cashgram-status** | Get the status of a created Cashgram. |
### SecureID
| Tool Name | Description |
| ------------------------------ | ------------------------------------------------- |
| **verify-name-match** | Verify names with variations. |
| **generate-kyc-link** | Generate a verification form for KYC information. |
| **get-kyc-link-status** | Get the status of a KYC verification form. |
| **generate-static-kyc-link** | Generate a static KYC link. |
| **deactivate-static-kyc-link** | Deactivate a static KYC link. |
## License
This project is licensed under the terms of the MIT open source license. Please refer to LICENSE for the full terms.
## Documentation
For detailed API documentation, visit the [Cashfree API Documentation](https://docs.cashfree.com/reference/).
## Support
For support, contact [[email protected]](mailto:[email protected]) or raise an issue in the [GitHub repository](https://github.com/cashfree/cashfree-mcp).
```
--------------------------------------------------------------------------------
/src/settings.ts:
--------------------------------------------------------------------------------
```typescript
export const SERVER_NAME: string = "cashfree-mcp";
export const SERVER_VERSION: string = "1.0.0";
```
--------------------------------------------------------------------------------
/src/config.readonly.ts:
--------------------------------------------------------------------------------
```typescript
// read-only
export const SUBDOMAIN: Readonly<string> = "cashfreepayments-d00050e9";
export const SERVER_URL: Readonly<string> = "https://leaves.mintlify.com";
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/build/project-config
FROM node:lts-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm install --production
# Copy source
COPY . .
# Default command (override via MCP client)
CMD ["node", "src/index.js"]
```
--------------------------------------------------------------------------------
/src/initialize.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Initializes and returns the MCP server instance.
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { SERVER_NAME, SERVER_VERSION } from "./settings.js";
import type { Config } from "./config.js";
export function initialize(config: Config): McpServer {
console.error("Initializing MCP Server...", config);
const server = new McpServer({
name: SERVER_NAME,
version: SERVER_VERSION,
});
return server;
}
```
--------------------------------------------------------------------------------
/scripts/copy-openapi-json.cjs:
--------------------------------------------------------------------------------
```
// Copy all JSON files from src/openapi to dist/openapi after tsc build
// Usage: node scripts/copy-openapi-json.cjs
const fs = require('fs');
const path = require('path');
const srcDir = path.join(__dirname, '../src/openapi');
const distDir = path.join(__dirname, '../dist/openapi');
if (!fs.existsSync(distDir)) {
fs.mkdirSync(distDir, { recursive: true });
}
const files = fs.readdirSync(srcDir);
for (const file of files) {
if (file.endsWith('.json')) {
const srcPath = path.join(srcDir, file);
const destPath = path.join(distDir, file);
fs.copyFileSync(srcPath, destPath);
}
}
```
--------------------------------------------------------------------------------
/src/connect.ts:
--------------------------------------------------------------------------------
```typescript
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
/**
* Connects the given MCP server to standard IO transport.
* Logs server status and handles connection errors gracefully.
*
* @param server - An instance of McpServer to be connected.
*/
export async function connectServer(server: McpServer): Promise<void> {
const transport = new StdioServerTransport();
try {
await server.connect(transport);
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error("Failed to connect MCP Server:", errorMessage);
}
}
```
--------------------------------------------------------------------------------
/.github/workflows/publish-mcp.yml:
--------------------------------------------------------------------------------
```yaml
name: Publish to MCP Registry
on:
push:
tags: ["v*"] # Triggers on version tags like v1.0.0
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Install MCP Publisher
run: |
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
- name: Login to MCP Registry
run: ./mcp-publisher login github-oidc
- name: Publish to MCP Registry
run: ./mcp-publisher publish
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"types": ["node"],
"target": "es2020",
"lib": ["es2020", "es2018", "dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"module": "node16",
"moduleResolution": "node16",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"declaration": true,
"declarationDir": "./dist",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"rootDir": "./src",
"typeRoots": ["./node_modules", "./node_modules/@types", "./src/@types"],
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noEmitOnError": false
},
"include": ["./src/**/*.ts", "./src/*"],
"exclude": ["node_modules", "dist", "coverage", "package.json"]
}
```
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
```typescript
import { PrimitiveSchemaDefinition } from "@modelcontextprotocol/sdk/types.js";
export interface InitializationConfiguration {
name: string;
trieveApiKey: string;
trieveDatasetId: string;
}
export interface SearchResult {
title: string;
content: string;
link: string;
}
export interface Endpoint {
url?: string;
method: string;
path: string;
title?: string;
description?: string;
request: { [key: string]: any };
servers?: Array<{ url: string }> | { [key: string]: any };
operation: {
summary?: string;
description?: string;
tags?: string[];
"x-mcp"?: McpConfiguration;
operationId?: string;
deprecated?: boolean;
security?: any[];
parameters?: any[];
requestBody?: any;
responses?: any;
[key: string]: any;
};
}
export interface McpConfiguration {
enabled: boolean;
config?: {
elicitation?: ElicitationConfiguration;
};
}
// Elicitation configuration for OpenAPI endpoints
export interface ElicitationConfiguration {
enabled: boolean;
fields: Record<string, ElicitationField>;
}
export interface ElicitationField {
required: boolean;
message: string;
schema: PrimitiveSchemaDefinition;
mapping: {
target: string;
transform?: 'string' | 'number' | 'boolean' | 'array';
};
}
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "@cashfreepayments/cashfree-mcp",
"mcpName": "io.github.cashfree/cashfree-mcp",
"version": "1.0.1",
"type": "module",
"description": "Cashfree MCP server for cashfree docs and APIs",
"engines": {
"node": ">=18.0.0"
},
"main": "dist/index.js",
"bin": {
"cashfree-mcp": "dist/index.js"
},
"files": [
"dist/**/*",
"README.md",
"LICENSE",
"THIRD_PARTY_LICENSES"
],
"scripts": {
"start": "npm run build && node dist/index.js",
"dev": "ts-node src/index.ts",
"build": "tsc && node scripts/copy-openapi-json.cjs",
"lint": "echo 'No linting configured'",
"check": "tsc --noEmit"
},
"author": "Cashfree",
"reference": "Mintlify mcp",
"dependencies": {
"@mintlify/openapi-parser": "^0.0.7",
"@mintlify/openapi-types": "^0.0.0",
"@mintlify/validation": "^0.1.320",
"@modelcontextprotocol/sdk": "^1.20.0",
"axios": ">=1.12.0",
"dashify": "^2.0.0",
"js-yaml": "^4.1.0",
"semantic-ui-react": "^2.1.5",
"trieve-ts-sdk": "^0.0.62",
"uuid": "^11.1.0"
},
"devDependencies": {
"@types/dashify": "^1.0.3",
"@types/js-yaml": "^4.0.9",
"@types/node": "^22.18.9",
"@types/react": "^19.1.4",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.1",
"eslint": "^9.27.0",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
}
}
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
#!/usr/bin/env node
/**
* Entry point for Cashfree MCP server.
* Initializes server, loads OpenAPI tools, and starts the server.
*/
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { connectServer } from "./connect.js";
import { initialize } from "./initialize.js";
import { createToolsFromOpenApi } from "./openapi/index.js";
import { createSearchTool } from "./search.js";
import { isMcpEnabled } from "./openapi/helpers.js";
import { readConfig } from "./config.js";
import { createCashienTool } from "./cashien.js";
import { createCFContextInitializerTool } from "./input-source-help.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function main() {
const config = readConfig();
const server = initialize(config);
const existingTools: Set<string> = new Set();
await createSearchTool(server);
await createCashienTool(server);
await createCFContextInitializerTool(server);
// Dynamically load OpenAPI-based tools
const openApiDir = path.join(__dirname, "openapi");
if (!fs.existsSync(openApiDir)) {
throw new Error(`OpenAPI directory not found at path: ${openApiDir}`);
}
const openApiFilePaths = fs
.readdirSync(openApiDir)
.filter((file) => file.startsWith("openapi-") && file.endsWith(".json"))
.filter((file) => isMcpEnabled(file));
await Promise.all(
openApiFilePaths.map(async (openApiPath, index) => {
return createToolsFromOpenApi(
path.join(openApiDir, openApiPath),
index,
server,
existingTools
);
})
);
await connectServer(server);
}
main().catch((error: unknown) => {
console.error("Fatal error in trying to initialize MCP server:", error);
process.exit(1);
});
```
--------------------------------------------------------------------------------
/src/cashien.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Provides the Cashien tool for API integration queries.
* This tool sends user queries to a specified endpoint and returns the response.
*/
import { z } from "zod";
import { formatErr } from "./utils.js";
import { v4 as uuidv4 } from "uuid";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
// Constants
const CASHIEN_API_URL =
"https://receiver.cashfree.com/pgnextgenconsumer/cashien/external/chat/message";
const GENERIC_ERR_MSG =
"Unable to process your request. Please try again after some time.";
// Types
interface CashienPayload {
conversationId: string;
userId: string;
messageId: string;
message: string;
}
interface CashienResponse {
status?: string;
message?: string;
}
// Tool definition
export function createCashienTool(server: McpServer) {
return server.tool(
"cashien",
"Use this tool to write code to integrate Cashfree APIs and SDKs. Supports both backend and frontend.",
{ query: z.string() },
async ({ query }) => {
try {
const response = await sendMessageToChatbot(query);
return {
content: [
{
type: "text",
text: response,
},
],
};
} catch (err) {
console.error("Error in createCashienTool:", err);
throw new Error(formatErr(err));
}
}
);
}
// Chatbot message handler
export async function sendMessageToChatbot(message: string): Promise<string> {
const payload: CashienPayload = {
conversationId: uuidv4(),
userId: uuidv4(),
messageId: uuidv4(),
message,
};
try {
const response = await fetch(`${CASHIEN_API_URL}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const finalResp: CashienResponse = await response.json();
if (finalResp.status === undefined || finalResp.status === "ERROR") {
return GENERIC_ERR_MSG;
}
return finalResp.message ?? GENERIC_ERR_MSG;
} catch (error) {
console.error("Error in sendMessageToChatbot:", error);
return GENERIC_ERR_MSG;
}
}
```
--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------
```yaml
# Smithery configuration file: https://smithery.ai/docs/build/project-config
startCommand:
type: stdio
commandFunction:
# A JS function that produces the CLI command based on the given config to start the MCP on stdio.
|-
(config) => ({ command: 'node', args: ['src/index.js'], env: { PAYMENTS_APP_ID: config.paymentsAppId, PAYMENTS_APP_SECRET: config.paymentsAppSecret, PAYOUTS_APP_ID: config.payoutsAppId, PAYOUTS_APP_SECRET: config.payoutsAppSecret, SECUREID_APP_ID: config.secureidAppId, SECUREID_APP_SECRET: config.secureidAppSecret, TWO_FA_PUBLIC_KEY_PEM_PATH: config.twoFaPublicKeyPemPath, TOOLS: config.tools, ENV: config.env } })
configSchema:
# JSON Schema defining the configuration options for the MCP.
type: object
required:
- paymentsAppId
- paymentsAppSecret
- payoutsAppId
- payoutsAppSecret
- secureidAppId
- secureidAppSecret
- tools
properties:
paymentsAppId:
type: string
description: Client ID for Payment Gateway
paymentsAppSecret:
type: string
description: Client Secret for Payment Gateway
payoutsAppId:
type: string
description: Client ID for Payouts
payoutsAppSecret:
type: string
description: Client Secret for Payouts
secureidAppId:
type: string
description: Client ID for Secure ID
secureidAppSecret:
type: string
description: Client Secret for Secure ID
twoFaPublicKeyPemPath:
type: string
description: Path to 2FA public key PEM file
tools:
type: string
description: Comma-separated list of tools to enable (pg,payouts,secureid)
env:
type: string
default: sandbox
description: "Environment: sandbox or production"
exampleConfig:
paymentsAppId: test_pg_id
paymentsAppSecret: test_pg_secret
payoutsAppId: test_payouts_id
payoutsAppSecret: test_payouts_secret
secureidAppId: test_secureid_id
secureidAppSecret: test_secureid_secret
twoFaPublicKeyPemPath: /path/to/public_key.pem
tools: pg,payouts,secureid
env: sandbox
```
--------------------------------------------------------------------------------
/server.json:
--------------------------------------------------------------------------------
```json
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
"name": "io.github.cashfree/cashfree-mcp",
"description": "Cashfree MCP server for cashfree docs and APIs",
"repository": {
"url": "https://github.com/cashfree/cashfree-mcp",
"source": "github"
},
"version": "1.0.0",
"packages": [
{
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"identifier": "@cashfreepayments/cashfree-mcp",
"version": "1.0.0",
"transport": {
"type": "stdio"
},
"environmentVariables": [
{
"description": "Payment Gateway App Id",
"format": "string",
"isSecret": true,
"name": "PAYMENTS_APP_ID"
},
{
"description": "Payment Gateway App Secret",
"format": "string",
"isSecret": true,
"name": "PAYMENTS_APP_SECRET"
},
{
"description": "Payouts App Id",
"format": "string",
"isSecret": true,
"name": "PAYOUTS_APP_ID"
},
{
"description": "Payouts App Secret",
"format": "string",
"isSecret": true,
"name": "PAYOUTS_APP_SECRET"
},
{
"description": "Path to the PEM file containing the public key for verifying 2FA signatures",
"format": "string",
"isSecret": false,
"name": "TWO_FA_PUBLIC_KEY_PEM_PATH"
},
{
"description": "SecureId App Id",
"format": "string",
"isSecret": true,
"name": "SECUREID_APP_ID"
},
{
"description": "SecureId App Secret",
"format": "string",
"isSecret": true,
"name": "SECUREID_APP_SECRET"
},
{
"description": "Tools (Comma-separated list of modules to enable. Available options: pg, payouts, secureid)",
"format": "string",
"isSecret": false,
"isRequired": true,
"name": "TOOLS"
},
{
"description": "Environment (production/sandbox default: sandbox)",
"format": "string",
"isSecret": false,
"isRequired": true,
"name": "ENV"
}
]
}
]
}
```
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
```typescript
import axios, { AxiosResponse } from "axios";
import { OpenAPI } from "@mintlify/openapi-types";
// A recursive type representing nested objects or strings
export type NestedRecord = string | { [key: string]: NestedRecord };
export type SimpleRecord = Record<string, NestedRecord>;
/**
* Initializes an object along a given path, creating nested objects if needed.
*/
export function initializeObject(
obj: SimpleRecord,
path: string[]
): SimpleRecord {
let current: NestedRecord = obj;
for (const key of path) {
if (!current[key] || typeof current[key] !== "object") {
current[key] = {};
}
current = current[key];
}
return current;
}
/**
* Gets a unique file ID based on spec title and version.
*/
export function getFileId(
spec: OpenAPI.Document,
index: number
): string | number {
var _a;
return ((_a = spec.info) === null || _a === void 0 ? void 0 : _a.title) &&
spec?.info?.version
? `${spec?.info?.title} - ${spec?.info?.version}`
: index;
}
/**
* Throws an error if the Axios response indicates a failure.
*/
export function throwOnAxiosError(
response: AxiosResponse,
errMsg: string
): void {
var _a, _b;
if (response.status !== 200) {
if (
((_a = response.headers["content-type"]) === null || _a === void 0
? void 0
: _a.includes("application/json")) &&
((_b = response.data) === null || _b === void 0 ? void 0 : _b.error)
) {
throw new Error(`${errMsg}: ${response.data.error}`);
} else {
throw new Error(
`${errMsg}: ${response.status} ${response.statusText || ""}`
);
}
}
if (!response.data) {
throw new Error(`${errMsg}: ${response.status} ${response.statusText}`);
}
}
/**
* Formats various types of errors into human-readable strings.
*/
export function formatErr(err: unknown) {
var _a, _b;
if (axios.isAxiosError(err)) {
if (err.message) {
return err.message;
} else if (err.response) {
return (_b =
(_a = err.response.data) === null || _a === void 0
? void 0
: _a.error) !== null && _b !== void 0
? _b
: `${err.response.status} ${err.response.statusText}`;
} else if (err.request) {
return "No response received from server";
} else {
err = "An unknown error occurred";
}
} else if (err instanceof Error) {
return err.message;
} else {
return JSON.stringify(err, undefined, 2);
}
}
```
--------------------------------------------------------------------------------
/src/search.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Provides search functionality for documentation using Trieve.
* Exports functions to fetch search configuration and register the search tool.
*/
import axios, { AxiosResponse } from "axios";
import { TrieveSDK } from "trieve-ts-sdk";
import { z } from "zod";
import { SUBDOMAIN, SERVER_URL } from "./config.readonly.js";
import { formatErr, throwOnAxiosError } from "./utils.js";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { InitializationConfiguration } from "./types.js";
const DEFAULT_BASE_URL = "https://api.mintlifytrieve.com";
/**
* Fetches search configuration and OpenAPI data for a given subdomain.
* @param subdomain - Subdomain to fetch config for.
* @returns The initialization configuration.
*/
export async function fetchSearchConfigurationAndOpenApi(
subdomain: string
): Promise<InitializationConfiguration> {
try {
const response: AxiosResponse<InitializationConfiguration> =
await axios.get(`${SERVER_URL}/api/mcp/config/${subdomain}`, {
validateStatus: () => true,
});
throwOnAxiosError(response, "Failed to fetch MCP config");
return response.data;
} catch (err) {
const friendlyError = formatErr(err).replace(
"Request failed with status code 404",
`${subdomain} not found`
);
throw new Error(friendlyError);
}
}
interface TrieveChunk {
chunk: {
metadata: {
title: string;
};
chunk_html: string;
link: string;
};
}
interface SearchResult {
title: string;
content: string;
link: string;
}
/**
* Queries Trieve and returns formatted search results.
* @param query - The search string.
* @param config - Trieve configuration values.
* @returns Array of search results.
*/
async function search(
query: string,
config: InitializationConfiguration
): Promise<SearchResult[]> {
const trieve = new TrieveSDK({
apiKey: config.trieveApiKey,
datasetId: config.trieveDatasetId,
baseUrl: DEFAULT_BASE_URL,
});
const data = await trieve.autocomplete({
page_size: 10,
query,
search_type: "fulltext",
extend_results: true,
score_threshold: 1,
});
if (!data?.chunks?.length) {
throw new Error("No results found");
}
return data.chunks.map(({ chunk }: TrieveChunk) => ({
title: chunk.metadata.title,
content: chunk.chunk_html,
link: chunk.link,
}));
}
/**
* Registers the "search" tool to the MCP server for querying documentation.
* @param server - The MCP server instance.
*/
export async function createSearchTool(server: McpServer): Promise<void> {
const config = await fetchSearchConfigurationAndOpenApi(SUBDOMAIN);
server.tool(
"search",
`Search across the ${config.name} documentation to fetch relevant context for a given query.`,
{ query: z.string() },
async ({ query }: { query: string }) => {
const results = await search(query, config);
const content = results.map(({ title, content, link }) => ({
type: "text" as const,
text: `Title: ${title}\nContent: ${content}\nLink: ${link}`,
}));
return { content };
}
);
}
```
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Reads and prepares configuration for Cashfree APIs (Payment, Payout, Verification).
* Handles environment-based base URLs and API credentials.
*/
import { getPublicKeyFromPath } from "./openapi/helpers.js";
export interface ApiConfig {
base_url?: string;
header: {
"x-client-id"?: string;
"x-client-secret"?: string;
};
TWO_FA_PUBLIC_KEY?: string;
}
export type Config = Record<
typeof PAYMENT_API_KEY | typeof PAYOUT_API_KEY | typeof VERIFICATION_API_KEY,
ApiConfig
>;
const BASE_URLS = {
sandbox: "https://sandbox.cashfree.com",
production: "https://api.cashfree.com",
};
// API Keys / Identifiers
export const PAYMENT_API_KEY = "Cashfree Payment Gateway APIs - 2025-01-01";
export const PAYOUT_API_KEY = "Cashfree Payout APIs - 2024-01-01";
export const VERIFICATION_API_KEY = "Cashfree Verification API's. - 2023-12-18";
// Default config structure
const DEFAULT_CONFIG: Config = {
[PAYMENT_API_KEY]: {
base_url: `${BASE_URLS.sandbox}/pg`,
header: {},
},
[PAYOUT_API_KEY]: {
base_url: `${BASE_URLS.sandbox}/payout`,
header: {},
},
[VERIFICATION_API_KEY]: {
base_url: `${BASE_URLS.sandbox}/verification`,
header: {},
},
};
export function readConfig(): Config {
const config: Config = JSON.parse(JSON.stringify(DEFAULT_CONFIG));
const isProduction = process.env.ENV === "production";
// Adjust base_url for sandbox vs production
const baseUrl = isProduction ? BASE_URLS.production : BASE_URLS.sandbox;
(
Object.keys(config) as Array<
| typeof PAYMENT_API_KEY
| typeof PAYOUT_API_KEY
| typeof VERIFICATION_API_KEY
>
).forEach((api) => {
config[api].base_url = `${baseUrl}${
config[api].base_url!.split(BASE_URLS.sandbox)[1]
}`;
});
// Helper to configure API credentials
const configureApiCredentials = ({
key,
idVar,
secretVar,
pubKeyVar,
}: {
key:
| typeof PAYMENT_API_KEY
| typeof PAYOUT_API_KEY
| typeof VERIFICATION_API_KEY;
idVar: string;
secretVar: string;
pubKeyVar?: string;
}) => {
const appId = process.env[idVar];
const appSecret = process.env[secretVar];
if (appId && appSecret) {
config[key].header = {
"x-client-id": appId,
"x-client-secret": appSecret,
};
}
if (pubKeyVar && process.env[pubKeyVar]) {
const publicKey = getPublicKeyFromPath(process.env[pubKeyVar]);
if (publicKey !== null && publicKey !== undefined) {
config[key].TWO_FA_PUBLIC_KEY = publicKey;
}
}
};
// Apply credentials for each API
(
[
{
key: PAYMENT_API_KEY,
idVar: "PAYMENTS_APP_ID",
secretVar: "PAYMENTS_APP_SECRET",
},
{
key: PAYOUT_API_KEY,
idVar: "PAYOUTS_APP_ID",
secretVar: "PAYOUTS_APP_SECRET",
pubKeyVar: "TWO_FA_PUBLIC_KEY_PEM_PATH",
},
{
key: VERIFICATION_API_KEY,
idVar: "SECUREID_APP_ID",
secretVar: "SECUREID_APP_SECRET",
pubKeyVar: "TWO_FA_PUBLIC_KEY_PEM_PATH",
},
] as {
key:
| typeof PAYMENT_API_KEY
| typeof PAYOUT_API_KEY
| typeof VERIFICATION_API_KEY;
idVar: string;
secretVar: string;
pubKeyVar?: string;
}[]
).forEach(configureApiCredentials);
return config;
}
```
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
```yaml
name: Publish Package to npm
on:
release:
types: [created]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"
cache: "npm"
- name: Install dependencies
run: npm ci
# No test step required as indicated in package.json
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build package
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: |
src/
package.json
README.md
LICENSE
THIRD_PARTY_LICENSES
publish:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist
path: ./
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"
registry-url: "https://registry.npmjs.org"
scope: "@cashfreepayments"
- name: Publish to npm
run: npm publish --access=public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-github-release:
needs: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"
- name: Get version from package.json
id: get_version
run: echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: Generate changelog
id: changelog
run: |
PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$PREVIOUS_TAG" ]; then
echo "CHANGELOG=$(git log --pretty=format:"- %s (%h)" $(git rev-list --max-parents=0 HEAD)..HEAD)" >> $GITHUB_OUTPUT
else
echo "CHANGELOG=$(git log --pretty=format:"- %s (%h)" $PREVIOUS_TAG..HEAD)" >> $GITHUB_OUTPUT
fi
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.get_version.outputs.VERSION }}
name: Release v${{ steps.get_version.outputs.VERSION }}
body: |
## Changes
${{ steps.changelog.outputs.CHANGELOG }}
## Installation
```
npm install @cashfreepayments/cashfree-mcp
```
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
--------------------------------------------------------------------------------
/src/input-source-help.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Provides help and instructions for input source variable errors.
* This tool can be called when there are issues with inputVariableSource parameters.
*/
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
/**
* Returns detailed instructions for handling input source variable errors.
* @returns Comprehensive help text for troubleshooting input source variables.
*/
function getToolUsageHelpInstructions(): string {
return `
# Input Source Mapping Guide
The **\`inputVariableSource\`** object specifies the origin of each input field in an API call.
It ensures transparency about where every value in the request body comes from.
---
## Structure
The structure of **\`inputVariableSource\`** must **exactly mirror** the request body.
Each field in the body must have a corresponding entry with its source type.
\`\`\`json
{
"inputVariableSource": {
"body": {
"field_name": "source_type",
"nested_object": {
"nested_field": "source_type"
}
}
}
}
\`\`\`
---
## Valid Source Types
- **"user_input"** — Value directly provided by the user
- **"generated_by_model"** — Value automatically generated by the model
- **"inferred_from_context"** — Value derived from previous context or data
---
## Common Errors & Fixes
| Issue | Example | Fix |
|-------|----------|-----|
| **Missing mapping** | \`inputVariableSource\` absent | Add the full mapping structure |
| **Incomplete mapping** | Some fields missing | Map every field in the body |
| **Invalid source type** | Unknown label used | Use only the 3 valid types |
| **Structure mismatch** | Structure differs from body | Ensure identical nesting |
---
## Example
\`\`\`json
{
"body": {
"order_id": "ORDER_123",
"amount": 1000,
"currency": "INR",
"customer_details": {
"customer_name": "John Doe",
"customer_email": "[email protected]"
}
},
"inputVariableSource": {
"body": {
"order_id": "user_input",
"amount": "user_input",
"currency": "generated_by_model",
"customer_details": {
"customer_name": "user_input",
"customer_email": "user_input"
}
}
}
}
\`\`\`
---
## Best Practices
1. **Always include \`inputVariableSource\`** — It is mandatory.
2. **Mirror body structure** — Nested keys must align exactly.
3. **Use correct types** — Only the three valid source types are accepted.
4. **Handle arrays carefully** — Map the array field as a whole, not its elements.
5. **Validate before sending** — Run a JSON structure check if in doubt.
---
## Troubleshooting
- **Validation failed:** Missing or mismatched fields → recheck structure
- **Unexpected type:** Ensure all values are valid source strings
- **Mapping missing:** Verify every body field has a mapped source
- **Nested mismatch:** Align nested objects one-to-one with request body
If issues persist, refer to the API endpoint documentation for any field-specific requirements.
`;
}
/**
* Registers the "get-input-source-help" tool to the MCP server.
* This tool provides comprehensive instructions for handling input source variable errors.
* @param server - The MCP server instance.
*/
export async function createCFContextInitializerTool(server: McpServer): Promise<void> {
server.tool(
"cashfree_context_initializer",
"This is the FIRST tool that must be called before using ANY other Cashfree MCP tool or generating Cashfree-related outputs. It initializes full context for the Cashfree ecosystem — including schemas, APIs, plugin behaviors, transformation logic, and usage conventions. Always invoke this tool before any reasoning, generation, or validation, so the model can load complete domain knowledge and ensure consistent, accurate responses across all Cashfree tools.",
{} as const,
async () => {
const instructions = getToolUsageHelpInstructions();
return {
content: [
{
type: "text" as const,
text: instructions,
},
],
};
}
);
}
```
--------------------------------------------------------------------------------
/src/openapi/zod.ts:
--------------------------------------------------------------------------------
```typescript
import { Blob } from "node:buffer";
import { z, ZodTypeAny } from "zod";
type Schema =
| {
type?: string;
required?: boolean;
enum?: any;
properties?: Record<string, Schema | Schema[]>;
requiredProperties?: string[];
items?: Schema | Schema[];
format?: string;
minimum?: number;
maximum?: number;
exclusiveMinimum?: boolean;
exclusiveMaximum?: boolean;
minLength?: any;
maxLength?: any;
pattern?: any;
minItems?: number;
maxItems?: number;
default?: unknown;
}
| Record<string, unknown>;
function panic(error: unknown): never {
throw error;
}
// WebFile polyfill implementation (based on fetch-blob)
class WebFile extends Blob {
private _name: string;
private _lastModified: number;
// Add webkitRelativePath to match File interface
public webkitRelativePath: string = "";
constructor(
init: (Blob | ArrayBuffer)[],
name: string = panic(
new TypeError("File constructor requires name argument")
),
options: FilePropertyBag = {}
) {
if (arguments.length < 2) {
throw new TypeError(
`Failed to construct 'File': 2 arguments required, but only ${arguments.length} present.`
);
}
super(init, options);
this._lastModified = 0;
this._name = "";
// Simulate WebIDL type casting for NaN value in lastModified option.
const lastModified =
options.lastModified === undefined
? Date.now()
: Number(options.lastModified);
if (!Number.isNaN(lastModified)) {
this._lastModified = lastModified;
}
this._name = String(name);
}
get name(): string {
return this._name;
}
get lastModified(): number {
return this._lastModified;
}
get [Symbol.toStringTag](): string {
return "File";
}
static [Symbol.hasInstance](object: unknown): boolean {
return (
!!object &&
object instanceof Blob &&
/^(File)$/.test(String((object as any)[Symbol.toStringTag]))
);
}
}
const File = typeof global.File === "undefined" ? WebFile : global.File;
const ANY = z.any();
const ANY_OPT = ANY.optional();
const BOOLEAN = z.boolean();
const BOOLEAN_OPT = BOOLEAN.optional();
const DATE = z.coerce.date();
const DATE_OPT = DATE.optional();
const FILE = z.instanceof(File);
const FILE_OPT = FILE.optional();
const NULL = z.null();
const NULL_OPT = NULL.optional();
const RECORD = z.record(z.any());
const RECORD_WITH_DEFAULT = RECORD.default({});
const RECORD_OPT = RECORD.optional();
const STRING = z.string();
const NUMBER = z.number();
const INTEGER = z.number().int();
export function dataSchemaArrayToZod(schemas: any) {
const firstSchema = dataSchemaToZod(schemas[0]);
if (!schemas[1]) {
return firstSchema;
}
const secondSchema = dataSchemaToZod(schemas[1]);
const zodSchemas: any = [firstSchema, secondSchema];
for (const schema of schemas.slice(2)) {
zodSchemas.push(dataSchemaToZod(schema));
}
return z.union(zodSchemas);
}
function getEnumSchema(enumList: any, type: string): ZodTypeAny {
const zodSchema = z.enum(enumList.map(String));
if (type === "string") return zodSchema;
return zodSchema.transform(Number);
}
export function dataSchemaToZod(schema: Schema): ZodTypeAny {
if (!("type" in schema) || Object.keys(schema).length === 0) {
return schema.required ? ANY : ANY_OPT;
}
switch (schema.type) {
case "null":
return schema.required ? NULL : NULL_OPT;
case "boolean":
return schema.required ? BOOLEAN : BOOLEAN_OPT;
case "enum<string>":
const strEnumSchema = getEnumSchema(schema.enum, "string");
return schema.required ? strEnumSchema : strEnumSchema.optional();
case "enum<number>":
case "enum<integer>":
const numEnumSchema = getEnumSchema(schema.enum, "number");
return schema.required ? numEnumSchema : numEnumSchema.optional();
case "file":
return schema.required ? FILE : FILE_OPT;
case "any":
return schema.required ? ANY : ANY_OPT;
case "string":
if ("enum" in schema && Array.isArray(schema.enum)) {
return schema.required
? z.enum((schema as any).enum)
: z.enum((schema as any).enum).optional();
}
if (schema.format === "binary") {
return schema.required ? FILE : FILE_OPT;
}
let stringSchema = STRING;
if (schema.minLength !== undefined) {
stringSchema = stringSchema.min(schema.minLength);
}
if (schema.maxLength !== undefined) {
stringSchema = stringSchema.max(schema.maxLength);
}
if (schema.pattern !== undefined) {
stringSchema = stringSchema.regex(new RegExp(schema.pattern));
}
switch (schema.format) {
case "email":
stringSchema = stringSchema.email();
break;
case "uri":
case "url":
stringSchema = stringSchema.url();
break;
case "uuid":
stringSchema = stringSchema.uuid();
break;
case "date-time":
return schema.required ? DATE : DATE_OPT;
}
if ("default" in schema) {
return schema.required
? stringSchema.default(schema.default as any)
: stringSchema.optional().default(schema.default as any);
}
return schema.required ? stringSchema : stringSchema.optional();
case "number":
case "integer":
if ("enum" in schema && Array.isArray(schema.enum)) {
const numEnumSchema = getEnumSchema(schema.enum, schema.type);
return schema.required ? numEnumSchema : numEnumSchema.optional();
}
let numberSchema = schema.type === "integer" ? INTEGER : NUMBER;
if (typeof schema.minimum === "number") {
numberSchema = numberSchema.min(schema.minimum);
}
if (typeof schema.maximum === "number") {
numberSchema = numberSchema.max(schema.maximum);
}
if (
schema.exclusiveMinimum !== undefined &&
typeof schema.minimum === "number"
) {
numberSchema = numberSchema.gt(schema.minimum);
}
if (
schema.exclusiveMaximum !== undefined &&
typeof schema.maximum === "number"
) {
numberSchema = numberSchema.lt(schema.maximum);
}
return schema.required ? numberSchema : numberSchema.optional();
case "array":
let itemSchema;
let arraySchema: any = z.any().array();
if (Array.isArray(schema.items)) {
itemSchema = dataSchemaArrayToZod(schema.items);
if (schema.items.length > 1) {
arraySchema = itemSchema;
} else {
arraySchema = itemSchema.array();
}
} else {
itemSchema = dataSchemaToZod(schema.items as any);
arraySchema = itemSchema.array();
}
if (schema.minItems !== undefined) {
arraySchema = arraySchema.min(schema.minItems);
}
if (schema.maxItems !== undefined) {
arraySchema = arraySchema.max(schema.maxItems);
}
return schema.required ? arraySchema : arraySchema.optional();
case "object":
const shape: Record<string, ZodTypeAny> = {};
// Handle both 'required' and 'requiredProperties' for compatibility
const requiredProperties = schema.requiredProperties || (schema as any).required;
const requiredPropertiesSet = new Set(
Array.isArray(requiredProperties) ? requiredProperties : []
);
// Special handling for the case where properties are arrays with individual required flags
const properties = schema.properties as any;
for (const [key, propSchema] of Object.entries(properties)) {
let zodPropSchema: ZodTypeAny;
let isRequired = false;
if (Array.isArray(propSchema)) {
// Handle array-wrapped schemas (from OpenAPI conversion)
zodPropSchema = dataSchemaArrayToZod(propSchema);
// Check if any schema in the array has required: true
isRequired = propSchema.some((s: any) => s.required === true);
} else {
zodPropSchema = dataSchemaToZod(propSchema as Schema);
isRequired = (propSchema as any).required === true;
}
// Check if property is in the required list OR has individual required flag
const shouldBeRequired = requiredPropertiesSet.has(key) || isRequired;
shape[key] = shouldBeRequired ? zodPropSchema : zodPropSchema.optional();
}
if (Object.keys(shape).length === 0) {
return schema.required ? RECORD_WITH_DEFAULT : RECORD_OPT;
}
return schema.required ? z.object(shape) : z.object(shape).optional();
default:
return ANY;
}
}
```
--------------------------------------------------------------------------------
/src/openapi/index.ts:
--------------------------------------------------------------------------------
```typescript
import { validate } from "@mintlify/openapi-parser";
import axios, { isAxiosError } from "axios";
import dashify from "dashify";
import fs from "fs";
import { getFileId } from "../utils.js";
import { Endpoint } from "../types.js";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import {
convertEndpointToCategorizedZod,
convertStrToTitle,
findNextIteration,
getEndpointsFromOpenApi,
loadEnv,
getValFromNestedJson,
generateCfSignature,
getElicitationConfig,
hasElicitationEnabled,
getElicitationRequestFields,
createElicitationRequest,
applyFieldMappings,
validateElicitationResponse,
} from "./helpers.js";
async function triggerElicitationFlow(
inputArgs: Record<string, any>,
endpoint: Endpoint,
server: McpServer
): Promise<Record<string, any>> {
const inputVariableSource = inputArgs.inputVariableSource || {};
// Check if elicitation is globally enabled and endpoint-specific configuration
if (!hasElicitationEnabled(endpoint)) {
return inputArgs;
}
const elicitationConfig = getElicitationConfig(endpoint);
if (!elicitationConfig) {
console.error(`No elicitation config found for endpoint: ${endpoint.title}`);
return inputArgs;
}
// Create empty elicitation request first
const elicitationRequest = createElicitationRequest(endpoint.title || endpoint.path, [], elicitationConfig);
// Get missing fields
const { missingFields } = getElicitationRequestFields(
elicitationConfig,
inputArgs,
inputVariableSource,
elicitationRequest
);
if (missingFields.length === 0) {
return inputArgs;
}
// Trigger MCP elicitation
const elicitationResult = await server.server.elicitInput(elicitationRequest.params);
if (elicitationResult?.action !== "accept" || !elicitationResult?.content) {
throw new Error(`Operation cancelled. Required information was not provided.`);
}
// Validate response
const validationResult = validateElicitationResponse(elicitationConfig, elicitationResult.content);
if (!validationResult.valid) {
throw new Error(`Validation errors: ${validationResult.errors.join(', ')}`);
}
// Merge mapped fields with original input args
const mappedArgs = applyFieldMappings(elicitationConfig, elicitationResult.content, inputArgs);
return mappedArgs;
}
export async function createToolsFromOpenApi(
openApiPath: string,
index: number,
server: McpServer,
existingTools: Set<string>
): Promise<void> {
let openapi: string;
try {
openapi = fs.readFileSync(openApiPath, "utf8");
} catch (error) {
return; // Skip if no file
}
const { valid, errors, specification } = await validate(openapi);
if (!valid || !specification || !specification.paths) {
console.error("Invalid OpenAPI file or missing paths:", errors);
return;
}
const endpoints = getEndpointsFromOpenApi(specification);
const endpointId = String(getFileId(specification, index));
const envVars = loadEnv(endpointId);
endpoints.forEach((endpoint: Endpoint) => {
const {
url: urlSchema,
method: methodSchema,
paths: pathsSchema,
queries: queriesSchema,
body: bodySchema,
headers: headersSchema,
cookies: cookiesSchema,
metadata: metadataSchema,
} = convertEndpointToCategorizedZod(endpointId, endpoint);
const serverArgumentsSchemas = Object.assign(
Object.assign(
Object.assign(
Object.assign(
Object.assign(Object.assign({}, pathsSchema), queriesSchema),
bodySchema
),
headersSchema
),
cookiesSchema
),
metadataSchema
);
if (!endpoint.title) {
endpoint.title = `${endpoint.method} ${convertStrToTitle(endpoint.path)}`;
}
if (existingTools.has(endpoint.title)) {
const lastCount = findNextIteration(existingTools, endpoint.title);
endpoint.title = `${endpoint.title}---${lastCount}`;
}
if (endpoint.title.length > 64) {
endpoint.title = endpoint.title.slice(0, -64);
}
existingTools.add(endpoint.title);
server.tool(
dashify(endpoint.title),
endpoint.description || endpoint.title,
serverArgumentsSchemas,
async (inputArgs: Record<string, any>) => {
try {
// Apply elicitation flow if enabled
inputArgs = await triggerElicitationFlow(inputArgs, endpoint, server);
} catch (error) {
console.error("Elicitation error:", error);
}
const inputParams: Record<string, any> = {};
const inputHeaders: Record<string, any> = {};
const inputCookies: Record<string, any> = {};
let urlWithPathParams = urlSchema;
let inputBody: any = undefined;
if ("body" in inputArgs) {
inputBody = inputArgs.body;
delete inputArgs.body;
}
Object.entries(inputArgs).forEach(([key, value]) => {
if (key in pathsSchema) {
urlWithPathParams = urlWithPathParams.replace(`{${key}}`, value);
} else if (key in queriesSchema) {
inputParams[key] = value;
} else if (key in headersSchema) {
inputHeaders[key] = value;
} else if (key in cookiesSchema) {
inputCookies[key] = value;
}
});
if (endpoint.request.security.length > 0) {
const securityParams = endpoint.request?.security?.[0]?.parameters;
if (securityParams?.header) {
Object.entries(securityParams.header).forEach(([key, value]) => {
let envKey = "";
if (
typeof value === "object" &&
value !== null &&
"type" in value
) {
const v = value as { type: string; scheme?: string };
if (v.type === "apiKey") {
envKey = `header.${key}.API_KEY`;
} else if (v.type === "http") {
envKey = `header.${key}.HTTP.${v.scheme}`;
if (v.scheme === "bearer" && envKey in envVars) {
inputHeaders["Authorization"] = `Bearer ${envVars[envKey]}`;
return;
}
}
const envValue = getValFromNestedJson(envKey, envVars);
if (envKey && envValue) {
inputHeaders[key] = envValue;
}
}
});
Object.entries(securityParams.header).forEach(([key]) => {
const headerValue = envVars.header?.[key];
if (headerValue) {
inputHeaders[key] = headerValue;
}
});
}
}
if (openApiPath.includes("PO") || openApiPath.includes("VRS")) {
const clientId =
typeof envVars.header?.["x-client-id"] === "string"
? envVars.header["x-client-id"]
: "";
const publicKey =
typeof envVars.TWO_FA_PUBLIC_KEY === "string"
? envVars.TWO_FA_PUBLIC_KEY
: "";
inputHeaders["x-cf-signature"] = generateCfSignature(
clientId,
publicKey
);
}
const requestConfig = {
method: methodSchema,
url: urlWithPathParams,
params: inputParams,
data: inputBody,
headers: inputHeaders,
};
try {
const response = await axios(requestConfig);
// Stringify the response data
let responseData = JSON.stringify(response.data, undefined, 2);
responseData = responseData.replace(
/("beneficiary_instrument_details"\s*:\s*)(\[[^\]]*\]|\{[^\}]*\})/gs,
'$1"[MASKED]"'
);
return {
content: [
{
type: "text",
text: responseData,
},
],
};
} catch (error) {
if (
typeof error === "object" &&
error !== null &&
"config" in error &&
typeof (error as any).config === "object" &&
(error as any).config !== null &&
"headers" in (error as any).config
) {
const errConfig = (error as any).config;
["x-client-id", "x-client-secret", "Authorization"].forEach(
(header) => {
if (errConfig.headers && errConfig.headers[header]) {
errConfig.headers[header] = "[MASKED]";
}
}
);
}
const errMsg = JSON.stringify(error, undefined, 2);
const data = JSON.stringify(
isAxiosError(error) && error.response ? error.response.data : {},
undefined,
2
);
return {
isError: true,
content: [
{
type: "text",
text: isAxiosError(error)
? `receivedPayload: ${data}\n\n errorMessage: ${error.message}\n\n${errMsg}`
: `receivedPayload: ${data}\n\n errorMessage: ${errMsg}`,
},
],
};
}
}
);
});
}
```
--------------------------------------------------------------------------------
/src/openapi/helpers.ts:
--------------------------------------------------------------------------------
```typescript
import { OpenApiToEndpointConverter } from "@mintlify/validation";
import { z } from "zod";
import { dataSchemaArrayToZod, dataSchemaToZod } from "./zod.js";
import { readConfig } from "../config.js";
import {
Endpoint,
ElicitationConfiguration,
} from "../types.js";
import {
ElicitRequest,
PrimitiveSchemaDefinition,
StringSchema,
NumberSchema
} from "@modelcontextprotocol/sdk/types.js";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import crypto from "crypto";
import fs from "fs";
export type CategorizedZod = {
url: string;
method: string;
paths: Record<string, z.ZodTypeAny>;
queries: Record<string, z.ZodTypeAny>;
headers: Record<string, z.ZodTypeAny>;
cookies: Record<string, z.ZodTypeAny>;
body?: { body: z.ZodTypeAny };
metadata?: Record<string, any>;
};
type RefCache = { [key: string]: any };
type Specification = {
paths: {
[path: string]: {
[method: string]: any;
};
};
};
export type NestedRecord =
| string
| {
[key: string]: NestedRecord;
};
export type SimpleRecord = Record<string, { [x: string]: undefined }>;
export function convertStrToTitle(str: string): string {
const spacedString = str.replace(/[-_]/g, " ");
const words = spacedString.split(/(?=[A-Z])|\s+/);
return words
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(" ");
}
export function findNextIteration(set: Set<string>, str: string): number {
let count = 1;
set.forEach((val) => {
if (val.startsWith(`${str}---`)) {
count = Number(val.replace(`${str}---`, ""));
}
});
return count + 1;
}
function resolveReferences(
spec: Record<string, any>,
refPath: string,
cache: Record<string, any> = {}
): any {
if (cache[refPath]) return cache[refPath];
if (!refPath.startsWith("#/"))
throw new Error(`External references not supported: ${refPath}`);
const pathParts = refPath.substring(2).split("/");
let current: any = spec;
for (const part of pathParts) {
if (!current[part]) throw new Error(`Reference not found: ${refPath}`);
current = current[part];
}
if (current && current.$ref) {
current = resolveReferences(spec, current.$ref, cache);
}
cache[refPath] = current;
return current;
}
function resolveAllReferences(
obj: any,
spec: Specification,
cache: RefCache
): any {
if (obj && obj.$ref) {
const resolved = resolveReferences(spec, obj.$ref, cache);
return resolveAllReferences({ ...resolved }, spec, cache);
}
if (typeof obj !== "object" || obj === null) {
return obj;
}
const result: { [key: string]: any } = Array.isArray(obj) ? [] : {};
for (const [key, value] of Object.entries(obj)) {
result[key] = resolveAllReferences(value, spec, cache);
}
return result;
}
export function getEndpointsFromOpenApi(specification: any): Endpoint[] {
const endpoints: Endpoint[] = [];
const paths = specification.paths;
const refCache: RefCache = {};
for (const path in paths) {
const operations = paths[path];
for (const method in operations) {
if (method === "parameters" || method === "trace") continue;
try {
const resolvedPathItem = resolveAllReferences(
operations[method],
specification,
refCache
);
if (!isMcpEnabledEndpoint(resolvedPathItem)) continue;
const rawEndpoint = OpenApiToEndpointConverter.convert(
{
...specification,
paths: { [path]: { [method]: resolvedPathItem } },
} as any,
path,
method as any
);
// Convert to our Endpoint type and ensure x-mcp configuration is preserved
const endpoint: Endpoint = {
...rawEndpoint,
operation: {
...resolvedPathItem,
"x-mcp": resolvedPathItem["x-mcp"]
}
};
endpoints.push(endpoint);
} catch (error: any) {
console.error(
`Error processing endpoint ${method.toUpperCase()} ${path}:`,
error.message
);
}
}
}
return endpoints;
}
export function loadEnv(key: string): SimpleRecord {
try {
const config: any = readConfig();
return config[key] || {};
} catch (error) {
if (error instanceof SyntaxError) throw error;
return {};
}
}
// Zod schema conversion helpers
function convertParameterSection(parameters: any, paramSection: any) {
if (parameters) {
Object.entries(parameters).forEach(([key, value]: any) => {
paramSection[key] = dataSchemaArrayToZod(value.schema);
});
}
}
function convertParametersAndAddToRelevantParamGroups(
parameters: any,
paths: any,
queries: any,
headers: any,
cookies: any
) {
convertParameterSection(parameters?.path, paths);
convertParameterSection(parameters?.query, queries);
convertParameterSection(parameters?.header, headers);
convertParameterSection(parameters?.cookie, cookies);
}
function convertSecurityParameterSection(
securityParameters: ArrayLike<unknown> | { [s: string]: unknown },
securityParamSection: { [x: string]: z.ZodString },
envVariables: { [x: string]: { [x: string]: undefined } },
location: string
) {
Object.entries(securityParameters).forEach(([key]) => {
if (envVariables[location][key] === undefined) {
securityParamSection[key] = z.string();
}
});
}
function convertSecurityParametersAndAddToRelevantParamGroups(
securityParameters: {
query: ArrayLike<unknown> | { [s: string]: unknown };
header: ArrayLike<unknown> | { [s: string]: unknown };
cookie: ArrayLike<unknown> | { [s: string]: unknown };
},
queries: { [x: string]: z.ZodString },
headers: { [x: string]: z.ZodString },
cookies: { [x: string]: z.ZodString },
envVariables: SimpleRecord
) {
convertSecurityParameterSection(
securityParameters.query,
queries,
envVariables,
"query"
);
convertSecurityParameterSection(
securityParameters.header,
headers,
envVariables,
"header"
);
convertSecurityParameterSection(
securityParameters.cookie,
cookies,
envVariables,
"cookie"
);
}
export function convertEndpointToCategorizedZod(
envKey: string,
endpoint: Endpoint
): CategorizedZod {
const envVariables = loadEnv(envKey);
const baseUrl =
envVariables.base_url ||
(Array.isArray(endpoint?.servers) ? endpoint.servers[0]?.url : undefined) ||
"";
const url = `${baseUrl}${endpoint.path}`;
const method = endpoint.method;
const paths: Record<string, any> = {};
const queries: Record<string, any> = {};
const headers: Record<string, any> = {};
const cookies: Record<string, any> = {};
let body: any | undefined = undefined;
convertParametersAndAddToRelevantParamGroups(
endpoint?.request?.parameters,
paths,
queries,
headers,
cookies
);
const securityParams = endpoint?.request?.security?.[0]?.parameters;
if (securityParams) {
convertSecurityParametersAndAddToRelevantParamGroups(
securityParams,
queries,
headers,
cookies,
envVariables
);
}
const jsonBodySchema = endpoint?.request?.body?.["application/json"];
const bodySchema = jsonBodySchema?.schemaArray?.[0];
if (bodySchema) {
let zodBodySchema = dataSchemaToZod(bodySchema);
// If endpoint has elicitation config, make fields optional
// Client capability check will happen at runtime
if (hasElicitationEnabled(endpoint)) {
zodBodySchema = makeElicitationFieldsOptional(zodBodySchema, endpoint);
}
body = { body: zodBodySchema };
}
const metadata = generateMetadataSchema();
// console.error("Generated metadata schema: ", JSON.stringify(metadata));
return {
url,
method,
paths,
queries,
body,
headers,
cookies,
metadata,
};
}
const SourceEnum = z.enum([
"user_input",
"generated_by_model",
"inferred_from_context"
]);
/**
* Recursive schema that allows nested metadata objects.
* Each key maps either to a source string or another nested object
* following the same structure.
*/
const RecursiveSourceSchema: z.ZodTypeAny = z.lazy(() =>
z.record(
z.union([SourceEnum, RecursiveSourceSchema])
).describe("Nested object mapping each field to its source (recursively)")
);
/**
* Generates metadata schema that mirrors input structure.
* Tracks sources for input fields (e.g. body, headers, query, path),
* allowing arbitrary nesting and unknown keys.
*/
export function generateMetadataSchema() {
const InputVariableSourceSchema = z.object({
body: RecursiveSourceSchema.describe(
"Mirrors the input body object, tracking sources for all nested fields"
)
}).describe("Tracks the source of input parameters (body, headers, query, path)");
return { inputVariableSource: InputVariableSourceSchema};
}
export function getValFromNestedJson(key: string, jsonObj: SimpleRecord): any {
if (!key || !jsonObj) return;
return jsonObj[key];
}
export function isMcpEnabled(path: string): boolean {
const product = path.split(".json")[0].split("-")[1];
const tools = process.env.TOOLS
? process.env.TOOLS.toLowerCase().split(",")
: [];
switch (product) {
case "PG":
return tools.includes("pg");
case "PO":
return tools.includes("payouts");
case "VRS":
return tools.includes("secureid");
default:
return false;
}
}
export function isMcpEnabledEndpoint(endpointSpec: Endpoint): boolean {
const mcp = (endpointSpec as any)["x-mcp"];
return mcp?.["enabled"] === true;
}
/**
* Generate a signature by encrypting the client ID and current UNIX timestamp using RSA encryption.
* @param {string} clientId - The client ID to be used in the signature.
* @param {string} publicKey - The RSA public key for encryption.
* @returns {string} - The generated signature.
*/
export function generateCfSignature(clientId: string, publicKey: string) {
try {
const timestamp = Math.floor(Date.now() / 1000); // Current UNIX timestamp
const data = `${clientId}.${timestamp}`;
const buffer = Buffer.from(data, "utf8");
const encrypted = crypto.publicEncrypt(publicKey, buffer);
return encrypted.toString("base64");
} catch (error) {
if (error instanceof Error) {
console.error(`Error generating signature: ${error.message}`);
} else {
console.error("Error generating signature: Unknown error");
}
}
}
/**
* Retrieve the public key from a given file path.
* @param {string} path - The file path to the public key.
* @returns {string} - The public key as a string.
* @throws {Error} - If the file cannot be read.
*/
export function getPublicKeyFromPath(path: string): string | null {
try {
return fs.readFileSync(path, "utf8");
} catch (error) {
console.error(
`Warning: Failed to read public key from path: ${
error instanceof Error ? error.message : "Unknown error"
}`
);
return null;
}
}
/**
* Check if elicitation should be used for this endpoint
* Returns true only if:
* 1. Global elicitation is enabled via ELICITATION_ENABLED environment variable
* 2. Endpoint has elicitation configuration
* 3. Endpoint has elicitation enabled
* Client support will be checked at runtime during execution
*/
export function shouldUseElicitation(endpoint: Endpoint): boolean {
return hasElicitationEnabled(endpoint);
}
/**
* Check if client supports elicitation by attempting to use it
* This is a runtime check that will be done during tool execution
*/
export async function checkElicitationSupport(_server: McpServer): Promise<boolean> {
try {
// Try a simple elicitation request to check if client supports it
// If it fails, the client doesn't support elicitation
return true; // For now, assume supported - actual check happens during execution
} catch (error) {
return false;
}
}
/**
* Make fields that have elicitation configuration optional in the Zod schema
* This allows elicitation to fill in missing required fields
*/
export function makeElicitationFieldsOptional(zodSchema: z.ZodTypeAny, endpoint: Endpoint): z.ZodTypeAny {
// Check if elicitation is globally enabled first
if (!hasElicitationEnabled(endpoint)) {
return zodSchema;
}
const elicitationConfig = getElicitationConfig(endpoint);
if (!elicitationConfig || !zodSchema) {
return zodSchema;
}
// Get the list of field paths that should be made optional (those configured for elicitation)
const elicitationFieldPaths = Object.entries(elicitationConfig.fields).map(([fieldName, fieldConfig]) => {
// Use the target path from mapping, or fall back to field name
const targetPath = fieldConfig.mapping?.target || fieldName;
// For body fields, remove the 'body.' prefix if present
return targetPath.startsWith('body.') ? targetPath.substring(5) : targetPath;
});
return makeFieldsOptionalAtPaths(zodSchema, elicitationFieldPaths);
}
/**
* Recursively make fields optional at specified paths in a Zod schema
*/
function makeFieldsOptionalAtPaths(zodSchema: z.ZodTypeAny, fieldPaths: string[]): z.ZodTypeAny {
if (!(zodSchema instanceof z.ZodObject)) {
return zodSchema;
}
const shape = zodSchema.shape;
const newShape: Record<string, z.ZodTypeAny> = {};
// Process each field in the schema
for (const [key, value] of Object.entries(shape)) {
// Check if this field should be made optional (exact match)
const shouldMakeOptional = fieldPaths.includes(key);
// Check for nested paths that start with this key
const nestedPaths = fieldPaths
.filter(path => path.startsWith(`${key}.`))
.map(path => path.substring(key.length + 1)); // Remove the key and dot prefix
if (shouldMakeOptional) {
// Make this field optional since it can be provided via elicitation
newShape[key] = makeFieldOptional(value as z.ZodTypeAny);
} else if (nestedPaths.length > 0 && value instanceof z.ZodObject) {
// Recursively process nested objects for nested field paths
newShape[key] = makeFieldsOptionalAtPaths(value, nestedPaths);
} else if (value instanceof z.ZodObject) {
// Process nested objects even if no specific paths match (for deeper nesting)
newShape[key] = makeFieldsOptionalAtPaths(value, fieldPaths);
} else {
// Keep the field as is
newShape[key] = value as z.ZodTypeAny;
}
}
return z.object(newShape);
}
/**
* Helper function to make a Zod field optional
*/
function makeFieldOptional(zodType: z.ZodTypeAny): z.ZodTypeAny {
// If it's already optional, return as is
if (zodType instanceof z.ZodOptional) {
return zodType;
}
// Make the field optional
return zodType.optional();
}
/**
* Extract elicitation configuration from an endpoint's x-mcp section
*/
export function getElicitationConfig(endpoint: Endpoint): ElicitationConfiguration | null {
// Try multiple locations for x-mcp configuration
const mcpConfig = endpoint.operation?.["x-mcp"] || (endpoint as any)["x-mcp"];
if (!mcpConfig || !mcpConfig.config?.elicitation) {
return null;
}
return mcpConfig.config.elicitation;
}
/**
* Check if an endpoint has elicitation enabled
* Now checks both global environment variable and endpoint-specific configuration
*/
export function hasElicitationEnabled(endpoint: Endpoint): boolean {
// First check if elicitation is globally enabled via environment variable
if (process.env.ELICITATION_ENABLED?.toLowerCase() !== 'true') {
return false;
}
// Then check endpoint-specific configuration
const config = getElicitationConfig(endpoint);
return config !== null && config.enabled && Object.keys(config.fields || {}).length > 0;
}
/**
* Identify missing required fields for elicitation
*/
export function getElicitationRequestFields(
elicitationConfig: ElicitationConfiguration,
providedArgs: Record<string, any>,
inputVariableSource: Record<string, any>,
elicitationRequest: any
): { missingFields: string[]; defaults: Record<string, any> } {
const missingFields: string[] = [];
const defaults: Record<string, any> = {};
const getValueFromInputVariableSource = (path: string): any => {
if (!inputVariableSource) return undefined;
const parts = path.split('.');
let current: any = inputVariableSource;
for (const part of parts) {
if (!current) return undefined;
current = current[part];
}
return current;
};
Object.entries(elicitationConfig.fields).forEach(([fieldName, fieldConfig]) => {
const targetPath = fieldConfig.mapping?.target || fieldName;
// For body fields, get the path relative to the body
const bodyRelativePath = targetPath.startsWith('body.') ? targetPath.substring(5) : targetPath;
// Check if value exists in provided args at the target path
const valueFromArgs = hasValueAtPath(providedArgs, targetPath)
? getValueAtPath(providedArgs, targetPath)
: hasValueAtPath(providedArgs, bodyRelativePath)
? getValueAtPath(providedArgs, bodyRelativePath)
: providedArgs[fieldName];
// Check input variable source using the full target path
const valueFromInputVariableSource = getValueFromInputVariableSource(targetPath);
// Use input variable source value as default if available
let defaultValue = valueFromArgs ?? (valueFromInputVariableSource && valueFromInputVariableSource !== 'generated_by_model' ? valueFromInputVariableSource : undefined);
if (valueFromInputVariableSource === 'generated_by_model') {
// Treat generated_by_model as default but still ask if required
defaultValue = valueFromArgs ?? undefined;
}
// Determine if we need to ask
const isMissing = fieldConfig.required && (valueFromArgs === undefined || valueFromArgs === '');
const isGeneratedByModel = valueFromInputVariableSource === 'generated_by_model';
if (isMissing || isGeneratedByModel) {
missingFields.push(fieldName);
// Only add to elicitation request schema if field is actually missing
if (!elicitationRequest.params.requestedSchema.properties[fieldName]) {
elicitationRequest.params.requestedSchema.properties[fieldName] = fieldConfig.schema;
}
// Set default value if available
if (defaultValue !== undefined) {
defaults[fieldName] = defaultValue;
elicitationRequest.params.requestedSchema.properties[fieldName].default = defaultValue;
}
}
});
return { missingFields, defaults};
};
// Helper to get value at path
function getValueAtPath(obj: any, path: string) {
return path.split('.').reduce((acc, key) => (acc ? acc[key] : undefined), obj);
}
/**
* Check if a value exists at a given path in an object
*/
function hasValueAtPath(obj: any, path: string): boolean {
const parts = path.split('.');
let current = obj;
for (const part of parts) {
if (current === null || current === undefined || !(part in current)) {
return false;
}
current = current[part];
}
return current !== null && current !== undefined && current !== '';
}
/**
* Create an elicitation request for missing fields
*/
export function createElicitationRequest(
toolName: string,
missingFieldNames: string[],
elicitationConfig: ElicitationConfiguration,
message?: string
): ElicitRequest {
const properties: Record<string, PrimitiveSchemaDefinition> = {};
const required: string[] = [];
for (const fieldName of missingFieldNames) {
const fieldConfig = elicitationConfig.fields[fieldName];
if (fieldConfig) {
properties[fieldName] = fieldConfig.schema;
if (fieldConfig.required) {
required.push(fieldName);
}
}
}
return {
method: "elicitation/create",
params: {
message: message || `Please provide the required parameters for ${toolName}:`,
requestedSchema: {
type: "object",
properties,
...(required.length > 0 && { required })
}
}
};
}/**
* Apply field mappings to elicitation response values
*/
export function applyFieldMappings(
elicitationConfig: ElicitationConfiguration,
elicitationResponse: Record<string, any>,
originalArgs: Record<string, any>
): Record<string, any> {
const mappedArgs = { ...originalArgs };
Object.entries(elicitationResponse).forEach(([fieldName, value]) => {
const fieldConfig = elicitationConfig.fields[fieldName];
if (fieldConfig && fieldConfig.mapping) {
const mapping = fieldConfig.mapping;
setValueAtPath(mappedArgs, mapping.target, value, mapping.transform);
} else {
// Check if any field in the config matches this field name
const matchingConfigField = Object.entries(elicitationConfig.fields).find(
([configFieldName]) => configFieldName === fieldName || configFieldName.split('.').pop() === fieldName
);
if (matchingConfigField) {
const [, configField] = matchingConfigField;
if (configField && configField.mapping) {
setValueAtPath(mappedArgs, configField.mapping.target, value, configField.mapping.transform);
}
} else {
// If no mapping exists, use the field name directly
mappedArgs[fieldName] = value;
}
}
});
return mappedArgs;
}
/**
* Set a value at a given path in an object
*/
function setValueAtPath(obj: any, path: string, value: any, transformation?: string): void {
const parts = path.split('.');
let current = obj;
// Navigate to the parent of the target
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
if (!(part in current) || current[part] === null || current[part] === undefined) {
current[part] = {};
}
current = current[part];
}
// Apply transformation if specified
let transformedValue = value;
if (transformation) {
transformedValue = applyTransformation(value, transformation);
}
// Set the final value
const finalPart = parts[parts.length - 1];
current[finalPart] = transformedValue;
}
/**
* Apply transformation to a value
*/
function applyTransformation(value: any, transformation: string): any {
switch (transformation) {
case 'number':
return Number(value);
case 'boolean':
return Boolean(value);
case 'string':
return String(value);
case 'array':
return Array.isArray(value) ? value : [value];
default:
return value;
}
}
/**
* Validate elicitation response against validation schema
*/
export function validateElicitationResponse(
elicitationConfig: ElicitationConfiguration,
response: Record<string, any>
): { valid: boolean; errors: string[] } {
const errors: string[] = [];
Object.entries(response).forEach(([fieldName, value]) => {
const fieldConfig = elicitationConfig.fields[fieldName];
if (fieldConfig && fieldConfig.schema) {
const schema = fieldConfig.schema;
// Simple validation based on schema type
if (schema.type === 'string') {
const stringSchema = schema as StringSchema & { pattern?: string; enum?: string[] };
if (stringSchema.pattern && typeof value === 'string' && typeof stringSchema.pattern === 'string') {
const regex = new RegExp(stringSchema.pattern);
if (!regex.test(value)) {
errors.push(`Field ${fieldName} does not match required pattern`);
}
}
if (typeof value === 'string') {
if (stringSchema.minLength && value.length < stringSchema.minLength) {
errors.push(`Field ${fieldName} is too short (minimum ${stringSchema.minLength} characters)`);
}
if (stringSchema.maxLength && value.length > stringSchema.maxLength) {
errors.push(`Field ${fieldName} is too long (maximum ${stringSchema.maxLength} characters)`);
}
}
if (stringSchema.enum && Array.isArray(stringSchema.enum) && !stringSchema.enum.includes(value)) {
errors.push(`Field ${fieldName} must be one of: ${stringSchema.enum.join(', ')}`);
}
}
if (schema.type === 'number' || schema.type === 'integer') {
const numberSchema = schema as NumberSchema;
if (typeof value === 'number') {
if (numberSchema.minimum !== undefined && value < numberSchema.minimum) {
errors.push(`Field ${fieldName} is too small (minimum ${numberSchema.minimum})`);
}
if (numberSchema.maximum !== undefined && value > numberSchema.maximum) {
errors.push(`Field ${fieldName} is too large (maximum ${numberSchema.maximum})`);
}
}
}
}
});
return {
valid: errors.length === 0,
errors
};
}
```
--------------------------------------------------------------------------------
/src/openapi/openapi-PO.json:
--------------------------------------------------------------------------------
```json
{
"openapi": "3.0.0",
"info": {
"version": "2024-01-01",
"title": "Cashfree Payout APIs",
"license": {
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"contact": {
"email": "[email protected]",
"name": "API Support",
"url": "https://discord.com/invite/QdZkNSxXsB"
},
"description": "Cashfree's Payout APIs provide developers with a streamlined pathway to integrate advanced payout capabilities into their applications, platforms and websites."
},
"externalDocs": {
"url": "https://api.cashfree.com/payout",
"description": "This url will have the information of all the APIs."
},
"servers": [
{
"url": "https://sandbox.cashfree.com/payout",
"description": "Sandbox server"
},
{
"url": "https://api.cashfree.com/payout",
"description": "Production server"
}
],
"tags": [
{
"name": "V2 Apis",
"description": "Collection of APIs to transfer funds to beneficiaries and manage beneficiaries."
}
],
"components": {
"securitySchemes": {
"XClientID": {
"type": "apiKey",
"in": "header",
"name": "x-client-id",
"description": "Client ID. You can find your app id in the [Merchant Dashboard](https://merchant.cashfree.com/payouts/developers/api-keys)."
},
"XClientSecret": {
"type": "apiKey",
"in": "header",
"name": "x-client-secret",
"description": "Client secret key. You can find your secret in the [Merchant Dashboard](https://merchant.cashfree.com/payouts/developers/api-keys)."
}
},
"schemas": {
"ErrorV2": {
"title": "Error",
"description": "Error Response for non-2XX cases",
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Type of the error received"
},
"code": {
"type": "string",
"description": "Code of the error received"
},
"message": {
"type": "string",
"description": "Detailed message explaining the response"
}
}
},
"Beneficiary": {
"title": "Create Beneficiary success response",
"description": "Contains the information of the created beneficiary",
"type": "object",
"properties": {
"beneficiary_id": {
"example": "JOHN18011343",
"type": "string",
"description": "It displays the unique Id you created to identify the beneficiary."
},
"beneficiary_name": {
"example": "John Doe",
"type": "string",
"description": "It displays the name of the beneficiary."
},
"beneficiary_instrument_details": {
"type": "object",
"description": "It displays the payment instrument details of the beneficiary.",
"properties": {
"bank_account_number": {
"example": "00111122233",
"type": "string",
"description": "It displays the bank account of the beneficiary."
},
"bank_ifsc": {
"example": "HDFC0000001",
"type": "string",
"description": "It displays the IFSC information of the beneficiary's bank account."
},
"vpa": {
"example": "test@upi",
"type": "string",
"description": "It displays the UPI VPA information of the beneficiary."
}
}
},
"beneficiary_contact_details": {
"type": "object",
"description": "It displays the contact details of the beneficiary.",
"properties": {
"beneficiary_email": {
"example": "[email protected]",
"type": "string",
"description": "It displays the email address of the beneficiary."
},
"beneficiary_phone": {
"example": "9876543210",
"type": "string",
"description": "It displays the phone number of the beneficiary without the country code."
},
"beneficiary_country_code": {
"example": "+91",
"type": "string",
"description": "It displays the country code of the beneficiary's phone number."
},
"beneficiary_address": {
"example": "177A Bleecker Street",
"type": "string",
"description": "It displays the address of the beneficiary."
},
"beneficiary_city": {
"example": "New York City",
"type": "string",
"description": "It displays the name of the city as present in the beneficiary's address."
},
"beneficiary_state": {
"example": "New York",
"type": "string",
"description": "It displays the name of the state as present in the beneficiary's address."
},
"beneficiary_postal_code": {
"example": "560001",
"type": "string",
"description": "It displays the PIN code as present in the beneficiary's address."
}
}
},
"beneficiary_status": {
"example": "VERIFIED",
"type": "string",
"enum": [
"VERIFIED",
"INVALID",
"INITIATED",
"CANCELLED",
"FAILED",
"DELETED"
],
"description": "It displays the current status of the beneficiary. Possible values are as follows\n- `VERIFIED`: Beneficiary is verified and is available for payouts\n- `INVALID`: Beneficiary is invalid\n- `INITIATED`: Beneficiary verification initiated\n- `CANCELLED`: Beneficiary verification cancelled\n- `FAILED`: Failed to verify beneficiary\n- `DELETED`: Beneficiary is deleted"
},
"added_on": {
"example": "2023-11-22T12:38:22Z",
"type": "string",
"description": "It displays the time of the addition of the beneficiary in UTC."
}
}
},
"CreateBeneficiaryRequest": {
"title": "Create Beneficiary request body",
"description": "Find the request parameters to create a beneficiary",
"type": "object",
"required": [
"beneficiary_id",
"beneficiary_name"
],
"properties": {
"beneficiary_id": {
"example": "JOHN18011343",
"type": "string",
"maxLength": 50,
"description": "It is the unique ID you create to identify the beneficiary. Alphanumeric, underscore ( _ ), pipe ( | ), and dot ( . ) are allowed."
},
"beneficiary_name": {
"example": "John Doe",
"type": "string",
"description": "It is the name of the beneficiary. The maximum character limit is 100. Only alphabets and whitespaces are allowed.",
"maxLength": 100
},
"beneficiary_instrument_details": {
"type": "object",
"description": "Beneficiary instrument details",
"properties": {
"bank_account_number": {
"example": "00111122233",
"type": "string",
"maxLength": 25,
"minLength": 4,
"description": "It is the beneficiary bank account number. The value should be between 9 and 18 characters. Alphanumeric characters are allowed. You need to input bank_ifsc if bank_account_number is passed."
},
"bank_ifsc": {
"example": "HDFC0000001",
"type": "string",
"description": "It is the IFSC information of the beneficiary's bank account in the standard IFSC format. The value should be 11 characters. (The first 4 characters should be alphabets, the 5th character should be a 0, and the remaining 6 characters should be numerals.). You need to input bank_account_number if bank_ifsc is passed."
},
"vpa": {
"example": "test@upi",
"type": "string",
"description": "It is the UPI VPA information of the beneficiary. Only valid UPI VPA information is accepted. It can be an Alphanumeric value with only period (.), hyphen (-), underscore ( _ ), and at the rate of (@). Hyphen (-) is accepted only before at the rate of (@)."
}
}
},
"beneficiary_contact_details": {
"type": "object",
"description": "It should contain the contact details of the beneficiary.",
"properties": {
"beneficiary_email": {
"example": "[email protected]",
"type": "string",
"maxLength": 200,
"description": "It is the email address of the beneficiary. The maximum character limit is 200. It should contain dot (.) and at the rate of (@)."
},
"beneficiary_phone": {
"example": "9876543210",
"type": "string",
"description": "It is the phone number of the beneficiary. Only reigstered Indian phone numbers are allowed. The value should be between 8 and 12 characters after stripping +91."
},
"beneficiary_country_code": {
"example": "+91",
"type": "string",
"description": "It is the country code (+91) of the beneficiary's phone number"
},
"beneficiary_address": {
"example": "177A Bleecker Street",
"type": "string",
"description": "It is the address information of the beneficiary."
},
"beneficiary_city": {
"example": "New York City",
"type": "string",
"description": "It is the name of the city as present in the beneficiary's address."
},
"beneficiary_state": {
"example": "New York",
"type": "string",
"description": "It is the name of the state as present in the beneficiary's address."
},
"beneficiary_postal_code": {
"example": "560001",
"type": "string",
"description": "It is the PIN code information as present in the beneficiary's address. The maximum character limit is 6. Only numbers are allowed."
}
}
}
}
},
"CreateTransferRequest": {
"title": "Standard Transfer V2",
"description": "Standard Transfer V2",
"type": "object",
"properties": {
"transfer_id": {
"type": "string",
"description": "It is the unique ID you create to identify the transfer. You can use a maximum of 40 characters to create a transfer_id. Alphanumeric and underscore ( _ ) are allowed.",
"maxLength": 40
},
"transfer_amount": {
"type": "number",
"format": "double",
"description": "It is the transfer amount. Decimal values are allowed. The minimum value should be equal to or greater than 1.00. (>= 1.00)"
},
"transfer_currency": {
"type": "string",
"description": "It is the currency of the transfer amount. The default value is INR."
},
"transfer_mode": {
"type": "string",
"description": "It is the mode of transfer. Allowed values are banktransfer, imps, neft, rtgs, upi, paytm, amazonpay, card. The default transfer_mode is banktransfer.",
"enum": [
"banktransfer",
"imps",
"neft",
"rtgs",
"upi",
"paytm",
"amazonpay",
"card",
"cardupi"
],
"maxLength": 20
},
"beneficiary_details": {
"type": "object",
"description": "It should contain the details of the beneficiary who receives the transfer amount.",
"properties": {
"beneficiary_id": {
"type": "string",
"description": "It is the unique ID you created to identify the beneficiary. Alphanumeric characters are allowed."
},
"beneficiary_name": {
"type": "string",
"description": "It is the name of the beneficiary. The maximum character limit is 100. Only alphabets and whitespaces are allowed. It is required if beneficiary_id is not present."
},
"beneficiary_instrument_details": {
"type": "object",
"description": "It should contain the details of where the beneficiary will receive the money. You input these details if you haven't added the beneficiary in the Payouts dashboard.",
"properties": {
"bank_account_number": {
"type": "string",
"description": "It is the beneficiary bank account number. The value should be between 9 and 18 characters. Alphanumeric characters are allowed. This value is required if beneficiary_id is not present and if the transfer_mode is banktransfer, imps, neft,rtgs mode."
},
"bank_ifsc": {
"type": "string",
"description": "It is the IFSC information of the beneficiary's bank account in the standard IFSC format. The value should be 11 characters. (The first 4 characters should be alphabets, the 5th character should be a 0, and the remaining 6 characters should be numerals.)"
},
"vpa": {
"type": "string",
"description": "It is the UPI VPA information of the beneficiary. Only valid UPI VPA information is accepted. It can be an Alphanumeric value with only period (.), hyphen (-), underscore ( _ ), and at the rate of (@). Hyphen (-) is accepted only before at the rate of (@). This value is required if the transfer_mode is upi."
},
"card_details": {
"type": "object",
"description": "It should contain the card details of the beneficiary.",
"properties": {
"card_token": {
"type": "string",
"description": "It is the tokenised card number or card token for this transfer."
},
"card_network_type": {
"type": "string",
"description": "It is the network type of the card - VISA/MASTERCARD.",
"enum": [
"VISA",
"MASTERCARD"
]
},
"card_cryptogram": {
"type": "string",
"description": "It is the formatted chip/cryptogram data relating to the token cryptogram. The maximum character limit is 600. It is optional for MASTERCARD and not required for VISA."
},
"card_token_expiry": {
"type": "string",
"description": "It is applicable only for MASTERCARD. The format for the valid token expiry date should be YYYY-MM. It cannot be null. Provide a valid tokenExpiry if collected from the customers. If unavailable, populate a static value with a forward year and month in the correct format (YYYY-MM). The maximum character limit is 10."
},
"card_type": {
"type": "string",
"description": "It is the type of the card. DEBIT and CREDIT are the only values allowed. The default value is CREDIT if the parameter does not exist or not specified."
},
"card_token_PAN_sequence_number": {
"type": "string",
"description": "A maximum of 3 alphanumeric characters are allowed. It is an optional parameter for MASTERCARD."
}
}
}
}
},
"beneficiary_contact_details": {
"type": "object",
"description": "It should contain the contact details of the beneficiary.",
"properties": {
"beneficiary_email": {
"type": "string",
"description": "It is the email address of the beneficiary. The maximum character limit is 200. It should contain dot (.) and at the rate of (@)."
},
"beneficiary_phone": {
"type": "string",
"description": "It is the phone number of the beneficiary. Only registered Indian phone numbers are allowed. The value should be between 8 and 12 characters after stripping +91."
},
"beneficiary_country_code": {
"type": "string",
"description": "It is the country code (+91) of the beneficiary's phone number."
},
"beneficiary_address": {
"type": "string",
"description": "It should contain the address of the beneficiary. The maximum character limit is 150. Alphanumeric characters and whitespaces are allowed."
},
"beneficiary_city": {
"type": "string",
"description": "It is the name of the city as present in the beneficiary address. The maximum character limit is 50. Alphanumeric characters and whitespaces are allowed."
},
"beneficiary_state": {
"type": "string",
"description": "It is the name of the state as present in the beneficiary address. The maximum character limit is 50. Alphanumeric characters and whitespaces are allowed."
},
"beneficiary_postal_code": {
"type": "string",
"description": "It is the PIN code as present in the address. It should be a 6 character numeric value."
}
}
}
}
},
"transfer_remarks": {
"type": "string",
"description": "It can contain any additional remarks for the transfer. Alphanumeric and whitespaces are allowed. The maximum character limit is 70.",
"maxLength": 70
},
"fundsource_id": {
"type": "string",
"description": "It is the ID of the fund source from which the transfer amount will be debited."
}
},
"required": [
"transfer_amount",
"transfer_id",
"beneficiary_details"
]
},
"CreateBatchTransferRequest": {
"title": "Batch Transfer V2",
"description": "Batch Transfer V2",
"type": "object",
"properties": {
"batch_transfer_id": {
"type": "string",
"description": "It is the unique ID you create to identify the batch transfer request. The maximum character limit is 60. Alphanumeric and underscore ( _ ) characters are allowed.",
"maxLength": 60
},
"transfers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"transfer_id": {
"type": "string",
"description": "It is the unique ID you create to identify the transfer. You can use a maximum of 40 characters to create a transfer_id. Alphanumeric and underscore ( _ ) are allowed.",
"maxLength": 40
},
"transfer_amount": {
"type": "number",
"format": "double",
"description": "It is the transfer amount. Decimal values are allowed. The minimum value should be equal to or greater than 1.00. (>= 1.00)"
},
"transfer_currency": {
"type": "string",
"description": "It is the currency of the transfer amount. The default value is INR."
},
"transfer_mode": {
"type": "string",
"description": "It is the mode of transfer. Allowed values are banktransfer, imps, neft, rtgs, upi, paytm, amazonpay, card. The default transfer_mode is banktransfer.",
"enum": [
"banktransfer",
"imps",
"neft",
"rtgs",
"upi",
"paytm",
"amazonpay",
"card",
"cardupi"
],
"maxLength": 20
},
"beneficiary_details": {
"type": "object",
"description": "It should contain the details of the beneficiary who receives the transfer amount.",
"properties": {
"beneficiary_id": {
"type": "string",
"description": "It is the unique ID you created to identify the beneficiary. Alphanumeric characters are allowed."
},
"beneficiary_name": {
"type": "string",
"description": "It is the name of the beneficiary. The maximum character limit is 100."
},
"beneficiary_instrument_details": {
"type": "object",
"description": "It should contain the details of where the beneficiary will receive the money. You input these details if you haven't added the beneficiary in the Payouts dashboard.",
"properties": {
"bank_account_number": {
"type": "string",
"description": "It is the beneficiary bank account number. The value should be between 9 and 18 characters. Alphanumeric characters are allowed. This value is required if beneficiary_id is not present and if the transfer_mode is banktransfer, imps, neft, rtgs mode."
},
"bank_ifsc": {
"type": "string",
"description": "It is the IFSC information of the beneficiary's bank account in the standard IFSC format. The value should be 11 characters. (The first 4 characters should be alphabets, the 5th character should be a 0, and the remaining 6 characters should be numerals.)"
},
"vpa": {
"type": "string",
"description": "It is the UPI VPA information of the beneficiary. Only valid UPI VPA information is accepted. It can be an Alphanumeric value with only period (.), hyphen (-), underscore ( _ ), and at the rate of (@). Hyphen (-) is accepted only before at the rate of (@). This value is required if the transfer_mode is upi."
}
}
},
"beneficiary_contact_details": {
"type": "object",
"description": "It should contain the contact details of the beneficiary.",
"properties": {
"beneficiary_email": {
"type": "string",
"description": "It is the email address of the beneficiary. The maximum character limit is 200. It should contain dot (.) and at the rate of (@)."
},
"beneficiary_phone": {
"type": "string",
"description": "It is the phone number of the beneficiary. Only registered Indian phone numbers are allowed. The value should be between 8 and 12 characters after stripping +91."
},
"beneficiary_country_code": {
"type": "string",
"description": "It is the country code (+91) of the beneficiary's phone number."
},
"beneficiary_address": {
"type": "string",
"description": "It should contain the address of the beneficiary. The maximum character limit is 150. Alphanumeric characters and whitespaces are allowed."
},
"beneficiary_city": {
"type": "string",
"description": "It is the name of the city as present in the beneficiary address. The maximum character limit is 50. Alphanumeric characters and whitespaces are allowed."
},
"beneficiary_state": {
"type": "string",
"description": "It is the name of the state as present in the beneficiary address. The maximum character limit is 50. Alphanumeric characters and whitespaces are allowed."
},
"beneficiary_postal_code": {
"type": "string",
"description": "It is the PIN code as present in the address. It should be a 6 character numeric value."
}
}
}
}
},
"transfer_remarks": {
"type": "string",
"description": "It can contain any additional remarks for the transfer. Alphanumeric and whitespaces are allowed. The maximum character limit is 70.",
"maxLength": 70
},
"fundsource_id": {
"type": "string",
"description": "It is the ID of the fund source from where you want to debit the transfer amount."
}
},
"required": [
"transfer_amount",
"transfer_id"
]
}
}
},
"required": [
"batch_transfer_id"
]
},
"CreateTransferResponse": {
"title": "Standard Transfer V2 Response",
"description": "Standard Transfer V2 Response",
"type": "object",
"properties": {
"transfer_id": {
"description": "It displays the unique ID you created to identify the transfer.",
"type": "string"
},
"cf_transfer_id": {
"description": "It displays the unique ID created by Cashfree Payments. You receive this ID in the response after initiating the standard transfer request.",
"type": "string"
},
"status": {
"description": "It displays the status of the transfer.",
"type": "string"
},
"beneficiary_details": {
"type": "object",
"description": "It displays the details of the beneficiary.",
"properties": {
"beneficiary_id": {
"description": "It displays the unique ID to identify the beneficiary to whom you initiated the transfer request.",
"type": "string"
},
"beneficiary_instrument_details": {
"type": "object",
"description": "It displays the details of where the beneficiary will receive the money.",
"properties": {
"bank_account_number": {
"type": "string",
"description": "It displays the bank account number of the beneficiary."
},
"ifsc": {
"type": "string",
"description": "It displays the IFSC information of the beneficiary's bank account."
},
"vpa": {
"type": "string",
"description": "It displays the UPI VPA information of the beneficiary."
}
}
}
}
},
"transfer_amount": {
"description": "It displays the transfer amount initiated in the request.",
"type": "number",
"format": "double"
},
"transfer_service_charge": {
"description": "It displays the service charge applicable for the successful transfer request.",
"type": "number",
"format": "double"
},
"transfer_service_tax": {
"description": "It displays the service tax applicable for the successful transfer request.",
"type": "number",
"format": "double"
},
"transfer_mode": {
"description": "It displays the mode of the transfer.",
"type": "string"
},
"transfer_utr": {
"description": "It displays the unique number that is generated to recognise any fund transfer that is created by the bank that facilitates the transfer.",
"type": "string"
},
"fundsource_id": {
"description": "It displays the ID of the fund source from where the money was debited for this transfer request.",
"type": "string"
},
"added_on": {
"description": "It displays the time of when the transfer request was added to the system.",
"type": "string"
},
"updated_on": {
"description": "It displays the updated time for the transfer.",
"type": "string"
}
}
},
"CreateBatchTransferResponse": {
"title": "Batch Transfer V2 Response",
"description": "Batch Transfer V2 Response",
"type": "object",
"properties": {
"batch_transfer_id": {
"type": "string",
"description": "It displays the unique ID you created to identify the batch transfer request."
},
"cf_batch_transfer_id": {
"type": "string",
"description": "It displays the unique ID created by Cashfree Payments. You receive this ID in the response after initiating the batch transfer request."
},
"status": {
"type": "string",
"description": "It displays the status of the API request."
}
}
},
"FetchBatchTransferResponse": {
"title": "Batch Transfer Status V2 Response",
"description": "Batch Transfer Status V2 Response",
"type": "object",
"properties": {
"batch_transfer_id": {
"description": "It displays the unique ID you created to identify the batch transfer.",
"type": "string"
},
"cf_batch_transfer_id": {
"description": "It displays the unique ID created by Cashfree Payments. You receive this ID in the response after initiating the batch transfer request.",
"type": "string"
},
"status": {
"description": "It displays the status of the batch transfer.",
"type": "string"
},
"transfers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CreateTransferResponse"
}
}
}
},
"inline_response_401": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "ERROR"
},
"subCode": {
"type": "string",
"example": "401"
},
"message": {
"type": "string",
"example": "Invalid clientId and clientSecret combination"
}
}
},
"inline_response_200_10": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "SUCCESS"
},
"subCode": {
"type": "string",
"example": "200"
},
"message": {
"type": "string",
"example": "Token is valid"
}
}
},
"v1_createCashgram_body": {
"required": [
"amount",
"cashgramId",
"linkExpiry",
"name",
"phone"
],
"type": "object",
"properties": {
"cashgramId": {
"type": "string",
"description": "Unique Id of the Cashgram. Alphanumeric, underscore (_), and hyphen (-) allowed (35 character limit)"
},
"amount": {
"type": "number",
"description": "Amount to be transferred, >= 1.00",
"format": "float"
},
"name": {
"type": "string",
"description": "Name of the contact"
},
"email": {
"type": "string",
"description": "Email of the contact"
},
"phone": {
"type": "string",
"description": "Phone number of the contact"
},
"linkExpiry": {
"type": "string",
"description": "Date to expire the cashgram link, Date format YYYY/MM/DD, maximum 30 days from the date of creation."
},
"remarks": {
"type": "string",
"description": "Specify remarks, if any."
},
"notifyCustomer": {
"type": "integer",
"description": "If value is 1, a link is sent to customers phone and email."
}
}
},
"inline_response_200_8": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "SUCCESS"
},
"subCode": {
"type": "string",
"example": "200"
},
"message": {
"type": "string",
"example": "Cashgram Created"
},
"data": {
"$ref": "#/components/schemas/inline_response_200_8_data"
}
}
},
"inline_response_409_1": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "ERROR"
},
"subCode": {
"type": "string",
"example": "409"
},
"message": {
"type": "string",
"example": "Cashgram with id JOHaN10 already exists"
}
}
},
"v1_deactivateCashgram_body": {
"required": [
"cashgramId"
],
"type": "object",
"properties": {
"cashgramId": {
"type": "string",
"description": "ID of the Cashgram to be deactivated. Alphanumeric and underscore (_) allowed (35 character limit)"
}
}
},
"inline_response_200_9": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "SUCCESS"
},
"subCode": {
"type": "string",
"example": "200"
},
"message": {
"type": "string",
"example": "Cashgram with id - JOHaN10 successfully deactivated!"
}
}
},
"inline_response_404_4": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "ERROR"
},
"subCode": {
"type": "string",
"example": "404"
},
"message": {
"type": "string",
"example": "Cashgram with id JOHaN10 does not exists"
}
}
},
"inline_response_200_11": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "SUCCESS"
},
"subCode": {
"type": "string",
"example": "200"
},
"message": {
"type": "string",
"example": "Cashgram details retrieved"
},
"data": {
"$ref": "#/components/schemas/inline_response_200_11_data"
}
}
},
"inline_response_200_8_data": {
"type": "object",
"properties": {
"referenceId": {
"type": "integer",
"example": 123456,
"default": 0
},
"cashgramLink": {
"type": "string",
"example": "http://csgr.am/abcdefg"
}
}
},
"inline_response_200_11_data": {
"type": "object",
"properties": {
"cashgramStatus": {
"type": "string",
"example": "ACTIVE"
},
"referenceId": {
"type": "integer",
"example": 123456,
"default": 0
},
"cashgramId": {
"type": "string",
"example": "JOHaN10"
},
"cashgramLink": {
"type": "string",
"example": "http://csgr.am/abcdefg"
}
}
}
},
"parameters": {
"xRequestIDHeader": {
"in": "header",
"name": "x-request-id",
"description": "It is the request ID for the API call. This ID can be used to resolve tech realted issues. Communicate this in your tech related queries to Cashfree Payments.",
"required": false,
"schema": {
"type": "string"
},
"example": "4dfb9780-46fe-11ee-be56-0242ac120002"
},
"apiVersionHeader": {
"in": "header",
"name": "x-api-version",
"description": "It is the API version to be used. The accepted format is YYYY-MM-DD.",
"schema": {
"type": "string",
"description": "It is the API version to be used.",
"default": "2024-01-01"
},
"example": "2024-01-01"
}
},
"requestBodies": {},
"responses": {},
"examples": {
"all_three_params_given": {
"summary": "All three parameters provided",
"description": "All three parameters are provided to get beneficiary details",
"value": {
"type": "invalid_request_error",
"code": "too_many_parameters_in_request",
"message": "Please provide either bank_account_number and bank_ifsc together or beneficiary_id alone. Do not include all three parameters in the request"
}
},
"bank_account_exists_with_a_different_ifsc_v2": {
"summary": "Beneficiary exists with the provided bank account number but a different IFSC",
"description": "beneficiary exists with given beneficiary_bank_account_number but beneficiary_ifsc is different",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_not_found",
"message": "Beneficiary exists with the given bank_account_number but a different bank_ifsc"
}
},
"bank_account_given_ifsc_not_given_in_get_v2": {
"description": "Bank account number is provided but ifsc is not provided",
"summary": "Missing IFSC but bank account number is provided",
"value": {
"type": "invalid_request_error",
"code": "bank_ifsc_missing",
"message": "bank_ifsc : should be provided with the request if bank_account_number is provided"
}
},
"bank_account_invalid": {
"description": "Bank account number contains characters that are not allowed",
"summary": "Provided bank account number contains characters that are not allowed",
"value": {
"type": "invalid_request_error",
"code": "bank_account_number_invalid",
"message": "bank_account_number : should be alphanumeric. value received: 123@"
}
},
"bank_account_number_too_large": {
"description": "Bank account number provided is too large",
"summary": "Provided bank account number is too large",
"value": {
"type": "invalid_request_error",
"code": "bank_account_number_length_exceeded",
"message": "bank_account_number : should not be more than 25 characters long. value received: 235142352346523462456345263452345"
}
},
"bank_account_number_too_short": {
"description": "Bank account number provided is too short",
"summary": "Provided bank account number is too short",
"value": {
"type": "invalid_request_error",
"code": "bank_account_number_length_short",
"message": "bank_account_number : should not be less than 4 characters long. value received: 12"
}
},
"bank_ifsc_given_account_not_given_in_get_v2": {
"summary": "Missing bank account number but IFSC is provided",
"description": "Bank ifsc is provided but bank account number is not provided",
"value": {
"type": "invalid_request_error",
"code": "bank_account_number_missing",
"message": "bank_account_number: should be provided with the request if bank_ifsc is provided"
}
},
"bene_creation_request_with_only_vpa": {
"description": "Beneficiary creation with only vpa",
"summary": "Create beneficiary with only VPA",
"value": {
"beneficiary_id": "JOHN18011343",
"beneficiary_name": "John Doe",
"beneficiary_instrument_details": {
"vpa": "test@upi"
},
"beneficiary_contact_details": {
"beneficiary_email": "[email protected]",
"beneficiary_phone": "9876543210",
"beneficiary_country_code": "+91",
"beneficiary_address": "177A Bleecker Street",
"beneficiary_city": "New York City",
"beneficiary_state": "New York",
"beneficiary_postal_code": "560011"
}
}
},
"bene_exist_for_bank_account_and_ifsc": {
"description": "Account number and ifsc are already registered as a beneficiary",
"summary": "Account number and IFSC are already registered for a beneficiary",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_already_exists",
"message": "Beneficiary already exists with the given beneficiary_bank_account_number and beneficiary_ifsc"
}
},
"bene_id_too_large_v2": {
"description": "Length of beneficiary_id is more than maximum allowed",
"summary": "Length of beneficiary_id exceeded the maximum limit",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_id_length_exceeded",
"message": "beneficiary_id : should not be more than 50 characters long. value received: kl12b3rkh1bv234lkbr3jl24tbrlk234bkt234t134kbr1hk34jr"
}
},
"beneficiary_id_not_found_v2": {
"summary": "Beneficiary with given beneficiary_id not found",
"description": "Beneficiary with the given beneficiary_id does not exist",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_not_found",
"message": "Beneficiary does not exist"
}
},
"beneficiary_id_not_passed": {
"description": "Beneficiary Id which is a mandatory parameter is not passed in the request",
"summary": "Missing beneficiary_id in the request",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_id_missing",
"message": "beneficiary_id : should contain only letters, numbers, hyphen, underscore, pipe, and dot. Value received: .\\qewqefwqev"
}
},
"beneficiary_with_account_does_not_exist_v2": {
"summary": "Beneficiary with given account details not found",
"description": "Beneficiary with given account details does not exist",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_not_found",
"message": "Beneficiary with the given bank_account_number and bank_ifsc does not exist"
}
},
"beneid_longer_than_max_limit_error": {
"summary": "Beneficiary Id can not have more than 50 characters",
"description": "Beneficiary ID cannot have more than 50 characters",
"value": {
"type": "invalid_request_error",
"code": "invalid_beneficiary_id",
"message": "Beneficiary with the given combination of beneficiary_bank_account_number and beneficiary_ifsc does not exist"
}
},
"create_beneficiary_request_v2": {
"description": "Find the request body for creating a beneficiary with all the available information",
"summary": "Create beneficiary with all the available information",
"value": {
"beneficiary_id": "JOHN18011343",
"beneficiary_name": "John Doe",
"beneficiary_instrument_details": {
"bank_account_number": "1223334444",
"bank_ifsc": "HDFC0000001",
"vpa": "test@upi"
},
"beneficiary_contact_details": {
"beneficiary_email": "[email protected]",
"beneficiary_phone": "9876543210",
"beneficiary_country_code": "+91",
"beneficiary_address": "177A Bleecker Street",
"beneficiary_city": "New York City",
"beneficiary_state": "New York",
"beneficiary_postal_code": "560011"
}
}
},
"delete_bene_success_response_v2": {
"description": "Example values for Remove Beneficiary V2 success response",
"value": {
"beneficiary_id": "JOHN18011343",
"beneficiary_name": "John Doe",
"beneficiary_instrument_details": {
"bank_account_number": "1223334444",
"bank_ifsc": "HDFC0000001",
"vpa": "test@upi"
},
"beneficiary_contact_details": {
"beneficiary_email": "[email protected]",
"beneficiary_phone": "9876543210",
"beneficiary_country_code": "+91",
"beneficiary_address": "177A Bleecker Street",
"beneficiary_city": "New York City",
"beneficiary_state": "New York",
"beneficiary_postal_code": "560011"
},
"beneficiary_status": "DELETED",
"added_on": "2023-12-04T15:50:00Z"
}
},
"duplicate_bene_creation_response": {
"summary": "Beneficiary exists with the given beneficiary ID",
"description": "Beneficiary with given beneficiary id already exist",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_id_already_exists",
"message": "Beneficiary already exists with the given beneficiary_id"
}
},
"get_beneficiary_success_v2": {
"description": "Example values for Get Beneficiary V2 success response",
"value": {
"beneficiary_id": "JOHN18011343",
"beneficiary_name": "John Doe",
"beneficiary_instrument_details": {
"bank_account_number": "1223334444",
"bank_ifsc": "HDFC0000001",
"vpa": "test@upi"
},
"beneficiary_contact_details": {
"beneficiary_email": "[email protected]",
"beneficiary_phone": "9876543210",
"beneficiary_country_code": "+91",
"beneficiary_address": "177A Bleecker Street",
"beneficiary_city": "New York City",
"beneficiary_state": "New York",
"beneficiary_postal_code": "560011"
},
"beneficiary_status": "VERIFIED",
"added_on": "2023-12-04T15:50:00Z"
}
},
"internal_server_error_v2": {
"summary": "Internal server error",
"description": "Error at Cashfree Payments' server",
"value": {
"type": "api_error",
"code": "internal_server_error",
"message": "Error at cashfree's server"
}
},
"invalid_bene_id_due_unacceptable_characters": {
"description": "Beneficiary ID contains characters that are not allowed",
"summary": "Beneficiary ID contains characters that are not allowed",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_id_invalid",
"message": "beneficiary_id : should contain only letters, numbers, hyphen, underscore, pipe, and dot. Value received: .\\qewqefwqev"
}
},
"invalid_ifsc": {
"description": "Invalid value given for IFSC",
"summary": "Invalid IFSC",
"value": {
"type": "invalid_request_error",
"code": "bank_ifsc_invalid",
"message": "bank_ifsc : please provide a valid IFSC. value received: SBIN00708410"
}
},
"no_bene_identifiers_provided_v2": {
"description": "No details are provided with the request to identifiy the beneficiary",
"summary": "Details are not provided with the request to identifiy the beneficiary",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_identifiers_missing",
"message": "beneficiary_identifiers : Either beneficiary_id or the combination of bank_account_number and bank_ifsc has to be provided with the request"
}
},
"same_bene_as_source_v2": {
"description": "Beneficiary account is the same as the source bank account",
"summary": "Beneficiary account is the same as the source bank account",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_account_same_as_source",
"message": "beneficiary_bank_account_number provided can not be same as source bank account"
}
},
"vba_beneiciary_not_allowed": {
"description": "Adding virtual bank account as a beneficiary is not allowed for the account",
"summary": "Virtual bank account is not allowed for the beneficiary",
"value": {
"type": "invalid_request_error",
"code": "vba_bene_not_allowed",
"message": "Virtual bank account as beneficiary_bank_account_number is not allowed for the account"
}
},
"transfer_request_v2": {
"summary": "Transfer request with beneficiary_id",
"description": "The API request to iniate a transfer with beneficiary_id",
"value": {
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
}
}
},
"transfer_request_v2_with_bene_details": {
"summary": "Transfer request with beneficiary_details",
"description": "The API request to iniate a transfer with beneficiary_details",
"value": {
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"transfer_mode": "imps",
"beneficiary_details": {
"beneficiary_details": {
"beneficiary_instrument_details": {
"bank_account_number": "1234554321",
"bank_ifsc": "SBIN0001161"
}
}
}
}
},
"transfer_request_v2_with_card_details": {
"summary": "Transfer request with card_details",
"description": "The API request to iniate a transfer with card_details",
"value": {
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"transfer_mode": "imps",
"beneficiary_details": {
"beneficiary_details": {
"beneficiary_instrument_details": {
"card_details": {
"card_token": "4640837721072836",
"card_network_type": "MASTERCARD",
"card_cryptogram": "jjoutwsdgfdou124354ljlsdhgout968957",
"card_token_expiry": "2032-10",
"card_type": "CREDIT",
"card_token_PAN_sequence_number": "001"
}
}
}
}
}
},
"transfer_request_v2_fundsource_id": {
"summary": "Transfer request with fundsource_id (when you want to debit money from a particular fund source)",
"description": "The API request to initiate a transfer and debit the money from a particular fund source",
"value": {
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"transfer_mode": "imps",
"beneficiary_details": {
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
}
},
"fundsource_id": "CASHFREE_1"
}
},
"batch_transfer_request_v2": {
"summary": "Batch transfer request",
"description": "The API request to initiate a batch transfer",
"value": {
"batch_transfer_id": "test_batch_transfer_id",
"transfers": [
{
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
}
},
{
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"transfer_mode": "imps",
"beneficiary_details": {
"beneficiary_details": {
"beneficiary_instrument_details": {
"bank_account_number": "1234554321",
"bank_ifsc": "SBIN0001161"
}
}
}
},
{
"transfer_id": "JUNOB2018",
"transfer_amount": 1,
"transfer_mode": "imps",
"beneficiary_details": {
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
}
},
"fundsource_id": "CASHFREE_1"
}
]
}
},
"transfer_received_response_v2": {
"summary": "Transfer received",
"description": "Transfer received by Cashfree Payments. Please check the status after some time.",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "RECEIVED",
"status_code": "RECEIVED",
"status_description": "The transfer has been received by Cashfree successfully for further processing. You should use Check Status API response or Webhooks to know the terminal state of the transfer request.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"transfer_pending_approval_response_v2": {
"summary": "Transfer is pending for approval",
"description": "Transfer is pending for approval.",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "APPROVAL_PENDING",
"status_code": "APPROVAL_PENDING",
"status_description": "The transfer requires approval. You can approve or reject the transfer request from the Cashfree Merchant Dashboard.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"transfer_completed_response_v2": {
"summary": "Transfer completed successfully",
"description": "Transfer completed successfully",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "SUCCESS",
"status_code": "COMPLETED",
"status_description": "The transfer has been initiated via the partner bank successfully, hence your account is debited and the request is successfuly processed by the beneficiary bank and has been credited to the end beneficiary.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011",
"beneficiary_instrument_details": {
"bank_account_number": "7766671501729",
"bank_ifsc": "SBIN0000003"
}
},
"transfer_amount": 1,
"transfer_service_charge": 1,
"transfer_service_tax": 0.18,
"transfer_mode": "BANK",
"transfer_utr": "TESTR92023012200543116",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"transfer_pending_response_v2": {
"summary": "Transfer pending at the bank",
"description": "Transfer initiated by Cashfree Payments and is pending at the bank's side",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "PENDING",
"status_code": "PENDING",
"status_description": "The transfer is currently in a Pending state, as Cashfree is awaiting a final confirmation from the partner bank for a terminal status. You should rely only on Check Status API response or Webhooks to know the terminal state of the transfer request.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011",
"beneficiary_instrument_details": {
"bank_account_number": "7766671501729",
"bank_ifsc": "SBIN0000003"
}
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"transfer_utr": "TESTR92023012200543116",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"transfer_failed_response_v2": {
"summary": "Transfer failed",
"description": "Amount cannot be transferred to beneficiary as the transfer failed",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "FAILED",
"status_code": "IMPS_MODE_FAIL",
"status_description": "The transfer has been reversed by the beneficiary bank because the beneficiary bank account doesnot support IMPS transfers. This rejection is done by the beneficiary bank for the specific beneficiary account. You can try NEFT or other channels to do the disbursals.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011",
"beneficiary_instrument_details": {
"bank_account_number": "7766671501729",
"bank_ifsc": "SBIN0000003"
}
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"transfer_rejected_response_v2": {
"summary": "Transfer rejected",
"description": "The transfer has been rejected by Cashfree Oatnebts. Please review the 'status_description' field to understand the reason for rejection.",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "REJECTED",
"status_code": "INVALID_MODE_FOR_PYID",
"status_description": "The transfer has been rejected because the payment instrument does not support this mode of transfer. You should get this mode activated on the payment instrument ID by contacting Cashfree, and then initiate a new transfer request.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"transfer_reversed_response_v2": {
"summary": "Transfer reversed",
"description": "The transfer has been reversed by bank. Please review the status_description field to understand the reason reversal.",
"value": {
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "REVERSED",
"status_code": "INVALID_ACCOUNT_FAIL",
"status_description": "The transfer has been reversed by the beneficiary bank because the Account Number of the beneficiary is invalid. After correcting the account number, you can reinitiate the transfer via Cashfree so that the transfer can be reattempted again by Cashfree with the partner bank(s).",
"beneficiary_details": {
"beneficiary_id": "JOHN18011",
"beneficiary_instrument_details": {
"bank_account_number": "7766671501729",
"bank_ifsc": "SBIN0000003"
}
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
},
"batch_transfer_received_response_v2": {
"summary": "Batch transfer received successfully",
"description": "Batch transfer received successfully by Cashfree Payments. Please check the status of the batch transfer after some time.",
"value": {
"batch_transfer_id": "test_batch_transfer_id",
"cf_batch_transfer_id": "123456",
"status": "RECEIVED"
}
},
"batch_transfer_pending_response_v2": {
"summary": "Batch transfer pending",
"description": "Batch Transfer pending at the bank. Please check the status of batch transfer after some time.",
"value": {
"batch_transfer_id": "test_batch_transfer_id",
"cf_batch_transfer_id": "123456",
"status": "PENDING",
"transfers": [
{
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123456",
"status": "SUCCESS",
"status_code": "COMPLETED",
"status_description": "The transfer has been initiated via the partner bank successfully, hence your account is debited and the request is successfuly processed by the beneficiary bank and has been credited to the end beneficiary.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011",
"beneficiary_instrument_details": {
"bank_account_number": "7766671501729",
"bank_ifsc": "SBIN0000003"
}
},
"transfer_amount": 1,
"transfer_service_charge": 1,
"transfer_service_tax": 0.18,
"transfer_mode": "BANK",
"transfer_utr": "TESTUTR",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
},
{
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123457",
"status": "PENDING",
"status_code": "PENDING",
"status_description": "The transfer is currently in a Pending state, as Cashfree is awaiting a final confirmation from the partner bank for a terminal status. You should rely only on Check Status API response or Webhooks to know the terminal state of the transfer request.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011",
"beneficiary_instrument_details": {
"bank_account_number": "7766671501729",
"bank_ifsc": "SBIN0000003"
}
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"transfer_utr": "TESTUTR2",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
},
{
"transfer_id": "JUNOB2018",
"cf_transfer_id": "123458",
"status": "REJECTED",
"status_code": "INVALID_MODE_FOR_PYID",
"status_description": "The transfer has been rejected because the payment instrument does not support this mode of transfer. You should get this mode activated on the payment instrument ID by contacting Cashfree, and then initiate a new transfer request.",
"beneficiary_details": {
"beneficiary_id": "JOHN18011"
},
"transfer_amount": 1,
"transfer_mode": "BANK",
"fundsource_id": "CASHFREE_1",
"added_on": "2021-11-24T13:39:25Z",
"updated_on": "2021-11-24T13:40:27Z"
}
]
}
},
"APIsDisabledExampleV2": {
"summary": "APIs disabled",
"description": "Forbidden request. APIs are disabled",
"value": {
"type": "invalid_request_error",
"code": "apis_not_enabled",
"message": "APIs not enabled. Please fill out the [Support Form](https://merchant.cashfree.com/merchants/landing?env=prod&raise_issue=1)"
}
},
"BeneficiaryNotFoundV2": {
"summary": "Beneficiary not found",
"description": "Beneficiary does not exist",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_not_found",
"message": "Beneficiary does not exist"
}
},
"authentication_internal_server_error": {
"summary": "Internal server error while authenticating request",
"description": "Internal server error while authenticating request",
"value": {
"type": "authentication_error",
"code": "internal_server_error",
"message": "Unable to authenticate the request. Please fill out the [Support Form](https://merchant.cashfree.com/merchants/landing?env=prod&raise_issue=1)"
}
},
"transfer_id_invalid": {
"description": "Invalid transfer_id",
"value": {
"type": "invalid_request_error",
"code": "transfer_id_invalid",
"message": "transfer_id should be alphanumeric"
}
},
"transfer_id_missing": {
"description": "Missing transfer_id",
"value": {
"type": "invalid_request_error",
"code": "transfer_id_missing",
"message": "transfer_id is missing in the request"
}
},
"transfer_amount_invalid": {
"description": "Invalid transfer_amount",
"value": {
"type": "invalid_request_error",
"code": "transfer_amount_invalid",
"message": "transfer_amount should be greater then 1.00"
}
},
"transfer_amount_missing": {
"description": "Misisng transfer_amount",
"value": {
"type": "invalid_request_error",
"code": "transfer_amount_missing",
"message": "transfer_amount is missing in the request"
}
},
"transfer_mode_invalid": {
"description": "Invalid transfer_mode",
"value": {
"type": "invalid_request_error",
"code": "transfer_mode_invalid",
"message": "transfer_mode is invalid allowed values are : bank, imps, neft, rtgs, upi, paytm, amazonpay, card and cardupi"
}
},
"beneficiary_id_invalid": {
"description": "Invalid beneficiary_id",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_id_invalid",
"message": "beneficiary_id should be alphanumeric"
}
},
"beneficiary_name_invalid": {
"description": "Invalid beneficiary_name",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_name_invalid",
"message": "beneficiary_name is invalid. only alphabets and whitespaces are allowed"
}
},
"beneficiary_bank_account_invalid": {
"description": "Invalid beneficiary bank account details",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_instrument_details.bank_account_number_invalid",
"message": "bank_account_number should be alphanumeric"
}
},
"beneficiary_bank_account_invalid_2": {
"description": "Bank account number in the request does not match with the beneficiary's bank account number",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_instrument_details.bank_account_number_invalid",
"message": "Bank account number passed in the request does not match with the beneficiary with beneficiary_id :: test_beneId"
}
},
"beneficiary_bank_ifsc_invalid": {
"description": "Invalid IFSC",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_instrument_details.bank_ifsc_invalid",
"message": "bank_ifsc should be in standard ifsc format"
}
},
"beneficiary_bank_ifsc_invalid_2": {
"description": "IFSC in the request does not match with the beneficiary's IFSC",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_instrument_details.bank_ifsc_invalid",
"message": "Bank ifsc passed in the request does not match with the beneficiary with beneficiary_id :: test_beneId"
}
},
"beneficiary_vpa_invalid": {
"description": "Invalid beneficiary VPA",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_instrument_details.vpa_invalid",
"message": "vpa is in invalid format"
}
},
"beneficiary_vpa_invalid_2": {
"description": "VPA in the request does not match with the beneficiary's VPA",
"value": {
"type": "invalid_request_error",
"code": "beneficiary_details.beneficiary_instrument_details.vpa_invalid",
"message": "Vpa passed in the request does not match with the beneficiary with beneficiary_id :: test_beneId"
}
},
"cf_transfer_id_not_found": {
"summary": "cf_transfer_id not found",
"description": "cf_transfer_id not found",
"value": {
"type": "invalid_request_error",
"code": "cf_transfer_id_not_found",
"message": "cf_transfer_id does not exist"
}
},
"transfer_id_not_found": {
"summary": "transfer_id not found",
"description": "transfer_id not found",
"value": {
"type": "invalid_request_error",
"code": "transfer_id_not_found",
"message": "transfer_id does not exist"
}
},
"cf_batch_transfer_id_not_found": {
"summary": "cf_batch_transfer_id not found",
"description": "cf_batch_transfer_id not found",
"value": {
"type": "invalid_request_error",
"code": "cf_batch_transfer_id",
"message": "cf_batch_transfer_id does not exist"
}
},
"batch_transfer_id_not_found": {
"summary": "batch_transfer_id not found",
"description": "batch_transfer_id not found",
"value": {
"type": "invalid_request_error",
"code": "batch_transfer_id_not_found",
"message": "batch_transfer_id does not exist"
}
},
"batch_transfer_id_already_exists": {
"summary": "batch_transfer_id not found",
"description": "batch_transfer_id not found",
"value": {
"type": "invalid_request_error",
"code": "batch_transfer_id_already_exists",
"message": "batch_transfer_id already exists. please pass unique id in each request"
}
},
"batch_transfer_id_missing": {
"description": "Missing batch_transfer_id",
"value": {
"type": "invalid_request_error",
"code": "batch_transfer_id_missing",
"message": "batch_transfer_id is missing in the request"
}
},
"batch_transfer_id_invalid": {
"description": "Invalid batch_transfer_id",
"value": {
"type": "invalid_request_error",
"code": "batch_transfer_id_invalid",
"message": "batch_transfer_id should be alphanumeric"
}
},
"batchTransfer_transfer_id_invalid": {
"description": "Invalid transfer_id",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].transfer_id_invalid",
"message": "transfer_id should be alphanumeric"
}
},
"batchTransfer_transfer_id_missing": {
"description": "Missing transfer_id",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].transfer_id_missing",
"message": "transfer_id is missing in the request"
}
},
"batchTransfer_transfer_amount_invalid": {
"description": "Invalid transfer_amount",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].transfer_amount_invalid",
"message": "transfer_amount should be greater then 1.00"
}
},
"batchTransfer_transfer_amount_missing": {
"description": "Missing transfer_amount",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].transfer_amount_missing",
"message": "transfer_amount is missing in the request"
}
},
"batchTransfer_transfer_mode_invalid": {
"description": "Invalid transfer_mode",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].transfer_mode_invalid",
"message": "transfer_mode is invalid allowed values are : bank, imps, neft, rtgs, upi, paytm, amazonpay, card and cardupi"
}
},
"batchTransfer_beneficiary_id_invalid": {
"description": "Invalid beneficiary_id",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].beneficiary_details.beneficiary_id_invalid",
"message": "beneficiary_id should be alphanumeric"
}
},
"batchTransfer_beneficiary_name_invalid": {
"description": "Invalid transfer_id",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].beneficiary_details.beneficiary_name_invalid",
"message": "beneficiary_name is invalid. only alphabets and whitespaces are allowed"
}
},
"batchTransfer_beneficiary_bank_account_invalid": {
"description": "beneficiary bank account is invalid",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].beneficiary_details.beneficiary_instrument_details.bank_account_number_invalid",
"message": "bank_account_number should be alphanumeric"
}
},
"batchTransfer_beneficiary_bank_ifsc_invalid": {
"description": "Invalid bank account details",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].beneficiary_details.beneficiary_instrument_details.bank_ifsc_invalid",
"message": "bank_ifsc should be in standard ifsc format"
}
},
"batchTransfer_beneficiary_vpa_invalid": {
"description": "Invalid beneficiary VPA",
"value": {
"type": "invalid_request_error",
"code": "transfers[0].beneficiary_details.beneficiary_instrument_details.vpa_invalid",
"message": "vpa is in invalid format"
}
}
},
"headers": {
"x-api-version": {
"schema": {
"type": "string",
"format": "YYYY-MM-DD",
"enum": [
"2022-09-01"
],
"default": "2024-01-01"
},
"description": "It displays the API version. The current version is `2022-09-01`."
},
"x-ratelimit-limit": {
"schema": {
"type": "integer"
},
"example": 200,
"description": "It displays the rate limit per minute set for your account for this API request."
},
"x-ratelimit-remaining": {
"schema": {
"type": "integer"
},
"example": 2,
"description": "It displays the remaining rate limit in the next minute for your account for this API requeste. Uses sliding window."
},
"x-ratelimit-retry": {
"schema": {
"type": "integer"
},
"example": 4,
"description": "It displays the number of seconds to wait if the rate limit is breached\n- Is 0 if withing the limit\n- Is between 1 and 59 if breached\n"
},
"x-request-id": {
"schema": {
"type": "string"
},
"example": "some-req-id",
"description": "It displays the request ID for the API request. Is blank or null if no `x-request-id` is sent during the request"
}
},
"x-elicitationConfig": {
"createTransfer": {
"enabled": true,
"fields": {
"transfer_amount": {
"required": true,
"message": "Please provide the amount to be transferred",
"schema": {
"type": "number",
"title": "Transfer Amount",
"description": "Amount to be transferred (minimum 1 INR)",
"minimum": 1
},
"mapping": {
"target": "body.transfer_amount",
"transform": "number"
}
}
}
},
"createCashgram": {
"enabled": true,
"fields": {
"amount": {
"required": true,
"message": "Please provide the amount for Cashgram",
"schema": {
"type": "number",
"title": "Cashgram Amount",
"description": "Amount for Cashgram (minimum 1 INR)",
"minimum": 1
},
"mapping": {
"target": "body.amount",
"transform": "number"
}
},
"phone": {
"required": true,
"message": "Please provide the beneficiary's phone number",
"schema": {
"type": "string",
"title": "Phone Number",
"description": "Beneficiary's phone number in E.164 format"
},
"mapping": {
"target": "body.phone",
"transform": "string"
}
}
}
},
"deactivateCashgram": {
"enabled": true,
"fields": {
"cashgram_id": {
"required": true,
"message": "Please provide the Cashgram ID to be deactivated",
"schema": {
"type": "string",
"title": "Cashgram ID",
"description": "The unique identifier of the Cashgram to be deactivated"
},
"mapping": {
"target": "path.cashgram_id",
"transform": "string"
}
}
}
}
}
},
"paths": {
"/transfers": {
"post": {
"summary": "Standard Transfer V2",
"x-mcp": {
"enabled": true,
"config": {
"elicitation": {
"$ref": "#/components/x-elicitationConfig/createTransfer"
}
}
},
"description": "Use this API to initiate an amount transfer at Cashfree Payments. It is an async request by default.",
"tags": [
"Transfers v2"
],
"operationId": "PayoutInitiateTransfer",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
}
],
"requestBody": {
"description": "Find the request parameters of the API request to transfer money to a beneficiary.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateTransferRequest"
},
"examples": {
"transfer_request": {
"$ref": "#/components/examples/transfer_request_v2"
},
"transfer_request_with_bene_details": {
"$ref": "#/components/examples/transfer_request_v2_with_bene_details"
},
"transfer_request_with_card_details": {
"$ref": "#/components/examples/transfer_request_v2_with_card_details"
},
"transfer_request_with_fundsource_id": {
"$ref": "#/components/examples/transfer_request_v2_fundsource_id"
}
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateTransferResponse"
},
"examples": {
"transfer_received_response_v2": {
"$ref": "#/components/examples/transfer_received_response_v2"
},
"transfer_pending_approval_response_v2": {
"$ref": "#/components/examples/transfer_pending_approval_response_v2"
},
"transfer_pending_response_v2": {
"$ref": "#/components/examples/transfer_pending_response_v2"
},
"transfer_completed_response": {
"$ref": "#/components/examples/transfer_completed_response_v2"
},
"transfer_failed_response_v2": {
"$ref": "#/components/examples/transfer_failed_response_v2"
},
"transfer_rejected_response_v2": {
"$ref": "#/components/examples/transfer_rejected_response_v2"
}
}
}
},
"headers": {
"x-api-version": {
"$ref": "#/components/headers/x-api-version"
},
"x-ratelimit-limit": {
"$ref": "#/components/headers/x-ratelimit-limit"
},
"x-ratelimit-remaining": {
"$ref": "#/components/headers/x-ratelimit-remaining"
},
"x-ratelimit-retry": {
"$ref": "#/components/headers/x-ratelimit-retry"
},
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"400": {
"description": "invalid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"transfer_id_missing": {
"$ref": "#/components/examples/transfer_id_missing"
},
"transfer_id_invalid": {
"$ref": "#/components/examples/transfer_id_invalid"
},
"transfer_amount_invalid": {
"$ref": "#/components/examples/transfer_amount_invalid"
},
"transfer_amount_missing": {
"$ref": "#/components/examples/transfer_amount_missing"
},
"transfer_mode_invalid": {
"$ref": "#/components/examples/transfer_mode_invalid"
},
"beneficiary_id_invalid": {
"$ref": "#/components/examples/beneficiary_id_invalid"
},
"beneficiary_name_invalid": {
"$ref": "#/components/examples/beneficiary_name_invalid"
},
"beneficiary_bank_account_invalid": {
"$ref": "#/components/examples/beneficiary_bank_account_invalid"
},
"beneficiary_bank_account_invalid_2": {
"$ref": "#/components/examples/beneficiary_bank_account_invalid_2"
},
"beneficiary_bank_ifsc_invalid": {
"$ref": "#/components/examples/beneficiary_bank_ifsc_invalid"
},
"beneficiary_bank_ifsc_invalid_2": {
"$ref": "#/components/examples/beneficiary_bank_ifsc_invalid_2"
},
"beneficiary_vpa_invalid": {
"$ref": "#/components/examples/beneficiary_vpa_invalid"
},
"beneficiary_vpa_invalid_2": {
"$ref": "#/components/examples/beneficiary_vpa_invalid_2"
}
}
}
}
},
"403": {
"description": "Forbidden error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/APIsDisabledExampleV2"
}
}
}
}
},
"404": {
"description": "Resource not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/BeneficiaryNotFoundV2"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/internal_server_error_v2"
},
"AuthenticationError": {
"$ref": "#/components/examples/authentication_internal_server_error"
}
}
}
}
}
}
},
"get": {
"summary": "Get Transfer Status V2",
"x-mcp": {
"enabled": true
},
"description": "Use this API to get the status of the initiated transfer. You can use either the transfer_id or cf_transfer_id to fetch the details.",
"tags": [
"Transfers v2"
],
"operationId": "PayoutFetchTransfer",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
},
{
"in": "query",
"name": "cf_transfer_id",
"description": "It is the unique ID created by Cashfree Payments. You receive it in the response of the initiated standard transfer request. (Either cf_transfer_id or transfer_id is mandatory)",
"example": "10023",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "transfer_id",
"description": "It is the unique ID you created to identify the standard transfer request.",
"example": "Sample_test",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateTransferResponse"
},
"examples": {
"transfer_received_response_v2": {
"$ref": "#/components/examples/transfer_received_response_v2"
},
"transfer_pending_approval_response_v2": {
"$ref": "#/components/examples/transfer_pending_approval_response_v2"
},
"transfer_pending_response_v2": {
"$ref": "#/components/examples/transfer_pending_response_v2"
},
"transfer_completed_response": {
"$ref": "#/components/examples/transfer_completed_response_v2"
},
"transfer_failed_response_v2": {
"$ref": "#/components/examples/transfer_failed_response_v2"
},
"transfer_rejected_response_v2": {
"$ref": "#/components/examples/transfer_rejected_response_v2"
},
"transfer_reversed_response_v2": {
"$ref": "#/components/examples/transfer_reversed_response_v2"
}
}
}
},
"headers": {
"x-api-version": {
"$ref": "#/components/headers/x-api-version"
},
"x-ratelimit-limit": {
"$ref": "#/components/headers/x-ratelimit-limit"
},
"x-ratelimit-remaining": {
"$ref": "#/components/headers/x-ratelimit-remaining"
},
"x-ratelimit-retry": {
"$ref": "#/components/headers/x-ratelimit-retry"
},
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"403": {
"description": "Forbidden error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/APIsDisabledExampleV2"
}
}
}
}
},
"404": {
"description": "Resource not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"CfTransferIdNotFound": {
"$ref": "#/components/examples/cf_transfer_id_not_found"
},
"TransferIdNotFound": {
"$ref": "#/components/examples/transfer_id_not_found"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/internal_server_error_v2"
},
"AuthenticationError": {
"$ref": "#/components/examples/authentication_internal_server_error"
}
}
}
}
}
}
}
},
"/transfers/batch": {
"post": {
"summary": "Batch Transfer V2",
"x-mcp": {
"enabled": true
},
"description": "Use this API to initiate a batch transfer request at Cashfree Payments. You can transfer money to multiple beneficiaries. The batch transfer limit is 5,000 in the production environment and 1,000 by default in the test environment.",
"tags": [
"Transfers v2"
],
"operationId": "PayoutInitiateBatchTransfer",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
}
],
"requestBody": {
"description": "Find the request parameters of the API request to transfer money to multiple beneficiaries.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateBatchTransferRequest"
},
"examples": {
"transfer_request": {
"$ref": "#/components/examples/batch_transfer_request_v2"
}
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateBatchTransferResponse"
},
"examples": {
"batch_transfer_received_response_v2": {
"$ref": "#/components/examples/batch_transfer_received_response_v2"
}
}
}
},
"headers": {
"x-api-version": {
"$ref": "#/components/headers/x-api-version"
},
"x-ratelimit-limit": {
"$ref": "#/components/headers/x-ratelimit-limit"
},
"x-ratelimit-remaining": {
"$ref": "#/components/headers/x-ratelimit-remaining"
},
"x-ratelimit-retry": {
"$ref": "#/components/headers/x-ratelimit-retry"
},
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"400": {
"description": "Invalid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"batch_transfer_id_missing": {
"$ref": "#/components/examples/batch_transfer_id_missing"
},
"batch_transfer_id_invalid": {
"$ref": "#/components/examples/batch_transfer_id_invalid"
},
"transfer_id_invalid": {
"$ref": "#/components/examples/batchTransfer_transfer_id_invalid"
},
"transfer_id_missing": {
"$ref": "#/components/examples/batchTransfer_transfer_id_missing"
},
"transfer_amount_invalid": {
"$ref": "#/components/examples/batchTransfer_transfer_amount_invalid"
},
"transfer_amount_missing": {
"$ref": "#/components/examples/batchTransfer_transfer_amount_missing"
},
"transfer_mode_invalid": {
"$ref": "#/components/examples/batchTransfer_transfer_mode_invalid"
},
"beneficiary_id_invalid": {
"$ref": "#/components/examples/batchTransfer_beneficiary_id_invalid"
},
"beneficiary_name_invalid": {
"$ref": "#/components/examples/batchTransfer_beneficiary_name_invalid"
},
"beneficiary_bank_account_invalid": {
"$ref": "#/components/examples/batchTransfer_beneficiary_bank_account_invalid"
},
"beneficiary_bank_ifsc_invalid": {
"$ref": "#/components/examples/batchTransfer_beneficiary_bank_ifsc_invalid"
},
"beneficiary_vpa_invalid": {
"$ref": "#/components/examples/batchTransfer_beneficiary_vpa_invalid"
}
}
}
}
},
"409": {
"description": "Batch transfer_id already exists",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/batch_transfer_id_already_exists"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/internal_server_error_v2"
},
"AuthenticationError": {
"$ref": "#/components/examples/authentication_internal_server_error"
}
}
}
}
}
}
},
"get": {
"summary": "Get Batch Transfer Status V2",
"x-mcp": {
"enabled": true
},
"description": "Use this API to get the status of the initiated batch transfer. You can use either the batch_transfer_id or cf_batch_transfer_id to fetch the details.",
"tags": [
"Transfers v2"
],
"operationId": "PayoutFetchBatchTransfer",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
},
{
"in": "query",
"name": "cf_batch_transfer_id",
"description": "It is the unique ID created by Cashfree Payments. You receive it in the response of the initiated batch transfer request. (Either cf_batch_transfer_id or batch_transfer_id is mandatory)",
"example": "10023",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "batch_transfer_id",
"description": "It is the unique ID you created to identify the batch transfer request.",
"example": "Sample_test",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FetchBatchTransferResponse"
},
"examples": {
"transfer_received_response": {
"$ref": "#/components/examples/batch_transfer_received_response_v2"
},
"transfer_pending_response": {
"$ref": "#/components/examples/batch_transfer_pending_response_v2"
}
}
}
},
"headers": {
"x-api-version": {
"$ref": "#/components/headers/x-api-version"
},
"x-ratelimit-limit": {
"$ref": "#/components/headers/x-ratelimit-limit"
},
"x-ratelimit-remaining": {
"$ref": "#/components/headers/x-ratelimit-remaining"
},
"x-ratelimit-retry": {
"$ref": "#/components/headers/x-ratelimit-retry"
},
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"404": {
"description": "Resource not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"CfBatchTransferIdNotFound": {
"$ref": "#/components/examples/cf_batch_transfer_id_not_found"
},
"BatchTransferIdNotFound": {
"$ref": "#/components/examples/batch_transfer_id_not_found"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/internal_server_error_v2"
},
"AuthenticationError": {
"$ref": "#/components/examples/authentication_internal_server_error"
}
}
}
}
}
}
}
},
"/beneficiary": {
"post": {
"summary": "Create Beneficiary V2",
"x-mcp": {
"enabled": false
},
"description": "Use this API to add a beneficiary to your Cashfree Payments account by providing the bank account number, IFSC, and other required details. Ensure the successful creation of the benficiary in your account before initiating a transfer.",
"tags": [
"Beneficiary v2"
],
"operationId": "PayoutCreateBeneficiary",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
}
],
"requestBody": {
"description": "Find the request parameters to create a beneficiary",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateBeneficiaryRequest"
},
"examples": {
"bene_creation_request_v2": {
"$ref": "#/components/examples/create_beneficiary_request_v2"
},
"bene_creation_request_with_only_vpa": {
"$ref": "#/components/examples/bene_creation_request_with_only_vpa"
}
}
}
}
},
"responses": {
"201": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Beneficiary"
},
"examples": {
"create_beneficiary_success_response_v2": {
"$ref": "#/components/examples/get_beneficiary_success_v2"
}
}
}
}
},
"400": {
"description": "Bad request error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"bene_id_too_long": {
"$ref": "#/components/examples/bene_id_too_large_v2"
},
"invalid_bene_id_due_unacceptable_characters": {
"$ref": "#/components/examples/invalid_bene_id_due_unacceptable_characters"
},
"bank_account_given_ifsc_not_given": {
"$ref": "#/components/examples/bank_account_given_ifsc_not_given_in_get_v2"
},
"bank_ifsc_given_account_not_given": {
"$ref": "#/components/examples/bank_ifsc_given_account_not_given_in_get_v2"
},
"bank_account_number_too_large": {
"$ref": "#/components/examples/bank_account_number_too_large"
},
"bank_account_number_too_short": {
"$ref": "#/components/examples/bank_account_number_too_short"
},
"bank_account_invalid": {
"$ref": "#/components/examples/bank_account_invalid"
},
"invalid_ifsc": {
"$ref": "#/components/examples/invalid_ifsc"
}
}
}
}
},
"403": {
"description": "Forbidden error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/APIsDisabledExampleV2"
}
}
}
}
},
"409": {
"description": "Duplicate error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"duplicate_bene_id": {
"$ref": "#/components/examples/duplicate_bene_creation_response"
},
"bene_exist_for_bank_account": {
"$ref": "#/components/examples/bene_exist_for_bank_account_and_ifsc"
}
}
}
}
},
"422": {
"description": "Unprocessable error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"same_as_source_error": {
"$ref": "#/components/examples/same_bene_as_source_v2"
},
"VBA_beneficiary_not_enabled": {
"$ref": "#/components/examples/vba_beneiciary_not_allowed"
}
}
}
}
}
}
},
"get": {
"summary": "Get Beneficiary V2",
"x-mcp": {
"enabled": false
},
"description": "Use this API to get the details of a particular beneficiary from your account. You can pass either beneficiary_id or the combination of bank_account_number and bank_ifsc to fetch the details.",
"tags": [
"Beneficiary v2"
],
"operationId": "PayoutFetchBeneficiary",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
},
{
"in": "query",
"name": "beneficiary_id",
"description": "It is the unique ID you created to identify the beneficiary while creating the beneficiary.",
"example": "JOHN18011343",
"schema": {
"type": "string",
"maxLength": 50
}
},
{
"in": "query",
"name": "bank_account_number",
"description": "It is the bank account number of the beneficiary. If bank_account_number is passed in query, bank_ifsc should also be passed.",
"example": "00001111222233",
"schema": {
"type": "string",
"maxLength": 25,
"minLength": 4
}
},
{
"in": "query",
"name": "bank_ifsc",
"description": "It is the IFSC information as present in the beneficiary's bank account information. If bank_ifsc is passed in query, bank_account_number should also be passed.",
"example": "HDFC0000001",
"schema": {
"type": "string",
"maxLength": 11,
"minLength": 11
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Beneficiary"
},
"examples": {
"valid_beneficiary_id": {
"$ref": "#/components/examples/get_beneficiary_success_v2"
}
}
}
},
"headers": {
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"all_three_params_given": {
"$ref": "#/components/examples/all_three_params_given"
},
"bank_account_given_ifsc_not_given": {
"$ref": "#/components/examples/bank_account_given_ifsc_not_given_in_get_v2"
},
"bank_ifsc_given_account_not_given": {
"$ref": "#/components/examples/bank_ifsc_given_account_not_given_in_get_v2"
},
"no_bene_identifiers_provided": {
"$ref": "#/components/examples/no_bene_identifiers_provided_v2"
},
"bene_id_too_long": {
"$ref": "#/components/examples/bene_id_too_large_v2"
},
"invalid_bene_id_due_unacceptable_characters": {
"$ref": "#/components/examples/invalid_bene_id_due_unacceptable_characters"
},
"bank_account_number_too_large": {
"$ref": "#/components/examples/bank_account_number_too_large"
},
"bank_account_number_too_short": {
"$ref": "#/components/examples/bank_account_number_too_short"
},
"bank_account_invalid": {
"$ref": "#/components/examples/bank_account_invalid"
},
"invalid_ifsc": {
"$ref": "#/components/examples/invalid_ifsc"
}
}
}
},
"headers": {
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"403": {
"description": "Forbidden error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/APIsDisabledExampleV2"
}
}
}
}
},
"404": {
"description": "Resource not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"BeneficiaryIdNotFound": {
"$ref": "#/components/examples/beneficiary_id_not_found_v2"
},
"BeneficiaryBankAccountAndIfscDoesNotExist": {
"$ref": "#/components/examples/beneficiary_with_account_does_not_exist_v2"
},
"BeneficiaryAccountExistWithDifferentIfsc": {
"$ref": "#/components/examples/bank_account_exists_with_a_different_ifsc_v2"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"InternalServerError": {
"$ref": "#/components/examples/internal_server_error_v2"
}
}
}
}
}
}
},
"delete": {
"summary": "Remove Beneficiary V2",
"x-mcp": {
"enabled": false
},
"description": "Use this API to remove an existing beneficiary from the list of added beneficiaries.",
"tags": [
"Beneficiary v2"
],
"operationId": "PayoutDeleteBeneficiary",
"deprecated": false,
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
},
{
"in": "query",
"name": "beneficiary_id",
"description": "It is the unique ID you create to identify the beneficiary. The maximum character limit is 50. Only alphabets and whitespaces are allowed.",
"example": "sample_test",
"schema": {
"type": "string",
"maxLength": 50
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Beneficiary"
},
"examples": {
"delete_beneficiary_success_response_v2": {
"$ref": "#/components/examples/delete_bene_success_response_v2"
}
}
}
},
"headers": {
"x-request-id": {
"$ref": "#/components/headers/x-request-id"
}
}
},
"400": {
"description": "Bad request error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"bene_id_too_long": {
"$ref": "#/components/examples/bene_id_too_large_v2"
}
}
}
}
},
"403": {
"description": "Forbidden error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"APIDisabled": {
"$ref": "#/components/examples/APIsDisabledExampleV2"
}
}
}
}
},
"404": {
"description": "Resource not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"BeneficiaryIdNotFound": {
"$ref": "#/components/examples/beneficiary_id_not_found_v2"
}
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorV2"
},
"examples": {
"InternalServerError": {
"$ref": "#/components/examples/internal_server_error_v2"
}
}
}
}
}
}
}
},
"/v1/authorize": {
"post": {
"summary": "Authorize",
"description": "Use this API to authenticate with the Cashfree system and obtain the authorization bearer token. All other API calls must have this token as Authorization header in the format 'Bearer <token>' (without quotes) for them to get processed. The generated token is valid for 6 minutes.",
"x-mcp": {
"enabled": true
},
"operationId": "authorize-2",
"security": [
{
"XClientID": [],
"XClientSecret": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/apiVersionHeader"
},
{
"$ref": "#/components/parameters/xRequestIDHeader"
}
],
"responses": {
"200": {
"description": "200",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_200_10"
}
}
}
},
"401": {
"description": "401",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_401"
}
}
}
}
},
"deprecated": false,
"x-readme": {
"code-samples": [
{
"language": "curl",
"code": "curl -X POST \\\n 'http://{{Host%20Url}}/payout/v1/authorize' \\\n -H 'X-Client-Id: {{client id}}' \\\n -H 'X-Client-Secret: {{client secret}}' \\"
}
],
"samples-languages": [
"curl"
]
}
}
},
"/v1/createCashgram": {
"post": {
"summary": "Create Cashgram",
"x-mcp": {
"enabled": true,
"config": {
"elicitation": {
"$ref": "#/components/x-elicitationConfig/createCashgram"
}
}
},
"description": "Use this API to create a Cashgram.",
"operationId": "create-cashgram1",
"parameters": [
{
"name": "Authorization",
"in": "header",
"description": "Bearer auth token",
"required": true,
"style": "simple",
"explode": false,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/v1_createCashgram_body"
}
}
}
},
"responses": {
"200": {
"description": "200",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_200_8"
}
}
}
},
"409": {
"description": "409",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_409_1"
}
}
}
}
},
"deprecated": false,
"security": [],
"x-readme": {
"code-samples": [
{
"language": "curl",
"code": "curl -X POST \\\n 'http://{{Host%20Url}}/payout/v1/createCashgram' \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {{Token}}'\n -d '{\n \"cashgramId\": \"JOHaN10\",\n \"amount\": \"1.00\",\n \"name\": \"John Doe\",\n \"email\": \"[email protected]\",\n \"phone\": \"9876543210\",\n \"linkExpiry\": \"2020/04/01\",\n \"remarks\": \"sample cashgram\",\n \"notifyCustomer\": 1\n}'"
},
{
"language": "text",
"code": "const cfSdk = require('cashfree-sdk');\nconst {Cashgram} = cfSdk.Payouts;\n\nconst response = await Cashgram.CreateCashgram({\n cashgramId: \"JOHaN10\",\n amount: \"1.00\",\n name: \"John Doe\",\n email: \"[email protected]\",\n phone: \"9876543210\",\n linkExpiry: \"2020/04/01\",\n remarks: \"sample cashgram\",\n notifyCustomer: 1\n });",
"name": "Node"
},
{
"language": "java",
"code": "import com.cashfree.lib.clients.Payouts;\nimport com.cashfree.lib.clients.Cashgram;\nimport com.cashfree.lib.domains.CashgramDetails\n\nPayouts payouts = Payouts.getInstance(\n Environment.PRODUCTION, \"<client_id>\", \"<client_secret>\");\npayouts.init();\nCashgram cashgram = new Cashgram(payouts);\n\nCashgramDetails cashgramDetails = new CashgramDetails()\n .setCashgramId(\"JOHaN10\")\n .setAmount(new BigDecimal(\"1.00\"))\n .setName(\"John Doe\")\n .setEmail(\"[email protected]\")\n .setPhone(\"9876543210\")\n .setLinkExpiry(LocalDateTime.now().plusMinutes(0))\n .setRemarks(\"sample cashgram\")\n .setNotifyCustomer(1);\ncashgram.createCashgram(cashgramDetails);\n}"
},
{
"language": "python",
"code": "from cashfree_sdk.payouts import Payouts\nfrom cashfree_sdk.payouts.cashgram import Cashgram\nc = Cashgram.create_cashgram(cashgramId=\"JOHaN10\", amount=\"1.1\", name=\"john doe\", email=\"[email protected]\", phone=\"9876543210\", \nlinkExpiry=\"2020/04/01\", remarks=\"sample cashgram\", notifyCustomer=1) "
}
],
"samples-languages": [
"curl",
"text",
"java",
"python"
]
}
}
},
"/v1/deactivateCashgram": {
"post": {
"summary": "Deactivate Cashgram",
"x-mcp": {
"enabled": true,
"config": {
"elicitation": {
"$ref": "#/components/x-elicitationConfig/deactivateCashgram"
}
}
},
"description": "",
"operationId": "deactivate-cashgram1",
"parameters": [
{
"name": "Authorization",
"in": "header",
"description": "Bearer auth token",
"required": true,
"style": "simple",
"explode": false,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/v1_deactivateCashgram_body"
}
}
}
},
"responses": {
"200": {
"description": "200",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_200_9"
}
}
}
},
"404": {
"description": "404",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_404_4"
}
}
}
}
},
"deprecated": false,
"security": [],
"x-readme": {
"code-samples": [
{
"language": "curl",
"code": "curl -X GET \\\n 'http://{{Host%20Url}}/payout/v1/deactivateCashgram?cashgramId=JOHaN10' \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {{Token}}'"
},
{
"language": "text",
"code": "const cfSdk = require('cashfree-sdk');\nconst {Cashgram} = cfSdk.Payouts;\nconst response = await Cashgram.DeactivateCashgram({\n cashgramId: \"JOHaN10\"\n });",
"name": "Node"
},
{
"language": "java",
"code": "import com.cashfree.lib.clients.Payouts;\nimport com.cashfree.lib.clients.Cashgram;\nimport com.cashfree.lib.domains.CashgramDetails\nPayouts payouts = Payouts.getInstance {\n Environment.PRODUCTION, \"<client_id>\", \"<client_secret>\");\npayouts.init();\nCashgram cashgram = new Cashgram(payouts);\ncashgram.deactivateCashgram(\"JOHaN10\");\n}"
},
{
"language": "python",
"code": "from cashfree_sdk.payouts import Payouts\nfrom cashfree_sdk.payouts.cashgram import Cashgram\nstatus = Cashgram.deactivate_cashgram(cashgramId=\"JOHaN10\")"
}
],
"samples-languages": [
"curl",
"text",
"java",
"python"
]
}
}
},
"/v1/getCashgramStatus": {
"get": {
"summary": "Get Cashgram Status",
"x-mcp": {
"enabled": true
},
"description": "Use this API to get the status of the Cashgram created.",
"operationId": "get-cashgram-status1",
"parameters": [
{
"name": "Authorization",
"in": "header",
"description": "Bearer auth token",
"required": true,
"style": "simple",
"explode": false,
"schema": {
"type": "string"
}
},
{
"name": "cashgramId",
"in": "query",
"description": "ID of the Cashgram",
"required": true,
"style": "form",
"explode": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "200",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_200_11"
}
}
}
},
"422": {
"description": "422",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/inline_response_404_4"
}
}
}
}
},
"deprecated": false,
"x-readme": {
"code-samples": [
{
"language": "curl",
"code": "curl -X GET \\\n 'http://{{Host%20Url}}/payout/v1/getCashgramStatus?cashgramId=JOHaN10' \\\n -H 'Content-Type: application/json' \\\n -H 'Authorization: Bearer {{Token}}'"
},
{
"language": "text",
"code": "const cfSdk = require('cashfree-sdk');\nconst {Cashgram} = cfSdk.Payouts;\n\nconst response = await Cashgram.GetCashgramStatus({\n cashgramId: \"JOHaN10\"\n });",
"name": "Node"
},
{
"language": "java",
"code": "import com.cashfree.lib.clients.Payouts;\nimport com.cashfree.lib.clients.Cashgram;\nimport com.cashfree.lib.domains.CashgramDetails\nPayouts payouts = Payouts.getInstance(\n Environment.PRODUCTION, \"<client_id>\", \"<client_secret>\");\npayouts.init();\nCashgram cashgram = new Cashgram(payouts);\ncashgram.getCashgramStatus(\"JOHaN10\");\n}"
},
{
"language": "python",
"code": "from cashfree_sdk.payouts import Payouts\nfrom cashfree_sdk.payouts.cashgram import Cashgram\nstatus = Cashgram.get_cashgram_status(cashgramId=\"JOHaN10\")"
}
],
"samples-languages": [
"curl",
"text",
"java",
"python"
]
}
}
}
}
}
```