agentsclimarketplace

Interswitch payment links

Skill rexedge/interswitch/skills/interswitch-payment-links

18 AI agent skills for Interswitch API integration — automate payment workflows with TypeScript, Node.js, and Next.js

Install
npx -y skills add rexedge/interswitch --skill interswitch-payment-links

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Interswitch Payment Links API — create shareable payment links, manage hosted fields, and process non-card payments. Use this skill whenever generating payment links for invoices, building no-code payment pages, implementing payment link management, or offering customers multiple payment options via links. Also use when you see references to payment links, Quickteller payment pages, pay-by-link, or non-card payment channels.

SKILL.md

7.3 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

Interswitch Payment Links API

Create and manage shareable payment links through the Quickteller Business platform. Enable customers to pay via a hosted payment page without building custom checkout UI.

Payment Link Features

  • Shareable URLs — Send payment links via email, SMS, WhatsApp
  • Multiple payment methods — Card, bank transfer, USSD, QR code
  • Customizable — Set amounts, descriptions, expiry dates
  • Trackable — Monitor link status and payments

Endpoints

EndpointMethodDescription
/api/v1/payment-linksPOSTCreate payment link
/api/v1/payment-linksGETList payment links
/api/v1/payment-links/{linkId}GETGet link details
/api/v1/payment-links/{linkId}PUTUpdate payment link
/api/v1/payment-links/{linkId}DELETEDeactivate payment link

Create Payment Link

interface CreatePaymentLinkRequest {
  name: string;                // Link display name
  description?: string;
  amount: number;              // Fixed amount in kobo (0 for variable)
  currency: string;            // 'NGN'
  type: 'ONE_TIME' | 'REUSABLE';
  redirectUrl?: string;        // Post-payment redirect
  customerEmail?: string;      // Pre-fill customer email
  expiryDate?: string;         // ISO 8601 expiry
  metadata?: Record<string, string>;
  customFields?: {
    fieldName: string;
    fieldType: 'TEXT' | 'EMAIL' | 'PHONE' | 'NUMBER';
    required: boolean;
  }[];
}

interface PaymentLinkResponse {
  responseCode: string;
  linkId: string;
  url: string;                 // Shareable payment URL
  name: string;
  amount: number;
  currency: string;
  type: string;
  status: 'ACTIVE' | 'EXPIRED' | 'DEACTIVATED';
  createdAt: string;
  paymentCount: number;
  totalCollected: number;
}

async function createPaymentLink(
  data: CreatePaymentLinkRequest
): Promise<PaymentLinkResponse> {
  const headers = await getAuthHeaders();

  const response = await fetch(
    `${process.env.INTERSWITCH_BASE_URL}/api/v1/payment-links`,
    {
      method: 'POST',
      headers: { ...headers, 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    }
  );

  return response.json();
}

List Payment Links

interface ListPaymentLinksParams {
  page?: number;
  pageSize?: number;
  status?: 'ACTIVE' | 'EXPIRED' | 'DEACTIVATED';
}

async function listPaymentLinks(
  params: ListPaymentLinksParams = {}
): Promise<{ links: PaymentLinkResponse[]; totalCount: number }> {
  const headers = await getAuthHeaders();

  const url = new URL(
    `${process.env.INTERSWITCH_BASE_URL}/api/v1/payment-links`
  );
  if (params.page) url.searchParams.set('page', String(params.page));
  if (params.pageSize) url.searchParams.set('pageSize', String(params.pageSize));
  if (params.status) url.searchParams.set('status', params.status);

  const response = await fetch(url.toString(), {
    method: 'GET',
    headers,
  });

  return response.json();
}

Get Link Details

async function getPaymentLink(
  linkId: string
): Promise<PaymentLinkResponse> {
  const headers = await getAuthHeaders();

  const response = await fetch(
    `${process.env.INTERSWITCH_BASE_URL}/api/v1/payment-links/${encodeURIComponent(linkId)}`,
    { method: 'GET', headers }
  );

  return response.json();
}

Update Payment Link

interface UpdatePaymentLinkRequest {
  name?: string;
  description?: string;
  amount?: number;
  expiryDate?: string;
  status?: 'ACTIVE' | 'DEACTIVATED';
}

async function updatePaymentLink(
  linkId: string,
  data: UpdatePaymentLinkRequest
): Promise<PaymentLinkResponse> {
  const headers = await getAuthHeaders();

  const response = await fetch(
    `${process.env.INTERSWITCH_BASE_URL}/api/v1/payment-links/${encodeURIComponent(linkId)}`,
    {
      method: 'PUT',
      headers: { ...headers, 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    }
  );

  return response.json();
}

Deactivate Payment Link

async function deactivatePaymentLink(
  linkId: string
): Promise<{ responseCode: string }> {
  const headers = await getAuthHeaders();

  const response = await fetch(
    `${process.env.INTERSWITCH_BASE_URL}/api/v1/payment-links/${encodeURIComponent(linkId)}`,
    { method: 'DELETE', headers }
  );

  return response.json();
}

Use Case Examples

Invoice Payment Link

const invoiceLink = await createPaymentLink({
  name: 'Invoice #INV-2024-001',
  description: 'Payment for web development services',
  amount: 50000000,           // ₦500,000
  currency: 'NGN',
  type: 'ONE_TIME',
  customerEmail: '[email protected]',
  redirectUrl: 'https://yoursite.com/payment/success',
  expiryDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
  metadata: {
    invoiceId: 'INV-2024-001',
    customerId: 'CUST_001',
  },
});

console.log('Payment link:', invoiceLink.url);
// Send to customer via email/SMS

Donation Page (Variable Amount)

const donationLink = await createPaymentLink({
  name: 'Support Our Cause',
  description: 'Donate any amount to our foundation',
  amount: 0,                  // Variable — customer chooses
  currency: 'NGN',
  type: 'REUSABLE',
  customFields: [
    { fieldName: 'Donor Name', fieldType: 'TEXT', required: true },
    { fieldName: 'Email', fieldType: 'EMAIL', required: true },
    { fieldName: 'Phone', fieldType: 'PHONE', required: false },
  ],
});

console.log('Donation page:', donationLink.url);

Event Ticket

const ticketLink = await createPaymentLink({
  name: 'Tech Conference 2025 - Regular Ticket',
  description: 'Access to all sessions and networking',
  amount: 2500000,            // ₦25,000
  currency: 'NGN',
  type: 'REUSABLE',
  redirectUrl: 'https://yoursite.com/ticket/confirmation',
  customFields: [
    { fieldName: 'Full Name', fieldType: 'TEXT', required: true },
    { fieldName: 'Company', fieldType: 'TEXT', required: false },
    { fieldName: 'Email', fieldType: 'EMAIL', required: true },
  ],
});

Non-Card Payment Options

Payment links support multiple payment methods:

MethodDescription
CardDebit/credit card (Verve, Visa, Mastercard)
Bank TransferDirect bank transfer
USSDUSSD banking codes
QR CodeScan-to-pay

Webhooks for Payment Links

Payment link events are delivered via webhooks:

  • PAYMENT_LINK.CREATED — Link generated
  • PAYMENT_LINK.COMPLETED — Payment received via link

See interswitch-webhooks skill for webhook setup.

Best Practices

  1. Set expiry dates for one-time payment links
  2. Use metadata to link payments back to your system records
  3. Monitor active links — Deactivate expired or unused links
  4. Implement redirect handling — Always verify payment server-side on redirect
  5. Track collections — Use totalCollected and paymentCount for reporting

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.