API Methods Reference¶
All methods are async. Import APClient from the top-level package:
from longwei import APClient
import httpx
async with httpx.AsyncClient() as client:
ap = await APClient.create(
instance="mastodon.social",
client=client,
access_token="your_token",
)
APClient constructor¶
APClient(instance, client, access_token, timeout)¶
Direct instantiation. Prefer APClient.create() for most use cases.
ap = APClient(
instance="mastodon.social",
client=client,
access_token="your_token", # optional
timeout=120, # optional; defaults to 120 seconds
)
| Parameter | Type | Description |
|---|---|---|
instance |
str |
Domain or URL of the instance; trailing slash is stripped |
client |
AsyncClient |
httpx.AsyncClient to use for requests |
access_token |
str \| None |
Bearer token; omit for public-only access |
timeout |
int \| None |
Request timeout in seconds; defaults to 120 |
APClient.create() (async factory)¶
Recommended entry point. Calls determine_instance_type() automatically.
ap = await APClient.create(
instance="mastodon.social",
client=client,
access_token="your_token",
timeout=30,
)
Returns a fully initialised APClient instance.
Instance attributes¶
After creation the following attributes are available on the instance:
| Attribute | Type | Default | Description |
|---|---|---|---|
instance |
str |
— | Normalised instance URL (https:// prefix added if absent) |
instance_type |
str |
INSTANCE_TYPE_MASTODON |
Detected server type |
max_status_len |
int |
500 |
Max characters per status |
max_attachments |
int |
4 |
Max media attachments per status |
max_att_size |
int |
10000000 |
Max attachment size in bytes |
supported_mime_types |
list[str] |
[] |
MIME types accepted for uploads |
ratelimit_limit |
int |
300 |
Requests allowed per rate-limit window |
ratelimit_remaining |
int |
300 |
Requests remaining in current window |
ratelimit_reset |
datetime |
now | When the rate-limit window resets |
pagination |
dict |
{"next": {…}, "prev": {…}} |
Pagination cursors from last response |
Credentials¶
verify_credentials()¶
Returns the authenticated account's profile.
Returns: Account
determine_instance_type()¶
Queries /api/v1/instance and sets instance_type, max_status_len, max_attachments,
max_att_size, and supported_mime_types on the instance. Called automatically by
APClient.create().
Returns: None
Timelines¶
get_public_timeline()¶
statuses: list[Status] = await ap.get_public_timeline(
local=False,
remote=False,
only_media=False,
max_id=None,
since_id=None,
min_id=None,
limit=20,
)
| Parameter | Type | Default | Description |
|---|---|---|---|
local |
bool |
False |
Show only local statuses |
remote |
bool |
False |
Show only remote statuses |
only_media |
bool |
False |
Show only statuses with media attached |
max_id |
str \| None |
None |
Return results older than this ID |
since_id |
str \| None |
None |
Return results newer than this ID |
min_id |
str \| None |
None |
Return results immediately newer than this ID |
limit |
int |
20 |
Max results to return (server max: 40) |
Returns: list[Status]
get_home_timeline()¶
statuses: list[Status] = await ap.get_home_timeline(
max_id=None,
since_id=None,
min_id=None,
limit=20,
)
Requires authentication. Returns statuses from accounts the authenticated user follows.
Returns: list[Status]
get_hashtag_timeline()¶
statuses: list[Status] = await ap.get_hashtag_timeline(
hashtag,
any_tags=None,
all_tags=None,
none_tags=None,
local=False,
remote=False,
only_media=False,
max_id=None,
since_id=None,
min_id=None,
limit=20,
)
| Parameter | Type | Default | Description |
|---|---|---|---|
hashtag |
str |
required | Hashtag to query, without the # prefix |
any_tags |
list[str] \| None |
None |
Also include statuses with any of these additional tags |
all_tags |
list[str] \| None |
None |
Also include statuses that contain all of these tags |
none_tags |
list[str] \| None |
None |
Exclude statuses with any of these tags |
local |
bool |
False |
Only local statuses |
remote |
bool |
False |
Only remote statuses |
only_media |
bool |
False |
Only statuses with media |
max_id / since_id / min_id |
str \| None |
None |
Pagination cursors |
limit |
int |
20 |
Max results (server max: 40) |
Returns: list[Status]
get_account_statuses()¶
statuses: list[Status] = await ap.get_account_statuses(
account_id,
max_id=None,
min_id=None,
since_id=None,
limit=None,
only_media=None,
exclude_replies=None,
exclude_reblogs=None,
tagged=None,
)
| Parameter | Type | Default | Description |
|---|---|---|---|
account_id |
str |
required | ID of the account |
max_id |
str \| None |
None |
Return statuses older than this ID |
min_id |
str \| None |
None |
Return statuses immediately newer than this ID |
since_id |
str \| None |
None |
Return statuses newer than this ID |
limit |
int \| None |
None |
Maximum number of results (server default: 20, max: 40) |
only_media |
bool \| None |
None |
Only return statuses with media attachments |
exclude_replies |
bool \| None |
None |
Skip statuses that are replies |
exclude_reblogs |
bool \| None |
None |
Skip statuses that are reblogs/boosts |
tagged |
str \| None |
None |
Filter by hashtag (without the #) |
Returns: list[Status]
Statuses¶
post_status()¶
status: Status = await ap.post_status(
status,
visibility=Visibility.PUBLIC,
media_ids=None,
sensitive=False,
spoiler_text=None,
scheduled_at=None,
in_reply_to_id=None,
language=None,
poll_options=None,
poll_expires_in=None,
poll_multiple=False,
poll_hide_totals=False,
)
| Parameter | Type | Default | Description |
|---|---|---|---|
status |
str |
required | Text content of the status |
visibility |
Visibility |
Visibility.PUBLIC |
Who can see the status |
media_ids |
list[str] \| None |
None |
IDs from post_media() to attach |
sensitive |
bool |
False |
Mark the status as sensitive |
spoiler_text |
str \| None |
None |
Content warning text |
scheduled_at |
datetime \| None |
None |
Schedule for future posting (at least 5 min ahead); timezone defaults to UTC if naive |
in_reply_to_id |
str \| None |
None |
ID of the status being replied to |
language |
str \| None |
None |
ISO 639-1 language code (e.g. "en") |
poll_options |
list[str] \| None |
None |
Answer strings for an attached poll (at least 2); mutually exclusive with media_ids |
poll_expires_in |
int \| None |
None |
Seconds until the poll closes; required when poll_options is set |
poll_multiple |
bool |
False |
Allow voters to select multiple options |
poll_hide_totals |
bool |
False |
Hide vote counts until the poll ends |
Returns: Status
delete_status()¶
| Parameter | Type | Default | Description |
|---|---|---|---|
status |
str \| Status |
required | Status ID or Status object |
delete_only_one |
bool |
False |
Set True to skip the random 0–3 s batch delay |
When a Status object is passed on a Pleroma instance, undo_reblog() or undo_favourite()
is called first if the status is reblogged or favourited.
Returns: Status (the deleted status)
reblog()¶
| Parameter | Type | Default | Description |
|---|---|---|---|
status_id |
str |
required | ID of the status to reblog |
visibility |
Visibility \| None |
None |
Override reblog visibility: public, unlisted, or private. Omit to use the account default. |
Returns: Status
undo_reblog()¶
| Parameter | Type | Description |
|---|---|---|
status |
str \| Status |
Status ID or Status object |
Returns: Status
undo_favourite()¶
| Parameter | Type | Description |
|---|---|---|
status |
str \| Status |
Status ID or Status object |
Returns: Status
Media¶
post_media()¶
Upload a media file. Returns a MediaAttachment
(use the id field as an entry in media_ids when calling post_status()).
Attempts POST /api/v2/media first; falls back to POST /api/v1/media on 404.
If the server responds with HTTP 202 (still processing), polls until the attachment
is ready before returning — the call always resolves with a fully-processed attachment.
| Parameter | Type | Default | Description |
|---|---|---|---|
file |
IO[bytes] |
required | File-like object opened in binary mode |
mime_type |
str |
required | MIME type, e.g. "image/jpeg" |
description |
str \| None |
None |
Alt-text for accessibility |
focus |
tuple[float, float] \| None |
None |
Focal point (x, y) in range [-1.0, 1.0] |
Returns: MediaAttachment
Search¶
search()¶
results = await ap.search(
query,
query_type,
resolve=True,
following=False,
account_id=None,
exclude_unreviewed=False,
max_id=None,
min_id=None,
limit=None,
offset=None,
)
| Parameter | Type | Default | Description |
|---|---|---|---|
query |
str |
required | Search query string |
query_type |
SearchType |
required | Constrain results to accounts, hashtags, or statuses |
resolve |
bool |
True |
Use WebFinger to resolve unknown remote accounts |
following |
bool |
False |
Only include accounts the user follows |
account_id |
str \| None |
None |
Restrict status search to this account |
exclude_unreviewed |
bool |
False |
Filter unreviewed tags (useful for trending) |
max_id |
str \| None |
None |
Results older than this ID |
min_id |
str \| None |
None |
Results newer than this ID |
limit |
int \| None |
None |
Max results per category (server default: 20, max: 40) |
offset |
int \| None |
None |
Skip the first N results |
Returns: SearchResults with .accounts, .statuses, and .hashtags lists
Attempts GET /api/v2/search first; falls back to GET /api/v1/search on 404 (e.g. Pleroma).
On v1 fallback only query, query_type, resolve, and limit are forwarded — the remaining
parameters are silently dropped as they are not part of the v1 spec.
Authentication (static methods)¶
See the Authentication guide for full details and examples.
| Method | Description |
|---|---|
APClient.create_app(instance_url, client, ...) |
Register an OAuth app; returns (client_id, client_secret) |
APClient.get_auth_token(instance_url, username, password, client, ...) |
Password grant; returns access token |
APClient.generate_authorization_url(instance_url, client_id, ...) |
Build OAuth redirect URL |
APClient.validate_authorization_code(client, instance_url, code, client_id, client_secret) |
Exchange code for token |
Pagination¶
After every timeline call, pagination cursors are stored on the client:
statuses = await ap.get_public_timeline(limit=20)
next_max_id = ap.pagination["next"]["max_id"]
if next_max_id:
more = await ap.get_public_timeline(limit=20, max_id=next_max_id)
ap.pagination layout:
{
"next": {"max_id": str | None, "min_id": str | None},
"prev": {"max_id": str | None, "min_id": str | None},
}
Rate limits¶
Rate limit state is updated after every response:
| Attribute | Description |
|---|---|
ap.ratelimit_limit |
Requests allowed per window |
ap.ratelimit_remaining |
Requests left in current window |
ap.ratelimit_reset |
datetime when window resets |
When ratelimit_remaining reaches 0 and the reset time is still in the future, the next
call raises RatelimitError before any HTTP request is made.
See Error Handling for handling patterns.