Skip to main content
If you are building a chat or messaging surface on top of Fanvue, most of what you need is in one place: the message object returned by GET /chats/{userUuid}/messages. This guide explains the fields that matter and how to answer the questions that come up most.

The message object

Each message in the data array carries these fields:
FieldWhat it tells you
uuidStable ID for the message.
textThe message body. Can be null (for example a media-only message).
sentAtWhen it was sent.
sender / recipientEach has a uuid and a handle (the user’s @ handle).
hasMedia / mediaType / mediaUuidsWhether the message has attachments, their type, and their ordered IDs.
typeWhat kind of message this is (see below).
pricingPresent for pay-to-view messages. pricing.USD.price is in cents. Null for ordinary messages.
purchasedAtTimestamp when the fan purchased this message, or null if not purchased.
isReadWhether the recipient has read the message.
sentByUserIdThe team member who sent it on the creator’s behalf, or null if the creator sent it directly.

Tell message types apart

The type field distinguishes ordinary messages, tips, and the platform’s automated messages. The values are:
  • Ordinary messages: SINGLE_RECIPIENT, CHAT_TEXT_REPLY, CHAT_TEXT_GENERATION, CHAT_TEXT_REWRITE.
  • Tips: TIP.
  • Voice calls: VOICE_CALL.
  • Automated messages: AUTOMATED_FIRST_MESSAGE_REPLY, AUTOMATED_NEW_SUBSCRIBER, AUTOMATED_NEW_FOLLOWER, AUTOMATED_NEW_PURCHASE, AUTOMATED_RE_SUBSCRIBED, AUTOMATED_RENEWED, AUTOMATED_CANCELED, AUTOMATED_CHAT_MESSAGE_REPLY.
So:
  • A tip is type === "TIP".
  • A pay-to-view (PPV) message has a non-null pricing (and usually hasMedia: true).
  • An ordinary message is one of the text types with pricing: null.
  • An automated or welcome message carries one of the AUTOMATED_* types. The automatic messages a fan receives (for example after subscribing or following) surface here, so you can filter them out of, or single them out from, a human conversation by checking for an AUTOMATED_ prefix.

Has the fan paid for a PPV message?

Use purchasedAt. It is the timestamp the fan purchased the message, or null if they have not. So:
  • purchasedAt is set: the fan has unlocked and paid for it.
  • purchasedAt is null on a message with pricing: it is still awaiting purchase.
Render “Paid” when purchasedAt is present and “Awaiting purchase” when a priced message has a null purchasedAt. Remember pricing.USD.price is in cents, so divide by 100 for display.

Has the message been read?

Each message has an isRead boolean, so you can show read state (the “two ticks” pattern) directly from the message list. For a live surface that updates as soon as a fan reads a message, subscribe to the message-read webhook rather than polling.

Which team member sent a message?

If an agency or team operates the account, sentByUserId is the UUID of the team member who sent the message on the creator’s behalf (null when the creator sent it directly). This is what you use to attribute a message, and any purchase it drove, to a specific chatter.

Sending a message

Send with POST /chats/{userUuid}/message. The body accepts text, mediaUuids, price, and templateUuid. To send pay-to-view media, include the mediaUuids you are selling and a price. To resolve and display the media you receive or send, see Working with Media.

A note on user names

Two name fields appear throughout the API, and they are not the same thing:
  • handle is the user’s unique @ handle.
  • displayName is the changeable display name a user shows publicly.
When you need a stable identifier use the uuid. When you show a name, use displayName, and fall back to handle. Both appear on the authenticated user (GET /users/me) and on the sender and recipient of every message.