Skip to content

Data Models

All objects returned by the API are Pydantic BaseModel instances. Fields use attribute access (status.id) rather than dict-style access (status["id"]).

Every field is optional (None by default) except where noted, because server implementations (Mastodon, Pleroma, GotoSocial) vary in what they return. Guard optional fields with is not None before use.

Unknown fields from the server response are silently accepted (extra="allow") and accessible via model.model_extra.

Import

from longwei import Account, Status

Nested types are not exported from the top-level package but can be imported from longwei.models if needed for type annotations:

from longwei.models import (
    Emoji, Field, Mention, Tag, Application,
    MediaAttachment, Card, PollOption, Poll,
)

Status

A status (post/toot) returned by timeline, search, or posting methods.

from longwei import Status
Field Type Description
id str \| None The status ID
created_at str \| None ISO 8601 creation timestamp (format varies by server)
in_reply_to_id str \| None ID of the status being replied to
in_reply_to_account_id str \| None ID of the account being replied to
sensitive bool \| None Whether the content is marked sensitive
spoiler_text str \| None Content warning text shown before expanding
visibility str \| None "public", "unlisted", "private", or "direct"
language str \| None ISO 639-1 language code
uri str \| None Canonical URI of the status
url str \| None URL of the status HTML page
replies_count int \| None Number of replies
reblogs_count int \| None Number of reblogs/boosts
favourites_count int \| None Number of favourites/likes
favourited bool \| None Whether the current user has favourited this status
reblogged bool \| None Whether the current user has reblogged this status
muted bool \| None Whether the current user has muted this conversation
bookmarked bool \| None Whether the current user has bookmarked this status
pinned bool \| None Whether this status is pinned to the account profile
text str \| None Plain-text source (when available; typically on own statuses)
content str \| None HTML body of the status
reblog Status \| None The original status if this is a reblog/boost
application Application \| None App that posted this status
account Account \| None Account that posted this status
media_attachments list[MediaAttachment] \| None Attached media files
mentions list[Mention] \| None Accounts mentioned in this status
tags list[Tag] \| None Hashtags used in this status
emojis list[Emoji] \| None Custom emojis used in this status
card Card \| None Link preview card
poll Poll \| None Attached poll

Example

timeline = await ap.get_public_timeline(limit=5)
for status in timeline:
    author = status.account.username if status.account else "unknown"
    content = (status.content or "")[:80]
    print(f"@{author}: {content}")

    if status.media_attachments:
        for media in status.media_attachments:
            print(f"  Media: {media.type}{media.url}")

    if status.poll:
        for option in status.poll.options:
            print(f"  Poll option: {option.title} ({option.votes_count} votes)")

Account

A user profile on an ActivityPub-compatible server.

from longwei import Account
Field Type Description
id str \| None The account ID
username str \| None Account username (local part only, no domain)
acct str \| None username@domain for remote; username for local accounts
display_name str \| None Display name
note str \| None Profile bio (HTML)
url str \| None URL of the account's profile page
avatar str \| None URL of the avatar image
avatar_static str \| None URL of a static (non-animated) avatar
header str \| None URL of the header/banner image
header_static str \| None URL of a static (non-animated) header
locked bool \| None Whether the account requires follow approval
bot bool \| None Whether the account is a bot
created_at str \| None ISO 8601 account creation timestamp
followers_count int \| None Number of followers
following_count int \| None Number of accounts followed
statuses_count int \| None Number of statuses posted
last_status_at str \| None Date of most recent status
emojis list[Emoji] \| None Custom emojis used in display name or bio
fields list[Field] \| None Profile metadata fields

Example

account = await ap.verify_credentials()
print(f"@{account.acct} ({account.display_name})")
print(f"Followers: {account.followers_count}")
if account.fields:
    for field in account.fields:
        print(f"  {field.name}: {field.value}")

Nested types

MediaAttachment

A media file attached to a status.

Field Type Description
id str \| None Attachment ID (used in media_ids when posting)
type str \| None "image", "video", "gifv", "audio", "unknown"
url str \| None URL of the media file
preview_url str \| None URL of a preview/thumbnail
remote_url str \| None URL of the original remote media (for remote statuses)
description str \| None Alt-text description
blurhash str \| None BlurHash string for placeholder display

Poll and PollOption

Poll is attached to a status when the status includes a poll.

Field Type Description
id str \| None Poll ID
expires_at str \| None ISO 8601 timestamp when the poll closes
expired bool \| None Whether the poll has closed
multiple bool \| None Whether multiple choices are allowed
votes_count int \| None Total votes cast
voters_count int \| None Unique accounts that voted
options list[PollOption] Poll options (defaults to [])
voted bool \| None Whether the current user has voted

Each PollOption has:

Field Type Description
title str \| None Option text
votes_count int \| None Votes for this option (None if results are hidden)

Card

A rich-preview card for a link embedded in a status.

Field Type Description
url str \| None URL of the linked resource
title str \| None Title of the linked page
description str \| None Description of the linked page
type str \| None "link", "photo", "video", "rich"
author_name str \| None Author of the linked page
author_url str \| None Author URL
provider_name str \| None Provider of the linked page
provider_url str \| None Provider URL
html str \| None Embed HTML (for video and rich types)
width int \| None Embed width in pixels
height int \| None Embed height in pixels
image str \| None Preview thumbnail URL

Mention

A user mentioned within a status.

Field Type Description
id str \| None Account ID of the mentioned user
username str \| None Username of the mentioned user
acct str \| None Webfinger acct: of the mentioned user
url str \| None Profile URL of the mentioned user

Tag

A hashtag used in a status.

Field Type Description
name str \| None Hashtag text (without the leading #)
url str \| None URL of the tag's timeline page

Emoji

A custom emoji used in a status or account display name.

Field Type Description
shortcode str \| None Shortcode, e.g. "blobcat"
url str \| None URL to the full emoji image
static_url str \| None URL to a static (non-animated) version
visible_in_picker bool \| None Whether shown in the emoji picker

Field

A profile metadata field (name/value pair) on an account.

Field Type Description
name str \| None Field label
value str \| None Field content (may be HTML)
verified_at str \| None ISO 8601 timestamp if the URL was verified; None otherwise

Application

The application that created a status.

Field Type Description
name str \| None Application name
website str \| None Application website URL

SearchResults

Returned by search().

Field Type Description
accounts list[Account] Matching accounts
statuses list[Status] Matching statuses
hashtags list[Tag] Matching hashtags
from longwei import SearchResults

results = await ap.search(query="cats", query_type=SearchType.STATUSES)
for status in results.statuses:
    print(status.id, status.content)

Working with Pydantic models

All models support standard Pydantic operations:

# Serialise to dict
status_dict = status.model_dump()

# Access server-specific extra fields not in the model definition
pleroma_data = status.model_extra.get("pleroma")

# Check which fields are defined in the model
print(Status.model_fields.keys())