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:

  • Subscription changes
  • Account level changes such as email changes or password resets
  • Custom contact forms for getting in touch, bug reports, feature requests, etc.
  • Logging outages or errors, so you know when someone gets in touch if they were affected
  • Invoicing events
  • Order refunds or delivery events

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 build a custom timeline entry.

You can use the custom timeline entry playground to prototype 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 Plain UI Components and 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 the upsertCustomTimelineEntry 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": "https://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": "https://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


If you have any problems, please get in touch with us by email on help@plain.com, and we will be happy to help.