Nylon PayNylon Pay

Example Prompts

Ready-to-paste prompts with expected code shape for Nylon Pay agent skills

Copy a prompt into your AI coding agent after loading the integration skill and your language's SKILL.md from the SDK package. Each section includes a use case, a paste-ready prompt, and runnable code shape in TypeScript, Python, and PHP.

Shared rules to mention when relevant:

  • Server-side only, secrets from environment variables
  • Branch on Result (isOk / is_ok) before reading .value
  • Prefer *AndResolve / *_and_resolve unless you need live events
  • Supplied reference values must be UUIDs (or omit for auto UUID v4)
  • Webhooks: verify against the raw request body

1. Checkout: collect mobile money and mark the order paid

Use case: An ecommerce backend charges UGX mobile money at checkout and updates the order when the collection finishes.

Prompt:

Use the Nylon Pay integration skill (/docs/skills) and the SDK SKILL.md for
my language (TypeScript, Python, or PHP).

Build a server-side checkout helper that:
1. Reads NYLONPAY_API_KEY and NYLONPAY_API_SECRET from env
2. Calls collectPaymentAndResolve (or collect_payment_and_resolve) for UGX mobile money
3. Accepts amount (integer smallest unit), customer name, E.164 phone, and an
   optional UUID reference (generate one if omitted)
4. Branches on Result before reading the value; on failure return a human-friendly
   parseError / parse_error message
5. On success return { reference, status, transactionId }

Server-side only. Do not put apiSecret in browser code.

Expected shape:

import { createNylonPay, parseError } from "@nile-squad/nylonpay-ts";
import { randomUUID } from "node:crypto";

const nylonpay = createNylonPay({
  apiKey: process.env.NYLONPAY_API_KEY!,
  apiSecret: process.env.NYLONPAY_API_SECRET!,
});

export async function collectCheckoutPayment(input: {
  amount: number;
  name: string;
  phoneNumber: string;
  reference?: string;
}) {
  const result = await nylonpay.collectPaymentAndResolve({
    amount: input.amount,
    currency: "UGX",
    method: "mobileMoney",
    description: "Checkout payment",
    customer: { name: input.name, phoneNumber: input.phoneNumber },
    reference: input.reference ?? randomUUID(),
  });

  if (!result.isOk) {
    return { ok: false as const, error: parseError(result.error).message };
  }

  return {
    ok: true as const,
    reference: result.value.reference,
    status: result.value.status,
    transactionId: result.value.id,
  };
}

2. Live UI: event-driven collect with success and failed handlers

Use case: An ops dashboard shows payment progress and fulfills only after success.

Prompt:

Use the Nylon Pay skill for my language.

Wire collectPayment / collect_payment with on("processing"), on("success"),
on("failed"), and on("error") handlers. Use a stable UUID reference for
idempotency. await payment.wait() at the end (returns transaction or null, does
not throw on failure). Server-side only. Secrets from env.

Expected shape:

const reference = "550e8400-e29b-41d4-a716-446655440000";

const payment = await nylonpay.collectPayment({
  amount: 10000,
  currency: "UGX",
  method: "mobileMoney",
  description: "Order #1234",
  customer: { name: "Jane", phoneNumber: "+256700000000" },
  reference,
});

payment.on("processing", () => console.log("Waiting for customer PIN"));
payment.on("success", ({ transaction }) => fulfillOrder(transaction));
payment.on("failed", ({ error }) => notifyCustomer(error));
payment.on("error", ({ error, category, retryable }) => {
  console.error({ error, category, retryable });
});

const tx = await payment.wait();

3. Disbursement: payout wages and classify retryable errors

Use case: A payroll job sends UGX to a phone destination and retries only when the SDK marks the failure as retryable.

Prompt:

Use the Nylon Pay skill for my language.

Implement make_payout_and_resolve / makePayoutAndResolve for UGX to a phone
destination. Read keys from env. Amounts are integers in the smallest currency
unit. Branch on Result; log retryable vs non-retryable failures separately.
Accept a UUID reference or generate one. Return a small object the payroll
runner can persist.

Expected shape:

import { parseError } from "@nile-squad/nylonpay-ts";
import { randomUUID } from "node:crypto";

export async function payWage(input: {
  amount: number;
  name: string;
  phoneNumber: string;
  reference?: string;
}) {
  const result = await nylonpay.makePayoutAndResolve({
    amount: input.amount,
    currency: "UGX",
    description: "Wage payout",
    customer: { name: input.name, phoneNumber: input.phoneNumber },
    destination: {
      accountHolderName: input.name,
      accountNumber: input.phoneNumber,
    },
    reference: input.reference ?? randomUUID(),
  });

  if (!result.isOk) {
    const error = parseError(result.error);
    return { ok: false as const, retryable: error.retryable, message: error.message };
  }

  return {
    ok: true as const,
    reference: result.value.reference,
    status: result.value.status,
  };
}

4. Webhook endpoint: verify signature, then fulfill

Use case: Your server receives Nylon Pay webhooks and must reject forged bodies before updating orders.

Prompt:

Use the Nylon Pay skill for my language.

Add a webhook endpoint that reads the raw request body, verifies x-nylon-signature,
returns HTTP 401 when invalid, and acknowledges with HTTP 200 after JSON decode.
Never verify against re-encoded JSON. Secret from env.

Expected shape:

const isValid = nylonpay.verifyWebhookSignature({
  payload: req.rawBody,
  signature: req.headers["x-nylon-signature"] as string,
  secret: process.env.NYLONPAY_WEBHOOK_SECRET!,
});

if (!isValid) {
  return res.status(401).send("Invalid signature");
}

const event = JSON.parse(req.rawBody.toString());
// fulfill from event
return res.status(200).send("ok");

Use case: Cards are not available on collectPayment. Create a hosted invoice and share paymentLink with the customer.

Prompt:

Use the Nylon Pay skill for my language.

Create a hosted invoice with createInvoice / create_invoice. Add a short comment
that cards are only available through this hosted flow, not collectPayment.
Branch on Result. Return invoiceNumber and paymentLink (not .url). Server-side only.

Expected shape:

// Cards are only available through the hosted invoice flow, not collectPayment.
const result = await nylonpay.createInvoice({
  amount: 25000,
  currency: "UGX",
  description: "Pro plan",
  customerEmail: "jane@example.com",
  customerName: "Jane",
  customerPhone: "+256700000000",
});

if (!result.isOk) {
  throw new Error(parseError(result.error).message);
}

const { invoiceNumber, paymentLink } = result.value;

6. Fraud reduction: verify phone, then collect

Use case: Before charging, confirm the phone resolves, then collect using the verified customer details.

Prompt:

Use the Nylon Pay skill for my language.

Before collectPaymentAndResolve:
1. Call verifyPhone / verify_phone on the customer number
2. If verification fails, return early with parseError message
3. If it succeeds, collect UGX mobile money using phoneNumber and customerName
   from the verification result

Branch on Result for both calls. Server-side only.

Expected shape:

const verified = await nylonpay.verifyPhone({
  phoneNumber: "+256700000000",
});
if (!verified.isOk) {
  return { ok: false as const, error: parseError(verified.error).message };
}

const phoneNumber = verified.value.phoneNumber;
const customerName = verified.value.customerName || "Jane";

const paid = await nylonpay.collectPaymentAndResolve({
  amount: 10000,
  currency: "UGX",
  method: "mobileMoney",
  description: "Verified checkout",
  customer: { name: customerName, phoneNumber },
});

if (!paid.isOk) {
  return { ok: false as const, error: parseError(paid.error).message };
}

return { ok: true as const, reference: paid.value.reference, status: paid.value.status };

PhoneVerification fields: phoneNumber, customerName, verified.


Tips for better agent output

  • Load the integration skill (/docs/skills) and name your language + SDK SKILL.md in the first line.
  • Say server-side only and env for secrets.
  • Prefer *AndResolve / *_and_resolve unless you need live events.
  • Mention raw body for webhooks and UUID references when relevant.
  • Ask for parseError / parse_error on failures so messages stay human-friendly.
  • Point at sibling SDKs when the repo is multi-language so the agent does not invent a second API.

On this page