update_invoice
Update an invoice with status 'posted' or 'requestPayment' by modifying optional fields: customer details, dates, payment type, shipping address, and line items.
Instructions
Update an invoice. PUT /invoices/{invoiceId}. Only invoices with status 'posted' or 'requestPayment' can be updated. All body fields optional. Accepted: companyGatewayId, customerId, customerEmail, customerName, customerPhone (max 45), customerPaymentMethodId, dateDue, dateFrom, dateTo, comments, paymentType (offlinePaymentProvider|thirdPartyPaymentProvider|walletPaymentProvider), paymentMethodId, shippingAddress (when provided: contactName, street1, city, zip, countryCode (ISO 3166-1 alpha-2), type residential|commercial), shippingAmount (cents), shippingServiceId, detail (line items: amount as '41.00' dollars or 4100 cents; tool sends cents). Note: billingAddress is not accepted on update. Invoice must have customer and customerPaymentMethod set to avoid server error.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| invoiceId | Yes | Invoice ID (required) | |
| companyGatewayId | No | Company gateway ID | |
| customerId | No | Customer ID | |
| customerEmail | No | Customer email (max 45) | |
| customerName | No | Customer name (max 45) | |
| customerPhone | No | Customer phone (max 45) | |
| customerPaymentMethodId | No | Customer payment method ID | |
| dateDue | No | Due date (valid date) | |
| dateFrom | No | Period from (valid date) | |
| dateTo | No | Period to (valid date) | |
| comments | No | Comments | |
| paymentType | No | offlinePaymentProvider, thirdPartyPaymentProvider, or walletPaymentProvider | |
| paymentMethodId | No | Payment method ID | |
| shippingAddress | No | When provided: contactName, street1, city, zip, countryCode (ISO 3166-1 alpha-2 country code, e.g. ES, AR, MX), type (residential|commercial) | |
| shippingAmount | No | Shipping amount in CENTS | |
| shippingServiceId | No | Shipping service ID | |
| detail | No | Line items: each { amount: '41.00' (dollars) or 4100 (cents), description?, qty? } |
Implementation Reference
- The handler function that parses args, transforms amounts to cents, maps shipping address, and calls the service layer's updateInvoice.
async function handler(client: Client, args: Record<string, unknown> | undefined) { const parsed = schema.safeParse(args); if (!parsed.success) { return errorResult(parsed.error.errors.map((e) => e.message).join("; ")); } const { invoiceId, shippingAddress: rawShipping, ...rest } = parsed.data; let shippingAddress: invoiceService.InvoiceAddressInput | undefined; if (rawShipping) { shippingAddress = await mapShippingAddressInputToApiShippingAddress(client, rawShipping); } const detail = rest.detail ? rest.detail.map((item) => ({ ...item, amount: normalizeAmountToCents(item.amount), })) : undefined; const body: invoiceService.UpdateInvoiceBody = { ...rest, detail, shippingAddress, }; return handleToolCall(() => invoiceService.updateInvoice(client, invoiceId, body)); } - Zod validation schema for the update_invoice tool's input parameters.
const schema = z.object({ invoiceId: z.string().min(1, "invoiceId is required"), companyGatewayId: z.number().int().positive().optional(), customerId: z.number().int().positive().optional(), customerEmail: z.string().max(45).optional(), customerName: z.string().max(45).optional(), customerPhone: z.string().max(45).optional(), customerPaymentMethodId: z.number().int().optional(), dateDue: z.string().optional(), dateFrom: z.string().optional(), dateTo: z.string().optional(), comments: z.string().optional(), paymentType: z.enum(paymentTypeEnum).optional(), paymentMethodId: z.number().int().optional(), shippingAddress: addressSchema.optional(), shippingAmount: z.number().int().min(0).optional(), shippingServiceId: z.string().optional(), detail: z.array(detailItemSchema).optional(), }); - TypeScript interface for the update invoice request body passed to the service layer.
export interface UpdateInvoiceBody { companyGatewayId?: number; customerId?: number; customerEmail?: string; customerName?: string; customerPhone?: string; customerPaymentMethodId?: number; dateDue?: string; dateFrom?: string; dateTo?: string; comments?: string; paymentType?: "offlinePaymentProvider" | "thirdPartyPaymentProvider" | "walletPaymentProvider"; paymentMethodId?: number; shippingAddress?: InvoiceAddressInput; shippingAmount?: number; shippingServiceId?: string; detail?: InvoiceDetailItemInput[]; [k: string]: unknown; } - src/tools/invoices/index.ts:16-27 (registration)Registration of updateInvoiceTool alongside all other invoice tools.
export function registerInvoiceTools(): Tool[] { return [ listInvoicesTool, getInvoiceTool, createInvoiceTool, updateInvoiceTool, deleteInvoiceTool, chargeInvoiceTool, chargeInvoiceExternalTool, voidInvoiceTool, ]; } - Service-layer helper that performs the PUT /invoices/{invoiceId} HTTP call.
export async function updateInvoice( client: Client, invoiceId: string, body: UpdateInvoiceBody ): Promise<unknown> { const payload = Object.fromEntries( Object.entries(body).filter(([, v]) => v !== undefined) ) as UpdateInvoiceBody; // Always send a JSON body; some server paths expect it and may throw getId() on null when body is missing return client.put<unknown>(`/invoices/${invoiceId}`, Object.keys(payload).length ? payload : {}); }