Skip to content

Commit

Permalink
Docs review (#4)
Browse files Browse the repository at this point in the history
* add my fixes to docs

* Update assignment.mdx

* First pass

* Customer cards

* Others

---------

Co-authored-by: preslavmihaylov <[email protected]>
Co-authored-by: Mathias Vagni <[email protected]>
Co-authored-by: Jordan Drake <[email protected]>
  • Loading branch information
4 people authored Nov 23, 2023
1 parent 4cb83e6 commit 54cd14c
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 92 deletions.
45 changes: 22 additions & 23 deletions api-reference/customer-cards.mdx
Original file line number Diff line number Diff line change
@@ -1,52 +1,51 @@
---
title: 'Customer Cards'
title: 'Customer cards'
sidebarTitle: 'Overview'
description: 'Live context straight from your own systems when helping customers.'
---

Customer Cards are a powerful feature in Plain that let you show information from your own systems while looking at a customer in Plain. This makes sure you always have important context when helping customers.
Customer cards are a powerful feature in Plain that let you show information from your own systems while looking at a customer in Plain. This makes sure you always have important context when helping customers.

## How it works
Customer cards are configured on Plain (see how to [how to create one](/api-reference/customer-cards/create-a-customer-card)) and requested by Plain from your APIs.

1. A customer is viewed in Plain.
2. Plain fires a request to your backend with:
## How they work

- The customer's email and, if set, `externalId`
- The configured Customer Card `key`s
1. A thread is viewed in Plain.
2. Plain fires a request to your API with:

3. Your backend responds with the JSON for each card
- The thread customer's email and, if set, `externalId`
- The configured customer card `key`s

3. Your API responds with the JSON for each card
4. Cards are shown to the user in Plain.

Based on your Customer Card settings, Plain will send a request to your API like the below example:
Based on your customer card settings, Plain will send a request to your API like the below example:

<Snippet file="customer-cards/customer-cards-basic-request.mdx" />

Your API should then reply with a list of cards matching the requested keys where each card contains the components you want to display:

<Snippet file="customer-cards/customer-cards-basic-response.mdx" />

<Note>
For a more detailed description of the protocol, check the
[protocol](/api-reference/customer-cards/protocol) page.
</Note>

## UI Components

To define what each customer card should look like, you use the Plain UI components. All the components are documented in the [Plain UI Components](/api-reference/ui-components/) section.

You can find example Customer Cards and an example API you can check out [team-plain/example-customer-cards](https://github.com/team-plain/example-customer-cards). Feel free to try these out in your workspace!

## Caching of cards

Caching of Customer Cards is controlled via two properties:

1. A time to live value (in seconds) in the Customer Card's settings. This can be changed under **Settings****Customer Cards**. Any changes will only apply to newly loaded Customer Cards.
2. An explicit time to live value (in seconds) in your API response with the key `timeToLiveSeconds`. This overrides the value from settings and allows your API to dynamically set the TTL using custom logic.

Any card that is past its expiry time will usually be deleted within a few minutes but no later than 48 hours after expiry.
You can find example customer cards and an example API you can check out [team-plain/example-customer-cards](https://github.com/team-plain/example-customer-cards). Feel free to try these out in your workspace!

## Example cards

To demonstrate what you can build with Customer Cards we've built some examples you can view and which are open source.
To demonstrate what you can build with customer cards we've built some examples you can view and which are open source.

[**Customer Cards Examples →**](https://github.com/team-plain/example-customer-cards)
[**Customer cards Examples →**](https://github.com/team-plain/example-customer-cards)

## Playground

The Customer Cards Playground lets you build and preview the component JSON needed to create a Customer Card. Use this to prototype a Customer Card before starting to build your integration.
The customer cards playground lets you build and preview the component JSON needed to create a customer card. Use this to prototype a customer card before starting to build your integration.

[**Customer Cards Playground**](https://app.plain.com/developer/customer-cards-playground/)
[**Customer cards playground**](https://app.plain.com/developer/customer-cards-playground/)
28 changes: 28 additions & 0 deletions api-reference/customer-cards/create-a-customer-card.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: 'Create a customer card'
description: 'Define the details of the customer card.'
---

To create a customer card head to **Settings****Customer cards** and enter the following details:

- **Title**: this will be displayed as the title of the card so even if the card fails to load users know which card is
errored.
- **Key**: the link between this config and your API. A key can only contain alphanumeric, hyphen, and underscore characters (regex: `[a-zA-Z0-9_-]+`)
- **Default time to live (seconds)**: by default how long Plain should cache customer cards. The minimum is 15 seconds, maximum is 1 year in seconds (31536000 seconds).
- **URL**: the URL of your API endpoint that will be built to return customer cards. It must start with `https://`.
- **Headers (optional)**: the headers Plain should pass along when making the request. While this is optional it is
**highly reccommend** to add authorization headers or other tokens that authenticate the request as your API may be
returning customer data.

<Note>
To get you started quickly, we've created a few example customer cards that you can configure and see how they look in your application. All example cards are available in our open-source repository:
[team-plain/example-customer-cards](https://github.com/team-plain/example-customer-cards)

Here is one you can try right now:

- Title: e.g. "Usage"
- Key: `usage`
- Default time to live: `120`
- URL: https://example-customer-cards.plain.com/

</Note>
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
---
title: 'Customer Cards Documentation'
title: 'Protocol'
description: 'Learn how we request customer cards from your API and how to respond to these requests.'
---

This page is intended for a technical audience that will be implementing a Customer Card API.
<Note>
This page is intended for a technical audience that will be implementing a customer card API.

Check out the [Customer Cards](/customer-cards) page for an overview.
Check out the [customer cards](/customer-cards) page for an overview of customer cards.

## Protocol overview
</Note>

Customer Cards are not proactively loaded, all of it is just-in-time and pulled when required.
Customer cards are not proactively loaded. They are just-in-time and pulled when required.
This means that if your APIs are slow then users of the Support App will see a loading spinner over the card.

The protocol is as follows:
Expand All @@ -20,52 +22,26 @@ The protocol is as follows:
details).
4. Your APIs are then called with the customer's details, so you can look up the customer's data in your systems
(see [request](#request) section for details).
5. Your APIs then return Customer Cards that consist of [Plain UI components](/api-reference/ui-components)
5. Your APIs then return customer cards that consist of [Plain UI components](/api-reference/ui-components)
(see [response](#response) section for details).
6. The cards are cached based on either an explicit TTL value in the response or the TTL in the card settings.
6. The cards are cached based on either an explicit TTL value in the response or the TTL in the card settings (see [caching](#caching)).
7. Cards are shown to the user in Plain.
8. Users can manually reload the card at any time in which case only that one card will be requested from your API.

A **few limits** to be aware of:

- Your API must **respond within 4 seconds**, or it will time out. See [retry strategy](#retry-strategy) for details on how timed-out requests are retried.
- You can have a **maximum of 25 Customer Cards per workspace** configured.
- Card **keys must be unique** within a workspace. A key can only contain alphanumeric, hyphen, and underscore characters (regex: `[a-zA-Z0-9_-]+`).

## Creating a Customer Card

To create a Customer Card head to **Settings****Customer Card** and enter the following details:

- **Title:** This will be displayed as the title of the card so even if the card fails to load users know which card is
errored.
- **Key:** The link between this config and your API. A key can only contain alphanumeric, hyphen, and underscore characters (regex: `[a-zA-Z0-9_-]+`)
- **Default time to live (seconds):** By default how long Plain should cache Customer Cards. The minimum is 15 seconds, maximum is 1 year in seconds (31536000 seconds).
- **URL:** The URL of your API endpoint that will be built to return Customer Cards. Must start with `https://`.
- **Headers (optional):** The headers Plain should pass along when making the request. While this is optional it is
**highly reccommend** to add authorization headers or other tokens that authenticate the request as your API will be
returning customer data.

<Note>
To get you started quickly, we've created a few example Customer Cards that you can configure and see how they look in your application. All example cards are available in our open-source repository:
[team-plain/example-customer-cards](https://github.com/team-plain/example-customer-cards)

Here is one you can try right now:

- Title: e.g. "Usage"
- Key: `usage`
- Default time to live: e.g. 120
- URL: https://example-customer-cards.plain.com/

</Note>
- You can configure a **maximum of 25 customer cards per workspace**.
- **Card keys must be unique within a workspace**. A key can only contain **alphanumeric**, **hyphen**, and **underscore** characters (regex: `[a-zA-Z0-9_-]+`).

## Request

Plain will make the following request to your backend:

- **Method:** `POST`
- **URL:** the URL you configured on Customer Card settings page.
- **Method**: `POST`
- **URL:** the URL you configured on customer cards settings page.
- **Headers:**
- All the headers you provided on Customer Card settings page. This should typically include authentication headers.
- All the headers you provided on customer cards settings page. This should typically include authentication headers.
- `Content-Type`: `application/json`
- `Accept`: `application/json`
- `Plain-Workspace-Id`: the ID of the workspace the customer is in. This is useful for logging or request routing.
Expand All @@ -82,9 +58,9 @@ Example request body:

### Request deduplication

If you configure multiple Customer Cards that have the same API details then Plain will batch them and make only one request.
If you configure multiple customer cards that have the same API details then Plain will batch them and make only one request.

The request deduplication logic for Customer Card configs is:
The request deduplication logic for customer card configs is:

- The following config properties are ignored: Title, Card key, Default TTL
- **API URL:** Leading and trailing whitespaces are trimmed and then compared. **This is case sensitive**.
Expand Down Expand Up @@ -114,7 +90,7 @@ Any extra cards in the response will be ignored.

</Callout>

Your API must respond with a **200 status code** or the response body won't be processed and will be treated as an error.
Your API must respond with a **`200` status code** or the response body won't be processed and will be treated as an error.

The response body must be a JSON object with:

Expand All @@ -132,19 +108,28 @@ Example response body for a card that has no data and should not be displayed an

<Snippet file="customer-cards/customer-cards-no-display-response.mdx" />

## Caching

We cache the responses we get from your APIs. This cache is controlled via two properties:

1. A time to live value (in seconds) in the customer card's settings. This can be changed under **Settings****Customer cards**. Any changes here will only apply to newly loaded customer cards.
2. An explicit time to live value (in seconds) in your API response with the key `timeToLiveSeconds`. This overrides the value from settings and allows your API to dynamically set the TTL using custom logic.

Any card that is past its expiry time will usually be deleted within a few minutes but no later than 48 hours after expiry.

## Retry strategy

Errors are classified into two categories:

1. Retriable errors: these are transient issues where retrying once is appropriate
2. Integration errors: these are typically programming or configuration errors. These errors won't be retried and cached for 5 minutes.
1. **Retriable errors**: these are transient issues where retrying once is appropriate
2. **Integration errors**: these are typically programming or configuration errors. These errors won't be retried and cached for 5 minutes.

### Retriable errors

The following errors are **retried once** after a **1-second delay**:

- HTTP 5xx response status code
- HTTP 429 Too Many Requests response status code
- HTTP `5xx` response status code
- HTTP `429` Too Many Requests response status code
- The request times out after 4 seconds.
- Plain fails to perform the request for some reason

Expand All @@ -154,10 +139,10 @@ Retriable errors are not cached, therefore if the cards are requested again via

The following errors are **not retried**:

- All HTTP 4xx response status codes except for HTTP 429 Too Many Requests response status code.
- A card key is missing in the response for example, if `subscription-details` is requested but the `cards` array in the response doesn't have an element with `subscription-details` key.
- All HTTP 4xx response status codes except for HTTP `429` Too Many Requests response status code
- A card key is missing in the response. For example, if `subscription-details` is requested but the `cards` array in the response doesn't have an element with the key `subscription-details`.
- The response body does not match the expected schema documented in [response](#response).

Integration errors are cached for 5 minutes and usually indicate a programming or configuration error.

Users can manually refresh a card in the UI in which case the card will be requested again.
Users can manually refresh a card in the UI, in which case the card will be requested again.
2 changes: 1 addition & 1 deletion api-reference/graphql/customers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ For example:

- You can [**put customers into groups**](/api-reference/graphql/customers/customer-groups/) to better organize your support queue. For example, you could group customers by pricing tier (e.g. Free Tier, Teams, Enterprise)
- You can [**create customers**](/api-reference/graphql/customers/upsert/) in Plain when they sign-up on your own site so that you can reach out to them proactively without waiting for them to get in touch.
- You can [**save your own customer's ID**](/api-reference/graphql/customers/upsert) for use with [**Customer Cards**](/customer-cards/).
- You can [**save your own customer's ID**](/api-reference/graphql/customers/upsert) for use with [**customer cards**](/customer-cards/).
2 changes: 1 addition & 1 deletion api-reference/graphql/customers/customer-groups.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: 'Customer groups'

Customer groups can be used to group and segment your customers. For example you could organise your customers by their tier "Free", "Growth, "Enterprise" or make use of groups to keep track of customers trialing beta features.

Customers can belong to one or many groups. You can filter your customers by group, allowing you to quickly focus on a subset of your customers.
Customers can belong to one or many groups. You can filter customer threads by group, allowing you to quickly focus on a subset of them.

This guide will show you how to add customers to groups using the API. You can also do this with the UI in Plain if you prefer.

Expand Down
4 changes: 2 additions & 2 deletions api-reference/graphql/threads.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ title: 'Threads'
sidebarTitle: Overview
---

Threads are the core of Plain's data model and equivalent to tickets or conversations in other support platforms. When you use Plain to help a customer you assign yourself to a thread and then mark the thread as done once you're done helping.
Threads are the core of Plain's data model and equivalent to tickets or conversations in other support platforms. When you use Plain to help a customer you assign yourself to a thread and then mark the thread as `Done` once you're done helping.

Threads are automatically created when a new email is received but can also be created via the API (when a customer submits a contact form for example).

Threads have a status which can be in either **Todo**, **Snoozed** or **Done** and can only be assigned to one person.
Threads have a status which can be in either `Todo`, `Snoozed` or `Done` and can only be assigned to one person.

Threads belong to one customer but can contain multiple email threads and customers.

Expand Down
8 changes: 4 additions & 4 deletions api-reference/graphql/threads/status-changes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ To change a threads status you need an API key with the following permissions:
- `thread:edit`
- `thread:read`

### Mark thread as done
### Mark thread as `Done`

When any activity happens in a thread, it will move back to `Todo`.

Expand All @@ -36,7 +36,7 @@ Unlike traditional ticketing software, we expect a ticket to move between `Todo`

You can snooze threads for a duration of time defined in seconds.

When any activity happens in a thread, it will be automatically unsnoozed and move to **Todo**. Otherwise threads will be unsnoozed when the timer runs out.
When any activity happens in a thread, it will be automatically unsnoozed and move to `Todo`. Otherwise threads will be unsnoozed when the timer runs out.

<Tabs>
<Tab title="Typescript SDK">
Expand All @@ -47,9 +47,9 @@ When any activity happens in a thread, it will be automatically unsnoozed and mo
</Tab>
</Tabs>

### Mark thread as Todo
### Mark thread as `Todo`

This is useful if you mistakenly marked a thread as done or snoozed a thread and want to unsnooze it. Otherwise just write a message or do what you want to do and the thread will be automatically moved back to do **Todo**.
This is useful if you mistakenly marked a thread as `Done` or snoozed a thread and want to unsnooze it. Otherwise just write a message or do what you want to do and the thread will be automatically moved back to do **Todo**.

<Tabs items={['Typescript SDK', 'GraphQL']}>
<Tab>
Expand Down
2 changes: 1 addition & 1 deletion api-reference/migrate-to-threads.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ In the ✨ **new** ✨ version of Plain:

- A customer has multiple threads
- A thread can be assigned
- A thread has a status which is either Todo, Snoozed or Done
- A thread has a status which is either `Todo`, `Snoozed` or `Done`
- A thread has labels (e.g. "Bug report")
- A thread has a priority
- All emails and comms belong to a specific thread
Expand Down
2 changes: 1 addition & 1 deletion api-reference/ui-components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: 'UI Components'
sidebarTitle: 'Overview'
---

UI components are a way of describing some UI when create threads or [events](/events) or building [Customer Cards](/customer-cards).
UI components are a way of describing some UI when create threads or [events](/events) or building [customer cards](/customer-cards).

For example - this is a button that links to Stripe.

Expand Down
2 changes: 1 addition & 1 deletion assignment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ If you want to assign a thread manually, you can use the shortcut **A** or use *

By default in Plain, once you are assigned to a thread, you will never be automatically unassigned. This ensures that if you pick up a support request, you can see it through. We call this behavior "sticky assignment".

If you'd like to change this behavior, you can do so in **Settings****Workflow**. Here you can choose to be automatically unassigned when a thread is marked as done or snoozed.
If you'd like to change this behavior, you can do so in **Settings****Workflow**. Here you can choose to be automatically unassigned when a thread is marked as `Done` or `Snoozed`.

We recommend turning sticky assignment off if your team has a shared support rota. That way, whoever is on-call can pick up any threads you didn't finish.

Expand Down
Loading

0 comments on commit 54cd14c

Please sign in to comment.