KView components

Every component and helper Kustomer gives KView templates, with live previews, a map of where each one fits, a playground, and the props for each.

KView templates build their UI from components Kustomer provides. They match the agent desktop, follow the agent's light or dark theme, and handle masked data for you. This page shows where each one fits, lets you try them, and lists every prop.

Components and helpers are global in a template: write <Field … /> or _.get(…) without importing anything.

Where components go

Each KView renders in one context, and some components are built for a specific one: Row edits attributes in the insights panel, Field lays out a KObject's body in the timeline, and CreateFormRow belongs in create forms.

InteractiveWhere components go
expanded-timeline

The body of a KObject when an agent expands it in the timeline.

Built for it
Also fits
Pick a part of the agent desktop to see the components built for it. Layout, buttons, pills, embedded cards and helpers work in every context.

Browse the components

Pick a component to see it render, change its props, and copy the template.

InteractiveKView components
38 shown
  • Order
    Order #4417

    An outer wrapper that can add Kustomer's standard padding.

  • Status
    shipped
    Notes
    Leave at the side door.

    Groups related content and leaves 28px of space below it.

  • Order number
    4417
    Placed
    Oct 2, 2026 3:04 PM
    Total
    129.5

    Lays out Columns in a row 16 units wide. Columns past 16 wrap to the next line; nothing checks the sum.

  • Size
    eight

    One column of a Grid, sized in sixteenths of the row.

  • Placed
    Oct 2, 2026 3:04 PM

    A labeled value, formatted from the attribute's metadata, so dates, numbers, booleans and links look the way they do elsewhere in Kustomer.

  • Carrier
    UPS Ground

    A label and a value as you pass them, in the field layout. It doesn't read metadata or format values.

  • An image carousel with a dot for each image, up to 450px tall. Renders nothing for an empty array.

  • Return reason

    An attribute row for the insights panel. Agents click the value to edit it, and Kustomer saves it to the record.

  • Loyalty tier
    gold

    A label and a value in the row layout. It isn't editable and doesn't read metadata.

  • One field of a KObject create form, with the input for its type.

  • Assignee
    Maya Chen

    The conversation's assignee, with Kustomer's picker for changing it.

  • Team
    Order support

    The conversation's team. Renders nothing when the org has no teams.

  • Priority
    3

    The conversation's priority, 1 to 5. Agents click to change it.

  • Priority
    3
    Assignee
    Maya Chen
    Deprecated

    A wrapper that older generated layouts put around rows. It no longer collapses anything.

  • JDJane Doe

    A link to a customer: avatar and name. Renders nothing until the customer loads.

  • Customer
    JDJane Doe

    Customer with a label, in the field layout.

  • Acme Outdoor

    A link to a company. Renders nothing until the company loads.

  • Company
    Acme Outdoor

    Company with a label, in the field layout.

  • Where is my order?

    A link to a conversation, with its channel's icon.

  • Conversation
    Where is my order?

    Conversation with a label, in the field layout.

  • Order #4398

    A link to a KObject, with its title.

  • Kobject
    Order #4398

    Kobject with a label, in the field layout.

  • The primary action in a view.

  • An outlined button for actions beside a primary one.

  • An outlined red button for destructive actions, such as cancelling an order.

  • A button without a border, for low-emphasis actions.

  • Open in Acme

    A row of buttons with 8px between them.

  • Shipped

    A small rounded status label. Each type has its own colors, and some add an icon.

  • Your page renders herekustomer.acme.exampleResizes as the page calls Kustomer.resize()

    An iframe of a page you host, sized to fit as the page calls Kustomer.resize() from the Cards SDK.

  • Your page renders herekustomer.acme.exampleFixed height 200px

    An iframe of a page you host, at a fixed size.

  • Assigned to
    Maya Chen

    Loads a Kustomer user and passes it to a function you write. Renders nothing until the user loads.

  • Lifetime value
    1840.50
    Helper

    Lodash. _.get reads nested values without throwing when a parent is missing.

  • Placed
    Oct 2, 2026
    Helper

    Moment.js, for formatting and comparing dates.

  • Helper

    Calls the Kustomer API as the agent, with the agent's permissions. Returns a promise that resolves to the response, or to the error: it never rejects.

  • Helper

    Runs one of your app's commands, so Kustomer's servers call your API with the app's secrets.

  • Helper

    Fills in merge fields, such as {{customer.email}}, from the view's data. Returns the fallback when any of them is empty.

  • createdAt
    March 14, 2024
    Helper

    Returns a standard attribute's display name in the agent's language, or the attribute name if it isn't a standard attribute.

  • Returns
    Returns are free within 30 days of delivery.
    Helper

    Renders one of the org's snippets in the agent's language, or the key if there's no such snippet.

Previews run your template in the browser with lookalikes of Kustomer's components and sample data. They follow Kustomer's rules, but spacing and icons can differ slightly from the agent desktop.

Try it

Write a template and see it render in any context. The Data tab holds the variables your template reads, as in the Data tab of Kustomer's KView editor; edit them to test missing or unusual values. Turn on Mask to see what an agent who can't view the customer's email and phone gets, and switch the preview to dark mode to check your colors.

InteractiveKView playground
Tab indents · Esc, Tab to leave
Order #4417kobject.order
Order number
4417
Placed
Oct 2, 2026 3:04 PM
Total
129.5
Shipped
Requests
  1. Clicks that call the API, run a command, open a link or save a row show up here. Nothing leaves your browser.
Runs in your browser against sample data, with lookalikes of Kustomer's components: API calls and commands are logged, not sent, and the page has no access to your API keys. To use a template, paste it into the Code tab of a KView's editor (Settings › Platform › Klasses), or into the template of your app's KView.

The playground follows Kustomer's rules: context variables are global, the template's last JSX expression is what renders, and syntax errors show the line and column. API calls, commands, links and edits are logged instead of sent, and relationship cards only find the records in the sample data.

Show rows only when they apply

In the insights panel and in create forms, a row can depend on other attributes: show Return reason only when the conversation's Contact reason is return, for example. Set this in the KView editor's Conditions tab, or in the visual builder with Only show this attribute if…. Conditions aren't available for expanded-timeline views.

InteractiveBuild a condition
Only show Return reason if…
or
Conditions tab
{
  "conversation_custom_returnReasonStr": {
    "condition": {
      "op": "or",
      "values": [
        {
          "op": "eq",
          "property": "conversation_custom_contactReasonStr",
          "values": [
            "return"
          ],
          "dependentFieldRequired": true
        },
        {
          "op": "startsWith",
          "property": "conversation_custom_categoryTree",
          "values": [
            "orders.returns"
          ]
        }
      ]
    }
  }
}
How the keys are built
Rowconversationresource_custom_customreturnReasonStrattribute
Testsconversationresource_custom_customcontactReasonStrattribute
Testsconversationresource_custom_customcategoryTreeattribute
Conversation details
Contact reason
Category
Return reason *

Required to mark the conversation done

  • Contact reason equals "return": Contact reason is "return"
  • Category is within "orders.returns": "orders.returns.damaged" is within "orders.returns"

At least one condition matches, so the row shows.

The builder follows the KView editor’s rules: which attributes a condition can test, which operators each type gets, and when dependentFieldRequired is allowed. Change the sample record in the preview to see the row show and hide. Paste the JSON into the editor’s Conditions tab; a view can hold one key per row.

The Conditions tab holds a JSON object with a key for each row that has conditions:

Conditions
{
  "conversation_custom_returnReasonStr": {
    "condition": {
      "op": "or",
      "values": [
        { "op": "eq", "property": "conversation_custom_contactReasonStr", "values": ["return"], "dependentFieldRequired": true },
        { "op": "exists", "property": "conversation_custom_trackingNumberStr", "values": [] }
      ]
    }
  }
}
KeyMeaning
Attribute keys<resource>_<attribute> for standard attributes, such as conversation_brand; <resource>_custom_<attribute> for custom ones, such as customer_custom_loyaltyTierStr; and kobject_custom_<klass>_<attribute> for KObjects, such as kobject_custom_order_giftBool.
condition.opAlways or: the row shows when any condition matches.
values[].opeq (equals the value; text ignores case), exists (has any value) or startsWith. The editor offers startsWith for free-text custom attributes and conversation and company names, where it's case-sensitive, and for tree attributes, where it matches the value or anything under it.
values[].propertyThe attribute to test, in the same key format: one of the view's own custom attributes, or a standard conversation, customer or company attribute.
values[].valuesRequired. One value, such as ["return"] or [true]: Kustomer only checks the first, so add a condition for each value you want to match. Use [] with exists.
values[].dependentFieldRequiredRequires the row before the conversation is marked done, once that condition matches. Only for custom conversation attributes in smartbar-details views, and not on conditions that test conversation_status or conversation_subStatus.

When a row's conditions stop matching, Kustomer hides it and clears its value if the agent can edit the record, so a stale answer doesn't stay behind. List attributes such as conversation_channels match eq when they include the value, and exists when they aren't empty.

Masked data and dark mode

Field, BasicField, Row, BasicRow and the other field components show masked values the way the agent is allowed to see them, and Kustomer turns a masked value placed directly inside an element, such as <div>{email}</div>, into its masked text. Anywhere else, such as inside a template string or a URL, you get the masked object itself. See Handle masked data.

Every component follows the agent's theme. For your own markup, use the theme variables instead of fixed colors.

Layout

Container

An outer wrapper that can add Kustomer's standard padding. Works in every context.

PropTypeDefaultDescription
usePaddingbooleanAdds 8px of padding on every side. Ignored in create forms.
childrenJSXThe content.
JSX
<Container usePadding>
  <BasicField label="Order" value={object.title} />
</Container>

Segment

Groups related content and leaves 28px of space below it. Works in every context.

PropTypeDefaultDescription
styleobjectInline styles as an object, such as style={{ padding: 8 }}. A CSS string is ignored.
childrenJSXThe content.
JSX
<div>
  <Segment>
    <BasicField label="Status" value={object.custom.statusStr} />
  </Segment>
  <Segment>
    <BasicField label="Notes" value={object.custom.notesTxt} />
  </Segment>
</div>

Grid

Lays out Columns in a row 16 units wide. Columns past 16 wrap to the next line; nothing checks the sum. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
styleobjectInline styles as an object, such as style={{ padding: 8 }}. A CSS string is ignored.
childrenJSXOne or more Columns.
JSX
<Grid>
  <Column size="ten">
    <Field type="kobject.order" field="orderNumberStr" value={object.custom.orderNumberStr} />
    <Field type="kobject.order" field="placedAt" value={object.custom.placedAt} />
  </Column>
  <Column size="six">
    <Field type="kobject.order" field="totalNum" value={object.custom.totalNum} />
  </Column>
</Grid>

Column

One column of a Grid, sized in sixteenths of the row. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
sizeone … sixteensixteenThe width in sixteenths, as a word. A number, such as size={8}, has no effect.
styleobjectInline styles as an object, such as style={{ padding: 8 }}. A CSS string is ignored.
childrenJSXThe content.
JSX
<Grid>
  <Column size="eight" style={{ background: 'var(--background-secondary)' }}>
    <BasicField label="Size" value="eight" />
  </Column>
</Grid>

Timeline fields

Field

A labeled value, formatted from the attribute's metadata, so dates, numbers, booleans and links look the way they do elsewhere in Kustomer. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
fieldstringRequired. The attribute name, such as totalNum. A name ending in Rel renders the related KObject as a card.
typestringRequired. The record type the attribute belongs to: customer, company, conversation or kobject.<klass>.
valueanyThe value, usually read with _.get(object, 'custom.totalNum').
labelstringReplaces the attribute's display name.
JSX
<Field type="kobject.order" field="placedAt" value={_.get(object, 'custom.placedAt')} />

BasicField

A label and a value as you pass them, in the field layout. It doesn't read metadata or format values. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
labelstringThe label.
valueanyThe value.
JSX
<BasicField label="Carrier" value="UPS Ground" />

Images

An image carousel with a dot for each image, up to 450px tall. Renders nothing for an empty array. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
imagesstring[]Required. Image URLs.
styleobjectInline styles as an object, such as style={{ padding: 8 }}. A CSS string is ignored.
JSX
<Images images={object.images} />

Detail rows

Row

An attribute row for the insights panel. Agents click the value to edit it, and Kustomer saves it to the record. Designed for smartbar-card and smartbar-details.

PropTypeDefaultDescription
fieldstringRequired. The attribute name, such as returnReasonStr.
objectstringRequired. conversation, customer, company or kobject: the record the row belongs to and saves to.
valueanyThe current value, such as _.get(conversation, 'custom.returnReasonStr').
labelstringReplaces the attribute's display name.
readOnlybooleanShows the value without letting agents edit it.
editablebooleanLets agents edit a KObject attribute. Conversation, customer and company rows are editable unless readOnly.
componentAttributesobject{ readOnly, fullWidth, displayName }. fullWidth: true puts the value under the label.
placeholderstring—Shown when there's no value.
contextstringcreate-form renders a CreateFormRow instead.
JSX
<Row
  object="conversation"
  field="returnReasonStr"
  value={_.get(conversation, 'custom.returnReasonStr')}
/>

BasicRow

A label and a value in the row layout. It isn't editable and doesn't read metadata. Designed for smartbar-card and smartbar-details.

PropTypeDefaultDescription
labelstringThe label.
valueanyThe value.
JSX
<BasicRow label="Loyalty tier" value={_.get(customer, 'custom.loyaltyTierStr', 'none')} />

CreateFormRow

One field of a KObject create form, with the input for its type. Designed for create-form.

PropTypeDefaultDescription
fieldstringRequired. The attribute name.
klassstringRequired. The Klass being created, such as kobject.order.
JSX
<div>
  <CreateFormRow klass="kobject.order" field="orderNumberStr" />
  <CreateFormRow klass="kobject.order" field="placedAt" />
</div>

RowAssignmentUser

The conversation's assignee, with Kustomer's picker for changing it. Designed for smartbar-details.

JSX
<RowAssignmentUser />

RowAssignmentTeam

The conversation's team. Renders nothing when the org has no teams. Designed for smartbar-details.

JSX
<RowAssignmentTeam />

RowPriority

The conversation's priority, 1 to 5. Agents click to change it. Designed for smartbar-details.

JSX
<RowPriority />

CollapsedRows

A wrapper that older generated layouts put around rows. It no longer collapses anything. Designed for smartbar-details.

PropTypeDefaultDescription
childrenJSXThe content.
JSX
<CollapsedRows>
  <RowPriority />
  <RowAssignmentUser />
</CollapsedRows>

Relationship cards

Customer

A link to a customer: avatar and name. Renders nothing until the customer loads. Works in every context.

PropTypeDefaultDescription
idstringRequired. The customer's ID.
JSX
<Customer id={customer.id} />

CustomerField

Customer with a label, in the field layout. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
idstringRequired. The customer's ID.
labelstringRequired. The label beside the card.
JSX
<CustomerField id={customer.id} label="Customer" />

Company

A link to a company. Renders nothing until the company loads. Works in every context.

PropTypeDefaultDescription
idstringRequired. The company's ID.
JSX
<Company id={company.id} />

CompanyField

Company with a label, in the field layout. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
idstringRequired. The company's ID.
labelstringRequired. The label beside the card.
JSX
<CompanyField id={company.id} label="Company" />

Conversation

A link to a conversation, with its channel's icon. Works in every context.

PropTypeDefaultDescription
idstringRequired. The conversation's ID.
JSX
<Conversation id={'64f0c1a2e7b9d1001f3a3001'} />

ConversationField

Conversation with a label, in the field layout. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
idstringRequired. The conversation's ID.
labelstringRequired. The label beside the card.
JSX
<ConversationField id={'64f0c1a2e7b9d1001f3a3001'} label="Conversation" />

Kobject

A link to a KObject, with its title. Works in every context.

PropTypeDefaultDescription
idstringRequired. The KObject's ID.
typestringRequired. The Klass, such as kobject.order.
JSX
<Kobject id={'64f0c1a2e7b9d1001f3a4002'} type="kobject.order" />

KobjectField

Kobject with a label, in the field layout. Designed for expanded-timeline and smartbar-card.

PropTypeDefaultDescription
idstringRequired. The KObject's ID.
typestringRequired. The Klass, such as kobject.order.
labelstringRequired. The label beside the card.
JSX
<KobjectField id={'64f0c1a2e7b9d1001f3a4002'} type="kobject.order" label="Kobject" />

Buttons and pills

Button

The primary action in a view. Works in every context.

PropTypeDefaultDescription
childrenstringRequired. The label.
onClickfunctionRuns when the agent clicks. Call KustomerRequest or runCommand here.
linkstringA URL to open in a new tab instead. The button renders as a link.
iconstringA Material Design Icons name shown before the label, such as refresh.
sizexSmall | smallsmall26px or 30px tall. medium is deprecated and renders as small.
growauto | fillautofill stretches the button to the width of its container.
marginSizenone | small | medium | large | xlarge | xxlargemediumSpace above and below. medium is 8px.
themedefault | aidefaultai uses the gradient Kustomer gives AI actions.
disabledbooleanGrays the button out; clicks don't run.
loadingbooleanShows a spinner in place of the icon and disables the button.
JSX
<Button icon="refresh"
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</Button>

ButtonSecondary

An outlined button for actions beside a primary one. Works in every context.

PropTypeDefaultDescription
childrenstringRequired. The label.
onClickfunctionRuns when the agent clicks. Call KustomerRequest or runCommand here.
linkstringA URL to open in a new tab instead. The button renders as a link.
iconstringA Material Design Icons name shown before the label, such as refresh.
sizexSmall | smallsmall26px or 30px tall. medium is deprecated and renders as small.
growauto | fillautofill stretches the button to the width of its container.
marginSizenone | small | medium | large | xlarge | xxlargemediumSpace above and below. medium is 8px.
themedefault | aidefaultai uses the gradient Kustomer gives AI actions.
disabledbooleanGrays the button out; clicks don't run.
loadingbooleanShows a spinner in place of the icon and disables the button.
JSX
<ButtonSecondary icon="refresh"
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</ButtonSecondary>

ButtonDanger

An outlined red button for destructive actions, such as cancelling an order. Works in every context.

PropTypeDefaultDescription
childrenstringRequired. The label.
onClickfunctionRuns when the agent clicks. Call KustomerRequest or runCommand here.
linkstringA URL to open in a new tab instead. The button renders as a link.
iconstringA Material Design Icons name shown before the label, such as refresh.
sizexSmall | smallsmall26px or 30px tall. medium is deprecated and renders as small.
growauto | fillautofill stretches the button to the width of its container.
marginSizenone | small | medium | large | xlarge | xxlargemediumSpace above and below. medium is 8px.
disabledbooleanGrays the button out; clicks don't run.
loadingbooleanShows a spinner in place of the icon and disables the button.
JSX
<ButtonDanger icon="refresh"
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</ButtonDanger>

ButtonText

A button without a border, for low-emphasis actions. Works in every context.

PropTypeDefaultDescription
childrenstringRequired. The label.
onClickfunctionRuns when the agent clicks. Call KustomerRequest or runCommand here.
linkstringA URL to open in a new tab instead. The button renders as a link.
iconstringA Material Design Icons name shown before the label, such as refresh.
endIconstringAn icon name shown after the label.
sizexSmall | smallsmall26px or 30px tall. medium is deprecated and renders as small.
growauto | fillautofill stretches the button to the width of its container.
marginSizenone | small | medium | large | xlarge | xxlargemediumSpace above and below. medium is 8px.
themedefault | danger | subtle | white | aidefaultThe text color. ai uses the AI gradient.
disabledbooleanGrays the button out; clicks don't run.
loadingbooleanShows a spinner in place of the icon and disables the button.
JSX
<ButtonText
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</ButtonText>

ButtonGroup

A row of buttons with 8px between them. Works in every context.

PropTypeDefaultDescription
growauto | fillautofill shares the full width between the buttons.
childrenJSXThe buttons.
JSX
<ButtonGroup>
  <Button onClick={() => runCommand('acme_orders.app.resend-receipt', { args: { orderId: '4417' } }, (err) => (err ? 'Not sent' : 'Receipt sent'))}>Resend receipt</Button>
  <ButtonSecondary link="https://shop.acme.example/orders/4417">Open in Acme</ButtonSecondary>
</ButtonGroup>

Pill

A small rounded status label. Each type has its own colors, and some add an icon. Works in every context.

PropTypeDefaultDescription
messagestringRequired. The text. Pill takes message, not children.
typeinfo | infoSecondary | success | alert | danger | active | inactive | complete | activeComplete | ai | neutralLight | neutralMedium | warning | errorRequired. warning looks like alert, error like danger, neutralLight like info and neutralMedium like infoSecondary.
iconstringReplaces the type's icon.
removeIconbooleanHides the type's icon.
tooltipstringShown on hover.
tooltipPositionstringtopWhere the tooltip opens: top, bottom, left or right.
JSX
<Pill type="success" message={_.startCase(object.custom.statusStr)} />

Embedding

DynamicCard

An iframe of a page you host, sized to fit as the page calls Kustomer.resize() from the Cards SDK. Works in every context.

PropTypeDefaultDescription
srcstringRequired. Your page, over HTTPS.
contextobjectSent to your page when it initializes and whenever the agent moves. Defaults to the view's context.
fillToWidthbooleanStretches to the width of the panel.
noPaddingbooleanRemoves the 10px of padding around the iframe.
JSX
<DynamicCard src={`https://kustomer.acme.example/card?customer=${customer.id}`} context={context} fillToWidth />

Card

An iframe of a page you host, at a fixed size. Works in every context.

PropTypeDefaultDescription
srcstringRequired. Your page, over HTTPS.
heightnumber | stringThe height, such as 320 or "320px".
widthnumber | string300The width.
contextobjectSent to your page, as with DynamicCard.
fillToWidthbooleanStretches to the width of the panel.
noPaddingbooleanRemoves the 10px of padding.
modalHeightnumber300The height of modals the page opens.
modalWidthnumber500The width of modals the page opens.
iframePermissionsstringThe iframe's allow attribute. Defaults to clipboard-read; clipboard-write; microphone *.
JSX
<Card src="https://kustomer.acme.example/returns" height={200} fillToWidth />

Data

WithUser

Loads a Kustomer user and passes it to a function you write. Renders nothing until the user loads. Works in every context.

PropTypeDefaultDescription
idstringRequired. The user's ID, such as conversation.assignedUsers[0].
children(user) => JSXRequired. Called with the user, flattened: id, name, displayName, email and its other attributes.
JSX
<WithUser id={conversation.assignedUsers[0]}>
  {(user) => <BasicRow label="Assigned to" value={user.displayName} />}
</WithUser>

Helpers

_

Lodash. _.get reads nested values without throwing when a parent is missing. Works in every context.

JSX
<BasicRow label="Lifetime value" value={_.get(customer, 'custom.lifetimeValueNum', 0).toFixed(2)} />

moment

Moment.js, for formatting and comparing dates. Works in every context.

JSX
<BasicField label="Placed" value={moment(object.custom.placedAt).format('MMM D, YYYY')} />

KustomerRequest

Calls the Kustomer API as the agent, with the agent's permissions. Returns a promise that resolves to the response, or to the error: it never rejects. Works in every context.

ParameterTypeDefaultDescription
request{ url, method, body }Required. A relative API path, such as /v1/customers/{id}; the HTTP method (default GET); and a body, sent as JSON.
formatResponseMessage(err, attributes) => stringCalled with (undefined, response.data.attributes) on success and (error) on failure. Return a string to show it as a toast.
JSX
<Button
  onClick={() =>
    KustomerRequest(
      { url: `/v1/customers/${customer.id}`, method: 'PATCH', body: { custom: { loyaltyTierStr: 'platinum' } } },
      (err, attributes) => (err ? 'Update failed' : `Tier set to ${attributes.custom.loyaltyTierStr}`),
    )
  }
>
  Upgrade to platinum
</Button>

runCommand

Runs one of your app's commands, so Kustomer's servers call your API with the app's secrets. Works in every context.

ParameterTypeDefaultDescription
namestringRequired. The command name, such as acme_orders.app.lookup-order.
body{ args, headers, body }The same body as the run endpoint.
formatResponseMessage(err, attributes) => stringCalled with the run's attributes, including statusCode. A string becomes a toast: a success toast below 400, an error toast otherwise.
JSX
<Button
  onClick={() =>
    runCommand('acme_orders.app.lookup-order', { args: { orderId: object.externalId } }, (err, run) =>
      err ? 'Acme is unreachable' : `Acme answered ${run.statusCode}`,
    )
  }
>
  Check with Acme
</Button>

renderHandlebars

Fills in merge fields, such as {{customer.email}}, from the view's data. Returns the fallback when any of them is empty. Works in every context.

ParameterTypeDefaultDescription
valuestringRequired. Text with merge fields. Each record also has email and phone shortcuts for its first email and phone.
fallbackLinkstringRequired. Returned when a merge field has no value.
dataobjectRequired. The values to merge, usually data, the template's whole context.
JSX
<ButtonSecondary link={renderHandlebars('https://shop.acme.example/admin?email={{customer.email}}', 'https://shop.acme.example/admin', data)}>
  Find in Acme
</ButtonSecondary>

internationalizeStandardAttribute

Returns a standard attribute's display name in the agent's language, or the attribute name if it isn't a standard attribute. Works in every context.

ParameterTypeDefaultDescription
attributestringRequired. The attribute name, such as createdAt.
klassstringRequired. customer, company, conversation or a KObject Klass.
JSX
<BasicRow label={internationalizeStandardAttribute('createdAt', 'customer')} value={moment(customer.createdAt).format('LL')} />

renderSnippet

Renders one of the org's snippets in the agent's language, or the key if there's no such snippet. Works in every context.

ParameterTypeDefaultDescription
snippetKeystringRequired. The snippet key.
JSX
<BasicRow label="Returns" value={renderSnippet('returns_policy')} />