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.