Update a payment link
deonpay_update_linkUpdate a payment link by UUID or short_code. Change amount, status, expiration, or name without resetting other fields. Customization merges, not replaces.
Instructions
Update an existing payment link by UUID or short_code. Only send the fields you want to change — others are preserved. Common uses: pause a link (status='paused'), change its amount, extend the expiration, or rename it. The customization object is MERGED with the existing one (it does not replace it), so you can update a single visual key without losing the rest. Type cannot typically be changed once payments exist.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Link UUID or short_code. | |
| name | No | ||
| description | No | ||
| amount | No | New amount in centavos. | |
| status | No | ||
| max_uses | No | ||
| expires_at | No | ISO 8601 date or datetime string, e.g. 2026-05-15 or 2026-05-15T10:00:00Z. | |
| allow_msi | No | ||
| msi_options | No | ||
| min_amount | No | ||
| max_amount | No | ||
| merchant_reference | No | ||
| metadata | No | ||
| customization | No | Visual overrides for the hosted page. Only the keys you set are merged into the merchant defaults. |
Implementation Reference
- src/tools/links.ts:149-175 (registration)Registration of the 'deonpay_update_link' tool on the MCP server with inputSchema and handler.
server.registerTool( "deonpay_update_link", { title: "Update a payment link", description: "Update an existing payment link by UUID or short_code. Only send the fields you want to change — others are preserved. Common uses: pause a link (status='paused'), change its amount, extend the expiration, or rename it. The customization object is MERGED with the existing one (it does not replace it), so you can update a single visual key without losing the rest. Type cannot typically be changed once payments exist.", inputSchema: { id: z.string().min(1).describe("Link UUID or short_code."), name: z.string().min(1).max(255).optional(), description: z.string().optional(), amount: z.number().int().min(100).optional().describe("New amount in centavos."), status: z.enum(["active", "paused", "expired"]).optional(), max_uses: z.number().int().min(1).optional(), expires_at: IsoDateStringSchema.optional(), allow_msi: z.boolean().optional(), msi_options: z.array(z.number().int()).optional(), min_amount: z.number().int().min(100).optional(), max_amount: z.number().int().min(100).optional(), merchant_reference: z.string().optional(), metadata: z.record(z.unknown()).optional(), customization: CustomizationSchema.optional(), }, }, safeHandler(async ({ id, ...rest }) => { return client.patch(`/links/${encodeURIComponent(id)}`, compact(rest)); }), ); - src/tools/links.ts:172-174 (handler)Handler function that sends a PATCH request to /links/{id} with the filtered update payload.
safeHandler(async ({ id, ...rest }) => { return client.patch(`/links/${encodeURIComponent(id)}`, compact(rest)); }), - src/tools/links.ts:155-170 (schema)Input schema for deonpay_update_link: id (required), and optional fields like name, description, amount, status, max_uses, expires_at, customization, etc.
inputSchema: { id: z.string().min(1).describe("Link UUID or short_code."), name: z.string().min(1).max(255).optional(), description: z.string().optional(), amount: z.number().int().min(100).optional().describe("New amount in centavos."), status: z.enum(["active", "paused", "expired"]).optional(), max_uses: z.number().int().min(1).optional(), expires_at: IsoDateStringSchema.optional(), allow_msi: z.boolean().optional(), msi_options: z.array(z.number().int()).optional(), min_amount: z.number().int().min(100).optional(), max_amount: z.number().int().min(100).optional(), merchant_reference: z.string().optional(), metadata: z.record(z.unknown()).optional(), customization: CustomizationSchema.optional(), }, - src/tools/_helpers.ts:57-91 (helper)safeHandler wraps the handler with try/catch to return MCP-shaped error results. compact strips undefined/null/empty values from the request body.
export function safeHandler<TArgs>( fn: (args: TArgs) => Promise<unknown>, ): (args: TArgs) => Promise<CallToolResult> { return async (args: TArgs) => { try { const value = await fn(args); return jsonResult(value); } catch (err) { return errorResult(err); } }; } /** * Encodes the local part / full email for use in path segments. RFC 3986 says * `@` is reserved as a sub-delim, so encodeURIComponent is the safe choice. */ export function encodePathSegment(value: string): string { return encodeURIComponent(value); } /** * Strips undefined / null / empty-string entries from a body before sending. * The DeonPay API accepts missing fields cleanly but treating "" as a valid * value would override server-side defaults — usually not what the LLM means. */ export function compact<T extends Record<string, unknown>>(obj: T): Partial<T> { const out: Record<string, unknown> = {}; for (const [key, value] of Object.entries(obj)) { if (value === undefined || value === null) continue; if (typeof value === "string" && value.trim() === "") continue; out[key] = value; } return out as Partial<T>; }