Customer operations
Use Roundtrip when a support, finance, or operations workflow needs a person to review context and submit structured input.
refund review
const refundWorkflow = roundtrip.webhooks.workflow({
name: "refund-review",
actions: {
review: ["submit-refund"] as const,
},
});
const notification = await roundtrip.notify({
channel: "customer-ops",
push: { title: "Refund request - order #4821" },
content: {
title: "Refund request - order #4821",
description: "Customer requests partial refund.",
status: "warning",
},
detail: {
title: "Review refund",
layout: [
{
type: "form",
id: "refund-review",
fields: [
{
type: "select",
name: "decision",
label: "Decision",
required: true,
options: [
{ label: "Approve full refund", value: "full" },
{ label: "Approve partial", value: "partial" },
{ label: "Deny", value: "deny" },
],
},
{ type: "textarea", name: "note", label: "Note to customer" },
],
submit: {
label: "Submit decision",
action: refundWorkflow.action("review", "submit-refund"),
style: "primary",
},
},
],
},
response: {
mode: "required",
behavior: "resolve",
webhook: "https://ops.example.com/roundtrip/webhooks",
},
metadata: { orderId: "4821", ticketId: "tkt_9" },
});handler
const refundWorkflow = roundtrip.webhooks.workflow({
name: "refund-review",
actions: {
review: ["submit-refund"] as const,
},
});
refundWorkflow.onAction("review", "submit-refund", async ({ data }) => {
const { decision, note } = data.values ?? {};
await applyRefundDecision({
orderId: data.metadata.orderId,
decision,
note,
});
});Attach files by uploading them first with roundtrip.files.upload, then include
attachments: [{ id: file.id }] in the notification.