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.
Check out the customer cards page for an overview of customer cards.
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:
A few limits to be aware of:
[a-zA-Z0-9_-]+
).Plain will make the following request to your backend:
POST
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.User-Agent
: Plain/1.0 (plain.com; help@plain.com)
cardKeys
: an array of card keys being requestedcustomer
: an object with the customer’s core details
id
: the id of the customer in Plainemail
: the email of the customerexternalId
(optional): string if the customer has an externalId
, otherwise it is null
.thread
(optional): an object with the thread’s details, if this customer card is being requested in the context of a thread
id
: the id of the thread in PlainexternalId
(optional): string if the thread has an externalId
, otherwise it is null
.Example request body:
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:
https://api.example.com/cards
https://api.example.com/cards/
https://api.example.com/Cards
Authorization
AUTHORIZATION
authorization
Bearer my-token
bearer my-token
bearer my-token
For each key requested a corresponding card MUST be returned in the response, otherwise an integration error will be returned for that card.
Any extra cards in the response will be ignored.
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:
cards
: an array of cards. Every cardKey
requested should have a corresponding key
returned. Any extra returned
cards will be ignored.
key
: the requested keytimeToLiveSeconds
(optional, nullable): can either be omitted or null
. If provided it will override the default time to live value. This allows you to control caching on a case-by-case basis.components
(nullable): null
to indicate that the card has no data or an array of Plain UI Components.Example response body for a card cached for 1 hour:
Example response body for a card that has no data and should not be displayed and TTL omitted:
We cache the responses we get from your APIs. This cache is controlled via two properties:
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.
Errors are classified into two categories:
The following errors are retried once after a 1-second delay:
5xx
response status code429
Too Many Requests response status codeRetriable errors are not cached, therefore if the cards are requested again via the Support App they will be re-requested.
The following errors are not retried:
429
Too Many Requests response status codesubscription-details
is requested but the cards
array in the response doesn’t have an element with the key subscription-details
.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.