create_invoice
Create an invoice for a subscription by providing customer, payment method, currency, gateway, line items, and due/period dates.
Instructions
Create an invoice. POST /invoices. Required: companyCurrencyId, companyGatewayId, customerId, paymentMethodId, detail (array, at least one line item), dateDue, dateFrom, dateTo. Optional: billingAddress, shippingAddress (when provided: contactName, street1, city, zip, countryCode (ISO 3166-1 alpha-2), type residential|commercial), customerEmail (max 45), customerName (max 45), customerPhone (max 45), paymentType (offlinePaymentProvider|thirdPartyPaymentProvider|walletPaymentProvider|otherPayment), shippingAmount (CENTS), terms (max 200), comments (max 200). Detail: amount can be '41.00' (dollars) or 4100 (cents). Tool always sends cents to publicAPI.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| companyCurrencyId | Yes | Company currency ID (required) | |
| companyGatewayId | Yes | Company gateway ID (required) | |
| detail | Yes | Line items (required, at least one). Each: amount as '41.00' (dollars) or 4100 (cents). Tool always sends cents to publicAPI. description (max 255), qty | |
| customerId | Yes | Customer ID (required) | |
| customerEmail | No | Customer email (max 45) | |
| customerName | No | Customer name (max 45) | |
| customerPhone | No | Customer phone (max 45) | |
| paymentMethodId | Yes | Payment method ID (required) | |
| customerPaymentMethodId | No | Customer payment method ID | |
| paymentType | No | offlinePaymentProvider, thirdPartyPaymentProvider, walletPaymentProvider, or otherPayment | |
| dateDue | Yes | Due date (valid date). Required. | |
| dateFrom | Yes | Period from (valid date). Required. | |
| dateTo | Yes | Period to (valid date). Required. | |
| billingAddress | No | Optional. If provided: contactName, street1, city, zip, countryCode (ISO 3166-1 alpha-2 country code, e.g. ES, AR, MX), type (residential|commercial) | |
| shippingAddress | No | Optional. Same shape as billingAddress | |
| shippingAmount | No | Shipping amount in CENTS | |
| terms | No | Terms (max 200) | |
| comments | No | Comments (max 200) |
Implementation Reference
- Main handler function for create_invoice. Parses input via Zod schema, normalizes amounts to cents, maps addresses, and calls invoiceService.createInvoice.
async function handler(client: Client, args: Record<string, unknown> | undefined) { const parsed = schema.safeParse(args); if (!parsed.success) { return errorResult(formatValidationErrors(parsed.error)); } const raw = parsed.data; const { customerPaymentMethodId: _customerPaymentMethodId, ...rest } = raw; const detail = raw.detail.map((item) => ({ ...item, amount: normalizeAmountToCents(item.amount), })); let billingAddress: invoiceService.InvoiceAddressInput | undefined; let shippingAddress: invoiceService.InvoiceAddressInput | undefined; if (raw.billingAddress) { billingAddress = await mapShippingAddressInputToApiShippingAddress(client, raw.billingAddress); } if (raw.shippingAddress) { shippingAddress = await mapShippingAddressInputToApiShippingAddress(client, raw.shippingAddress); } const body: invoiceService.CreateInvoiceBody = { ...rest, detail, billingAddress, shippingAddress, }; return handleToolCall(() => invoiceService.createInvoice(client, body)); } - Zod input validation schema for create_invoice. Defines required fields (companyCurrencyId, companyGatewayId, customerId, paymentMethodId, detail, dateDue, dateFrom, dateTo) and optional fields (billingAddress, shippingAddress, etc.).
const schema = z .object({ companyCurrencyId: z.number().int().positive("companyCurrencyId is required"), companyGatewayId: z.number().int().positive("companyGatewayId is required"), customerId: z.number().int().positive("customerId is required"), paymentMethodId: z.number().int().positive("paymentMethodId is required"), detail: z.array(detailItemSchema).min(1, "detail must have at least one line item"), customerEmail: z.string().max(45).optional(), customerName: z.string().max(45).optional(), customerPhone: z.string().max(45).optional(), customerPaymentMethodId: z.number().int().optional(), paymentType: z.enum(paymentTypeEnum).optional(), dateDue: z .string({ required_error: "dateDue is required" }) .min(1, "dateDue is required"), dateFrom: z .string({ required_error: "dateFrom is required" }) .min(1, "dateFrom is required"), dateTo: z .string({ required_error: "dateTo is required" }) .min(1, "dateTo is required"), billingAddress: z.preprocess(stripEmptyAddress, addressSchema.optional()), shippingAddress: z.preprocess(stripEmptyAddress, addressSchema.optional()), shippingAmount: z.number().int().min(0).optional(), terms: z.string().max(200).optional(), comments: z.string().max(200).optional(), }); - TypeScript interface CreateInvoiceBody that defines the shape of the body sent to the POST /invoices API endpoint.
export interface CreateInvoiceBody { companyCurrencyId: number; companyGatewayId: number; customerId: number; paymentMethodId: number; detail: InvoiceDetailItemInput[]; customerEmail?: string; customerName?: string; customerPhone?: string; customerPaymentMethodId?: number; paymentType?: "offlinePaymentProvider" | "thirdPartyPaymentProvider" | "walletPaymentProvider" | "otherPayment"; dateDue?: string; dateFrom?: string; dateTo?: string; billingAddress?: InvoiceAddressInput; shippingAddress?: InvoiceAddressInput; /** shippingAmount in CENTS */ shippingAmount?: number; terms?: string; comments?: string; [k: string]: unknown; } - src/tools/invoices/index.ts:20-31 (registration)Registration of createInvoiceTool in the registerInvoiceTools() function that returns all invoice tools.
createInvoiceTool, updateInvoiceTool, deleteInvoiceTool, chargeInvoiceTool, chargeInvoiceExternalTool, voidInvoiceTool, ]; } export { listInvoicesTool } from "./listInvoices.js"; export { getInvoiceTool } from "./getInvoice.js"; export { createInvoiceTool } from "./createInvoice.js"; - Helper functions moneyStringToCents and normalizeAmountToCents that convert dollar strings (e.g. '41.00') or integer cents to cents for the API.
function moneyStringToCents(input: string): number { const s = input.trim(); // If there's a decimal separator, treat as dollars with up to 2 decimals. if (s.includes(".")) { if (!/^\d+(\.\d{1,2})$/.test(s)) { throw new Error( `Invalid amount string "${input}". Expected a number like "41.00" (up to 2 decimals).` ); } const [whole, frac] = s.split("."); const cents = Number(whole) * 100 + Number((frac + "00").slice(0, 2)); return cents; } // No decimal point: treat as already-in-cents (backward compatibility with old behavior). if (!/^\d+$/.test(s)) { throw new Error(`Invalid amount string "${input}". Expected "41.00" or integer cents like "4100".`); } return Number(s); } function normalizeAmountToCents(amount: unknown): number { if (typeof amount === "number") { if (!Number.isInteger(amount) || amount < 0) throw new Error("amount must be a non-negative integer (cents)"); return amount; } if (typeof amount === "string") { return moneyStringToCents(amount); } throw new Error("amount must be a number (cents) or string (e.g. '41.00' or '4100')"); }