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.
Keeping chats in sync? Don’t re-poll this endpoint per chat — receive messages in real time with webhooks and pull deltas in bulk. See Efficient Chat Sync.

The message object

Each message in the data array carries these fields:

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.

Pay-to-view price limits

price is in cents. The allowed range for a chat pay-to-view message is:
The send endpoint validates the minimum only. A price above the creator’s ceiling is accepted, and the message is delivered looking like a normal pay-to-view — but the purchase is rejected when the fan tries to pay, so the message can never be unlocked and the creator earns nothing.Enforce the $500 ceiling in your own code before you send. Do not rely on the API to reject an over-ceiling price; validating it up front is a pending platform fix.
2,500isfrequentlyquotedasthechatpaytoviewmaximum.ItisnotthedefaultitappliesonlytocreatorsFanvuehasexplicitlyexemptedfromfanspendinglimits.Assume2,500 is frequently quoted as the chat pay-to-view maximum. It is not the default — it applies only to creators Fanvue has explicitly exempted from fan spending limits. Assume 500 unless you have confirmed otherwise for that specific creator. There is no API field that exposes which ceiling applies.

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.