Florality
FeaturesPricingSecurityFAQAbout
Sign upSign in
Public REST APIv1

REST reference & guides

Public REST APIv1

REST reference & guides

Get started

  • Overview
  • Authentication
  • Scopes
  • Errors

API reference

  • Members
  • Groups
  • Entries
  • Front
  • Appearance
  • Custom fields
  • Trash
  • Search
  • Member statuses
  • Systems
  • Messaging
  • Privacy buckets
  • Terminology
  • Friends
    • GETList friends
    • POSTRequests
    • GETFriend members
    • GETFront
    • GETNotes
  • Subscriptions
  • Billing
  • Import
  • Social
  • Guestbook & poll
  • Group layout
  • Activity
  1. Documentation
  2. Friends
API keys
Florality

Organise your system. One front at a time.

Get startedSign in

Product

  • Features
  • Pricing
  • Public REST API
  • Security

Company

  • About
  • Our team
  • Changelog
  • Contact

Resources

  • FAQ
  • Trust & Safety
  • Privacy Policy
  • Terms of Service
  • Refunds and cancellation

© 2026 Florality. All rights reserved.

Privacy·Terms·

Friends

The Friends API manages your friendships (requests, list, block) and lets an authenticated friend read or write another user's shared data: members, groups, front, notes, statuses, and custom fields: subject to Privacy buckets and per-bucket friend permissions.

Base path: /api/v1/friends. Primary scope: friends (read / read_write). See Authentication and Scopes.

Path parameter friendUserId (or requesterUserId on accept) the account that owns the data for friend-scoped routes, not necessarily the API key holder.


Concepts

Viewer vs owner

  • Viewer: account identified by the API key.
  • Owner: user whose account data is accessed (/api/v1/friends/{friendUserId}/…).
  • Routes under /api/v1/friends (no nested id) operate on your friendships as viewer.:
  • Nested routes require an accepted friendship (and no block) unless noted; failures often return 404 instead of 403 to avoid leaking existence.:

Friendship status

Filter list/page with status:

  • pending: outgoing or incoming request not yet accepted
  • accepted: active friends
  • blocked
  • revoked

Privacy and permissions

Access is enforced in services via resolveFriendAccess and privacy bucket overlap. Each friend is assigned one or more buckets; each bucket defines coarse permission groups (members_view, member_profile, front, member_notes, etc.) at none, read, or read_write. Manage buckets with the Privacy buckets..

Friend write actions (notes, front changes, custom field values) are audited on the owner's account (friend_write.* audit actions).

Related APIs (other scopes)

  • Social: GET /api/v1/friends/{friendUserId}/social (social: read)

Endpoint index

Your friendships

MethodPathScope
GET/api/v1/friendsread
GET/api/v1/friends/pageread
GET/api/v1/friends/requestsread
GET/api/v1/friends/suggestionsread
POST/api/v1/friends/request-by-usernameread_write
POST/api/v1/friends/block-by-usernameread_write
POST/api/v1/friends/requests/{requesterUserId}/acceptread_write
GET/api/v1/friends/searchread
GET/api/v1/friends/search/catalogread
GET/api/v1/friends/search/membersread
GET/api/v1/friends/{friendUserId}read
POST/api/v1/friends/{friendUserId}/requestread_write
POST/api/v1/friends/{friendUserId}/revokeread_write
POST/api/v1/friends/{friendUserId}/blockread_write

Friend-scoped data (owner = path id)

MethodPath suffixScope
GET/members, /members/{memberId}read
GET/groups, /groups/folderread
GET/frontread
PUT/front (sole front)read_write
GET/front/history, /front/history/monthread
GET/front/writable-member-idsread
POST/front/membersread_write
DELETE/front/members/{memberId}, /front/tier-presence/{memberId}read_write
PATCH/front/orderread_write
GET/POST/entriesread / read_write
PATCH/DELETE/entries/{entryId}read_write
GET/member-statuses, /member-statuses/members/{memberId}read
GET/custom-fields?memberId=read
PUT/custom-fields/{fieldId}/valueread_write

Prefix every suffix with /api/v1/friends/{friendUserId}.


List friends

GET/api/v1/friends

Query

ParamRequiredNotes
statusnopending | accepted | blocked | revoked

Returns FriendListRow[] for the API key user.

JSON
{
  "id": "friendship-row-uuid",
  "friendUserId": "a0a0a0a0-a0a0-a0a0-a0a0-a0a0a0a0a0a0",
  "status": "accepted",
  "name": "River",
  "username": "river_pl",
  "imageUrl": "https://img.clerk.com/…",
  "friendPronouns": "they/them",
  "friendStatus": "Usually around evenings",
  "friendBannerUrl": "/api/v1/users/…/friend-banner?…",
  "isAdmin": false,
  "planKey": "pro",
  "donorSupporterUnlocked": true,
  "closedBetaParticipantAt": null,
  "privacyBucketIds": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"],
  "createdAt": 1714233600000,
  "acceptedAt": 1714237200000
}
Shell
curl -sS \
  -H "Authorization: Bearer YOUR_TOKEN" \
  "https://api.floralitys.com/api/v1/friends?status=accepted"

Paginated friends

GET/api/v1/friends/page

Query

ParamRequiredNotes
limityes1–200
cursornoOpaque offset from previous nextCursor
querynoFilter by friend display name (case-insensitive)
statusnoSame as list endpoint
JSON
{
  "items": [ /* FriendListRow[] */ ],
  "nextCursor": 25
}
Shell
curl -sS \
  -H "Authorization: Bearer YOUR_TOKEN" \
  "https://api.floralitys.com/api/v1/friends/page?limit=25&query=river"

Friend requests

GETGET /api/v1/friends/requests: incoming pending requests (FriendListRow[]; friendUserId is the requester).

POSTPOST /api/v1/friends/{friendUserId}/request: send request to user id. 204.

POSTPOST /api/v1/friends/request-by-username: body { username: clerk_username }. 201 { friendUserId, username }.

POSTPOST /api/v1/friends/requests/{requesterUserId}/accept: accept incoming. 204.

POSTPOST /api/v1/friends/{friendUserId}/revoke: end friendship. 204.

POSTPOST /api/v1/friends/{friendUserId}/block: optional body { reason: … } (max 280 chars). 204.

POSTPOST /api/v1/friends/block-by-username: body { username, reason? }. 200 { username }. Blocks even without prior friendship.

Suggestions

GET/api/v1/friends/suggestions: Accepted-friend graph recommendations (friends of friends) filtered by profile suggestion visibility and reach policy.

Optional query limit (1–50, default 20). Returns FriendSuggestionRow[].

JSON
{
  "friendUserId": "a0a0a0a0-a0a0-a0a0-a0a0-a0a0a0a0a0a0",
  "mutualFriendCount": 3,
  "name": "River",
  "username": "river_pl",
  "imageUrl": "https://img.clerk.com/…",
  "friendPronouns": "they/them",
  "friendStatus": "Usually around evenings",
  "friendBannerUrl": "/api/v1/users/…/friend-banner?…",
  "isAdmin": false,
  "planKey": "pro",
  "donorSupporterUnlocked": true,
  "closedBetaParticipantAt": null
}
Shell
curl -sS \
  -H "Authorization: Bearer YOUR_TOKEN" \
  "https://api.floralitys.com/api/v1/friends/suggestions?limit=20"

Friend profile

GET/api/v1/friends/{friendUserId}

Public friend card: Clerk username/image, friend-facing profile fields, plan badges, and friendProfileTabs booleans (members, frontHistory, notes) indicating which tabs the viewer may use. Requires accepted friendship.

JSON
{
  "friendUserId": "a0a0a0a0-a0a0-a0a0-a0a0-a0a0a0a0a0a0",
  "name": "River",
  "username": "river_pl",
  "imageUrl": "https://img.clerk.com/…",
  "displayName": "River 🌊",
  "friendPronouns": "they/them",
  "friendStatus": "Usually around evenings",
  "friendTimezone": "Europe/London",
  "friendCountry": "GB",
  "friendAboutMarkdown": "Hi!",
  "friendBannerUrl": "/api/v1/users/…/friend-banner?…",
  "isAdmin": false,
  "planKey": "pro",
  "donorSupporterUnlocked": true,
  "closedBetaParticipantAt": null,
  "friendProfileTabs": {
    "members": true,
    "membersDirectory": false,
    "frontHistory": true,
    "notes": true
  }
}

Search (friend-filtered)

Search the owner's catalog as a friend viewer. All endpoints require ownerUserId (UUID) and friendship access is enforced per result.

MethodPathQuery
GET/api/v1/friends/searchownerUserId, q (min 1 char), optional limitPerType (1–50)
GET/api/v1/friends/search/catalogownerUserId: full searchable index, filtered
GET/api/v1/friends/search/membersownerUserId, q, optional limit (1–50)

Result rows use search result types (member, note, etc.); members and notes are dropped when the viewer lacks bucket permission.


Members visible to a friend

GET/api/v1/friends/{friendUserId}/members

Active members on the owner account that pass members.view, with profile fields redacted per bucket rules (same shapes as Members API dashboard media URLs tagged with ownerUserId)..

GET/api/v1/friends/{friendUserId}/members/{memberId}: Single member; requires members.profile.read. 404 if not visible.

Shell
curl -sS \
  -H "Authorization: Bearer YOUR_TOKEN" \
  "https://api.floralitys.com/api/v1/friends/OWNER_USER_UUID/members"

Groups and folders

GET/api/v1/friends/{friendUserId}/groups

Directory tree visible to the friend (groups.read via buckets). Accepted friendship required.

GET/api/v1/friends/{friendUserId}/groups/folder

Query

ParamNotes
folderIdFolder UUID, or omit / null for root view

Returns folder contents the friend may see (members, subfolders, metadata).


Front (who is fronting)

Read and optionally mutate the owner's live front state. Write routes need members.front.write on the friend's merged bucket matrix and visible members.

Current front

GET/api/v1/friends/{friendUserId}/front

Returns primary, alsoFronting, tieredMembers, and top-level note. Members hidden by front.read or members.view are stripped. On server errors, returns an empty front object instead of 500.

JSON
{
  "primary": {
    "member": { "_id": "member-uuid", "name": "Alex", "avatarUrl": "/api/v1/members/…" },
    "activeSession": { "note": "At work", "startedAt": 1714237200000 }
  },
  "alsoFronting": [],
  "tieredMembers": [],
  "note": "At work"
}

Set sole front

PUT/api/v1/friends/{friendUserId}/front

Body { memberId: uuid }: clears all fronts, then fronts that member. 204.

Shell
curl -sS -X PUT \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"memberId":"MEMBER_UUID"}' \
  "https://api.floralitys.com/api/v1/friends/OWNER_USER_UUID/front"

Add / remove / reorder

  • POST/front/members: body { memberId }
  • DELETE/front/members/{memberId}:
  • DELETE/front/tier-presence/{memberId}: remove tier-only presence
  • GET/front/order: body { memberIds: [uuid, …] }
  • GET/front/writable-member-ids: member ids the viewer may front-manage

Front history

GET/front/history

Query: optional limit (1–50, default 20), cursorStartedAt + cursorId, startTime, endTime (epoch ms). Returns { items, count, nextCursor } with members filtered like live front. count is the friend's total matching sessions (before per-member privacy filtering on items).

GET/front/history/month: Required startTime, endTime; optional maxSessions (1–50000). Calendar-style aggregation for friends with tab access.


Entries (notes)

Friend-visible notes on the owner account. Permissions: members.notes.read / members.notes.write per linked member.

GET/api/v1/friends/{friendUserId}/entries

Query

ParamNotes
limit1–100, default 50
memberIdFilter to one member; returns [] if not readable

Each row includes viewerCanWrite. Scans up to 500 entries server-side to fill the limit.

JSON
{
  "_id": "entry-uuid",
  "title": "Check-in",
  "content": "…",
  "createdAt": 1714233600000,
  "updatedAt": 1714237200000,
  "members": [{ "id": "member-uuid", "name": "Alex" }],
  "member": { "id": "member-uuid", "name": "Alex" },
  "viewerCanWrite": true
}

POST/entries: body { "content", "title?", "memberId?" | "memberIds?" }. 201 { "id" } or 403 with plan/limit code.

Shell
curl -sS -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"Shared note","memberIds":["MEMBER_UUID"]}' \
  "https://api.floralitys.com/api/v1/friends/OWNER_USER_UUID/entries"

PATCH/entries/{entryId}: partial update; write permission required on all affected members. 204.

DELETE/entries/{entryId}: 204.


Member statuses (friend view)

Resolved status tags visible to the friend (bucket-gated). Uses friends: read, not the owner's memberStatuses scope.

  • GET/member-statuses: account-level resolved statuses for owner/friend pair
  • GET/member-statuses/members/{memberId}: statuses on one member

See Member statuses: friend-visible for response shapes. If friendUserId equals your own user id, returns your self-scoped resolution instead..


Custom fields

GET/api/v1/friends/{friendUserId}/custom-fields?memberId={uuid}

Required memberId. Returns definitions with values where bucket overlap and field-level read permission pass. Each field includes viewerCanWrite.

emptyHint: emptyHint: null | no_definitions | none_visible.

JSON
{
  "fields": [
    {
      "id": "field-def-uuid",
      "name": "Favorite color",
      "type": "text",
      "value": "Blue",
      "viewerCanWrite": true
    }
  ],
  "emptyHint": null
}

PUT/custom-fields/{fieldId}/value: body { "memberId", "value": string | string[] }. 204.


Errors

JSON body { code, message }:

  • UNAUTHORIZED (401): missing/invalid token
  • FORBIDDEN (403): scope or explicit permission denial (e.g. front write)
  • NOT_FOUND (404): unknown id or friendship not visible
  • CONFLICT (409): duplicate request or invalid state transition
  • BAD_REQUEST (400): validation

See Errors.

JSON
{
  "code": "NOT_FOUND",
  "message": "Not found."
}
Plain text
// 204 No Content: empty response body