Profiles
Fetch, search, and update Bluesky user profiles.
Domain Types
Profile
A full user profile with engagement counts and relationship state, returned by getProfile and getProfiles.
Field |
Type |
Description |
|---|---|---|
|
|
Decentralized identifier |
|
|
User handle (e.g. |
|
|
Display name (defaults to |
|
|
Bio text (defaults to |
|
|
Avatar image URL |
|
|
Banner image URL |
|
|
Total number of posts |
|
|
Number of followers |
|
|
Number of accounts followed |
|
|
Whether you follow this user |
|
|
Whether this user follows you |
|
|
Whether you are blocking this user |
|
|
Whether this user is blocking you |
|
|
Whether you have muted this user |
ProfileSummary
A lightweight profile used in feeds, notifications, search results, and follower lists.
Field |
Type |
Description |
|---|---|---|
|
|
Decentralized identifier |
|
|
User handle |
|
|
Display name (defaults to |
|
|
Avatar image URL |
Pass a ProfileSummary to getProfile if you need the full Profile with counts and relationship flags.
Functions
Reading Profiles
Function |
Accepts |
Returns |
Description |
|---|---|---|---|
|
|
|
Get a single full profile |
|
|
|
Get up to 25 profiles in one request |
|
|
|
List an actor's followers |
|
|
|
List accounts an actor follows |
|
|
|
Suggested follows based on an actor |
|
|
|
General account suggestions |
|
|
|
Search users by name, handle, or bio |
|
|
|
Lightweight typeahead search (no pagination) |
|
|
|
Get blocked users (paginated) |
|
|
|
Get muted users (paginated) |
|
|
|
Get relationship details between users |
|
|
|
Get followers you also follow (SRTP) |
|
|
|
Get user's lists (SRTP) |
Relationship
Field |
Type |
Description |
|---|---|---|
|
|
The other user's DID |
|
|
AT-URI of follow record if you follow them |
|
|
AT-URI of follow record if they follow you |
taskResult {
let! profile = Bluesky.getProfile agent aliceHandle
printfn "%s: %d followers" profile.DisplayName profile.FollowersCount
let! followers = Bluesky.getFollowers agent profile (Some 50L) None
for f in followers.Items do
printfn " @%s" (Handle.value f.Handle)
}
Engagement Info
Function |
Accepts |
Returns |
Description |
|---|---|---|---|
|
|
|
Who liked a post |
|
|
|
Who reposted a post |
taskResult {
let! likers = Bluesky.getLikes agent post (Some 50L) None
for p in likers.Items do
printfn "@%s liked this" (Handle.value p.Handle)
}
Writing
Function |
Accepts |
Returns |
Description |
|---|---|---|---|
|
|
|
Transform the profile record with optimistic concurrency |
|
|
|
Set or clear display name (auto-retries on conflict) |
|
|
|
Set or clear bio (auto-retries on conflict) |
|
|
|
Upload and set avatar, or clear with |
|
|
|
Upload and set banner, or clear with |
|
|
|
Low-level read-modify-write with CAS retry |
|
|
|
Change the authenticated user's handle |
Field-specific setters (setDisplayName, setDescription, setAvatar, setBanner) auto-retry once on conflict -- safe because they touch a single field. updateProfile does not retry; the caller controls the transform.
taskResult {
// Simple field setters
do! Bluesky.setDisplayName agent (Some "New Display Name")
do! Bluesky.setDescription agent (Some "F# developer | AT Protocol enthusiast")
// Set avatar from file
let avatarBytes = System.IO.File.ReadAllBytes "avatar.jpg"
do! Bluesky.setAvatar agent (Some (avatarBytes, Jpeg))
// Full transform for multiple fields at once
do! Bluesky.updateProfile agent (fun p ->
{ p with DisplayName = Some "Updated Name"
Description = Some "Updated bio" })
}
Note: updateProfile and upsertProfile operate on the raw AppBskyActor.Profile.Profile type (all Option fields), not the convenience Profile domain type.
SRTP Polymorphism
Read functions that take an actor accept multiple types via SRTP:
getProfile,getFollowers,getFollows,getSuggestedFollows,getAuthorFeed,getActorLikesacceptHandle,Did,ProfileSummary, orProfilegetProfilestakes aDid listgetLikes,getRepostedByacceptTimelinePost,PostRef, orAtUri
taskResult {
let! profile = Bluesky.getProfile agent aliceHandle
// Pass the Profile directly to get followers
let! followers = Bluesky.getFollowers agent profile (Some 50L) None
// Pass a ProfileSummary from the result
let first = followers.Items.Head
let! fullProfile = Bluesky.getProfile agent first
()
}
namespace FSharp
--------------------
namespace Microsoft.FSharp
module AtpAgent from FSharp.ATProto.Core
<summary> Functions for creating and authenticating <see cref="AtpAgent" /> instances. </summary>
--------------------
type AtpAgent = { HttpClient: HttpClient mutable BaseUrl: Uri mutable Session: AtpSession option ExtraHeaders: (string * string) list AuthenticateRequest: (HttpRequestMessage -> unit) option RefreshAuthentication: (unit -> Task<Result<unit,XrpcError>>) option OnSessionChanged: (unit -> unit) option }
<summary> Client agent for communicating with an AT Protocol Personal Data Server (PDS). Holds the HTTP client, base URL, optional authenticated session, and extra headers. </summary>
<remarks> Create an agent with <see cref="AtpAgent.create" /> or <see cref="AtpAgent.createWithClient" />, then authenticate with <see cref="AtpAgent.login" />. The agent's <see cref="Session" /> field is mutable: it is updated automatically on login and token refresh. </remarks>
<example><code> let agent = AtpAgent.create "https://bsky.social" let! session = AtpAgent.login "my-handle.bsky.social" "app-password-here" agent </code></example>
module TimelinePost from FSharp.ATProto.Bluesky
--------------------
type TimelinePost = { Uri: AtUri Cid: Cid Author: ProfileSummary Text: string Facets: Facet list LikeCount: int64 RepostCount: int64 ReplyCount: int64 QuoteCount: int64 IndexedAt: DateTimeOffset ... }
<summary> A post with engagement counts and viewer state, used in feeds and timelines. Maps from <c>PostView</c>. </summary>
module Handle from FSharp.ATProto.Syntax
<summary> Functions for creating, validating, and extracting data from <see cref="Handle" /> values. </summary>
--------------------
type Handle = private | Handle of string override ToString: unit -> string
<summary> A handle (domain name) used as a human-readable identifier in the AT Protocol. Handles are DNS-based names (e.g. <c>my-handle.bsky.social</c>) that resolve to a <see cref="Did" />. They must be valid domain names with at least two segments and a maximum length of 253 characters. </summary>
<remarks> See the AT Protocol specification: https://atproto.com/specs/handle </remarks>
<summary> High-level convenience methods for common Bluesky operations: posting, replying, liking, reposting, following, blocking, uploading blobs, and deleting records. All methods require an authenticated <see cref="AtpAgent" />. </summary>
<summary> Get a user's profile. Accepts a <see cref="Handle" />, <see cref="Did" />, <see cref="ProfileSummary" />, or <see cref="Profile" />. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="actor">A <see cref="Handle" />, <see cref="Did" />, <see cref="ProfileSummary" />, or <see cref="Profile" />.</param>
<returns>A <see cref="Profile" /> on success, or an <see cref="XrpcError" />.</returns>
<summary> Get the followers of an actor. Accepts a <see cref="Handle" />, <see cref="Did" />, <see cref="ProfileSummary" />, or <see cref="Profile" />. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="actor">A <see cref="Handle" />, <see cref="Did" />, <see cref="ProfileSummary" />, or <see cref="Profile" />.</param>
<param name="limit">Maximum number of followers to return (optional).</param>
<param name="cursor">Pagination cursor from a previous response (optional).</param>
<returns>A page of <see cref="ProfileSummary" /> with an optional cursor, or an <see cref="XrpcError" />.</returns>
<summary> Extract the string representation of a handle. </summary>
<param name="handle">The handle to extract the value from.</param>
<returns>The full handle string (e.g. <c>"my-handle.bsky.social"</c>).</returns>
<summary> Get the accounts that have liked a specific post. Accepts an <see cref="AtUri" />, <see cref="PostRef" />, or <see cref="TimelinePost" />. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="target">The post (an <see cref="AtUri" />, <see cref="PostRef" />, or <see cref="TimelinePost" />).</param>
<param name="limit">Maximum number of likes to return (optional).</param>
<param name="cursor">Pagination cursor from a previous response (optional).</param>
<returns>A page of <see cref="ProfileSummary" /> with an optional cursor, or an <see cref="XrpcError" />.</returns>
<summary>Set or clear the authenticated user's display name. Retries once on conflict.</summary>
<summary>Set or clear the authenticated user's bio/description. Retries once on conflict.</summary>
<summary>Provides static methods for the creation, copying, deletion, moving, and opening of a single file, and aids in the creation of <see cref="T:System.IO.FileStream" /> objects.</summary>
<summary> Set or clear the authenticated user's avatar image. Uploads the blob first, then updates the profile record. Retries once on conflict. Pass <c>None</c> to clear the avatar. </summary>
<summary> Update the authenticated user's profile by applying a transform function. Reads the current profile, applies the transform, then writes back with optimistic concurrency. </summary>
<param name="agent">An authenticated <see cref="AtpAgent" />.</param>
<param name="transform">A function that transforms the current profile record.</param>
<returns><c>Ok ()</c> on success, or an <see cref="XrpcError" /> (including on swap conflict).</returns>