Models
Every body the routes take and answer. A field marked always is in every answer; the others are left out when they have no value.
Where a line of content sits across its width. A carousel screen’s alignment is start or center; a block’s may be end too.
One of: start, center, end.
AppEvent
Section titled “AppEvent”The name of something a person did in the app that no server sees for itself. These are the standard ones, which PurrCRM’s package records for every app; an app’s own events are sent beside them by name, and PurrCRM takes each that the app defines. What the backend already sees (a request, a claim, an order, a sign-in) is recorded by the server that sees it, never sent by the app.
One of: app_opened, session_ended, screen_viewed, app_updated, push_permission_changed, location_permission_changed, push_opened, link_opened.
AppLinksReport
Section titled “AppLinksReport”PUT /guest/v1/app-links: what a build of the app declares, with the digest the SDK sent on its check-ins (LinksDigest), which PurrCRM checks against the links.
| Field | Type | Description |
|---|---|---|
app_version (always) | string | |
digest (always) | string | |
links (always) | array of DeclaredLink |
AppMode
Section titled “AppMode”One of: live, test.
Article
Section titled “Article”One published article, whole.
| Field | Type | Description |
|---|---|---|
blocks (always) | array of Block | |
collection | Collection | The collection it is in, when it is in one. |
id (always) | string | |
language | string | The language it is in: the one asked for when it has a translation into it, else the app’s default. Languages are every language it can be read in, the default first (the web’s hreflang). |
languages | array of string | |
out_of_date | boolean | Says the translation it is read in was written from a default that has changed since: it may be out of date. |
related (always) | array of ArticleSummary | Other articles in the same collection, at most three. |
slug (always) | string | |
summary | string | |
title (always) | string | |
updated_at (always) | string (date-time) |
ArticleRatingBody
Section titled “ArticleRatingBody”The guest saying whether an article helped. Asked again, the newer answer is kept.
| Field | Type | Description |
|---|---|---|
helpful (always) | boolean |
Articles
Section titled “Articles”Answers a search: the best matches first.
| Field | Type | Description |
|---|---|---|
items (always) | array of ArticleSummary | |
language | string | As Collections’ is: a search looks at the articles’ words in it, and at the default’s where an article has none. |
ArticleSummary
Section titled “ArticleSummary”An article in a list.
| Field | Type | Description |
|---|---|---|
collection | string | The slug of the collection it is in; empty for none. |
id (always) | string | |
slug (always) | string | |
summary | string | |
title (always) | string | |
updated_at (always) | string (date-time) |
Attachment
Section titled “Attachment”A picture in a part.
| Field | Type | Description |
|---|---|---|
bytes (always) | integer | |
content_type (always) | string | |
expires_at (always) | string (date-time) | |
id (always) | string | |
url (always) | string | Where to fetch it, until ExpiresAt; ask for the conversation again for a new one after that. |
AttachmentBody
Section titled “AttachmentBody”Asks for somewhere to upload a picture.
| Field | Type | Description |
|---|---|---|
bytes (always) | integer | The picture’s size, at most MaxAttachmentBytes. |
content_type (always) | string | One of AttachmentTypes. |
AttachmentUpload
Section titled “AttachmentUpload”Where to upload a picture: a form POST to URL with Fields first and the file last, as a field named “file”. The picture is sent by naming ID in a MessageBody before ExpiresAt.
| Field | Type | Description |
|---|---|---|
expires_at (always) | string (date-time) | |
fields (always) | object of string | |
id (always) | string | |
max_bytes (always) | integer | |
url (always) | string |
Author
Section titled “Author”Who wrote a part, as the guest is shown it: a member of staff by their first name, never their account or their address.
| Field | Type | Description |
|---|---|---|
kind (always) | AuthorKind (one of guest, teammate, bot, system) | |
name | string | A teammate’s first name or the bot’s name; empty for the guest and the messenger. |
AuthorKind
Section titled “AuthorKind”Who wrote a part.
One of: guest, teammate, bot, system.
BackgroundKind
Section titled “BackgroundKind”What a screen’s background is.
One of: plain, color, gradient, image.
Banner
Section titled “Banner”A short message over a screen.
| Field | Type | Description |
|---|---|---|
blocks (always) | array of Block | Paragraphs and headings only, at most MaxBannerBlocks. |
dismissible (always) | boolean | Dismissible shows a close button. |
link | string | Where tapping the banner goes, as Block.Link; empty for nowhere. |
style (always) | BannerStyle (one of inline, floating) |
BannerStyle
Section titled “BannerStyle”Where a banner is drawn.
One of: inline, floating.
One block of content. Only the fields its Type names are set.
| Field | Type | Description |
|---|---|---|
align | Align (one of start, center, end) | A text block’s, or an emoji’s; empty is the screen’s. |
alt | string | What a picture shows, for a guest who cannot see it. Required with ImageURL. |
aspect | ImageAspect (one of auto, 1:1, 4:3, 16:9, 3:4) | Aspect, Fit and Shape are a picture’s, as CarouselImage’s are. |
color | string | A text block’s colour, or a callout’s tint: empty is the screen’s text colour (ink, or white or near-black over a background of the screen’s own, by contrast). |
emoji | string | An emoji block’s, or the one before a callout’s words. |
fit | ImageFit (one of cover, contain) | |
image_url | string | |
items | array of ListItem | |
label | string | |
level | integer | A heading’s, 1 to MaxHeadingLevel. |
link | string | Where a button or a picture goes: a path in the app, which opens only if the app’s allow-list names it, or an https URL, which opens in the browser. |
shape | ImageShape (one of rounded, circle, square) | |
size | string | A word of the block’s own: a TextSize for a paragraph, a heading or a list, an ImageSize for a picture, a SpacerSize for a spacer. Empty is the default carousel_style.json gives the block: a heading’s follows its level, a paragraph’s is body. |
spans | array of Span | |
style | ButtonStyle (one of primary, secondary, text) | A button’s; empty is primary. |
tone | CalloutTone (one of info, good, warn) | A callout’s tint when it has no Color; empty is info. |
type (always) | BlockType (one of paragraph, heading, bullets, numbers, image, button, divider, eyebrow, callout, checklist, spacer, emoji) | |
weight | TextWeight (one of regular, medium, bold) | A paragraph’s or a heading’s; empty is regular for a paragraph and bold for a heading. |
BlockType
Section titled “BlockType”What one block of content is. Every message, post, banner, carousel screen, article and email is a list of blocks, never HTML: the app draws each natively, and PurrCRM renders email from the same list. A block type this app does not know is not drawn.
One of: paragraph, heading, bullets, numbers, image, button, divider, eyebrow, callout, checklist, spacer, emoji.
BotButton
Section titled “BotButton”One reply button: tapping it answers with its ID, and shows the guest’s answer as Label.
| Field | Type | Description |
|---|---|---|
id (always) | string | |
label (always) | string |
BotKind
Section titled “BotKind”What a help-bot part asks of the guest.
One of: says, asks, collects, suggests, hands_off, resolves.
BotPart
Section titled “BotPart”What a help-bot part asks of the guest, by Kind.
| Field | Type | Description |
|---|---|---|
articles | array of ArticleSummary | A suggestion’s, each opened in the help center. |
buttons | array of BotButton | An ask’s, and a suggestion’s yes and no. |
collect | CollectField (one of text, email, order_ref) | The data a collecting part asks for. |
kind (always) | BotKind (one of says, asks, collects, suggests, hands_off, resolves) | |
order_ref | OrderRef | What a collected order reference looks like, the app’s own: with Collect order_ref, so that the app checks an answer as PurrCRM will. |
reply | ReplyExpectation | A hand-off’s: how soon a person answers. |
BotReplyBody
Section titled “BotReplyBody”Answers the bot part PartID: with one of its buttons, by Button, or with the data it collects, as Value.
| Field | Type | Description |
|---|---|---|
button | string | |
part_id (always) | string | |
value | string |
ButtonAction
Section titled “ButtonAction”What a carousel’s button does.
One of: next, screen, back, end, link, permission.
ButtonShape
Section titled “ButtonShape”A carousel’s buttons’ shape.
One of: pill, rounded.
ButtonStyle
Section titled “ButtonStyle”How a button is drawn: primary is filled with the accent, secondary is outlined, text is the words alone.
One of: primary, secondary, text.
CalloutTone
Section titled “CalloutTone”A callout’s tint by what it says.
One of: info, good, warn.
Carousel
Section titled “Carousel”Screens the guest moves through, which may branch: each button and each answer of a choice says where it goes (a screen, or the end), and a screen’s Next says where Next and a forward swipe go. Screens may loop back (“Try again”); every screen the guest can reach has a way to the end, and a screen nothing leads to is kept but never shown.
| Field | Type | Description |
|---|---|---|
locked | boolean | A carousel the guest leaves only through its own buttons, for onboarding they must finish: no close button and no Skip, and a drag down, a tap outside and the system’s back do nothing. Left out (false) is the usual carousel, which the guest may close at any time: a carousel is dismissible unless it says otherwise. |
presentation | CarouselPresentation (one of sheet, card, full) | How it is shown; empty is a sheet. |
progress | CarouselProgress (one of dots, bar, none) | What the top bar shows of how far the guest is; empty is dots for a carousel of one line of at most seven screens, with no choice or button that branches, and a bar otherwise. |
screens (always) | array of CarouselScreen | 1 to MaxCarouselScreens, in the editor’s order, which is also where a screen’s Next goes when it names none. |
skip | boolean | Skip shows “Skip” in the top bar in place of the close button: it closes the carousel as the close button does. A locked carousel has none. |
start | string | The id of the screen it opens on; empty is the first. |
style | CarouselStyle | The carousel’s look, which a screen’s own Style overrides field by field; left out is the defaults. |
CarouselBackground
Section titled “CarouselBackground”What is behind a screen. Text over a background of colour, gradient or image is drawn white or near-black, whichever reads better against it, unless a block sets its own colour.
| Field | Type | Description |
|---|---|---|
angle | integer | A gradient’s direction in degrees, 0 to 359: 0 runs from the bottom up, 90 from left to right, as CSS’s linear-gradient. |
color | string | A colour’s, and a gradient’s first stop. |
color2 | string | A gradient’s last stop. |
image_url | string | An image background’s, an https address. It is a decoration, with no alt text: what it says belongs in the blocks. |
kind (always) | BackgroundKind (one of plain, color, gradient, image) | |
scrim | Scrim (one of none, light, dark) | Scrim darkens or lightens an image under the words; empty is none. |
CarouselButton
Section titled “CarouselButton”One of a screen’s buttons.
| Field | Type | Description |
|---|---|---|
do (always) | ButtonAction (one of next, screen, back, end, link, permission) | What it does, and says which of the rest it has. |
id (always) | string | Names it in receipts and in staff’s Records: letters, digits, - and _, at most 40, unique among the carousel’s buttons and options. |
label (always) | string | |
link | string | What link opens, as Block.Link. |
permission | CarouselPermission (one of notifications, location) | What permission asks the phone for. The app asks the way it always does, and a guest who refused before is sent to the phone’s settings instead. |
screen | string | Where screen goes (a screen’s id or “end”), and where permission goes once the phone has answered (empty is the screen’s Next). |
style | ButtonStyle (one of primary, secondary, text) | Empty for primary. |
CarouselChoice
Section titled “CarouselChoice”A question on a screen, answered by tapping options.
| Field | Type | Description |
|---|---|---|
multiple | boolean | Multiple lets the guest pick several, then Continue to the screen’s Next; a single choice goes on as soon as one is tapped, to that option’s Next. |
options (always) | array of CarouselOption | 2 to MaxCarouselOptions. |
CarouselImage
Section titled “CarouselImage”A screen’s hero picture.
| Field | Type | Description |
|---|---|---|
alt (always) | string | What it shows, for a guest who cannot see it. |
aspect | ImageAspect (one of auto, 1:1, 4:3, 16:9, 3:4) | Aspect, Fit and Shape are empty for auto, cover and rounded. |
fit | ImageFit (one of cover, contain) | |
shape | ImageShape (one of rounded, circle, square) | |
size | ImageSize (one of small, medium, large, full) | How tall it is (carousel_style.json’s hero heights); empty is medium, and full for image_full. |
url (always) | string | An https address. |
CarouselLayout
Section titled “CarouselLayout”How a screen is laid out.
One of: centred, image_top, image_full, text.
CarouselOption
Section titled “CarouselOption”One answer of a choice.
| Field | Type | Description |
|---|---|---|
emoji | string | Drawn before the label; empty for none. |
id (always) | string | Names it in receipts and in staff’s Records, as a button’s does, and is unique among the carousel’s buttons and options. |
label (always) | string | |
next | string | Where tapping it goes, in a single choice: a screen’s id, or “end”; empty is the screen’s Next. A multiple choice’s options have none. |
CarouselPermission
Section titled “CarouselPermission”What a carousel’s screen may ask the guest to allow. The app asks the way it always does, and a guest who refused before is sent to the phone’s settings instead.
One of: notifications, location.
CarouselPresentation
Section titled “CarouselPresentation”How a carousel is shown.
One of: sheet, card, full.
CarouselProgress
Section titled “CarouselProgress”What a carousel’s top bar shows of how far the guest is.
One of: dots, bar, none.
CarouselScreen
Section titled “CarouselScreen”One screen of a carousel.
| Field | Type | Description |
|---|---|---|
align | Align (one of start, center, end) | Start or center; empty is center, and start on a text screen. |
background | CarouselBackground | Behind the screen; left out is the sheet’s own. |
blocks (always) | array of Block | |
buttons | array of CarouselButton | 0 to MaxCarouselButtons, stacked: the first is the main one. None gives the screen the app’s Next (or Done). |
choice | CarouselChoice | A question the screen asks; left out for none. |
id (always) | string | Names the screen to the targets that go to it, and in receipts: letters, digits, - and _, at most 40, and never “end”. Unique among the carousel’s screens. |
image | CarouselImage | The screen’s hero picture, apart from its blocks: above them for image_top, behind them for image_full (which need one), and a smaller one above the words for centred. A text screen has none. |
layout | CarouselLayout (one of centred, image_top, image_full, text) | How the screen is laid out; empty is centred. |
name | string | Staff’s own word for the screen, in the editor and the report. It is never sent to the app. |
next | string | Where Next, a forward swipe, a multiple choice’s Continue and a single choice’s options with no Next of their own go: a screen’s id, or “end”. Empty is the screen after this one in the list, or the end after the last. |
style | CarouselStyle | Style overrides the carousel’s Style for this screen, field by field; left out is the carousel’s. |
valign | VAlign (one of top, center, bottom) | Where the content sits in the screen’s height; empty is center for centred, bottom for image_full, and top otherwise. |
CarouselStyle
Section titled “CarouselStyle”A carousel’s look. Every field is optional: empty is the default (carousel_style.json’s “defaults”), and on a screen, the carousel’s.
| Field | Type | Description |
|---|---|---|
accent | string | Accent colours the buttons, the progress and a choice’s ticks; empty is the app’s brand accent. |
button_shape | ButtonShape (one of pill, rounded) | |
corner | Corner (one of soft, round, square) | |
text_scale | TextScale (one of compact, regular, large) |
Category
Section titled “Category”Category groups events on PurrCRM site’s dashboard and in its pickers. The standard events have the standard categories below; an app’s own event names its own (lower-case letters, digits and underscores), which may be account, app or a word of the app’s, never PurrCRM.
One of: account, app, crm.
Checkin
Section titled “Checkin”Answers a check-in: what to show now, in the order to show it.
| Field | Type | Description |
|---|---|---|
messages (always) | array of InAppMessage | The in-app messages to show, the most important first: at most one large one (MessageKind.Large) a session, and at most one banner. A message answered again, not yet seen, is the same message: the app shows it once. |
next_checkin_seconds (always) | integer | The soonest the app should check in again. |
send_links | boolean | Asks the app for the destinations it declares (PUT /guest/v1/app-links), once: the check-in’s LinksDigest is one PurrCRM has not been sent. |
test_phone | boolean | A guest staff chose as a test phone: the app offers a way to check for tests at once, rather than at the next check-in. |
throttled | boolean | A check-in sooner than CheckinEvery after the last: nothing new is in it, and what the app shows stays as it is. A test phone with tests waiting is never throttled. |
unread (always) | integer | The messenger’s unread count, a chat staff started included. |
unread_notices (always) | integer | The inbox’s unread count: the notices PurrCRM pushed the guest and they have not read, for the bell. |
CheckinBody
Section titled “CheckinBody”The app asking what to show: when it opens or comes back to the front, and after it sends a batch of events.
| Field | Type | Description |
|---|---|---|
app_version (always) | string | |
holds_for_screens | boolean | Says the app holds a message meant for some screens (InAppMessage.Screens) until one of them is on: an SDK that knows how, whose host has named a screen this run. A message for some screens is never answered to an app that does not say so. |
links_digest | string | LinksDigest of the destinations the app declares, when it declares any: a check-in answers SendLinks for one PurrCRM has not been sent. |
platform (always) | DevicePlatform (one of ios, android, web) | |
screen | string | The named route on screen, when the app knows it. |
session_id (always) | string | The app’s id for this time in front, drawn when it opened or came back: a guest is shown one large message a session. |
time_zone | string | The phone’s IANA zone, for quiet hours and sending windows; left out when the phone does not say. |
CollectField
Section titled “CollectField”The kind of data the bot asks for.
One of: text, email, order_ref.
Collection
Section titled “Collection”A group of help articles.
| Field | Type | Description |
|---|---|---|
articles (always) | integer | How many published articles the guest can read in it. |
description | string | |
id (always) | string | |
slug (always) | string | |
title (always) | string |
CollectionArticles
Section titled “CollectionArticles”One collection and its articles, in staff’s order.
| Field | Type | Description |
|---|---|---|
articles (always) | array of ArticleSummary | |
collection (always) | Collection | |
language | string | As Collections’ is. |
Collections
Section titled “Collections”Every collection with an article in it, in staff’s order.
| Field | Type | Description |
|---|---|---|
items (always) | array of Collection | |
language | string |
Consent
Section titled “Consent”What PurrCRM keeps of the guest’s choices about its pushes.
| Field | Type | Description |
|---|---|---|
offers_by_push (always) | boolean |
ConsentBody
Section titled “ConsentBody”PUT consent: what the guest chose in the host’s own screens, when the host lets them choose there. Only what is sent changes.
| Field | Type | Description |
|---|---|---|
offers_by_push | boolean | The guest agreeing to offers by push: a marketing push goes only to a guest who has. |
Conversation
Section titled “Conversation”One conversation, with every part the guest sees, oldest first.
| Field | Type | Description |
|---|---|---|
assignee | Author | The member of staff answering, when one is. |
awaiting | string | The id of the bot part the help bot is waiting on an answer to; empty when it waits on none. |
created_at (always) | string (date-time) | |
id (always) | string | |
last_seq (always) | integer | The newest part’s Seq, including those the guest is not shown, so a wait asked after it waits for the next. |
parts (always) | array of Part | |
reply (always) | ReplyExpectation | |
state (always) | ConversationState (one of open, snoozed, closed) | Open or closed; snoozed is shown as open. |
ticket_id | string | The ticket this conversation is about, when there is one. |
unread (always) | integer | How many staff parts the guest has not read. |
updated_at (always) | string (date-time) |
ConversationPage
Section titled “ConversationPage”A page of the guest’s conversations, the most recently changed first. NextBefore is there when older ones are.
| Field | Type | Description |
|---|---|---|
items (always) | array of ConversationSummary | |
next_before | string |
ConversationState
Section titled “ConversationState”Where a conversation has got to. A guest is only ever shown open or closed: a conversation staff snoozed is still open to the guest who is waiting on it.
One of: open, snoozed, closed.
ConversationSummary
Section titled “ConversationSummary”A conversation in a list.
| Field | Type | Description |
|---|---|---|
created_at (always) | string (date-time) | |
id (always) | string | |
preview (always) | string | The newest part the guest sees, as a line of text. |
preview_author (always) | Author | |
state (always) | ConversationState (one of open, snoozed, closed) | |
unread (always) | integer | |
updated_at (always) | string (date-time) |
ConversationUpdate
Section titled “ConversationUpdate”Answers a wait: the parts after the one asked after that the guest sees, and the conversation as it is now. Parts is empty when the wait ran out with nothing new.
| Field | Type | Description |
|---|---|---|
awaiting | string | As Conversation.Awaiting, now. |
last_seq (always) | integer | What the next wait is after: the newest part this answer read, which is the conversation’s newest unless the parts since were too many for one answer. |
parts (always) | array of Part | |
state (always) | ConversationState (one of open, snoozed, closed) | |
unread (always) | integer |
Corner
Section titled “Corner”How round a carousel’s corners are: its sheet, its pictures, its tiles (carousel_style.json’s radii).
One of: soft, round, square.
crm.Consent
Section titled “crm.Consent”What the person agreed to.
| Field | Type | Description |
|---|---|---|
changed_at | string (date-time) | When the person made the offers choices this carries (OffersByEmail, OffersByPush), where the app keeps them. PurrCRM also learns these choices from the person directly (an email’s unsubscribe, the preference centre, the SDK’s screens, staff), and the newer choice wins: |
offers_by_email | boolean | Their agreeing to offers by email: a marketing email is sent only to a person who has. |
offers_by_push | boolean | Their agreeing to offers by push: a marketing push is sent only to a person who has, when PurrCRM pushes for the app itself. |
product_events | boolean | Their agreeing to what they do in the app being recorded (“Help improve …”): false drops every batch their app sends. |
DeclaredEvent
Section titled “DeclaredEvent”What was done with one definition.
| Field | Type | Description |
|---|---|---|
added | array of string | The props a DeclarePropsAdded gave the event. |
index (always) | integer | |
name (always) | string | |
outcome (always) | DeclareOutcome (one of created, props_added, unchanged, refused) | |
problem | string | Why a DeclareRefused was not added. |
DeclaredEvents
Section titled “DeclaredEvents”Answers EventDefinitions: one DeclaredEvent for each definition, in the order they were sent, and how many of each outcome.
| Field | Type | Description |
|---|---|---|
created (always) | integer | |
items (always) | array of DeclaredEvent | |
props_added (always) | integer | |
refused (always) | integer | |
unchanged (always) | integer |
DeclaredLink
Section titled “DeclaredLink”One destination the app declares (the SDK’s CrmLink): a name for staff, its path template (PurrCRM.AppLink’s grammar), the page on the web for a phone without the app, and the screen it shows.
| Field | Type | Description |
|---|---|---|
name (always) | string | |
path (always) | string | |
screen | string | |
web_url | string |
DeclareOutcome
Section titled “DeclareOutcome”What a declaration did with one definition.
One of: created, props_added, unchanged, refused.
Definition
Section titled “Definition”One event an app has.
| Field | Type | Description |
|---|---|---|
category (always) | Category (one of account, app, crm) | |
description (always) | string | What PurrCRM site says the event means. |
name (always) | Name (one of signed_up, signed_in, profile_updated, marketing_consent_changed, account_deletion_requested, notice_read, push_sent, email_sent, email_delivered, email_opened, email_clicked, email_bounced, email_complained, email_unsubscribed, conversation_started, message_sent, conversation_rated, bot_resolved, handed_off, ticket_created, ticket_resolved, article_viewed, article_rated, sla_breached, conversation_state_changed, message_seen, message_clicked, message_dismissed, message_answered, message_completed, survey_shown, survey_answered, survey_completed, survey_dismissed, goal_reached, segment_entered, segment_left) | |
passive | boolean | An event that happens to a person rather than one they do: it is recorded, and does not move when they were last seen. |
props | array of Prop | |
source (always) | Source (one of app, server, crm, both) |
DeviceBody
Section titled “DeviceBody”PUT devices: the registration token the host’s Firebase gave this device, which the package registers on every start and again whenever it changes.
| Field | Type | Description |
|---|---|---|
app_version | string | AppVersion and Locale are what the app is and speaks, for staff to tell devices apart; both may be left out. |
locale | string | |
platform (always) | PushPlatform (one of android, ios, web) | |
token (always) | string |
DevicePlatform
Section titled “DevicePlatform”What the app runs on, as every batch of events and every check-in says: a phone, or a browser (a website or web app calling the guest API, or a Flutter app built for the web).
One of: ios, android, web.
EmailEvent
Section titled “EmailEvent”A mail provider telling PurrCRM what became of an email it sent, signed as InboundEmail is:
| Field | Type | Description |
|---|---|---|
address (always) | string | |
detail | string | |
hard | boolean | A bounce that is permanent; a soft one is counted and suppresses nothing. |
id (always) | string | The provider’s id for the event: the same event posted twice is counted once. |
kind (always) | EmailEventKind (one of bounce, complaint, delivered) | |
message_id (always) | string | |
occurred_at (always) | string (date-time) |
EmailEventKind
Section titled “EmailEventKind”What became of an email.
One of: bounce, complaint, delivered.
EventBody
Section titled “EventBody”One thing the guest did.
| Field | Type | Description |
|---|---|---|
id (always) | string | The app’s own id for the event, a UUID drawn when it happened. A batch sent twice (the answer was lost) is kept once. |
name (always) | AppEvent (one of app_opened, session_ended, screen_viewed, app_updated, push_permission_changed, location_permission_changed, push_opened, link_opened) | |
occurred_at (always) | string (date-time) | |
props | object of string | What the event’s comment in AppEvents names, as strings: PurrCRM reads a number from its string by the event’s definition. Left out when there are none. |
EventDefinitions
Section titled “EventDefinitions”PUT /server/v1/event-definitions: the app’s own events, as its servers declare them.
| Field | Type | Description |
|---|---|---|
definitions (always) | array of Definition |
EventRejected
Section titled “EventRejected”One event of a batch refused, by its place in the batch.
| Field | Type | Description |
|---|---|---|
id (always) | string | |
index (always) | integer | |
reason (always) | string |
EventsAccepted
Section titled “EventsAccepted”Answers a batch.
| Field | Type | Description |
|---|---|---|
accepted (always) | integer | How many of the batch’s events were kept, which is fewer than were sent when some had been sent before, were refused, or the guest has turned product events off. The first batch of a guest PurrCRM has not met yet is accepted whole, and kept a moment later, once PurrCRM knows whether the guest turned product events off. |
rejected | array of EventRejected | The events refused, each alone: a name the app does not define, one its servers send, or one older than MaxEventAge. Left out when there are none. |
EventsBody
Section titled “EventsBody”A batch of events, oldest first, with the facts about the phone that every event in it shares.
| Field | Type | Description |
|---|---|---|
app_version (always) | string | |
events (always) | array of EventBody | |
platform (always) | DevicePlatform (one of ios, android, web) | |
sent_at | string (date-time) | The phone’s clock as it sent the batch, drawn again for each attempt: PurrCRM measures the phone’s clock by it (ClockSkew) and moves every event’s OccurredAt by as much, so that a phone whose clock is wrong neither makes everything late nor puts it in the future. Left out by apps older than it, whose events are taken as their clocks say. |
time_zone | string | The phone’s IANA zone name (“Europe/London”), which PurrCRM uses for a guest’s quiet hours. Left out when the phone does not say. |
ExportArticleRating
Section titled “ExportArticleRating”The guest saying whether an article helped.
| Field | Type | Description |
|---|---|---|
article (always) | string | |
helpful (always) | boolean | |
rated_at (always) | string (date-time) |
ExportAttribute
Section titled “ExportAttribute”One attribute and its value.
| Field | Type | Description |
|---|---|---|
name (always) | string | |
value (always) | string |
ExportCollected
Section titled “ExportCollected”One thing the help bot kept from a conversation: what it is called (order_ref, email) and what the guest gave.
| Field | Type | Description |
|---|---|---|
conversation_id (always) | string | |
key (always) | string | |
value (always) | string |
ExportConsentChange
Section titled “ExportConsentChange”One change of the guest’s choices, for their export: a topic’s (by its name), or a channel’s own switch (no topic).
| Field | Type | Description |
|---|---|---|
at (always) | string (date-time) | |
channel (always) | PreferenceChannel (one of email, push, in_app, chat) | |
source (always) | string | |
subscribed (always) | boolean | |
topic | string | |
wording | string |
ExportContact
Section titled “ExportContact”What the PurrCRM service keeps about a guest, their contact, for the guest’s export (Export.CRM): the attributes the app’s staff see on their profile, the tags and notes staff gave them, and the events recorded about them, newest first.
| Field | Type | Description |
|---|---|---|
article_ratings | array of ExportArticleRating | |
attributes (always) | array of ExportAttribute | The standard attributes PurrCRM derives from what the guest did (first seen, app version, orders, …) and the custom ones staff keep, by name, each value as a string. Only those that have a value. |
collected | array of ExportCollected | |
consent_history | array of ExportConsentChange | |
conversations | array of ExportConversation | Conversations, Tickets and ArticleRatings are the messenger’s and the help center’s; left out by a PurrCRM older than them, or when there are none. |
devices | array of ExportDevice | The devices the guest registered for PurrCRM’s pushes, and Notices their inbox; left out by a PurrCRM older than them, or when there are none. |
events (always) | array of ExportEvent | |
events_truncated | boolean | The export holding only the newest MaxExportEvents events of more. |
notes (always) | array of ExportNote | What staff wrote about the guest. Who wrote each is left out: that is the member of staff’s, not the guest’s. |
notices | array of ExportNotice | |
receipts | array of ExportReceipt | Receipts and SurveyResponses are outbound’s: the messages the guest was sent or shown, and their answers to surveys; left out by a PurrCRM older than them, or when there are none. |
subscriptions | array of ExportSubscription | The guest’s own choices about the app’s topics, and ConsentHistory every change of them and of their channels’ switches; left out by a PurrCRM older than them, or when there are none. |
survey_responses | array of ExportSurveyResponse | |
tags (always) | array of string | The names of the tags staff put on the guest. |
test_phone | ExportTestPhone | The guest’s account being a test phone, which staff send messages to so as to try them, and TestSends the tests sent to it (kept a week); left out by a PurrCRM older than them, or when there are none. |
test_sends | array of ExportTestSend | |
tickets | array of ExportTicket | |
workflows | array of ExportWorkflowRun | The runs of PurrCRM’s workflows the guest was in, and Collected what the help bot kept from their conversations; left out by a PurrCRM older than them, or when there are none. |
ExportConversation
Section titled “ExportConversation”One of the guest’s conversations, for their export: every part they could see, and their rating. Staff’s notes are left out, and so is who each member of staff is beyond the name they were shown.
| Field | Type | Description |
|---|---|---|
created_at (always) | string (date-time) | |
id (always) | string | |
parts (always) | array of ExportPart | |
rating | integer | |
remark | string | |
state (always) | ConversationState (one of open, snoozed, closed) |
ExportDevice
Section titled “ExportDevice”One device the guest registered for pushes, for their export. Its token is a credential for the device and is left out.
| Field | Type | Description |
|---|---|---|
app_version | string | |
created_at (always) | string (date-time) | |
last_seen_at (always) | string (date-time) | |
locale | string | |
platform (always) | PushPlatform (one of android, ios, web) |
ExportEvent
Section titled “ExportEvent”One event recorded about the guest: one of AppEvents, or a server event.
| Field | Type | Description |
|---|---|---|
name (always) | string | |
occurred_at (always) | string (date-time) | |
props | object of string |
ExportNote
Section titled “ExportNote”One note staff wrote about the guest.
| Field | Type | Description |
|---|---|---|
body (always) | string | |
created_at (always) | string (date-time) |
ExportNotice
Section titled “ExportNotice”One notice in the guest’s inbox, for their export.
| Field | Type | Description |
|---|---|---|
body (always) | string | |
created_at (always) | string (date-time) | |
link | string | |
read_at | string (date-time) | |
title (always) | string | |
type (always) | PushType (one of support_reply, crm_message) |
ExportPart
Section titled “ExportPart”One part of an exported conversation. A picture is named by its content type and size: the file is sent on request, not in the export.
| Field | Type | Description |
|---|---|---|
attachments | array of string | |
author (always) | Author | |
blocks | array of Block | |
created_at (always) | string (date-time) | |
kind (always) | PartKind (one of message, reply, note, bot, assignment, state, rating_request) | |
text | string |
ExportReceipt
Section titled “ExportReceipt”One message the guest was sent or shown, for their export: what it was and what they did with it.
| Field | Type | Description |
|---|---|---|
clicked_at | string (date-time) | |
completed_at | string (date-time) | |
dismissed_at | string (date-time) | |
kind (always) | MessageKind (one of chat, post, banner, carousel, survey, push, email) | |
message (always) | string | The message’s name, as staff called it. |
seen_at | string (date-time) | |
sent_at | string (date-time) | |
variant | string |
ExportSubscription
Section titled “ExportSubscription”One of the guest’s choices about a topic by a channel, for their export: when and how it was made, and under which wording.
| Field | Type | Description |
|---|---|---|
changed_at (always) | string (date-time) | |
channel (always) | PreferenceChannel (one of email, push, in_app, chat) | |
source (always) | string | |
subscribed (always) | boolean | |
topic (always) | string | |
wording | string |
ExportSurveyAnswer
Section titled “ExportSurveyAnswer”One answer, as the words of the question and of the answer.
| Field | Type | Description |
|---|---|---|
answer (always) | string | |
question (always) | string |
ExportSurveyResponse
Section titled “ExportSurveyResponse”The guest’s answers to one survey.
| Field | Type | Description |
|---|---|---|
answers (always) | array of ExportSurveyAnswer | |
completed_at | string (date-time) | |
started_at (always) | string (date-time) | |
survey (always) | string |
ExportTestPhone
Section titled “ExportTestPhone”The guest’s account being a test phone: staff’s name for it, and since when. Who in staff chose it is theirs, not the guest’s, and is left out.
| Field | Type | Description |
|---|---|---|
added_at (always) | string (date-time) | |
label | string |
ExportTestSend
Section titled “ExportTestSend”One test staff sent to the guest’s test phone: what it was, and what became of it. Who sent it is left out.
| Field | Type | Description |
|---|---|---|
answers | array of ExportSurveyAnswer | A survey test’s, in the words of the questions. |
clicked_at | string (date-time) | |
completed_at | string (date-time) | |
dismissed_at | string (date-time) | |
kind (always) | MessageKind (one of chat, post, banner, carousel, survey, push, email) | |
name (always) | string | The message’s, as staff called it when they sent it, or the built-in sample’s, when Sample. |
outcome | string | A push’s or a chat’s: sent, notifications_off, not_sent or started. |
picked_up_at | string (date-time) | When the app took an in-app test at a check-in; what the guest did with it follows. |
sample | boolean | |
seen_at | string (date-time) | |
sent_at (always) | string (date-time) |
ExportTicket
Section titled “ExportTicket”One of the guest’s tickets, for their export.
| Field | Type | Description |
|---|---|---|
created_at (always) | string (date-time) | |
fields (always) | array of TicketField | |
ref (always) | string | |
resolved_at | string (date-time) | |
state (always) | TicketState (one of submitted, in_progress, waiting_on_guest, resolved) | |
title (always) | string | |
type (always) | string |
ExportWorkflowRun
Section titled “ExportWorkflowRun”One run of a workflow the guest was in: the workflow’s name, where the run is and, once it has ended, how.
| Field | Type | Description |
|---|---|---|
ended_at | string (date-time) | |
outcome | string | |
started_at (always) | string (date-time) | |
state (always) | string | |
workflow (always) | string |
Feature
Section titled “Feature”One of PurrCRM’s parts an app has switched on for its guests. The app shows nothing of a part it has not been given, and ignores a word it does not know, so a part can be switched on without a release and an older app is not broken by a newer word.
One of: messenger, help_center, in_app_messages.
FieldType
Section titled “FieldType”What a ticket’s field holds.
One of: text, list, number, bool, date.
ForgetDeviceBody
Section titled “ForgetDeviceBody”DELETE devices: the token the package registered, on sign-out, so that the next guest on the device is not pushed the last one’s.
| Field | Type | Description |
|---|---|---|
token (always) | string |
HomeCard
Section titled “HomeCard”One card of the messenger’s home. Only what its Kind uses is set: a link card’s Title, Text and Link; a status card’s Text, and its Title and Link when it has them; an articles card’s Articles. The send, search, conversations and tickets cards are drawn from the rest of the home (its open conversations, its tickets) and the app’s own words.
| Field | Type | Description |
|---|---|---|
articles | array of ArticleSummary | |
id (always) | string | The card’s, as staff made it: the same on every read. |
kind (always) | HomeCardKind (one of send, search_help, articles, conversations, tickets, link, status) | |
link | string | A path in the app or an https link, personalised. |
text | string | |
title | string |
HomeCardKind
Section titled “HomeCardKind”What a card of the messenger’s home is.
One of: send, search_help, articles, conversations, tickets, link, status.
Identify
Section titled “Identify”PUT /server/v1/contacts/{external_id}: who the person is. Only what is sent changes.
| Field | Type | Description |
|---|---|---|
attributes | object of any | The app’s custom attributes, by name, each held to its definition: a string, a number, true or false, a date as 2026-09-27 or an RFC 3339 time, or a list of strings. Null removes the value. One PurrCRM computes is refused; one the app does not define is made on first sight, its type worked out, for review, unless the app’s strict data refuses it. |
consent | crm.Consent | |
display_name | string | What they are called, at most 100 characters. |
email | string | Their address, which PurrCRM sends email to. |
language | string | Their language as a BCP 47 tag (“en”, “en-GB”). |
provider | string | How they sign in, in the app’s own word: apple, google, password, or any other of at most 40 characters. |
signed_up_at | string (date-time) | When they made their account. |
time_zone | string | Their IANA zone (“Europe/London”). |
IdentifyAnswer
Section titled “IdentifyAnswer”Answers an Identify: the person, and whether this made them.
| Field | Type | Description |
|---|---|---|
created (always) | boolean | |
external_id (always) | string |
ImageAspect
Section titled “ImageAspect”A picture’s shape, width to height; auto is the picture’s own.
One of: auto, 1:1, 4:3, 16:9, 3:4.
ImageFit
Section titled “ImageFit”How a picture fills its box: cover crops it to fill, contain shows it whole.
One of: cover, contain.
ImageShape
Section titled “ImageShape”A picture’s corners.
One of: rounded, circle, square.
ImageSize
Section titled “ImageSize”How much of the screen a picture takes: a hero’s height, or an image block’s width.
One of: small, medium, large, full.
InAppMessage
Section titled “InAppMessage”One message to show: its kind’s content, and the variant the guest was given, which every receipt about it says again.
| Field | Type | Description |
|---|---|---|
banner | Banner | Exactly one of these is set, the one Kind names. |
carousel | Carousel | |
id (always) | string | |
kind (always) | MessageKind (one of chat, post, banner, carousel, survey, push, email) | |
post | Post | |
screens | array of string | The screens it is shown on, when it is meant for some: the app holds it until one of them is on (the screen its host names), and shows it then. Left out for a message shown wherever the guest is. |
survey | Survey | |
test | boolean | A copy staff sent to a test phone: ID is the test’s, not the message’s. It is shown at once, whatever the caps, the audience and the one large message a session, and what the guest does with it (receipts, answers) is kept with the test, never in the message’s report or results. |
variant (always) | string |
InboundEmail
Section titled “InboundEmail”A reply by email to one of PurrCRM’s support emails, as the mail provider’s inbound hook posts it to PurrCRM, signed:
| Field | Type | Description |
|---|---|---|
from (always) | string | |
id (always) | string | The provider’s id for the message: the same message posted twice is threaded once. |
received_at (always) | string (date-time) | |
subject | string | |
text (always) | string | The plain-text body, the quoted email under the reply still in it: PurrCRM keeps the reply alone. |
to (always) | array of string |
ListItem
Section titled “ListItem”One item of a list.
| Field | Type | Description |
|---|---|---|
spans (always) | array of Span |
MessageBody
Section titled “MessageBody”The guest writing: in a new conversation, in one of theirs, or on a ticket. Text, pictures, or both.
| Field | Type | Description |
|---|---|---|
attachment_ids | array of string | Pictures uploaded through an AttachmentUpload and not yet sent. |
text (always) | string |
MessageKind
Section titled “MessageKind”What an outbound message is. Only the in-app kinds reach the app at a check-in (InAppKinds); a chat arrives in the messenger as a conversation staff started, a push as a Push of type crm_message, and an email by email.
One of: chat, post, banner, carousel, survey, push, email.
MessengerHome
Section titled “MessengerHome”The messenger’s first screen.
| Field | Type | Description |
|---|---|---|
articles (always) | array of ArticleSummary | The help center’s featured articles, when the help center is switched on; empty otherwise. |
layout | MessengerLayout | The home as the app’s staff set it: its greeting, its team, its cards in order and its options, worked out for this guest now. Null until they publish one, and the app then draws its own home as before. |
open (always) | array of ConversationSummary | The guest’s open conversations, the most recently changed first, at most three. |
opening | MessengerOpening | What the help bot says to a new conversation before the guest writes, worked out for them now; null when no help bot greets them, or when the one that would does something first that only a conversation can have done (a tag, a webhook, a hand-off), and so speaks once they have written. Null too while the app’s staff allow no new conversation now (MessengerLayout.NewConversation). |
reply (always) | ReplyExpectation | |
tickets (always) | array of SupportTicketSummary | The guest’s tickets not yet resolved, and those resolved in the last week. |
unread (always) | integer | Every staff part the guest has not read, in every conversation: the badge on the app’s top bar. |
MessengerLayout
Section titled “MessengerLayout”The messenger’s home as the app’s staff published it, for one guest at one moment: the greeting with their name in it, the faces, how soon a reply comes, the cards they are to see now (in order, those for a segment they are not in, a status out of its dates and the help center’s while it is off already left out) and what they may do.
| Field | Type | Description |
|---|---|---|
attachments (always) | boolean | The guest being able to send pictures: PurrCRM refuses a picture (attachment_invalid) while it is false. |
away_text | string | Said in place of either while the team is away (Reply.Open false); empty for “We’re back …”. |
cards (always) | array of HomeCard | |
faces (always) | TeamFaces (one of auto, chosen, none) | |
greeting (always) | string | The heading, personalised; empty for the app’s own words (“Talk to the … team”). |
help_center (always) | boolean | The home pointing to the help center (a search card, articles, a link to browse it). |
intro (always) | string | A line under it, personalised; empty for none. |
names | boolean | Names writes the chosen teammates’ names under their faces. |
new_conversation (always) | NewConversations (one of always, when_none_open, never) | When the guest may start one; the send card is left out of Cards whenever they may not now. |
reply_text | string | Says how soon a reply comes in staff’s own words, in place of the line worked out from Reply; empty for that line. |
team (always) | array of Author | The teammates to show when Faces is chosen, by first name, as Author of kind teammate; empty otherwise. |
MessengerOpening
Section titled “MessengerOpening”A help bot’s first words to a new conversation, as the guest would be shown them now: the bot’s parts up to its first question (an ask, or a collection), in the shape of a conversation’s, numbered from 1. Nothing is kept: a conversation is made when the guest answers (StartBody), and its ids are not these.
| Field | Type | Description |
|---|---|---|
awaiting | string | The id of the part whose question the bot waits on, as Conversation.Awaiting: its buttons are live, or the composer asks for what it collects. Empty when the bot says something and asks nothing. |
parts (always) | array of Part | |
version (always) | integer | |
workflow (always) | string | Workflow and Version are the help bot’s, for StartBody.Opening. |
The name of an event: one of the standard events below, which every app has, or one of an app’s own. An app’s own events, and a standard event the app sends (guest.AppEvents), arrive from the app; the rest from the app’s servers or PurrCRM itself.
One of: signed_up, signed_in, profile_updated, marketing_consent_changed, account_deletion_requested, notice_read, push_sent, email_sent, email_delivered, email_opened, email_clicked, email_bounced, email_complained, email_unsubscribed, conversation_started, message_sent, conversation_rated, bot_resolved, handed_off, ticket_created, ticket_resolved, article_viewed, article_rated, sla_breached, conversation_state_changed, message_seen, message_clicked, message_dismissed, message_answered, message_completed, survey_shown, survey_answered, survey_completed, survey_dismissed, goal_reached, segment_entered, segment_left.
NewConversations
Section titled “NewConversations”When a guest may start a conversation.
One of: always, when_none_open, never.
Notice
Section titled “Notice”One notice in the guest’s inbox PurrCRM keeps: what it pushed them, kept to read again.
| Field | Type | Description |
|---|---|---|
body (always) | string | |
created_at (always) | string (date-time) | |
id (always) | string | |
link | string | A path in the app, which the app’s allow-list decides whether to open. |
read_at | string (date-time) | |
title (always) | string | |
type (always) | PushType (one of support_reply, crm_message) |
NoticePage
Section titled “NoticePage”A page of the guest’s inbox, newest first.
| Field | Type | Description |
|---|---|---|
next_before | string | The notice to ask for older ones before, and empty on the last page. |
notices (always) | array of Notice | |
unread (always) | integer | Unread counts the whole inbox, not only this page: the number on the bell. |
NoticesReadBody
Section titled “NoticesReadBody”POST notices/read: the notices shown, or all of them. A notice that is not the guest’s is left alone.
| Field | Type | Description |
|---|---|---|
all | boolean | |
ids | array of string |
OpeningRef
Section titled “OpeningRef”Names an opening by its workflow and the version it was worked out from.
| Field | Type | Description |
|---|---|---|
version (always) | integer | |
workflow (always) | string |
OpenMessageBody
Section titled “OpenMessageBody”POST /guest/v1/messages/{message_id}/open: the session the app opened the message in.
| Field | Type | Description |
|---|---|---|
session_id (always) | string |
OrderRef
Section titled “OrderRef”An app’s order reference: what its guests call an order’s reference, what one looks like, and the event prop that names a guest’s latest order. The help bot collects one only in an app that has it, and a customer ticket’s order_ref field is prefilled from Prop.
| Field | Type | Description |
|---|---|---|
example (always) | string | One that matches, which the bot shows (“ORD-7K2QD”). |
label (always) | string | What the app calls it, “Order number”: at most 40 characters. |
pattern (always) | string | What a reference looks like, a regular expression (RE2) the whole answer must match, at most MaxOrderRefPattern bytes. |
prop | string | The event prop naming the order, which prefills a ticket’s order_ref field from the guest’s newest event that carries it; empty prefills nothing. |
upper | boolean | An answer matched and kept in upper case, so that a guest may type it in either. |
One part of a conversation: one message, reply or change. Only the fields its Kind names are set.
| Field | Type | Description |
|---|---|---|
attachments | array of Attachment | |
author (always) | Author | |
blocks | array of Block | A reply’s or the bot’s words (the content schema above). |
bot | BotPart | What a help-bot part asks of the guest. |
created_at (always) | string (date-time) | |
id (always) | string | |
kind (always) | PartKind (one of message, reply, note, bot, assignment, state, rating_request) | |
rating | integer | The guest’s answer to a rating request, 1 to MaxRating, once they give it. |
seq (always) | integer | Seq orders a conversation’s parts, from 1, and is what a wait is asked after. |
state | ConversationState (one of open, snoozed, closed) | Where a state part moved the conversation to. |
text | string | What the guest wrote, as they wrote it: never read as markup. |
PartKind
Section titled “PartKind”What one part of a conversation is.
One of: message, reply, note, bot, assignment, state, rating_request.
A full screen of blocks, from a member of staff.
| Field | Type | Description |
|---|---|---|
blocks (always) | array of Block | |
sender | Author | Who it is from, by first name; left out for the app itself (its brand’s name). |
PreferenceChannel
Section titled “PreferenceChannel”A way a topic reaches the guest.
One of: email, push, in_app, chat.
PreferenceChoice
Section titled “PreferenceChoice”One choice.
| Field | Type | Description |
|---|---|---|
channel (always) | PreferenceChannel (one of email, push, in_app, chat) | |
subscribed (always) | boolean | |
topic_id (always) | string |
Preferences
Section titled “Preferences”The guest’s choices: every topic of the app’s that is not archived, by name, and whether every channel is off (AllOff: they get no marketing at all).
| Field | Type | Description |
|---|---|---|
all_off (always) | boolean | |
topics (always) | array of PreferenceTopic |
PreferencesBody
Section titled “PreferencesBody”Changes the guest’s choices: each choice where it differs from what they had, or AllOff, “Unsubscribe from all marketing”, which turns every channel and every topic off. Wording names the version of the words they chose under (the SDK’s preferences screen sends “crm_sdk/preferences-1”), kept with the choice as it is sent.
| Field | Type | Description |
|---|---|---|
all_off | boolean | |
choices | array of PreferenceChoice | |
wording | string |
PreferenceState
Section titled “PreferenceState”One channel of a topic: whether the guest hears it.
| Field | Type | Description |
|---|---|---|
channel (always) | PreferenceChannel (one of email, push, in_app, chat) | |
subscribed (always) | boolean |
PreferenceTopic
Section titled “PreferenceTopic”One of the app’s topics, and the guest’s state on each channel it uses.
| Field | Type | Description |
|---|---|---|
channels (always) | array of PreferenceState | |
description | string | |
id (always) | string | |
name (always) | string |
Problem
Section titled “Problem”A refusal (RFC 9457). Switch on code, never on detail, which is a sentence for people and may be reworded.
| Field | Type | Description |
|---|---|---|
code (always) | string | What went wrong, as a word to switch on: bad_request, unauthorized, token_expired, not_found, rate_limited, app_unavailable and the others each route lists. |
detail | string | What went wrong, in a sentence that can be shown to a person. |
errors | array of object | The fields that were wrong, for a 400 that has them. |
request_id | string | The request’s id, to quote when asking for help. |
status (always) | integer | The HTTP status. |
title (always) | string | The HTTP status in words. |
type (always) | string | A URI for the kind of problem; about:blank for most. |
One prop an event carries.
| Field | Type | Description |
|---|---|---|
key (always) | string | |
type (always) | PropType (one of string, number, bool, time, money) |
PropType
Section titled “PropType”How PurrCRM reads a prop’s string: what it may be compared with in a rule, and how the dashboard breaks it down.
One of: string, number, bool, time, money.
PublicApp
Section titled “PublicApp”An app’s public face: how it is named and coloured, what it has switched on, and the SDK it needs. Nothing in it is secret.
| Field | Type | Description |
|---|---|---|
brand (always) | PublicBrand | |
currency (always) | string | The ISO 4217 code its money is in. |
features (always) | array of Feature (one of messenger, help_center, in_app_messages) | The parts of the guest experience it has on. |
handle | string | The readable name a live app’s public help center goes by now, <workspace slug>.<app slug> (/help/a/acme.rewards), whichever name or key it was asked by: the address the site sends an old name on to, and names as the canonical one. Left out for a test app, whose help center goes by its key alone. |
key (always) | string | The app’s public key, the one asked for. |
languages | array of string | The languages its content is written in: its default first, then the others. Left out by a CRM older than that. |
link_base | string | Where the app’s links are, with no slash at the end: https://<PurrCRM’s host>/l/<name>, or https://<its own link host>; left out while it has no link domain. The SDK takes a link under it as the app’s own (its handleLink). |
min_sdk_version | string | The oldest SDK the app’s staff want its guests on (“0.6.0”); left out when they have set none. |
mode (always) | AppMode (one of live, test) | AppModeLive, or AppModeTest for an app’s test app: a staging build’s, with test data of its own (the SDK’s isTestMode). |
order_ref | OrderRef | Its order reference; left out for an app without one. |
PublicBrand
Section titled “PublicBrand”An app’s brand as its guests see it: its name (never empty), its accent (#rrggbb, or empty for the SDK’s own), its logo (an https address, or empty) and where its guests may write.
| Field | Type | Description |
|---|---|---|
accent | string | |
logo_url | string | |
name (always) | string | |
support_email | string |
PublicLinkApp
Section titled “PublicLinkApp”GET /public/v1/links/apps/{name}: what the landing page of a link the phone did not open the app with shows. Nothing in it is secret.
| Field | Type | Description |
|---|---|---|
app_store_url | string | |
brand (always) | PublicBrand | |
key (always) | string | The app’s public key. |
link_base (always) | string | Where the app’s links are (PublicApp.LinkBase). |
name (always) | string | |
play_store_url | string |
PublicPreferences
Section titled “PublicPreferences”What the public preference centre shows: the app’s brand, the address the link was sent to with most of it hidden, and the guest’s preferences. Nothing else about them.
| Field | Type | Description |
|---|---|---|
accent | string | Accent (#rrggbb) and LogoURL are the app’s, for the page to wear; either may be absent. |
all_off (always) | boolean | |
email | string | The contact’s address, all but its first letter and its domain hidden (“j•••@example.com”); empty for none. |
logo_url | string | |
product (always) | string | |
topics (always) | array of PreferenceTopic |
PublicRatingBody
Section titled “PublicRatingBody”POST /public/v1/help/articles/{slug}/rating: whether a public article helped a reader of the web’s help center, who has no account. Visitor is the page’s own id for its reader, a UUID it keeps in a cookie, so that a second answer replaces the first. Rate-limited per address; 204, or 404 for an article the web may not read.
| Field | Type | Description |
|---|---|---|
helpful (always) | boolean | |
language | string | The language the reader read it in (Article.Language), for the help report; left out, the app’s default. |
visitor (always) | string |
PushPlatform
Section titled “PushPlatform”What a device registered for PurrCRM’s pushes runs: a phone, or a browser, which FCM reaches through web push.
One of: android, ios, web.
PushType
Section titled “PushType”What a push PurrCRM sends, or a notice in the inbox, is about. An app’s own pushes, sent by its own servers, are the app’s.
One of: support_reply, crm_message.
QuestionType
Section titled “QuestionType”How a question is answered.
One of: nps, numeric, stars, emoji, dropdown, short_text, long_text, single_choice, multi_choice.
RatingBody
Section titled “RatingBody”The guest’s answer to a rating request.
| Field | Type | Description |
|---|---|---|
rating (always) | integer | 1 (bad) to MaxRating (great). |
remark | string | Anything they want to add. |
ReadBody
Section titled “ReadBody”Says the guest has seen a conversation up to a part.
| Field | Type | Description |
|---|---|---|
seq (always) | integer |
ReceiptAction
Section titled “ReceiptAction”What the guest did with a message the app showed.
One of: seen, clicked, dismissed, completed, answered.
ReceiptBody
Section titled “ReceiptBody”What the guest did with a message the app showed.
| Field | Type | Description |
|---|---|---|
action (always) | ReceiptAction (one of seen, clicked, dismissed, completed, answered) | |
answers | array of string | |
button | string | |
link | string | What was tapped, for clicked. |
message_id (always) | string | |
path | array of string | |
screen | string | A carousel’s receipts say where the guest was. Screen is the screen it is about: the one answered, the one whose button was tapped, the one the carousel ended or was closed on. Button is the button tapped, for clicked (with Link too, for a link button). Answers are the options picked, for answered: one for a single choice, up to MaxCarouselOptions for a multiple. Path is the screens’ ids the guest has seen so far, in order (a screen seen twice is in it twice), at most MaxReceiptPath (the first ones kept), for completed and dismissed, and on any other carousel receipt that has it. |
session_id | string | The check-in’s session. |
test | boolean | About a test copy (InAppMessage.Test): MessageID is the test’s. |
variant (always) | string |
ReplyExpectation
Section titled “ReplyExpectation”How soon the guest can expect an answer.
| Field | Type | Description |
|---|---|---|
open (always) | boolean | Staff being at work now, by the team’s office hours. |
opens_at | string (date-time) | When they are next at work, when they are not now. |
within (always) | ReplyTime (one of minutes, hours, day) |
ReplyTime
Section titled “ReplyTime”How soon staff usually answer, which the team that answers says in PurrCRM’s settings, for “we usually reply in …”.
One of: minutes, hours, day.
A gradient laid over a picture so that words read on it (carousel_style.json’s scrims).
One of: none, light, dark.
ServerAccepted
Section titled “ServerAccepted”Answers a batch: how many were new and kept, and the ones refused, by their place in the batch.
| Field | Type | Description |
|---|---|---|
accepted (always) | integer | |
rejected (always) | array of ServerRejection |
ServerEvent
Section titled “ServerEvent”One thing a person did, as a server saw it.
| Field | Type | Description |
|---|---|---|
at (always) | string (date-time) | |
external_id (always) | string | |
id (always) | string | The server’s idempotency key, 1 to 100 bytes: derive it from what the event is about, so that a retry carries the same one. |
name (always) | string | |
props | object of string | The event’s props, each as a string its definition reads by its type. |
ServerEvents
Section titled “ServerEvents”POST /server/v1/events.
| Field | Type | Description |
|---|---|---|
events (always) | array of ServerEvent |
ServerRejection
Section titled “ServerRejection”One event refused, and why.
| Field | Type | Description |
|---|---|---|
id (always) | string | |
index (always) | integer | |
reason (always) | string |
SignupAccepted
Section titled “SignupAccepted”A sign-up taken: a link is on its way to the address, or, when it has an account already, an email saying so. The answer is the same either way.
| Field | Type | Description |
|---|---|---|
email (always) | string |
SignupBody
Section titled “SignupBody”POST /public/v1/signup: a new customer’s address and password (the staff password rules), and the names of their workspace and its first app.
| Field | Type | Description |
|---|---|---|
app_name (always) | string | |
email (always) | string | |
password (always) | string | |
turnstile_token | string | |
workspace_name (always) | string |
Source
Section titled “Source”Who sends an event: the app (its SDK), the app’s servers (the server API), or PurrCRM itself. A definition says which sends it, and an event recorded keeps who sent it, as a fact. One of an app’s own events may be sent by both the app and its servers (SourceBoth); an event is never recorded as sent by both.
One of: app, server, crm, both.
A run of text with one style.
| Field | Type | Description |
|---|---|---|
bold | boolean | |
color | string | A colour in content: a theme token (ColorToken), which the app draws in its light or dark mode’s shade, or a fixed “#rrggbb”. Where a colour may be empty, empty is the default of where it is. |
highlight | boolean | |
italic | boolean | |
link | string | Link makes the run a link, as Block.Link. |
strike | boolean | |
text (always) | string | |
underline | boolean | Underline, Strike, Highlight and Color are formatting (BlockContext.Formatting). Highlight is a wash of the accent behind the run; Color is the run’s own colour, the accent or one of the palette’s, over the block’s. |
StartBody
Section titled “StartBody”The guest starting a conversation: what they wrote (a MessageBody’s text and pictures), or, with Opening, a tap on one of its question’s buttons (Button) instead. Opening names the help bot’s opening the guest was shown (MessengerHome.Opening), whose parts then come first in the conversation; without it, the guest’s words do, as before there were openings.
| Field | Type | Description |
|---|---|---|
attachment_ids | array of string | |
button | string | The id of the opening’s button the guest tapped, with no words or pictures; empty when they wrote. |
opening | OpeningRef | The opening the guest was shown when they wrote or tapped; nil for none. |
text (always) | string |
SupportTicket
Section titled “SupportTicket”One of the guest’s tickets: the fields staff let the guest see, and the conversation about it, oldest first.
| Field | Type | Description |
|---|---|---|
conversation_id | string | The conversation the ticket’s parts are in. |
created_at (always) | string (date-time) | |
description | array of Block | What staff wrote the ticket is for, in blocks. |
fields (always) | array of TicketField | |
id (always) | string | |
parts (always) | array of Part | |
ref (always) | string | |
resolved_at | string (date-time) | |
state (always) | TicketState (one of submitted, in_progress, waiting_on_guest, resolved) | |
title (always) | string | |
type (always) | string | |
updated_at (always) | string (date-time) |
SupportTicketPage
Section titled “SupportTicketPage”The guest’s tickets, the most recently changed first.
| Field | Type | Description |
|---|---|---|
items (always) | array of SupportTicketSummary |
SupportTicketSummary
Section titled “SupportTicketSummary”A ticket in a list.
| Field | Type | Description |
|---|---|---|
id (always) | string | |
ref (always) | string | How the guest and staff name it: “T-1042”. |
state (always) | TicketState (one of submitted, in_progress, waiting_on_guest, resolved) | |
title (always) | string | |
type (always) | string | |
updated_at (always) | string (date-time) |
Survey
Section titled “Survey”The questions of a survey message. Steps are shown in order, unless a step’s branch on a closed answer jumps ahead; reaching a thank-you step, or the end, finishes it.
| Field | Type | Description |
|---|---|---|
format (always) | SurveyFormat (one of small, large) | |
intro | array of Block | The first screen of a large survey; left out for none. |
steps (always) | array of SurveyStep |
SurveyAnswer
Section titled “SurveyAnswer”The guest’s answer to one question: Number for a scale, Choices (option ids) for a choice, with Other when “other” is among them, and Text for the guest’s own words.
| Field | Type | Description |
|---|---|---|
choices | array of string | |
number | integer | |
other | string | |
question_id (always) | string | |
text | string |
SurveyAnswerBody
Section titled “SurveyAnswerBody”Answers given so far, sent as each step is answered: PurrCRM keeps them even if the guest never finishes. A newer answer to the same question replaces the older.
| Field | Type | Description |
|---|---|---|
answers (always) | array of SurveyAnswer | |
test | boolean | A test copy’s answers (InAppMessage.Test), by the test’s id. |
variant (always) | string |
SurveyBranch
Section titled “SurveyBranch”SurveyBranch sends the guest to another step when a closed question’s answer is one of Values (an option’s id), or a number from Min to Max.
| Field | Type | Description |
|---|---|---|
max | integer | |
min | integer | |
next (always) | string | The id of a later step. |
question_id (always) | string | |
values | array of string |
SurveyFormat
Section titled “SurveyFormat”How a survey is shown.
One of: small, large.
SurveyOption
Section titled “SurveyOption”One option of a choice question.
| Field | Type | Description |
|---|---|---|
id (always) | string | |
label (always) | string |
SurveyQuestion
Section titled “SurveyQuestion”One question.
| Field | Type | Description |
|---|---|---|
description | string | |
id (always) | string | |
max | integer | |
max_label | string | |
min | integer | Min and Max are a numeric scale’s ends, 0 or 1 to at most 10. |
min_label | string | MinLabel and MaxLabel are the words under a scale’s ends. |
options | array of SurveyOption | A choice question’s, in order. |
other | boolean | Other adds “Other” to a single or multiple choice, with the guest’s own words. |
placeholder | string | The hint in a text answer’s box. |
required | boolean | |
title (always) | string | |
type (always) | QuestionType (one of nps, numeric, stars, emoji, dropdown, short_text, long_text, single_choice, multi_choice) |
SurveyStep
Section titled “SurveyStep”One screen of a survey.
| Field | Type | Description |
|---|---|---|
blocks | array of Block | A thank-you step’s words. |
branches | array of SurveyBranch | Tried in order when the step is answered; the first that matches says which step is next. None matching, or none at all, is the step after this one. |
id (always) | string | |
kind (always) | SurveyStepKind (one of questions, thank_you) | |
questions | array of SurveyQuestion | A questions step’s. |
SurveyStepKind
Section titled “SurveyStepKind”What a survey’s step is.
One of: questions, thank_you.
SurveySubmit
Section titled “SurveySubmit”SurveySubmit finishes a survey: every answer along the path the guest took. Only then are answers written to the guest’s attributes.
| Field | Type | Description |
|---|---|---|
answers (always) | array of SurveyAnswer | |
test | boolean | A test copy finished (InAppMessage.Test): nothing is written to the guest’s attributes. |
variant (always) | string |
TeamFaces
Section titled “TeamFaces”Whose faces the home shows.
One of: auto, chosen, none.
TextScale
Section titled “TextScale”How large a carousel’s words are, beside the phone’s own text size, which scales them again.
One of: compact, regular, large.
TextWeight
Section titled “TextWeight”How heavy a text block’s words are.
One of: regular, medium, bold.
TicketField
Section titled “TicketField”One field of a ticket and its value: Text for a text or a list field (the option chosen), Number, Bool, or Date (YYYY-MM-DD). A field with no value has none of them.
| Field | Type | Description |
|---|---|---|
bool | boolean | |
date | string | |
key (always) | string | |
label (always) | string | |
number | number | |
text | string | |
type (always) | FieldType (one of text, list, number, bool, date) |
TicketState
Section titled “TicketState”Where a ticket has got to, in the guest’s words.
One of: submitted, in_progress, waiting_on_guest, resolved.
UnreadCount
Section titled “UnreadCount”How many notices are still unread, for the bell.
| Field | Type | Description |
|---|---|---|
unread (always) | integer |
VAlign
Section titled “VAlign”Where a screen’s content sits in its height.
One of: top, center, bottom.