Skip to main content

Creating a custom timeline entry

info

This recipe assumes you've already familiarized yourself with the Core API getting started, Authentication, and Error Handling pages.

Custom timeline entries are events specific to your business that represent important context when helping customers. For example:

  • Order refunds or delivery events
  • Subscription changes
  • Account level changes such as email changes or password resets
  • Contact form submissions
  • Outages or errors

In this recipe we'll be creating a refund timeline entry as seen in the screenshot:

A custom timeline entry in a customer's timeline

Getting started

Before we dive deep into making API requests we first need to create build a custom timeline entry.

We'll use the custom timeline entry playground to build an entry. In this example we'll use the "Refund processed" template.

The components that you can use in the custom timeline entry are documented in the CustomTimelineEntryComponent Union.

You'll need to replace the "customerId": "c_XXXXXXXXXXXXXXXXXXXXXXXXXX" with a real customer ID, which you can get from the Support App or by creating one.

We’ll be using an upsert mutation which allows to create a new custom timeline entry or update one if it exists. This mutation requires the following permissions:

  • timeline:create
  • timeline:edit

Creating a custom timeline entry

Mutation

The GraphQL mutation is the following:

mutation upsertCustomTimelineEntry($input: UpsertCustomTimelineEntryInput!) {
upsertCustomTimelineEntry(input: $input) {
result
timelineEntry {
id
customerId
timestamp {
iso8601
}
entry {
... on CustomEntry {
title
components {
... on ComponentText {
__typename
text
textSize
textColor
}
... on ComponentSpacer {
__typename
spacerSize
}
... on ComponentDivider {
__typename
spacingSize
}
... on ComponentLinkButton {
__typename
url
label
}
}
}
}
actor {
... on MachineUserActor {
machineUser {
id
fullName
publicName
}
}
}
}
error {
message
type
code
fields {
field
message
type
}
}
}
}
note

The TimelineEntry Object and Custom Entry Object have more fields you can select, but in this recipe we're only selecting a few important ones.

Variables

caution

Remember to replace c_XXXXXXXXXXXXXXXXXXXXXXXXXX with an existing customer's id.

{
"input": {
"customerId": "c_XXXXXXXXXXXXXXXXXXXXXXXXXX",
"title": "Refund processed",
"components": [
{
"componentText": {
"text": "Invoice **#1301** was refunded to customer"
}
},
{
"componentSpacer": {
"spacerSize": "XS"
}
},
{
"componentText": {
"textSize": "L",
"textColor": "SUCCESS",
"text": "**+ $413.20**"
}
},
{
"componentDivider": {
"spacingSize": "M"
}
},
{
"componentLinkButton": {
"url": "http://stripe.com",
"label": "View in Stripe"
}
}
]
}
}

Response

{
"data": {
"upsertCustomTimelineEntry": {
"result": "CREATED",
"timelineEntry": {
"id": "t_01G9F4N117KW1VDPCFB8JSM5SF",
"customerId": "c_01G8JNBQMCJ46JTR7FEB68HTN0",
"timestamp": {
"iso8601": "2022-08-02T11:21:58.055Z"
},
"entry": {
"title": "Refund processed",
"externalId": null,
"components": [
{
"__typename": "ComponentText",
"text": "Invoice **#1301** was refunded to customer",
"textSize": null,
"textColor": null
},
{
"__typename": "ComponentSpacer",
"spacerSize": "XS"
},
{
"__typename": "ComponentText",
"text": "**+ $413.20**",
"textSize": "L",
"textColor": "SUCCESS"
},
{
"__typename": "ComponentDivider",
"spacingSize": "M"
},
{
"__typename": "ComponentLinkButton",
"url": "http://stripe.com",
"label": "View in Stripe"
}
]
},
"actor": {
"machineUser": {
"id": "mu_01G8WQ1WJSRXH5C2PD5NR9TNSD",
"fullName": "Order service (Custom timeline entry)",
"publicName": "Demo Inc. Orders"
}
}
},
"error": null
}
}
}

Navigating to the customer's timeline you should also see the custom timeline entry created:

A custom timeline entry in a customer's timeline