{"openapi":"3.1.0","info":{"title":"nexus-webapi","description":"Nexus API exposes a social-media-like API capable of powerful Web-of-Trust inference","license":{"name":"MIT","identifier":"MIT"},"version":"0.4.1"},"paths":{"/v0/bootstrap/{user_id}":{"get":{"tags":["Bootstrap"],"description":"Initial payload for all data required to bootstrap the pubky.app application. The client app will request it while the user is performing sign-in/sign-up in order to pre-populate the client DB","operationId":"bootstrap_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"Initial payload to bootstrap the client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Bootstrap"}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/events":{"get":{"tags":["Events"],"operationId":"get_events_handler","parameters":[{"name":"cursor","in":"query","description":"Cursor","required":true,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"limit","in":"query","description":"Number of events to return (1–1000, **default** 500)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_500_1000"}}],"responses":{"200":{"description":"Events list as plain text with cursor","content":{"text/plain":{"schema":{"type":"string"},"example":"PUT pubky://<pk>/<path>\nDEL pubky://<pk>/<path>\nPUT pubky://<pk>/<path>\ncursor: 2"}}},"400":{"description":"Bad request"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/files/by_ids":{"post":{"tags":["File"],"description":"List files by URIs. This is a POST request because we're passing a potentially large list of file URIs in the request body.","operationId":"file_details_by_uris_handler","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilesByIdsBody"}}},"required":true},"responses":{"200":{"description":"List of File Details","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FileDetails"}}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/files/file/{file_id}":{"get":{"tags":["File"],"description":"File details","operationId":"file_details_handler","parameters":[{"name":"file_id","in":"path","description":"File Pubky Uri","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File Details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileDetails"}}}},"400":{"description":"Malformed file URI"},"404":{"description":"File not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/info":{"get":{"tags":["Info"],"operationId":"info_handler","responses":{"200":{"description":"Server info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInfo"}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/ingest/{user_id}":{"put":{"tags":["Bootstrap"],"description":"Ingest a user by resolving their homeserver and persisting a user node in the graph. If the user is already known, this is a no-op.","operationId":"ingest_user_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"User successfully ingested (or already known)"},"403":{"description":"User is hosted on a blacklisted HS"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/post/{author_id}/{post_id}":{"get":{"tags":["Post"],"description":"Post view","operationId":"post_view_handler","parameters":[{"name":"author_id","in":"path","description":"Author Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"path","description":"Post Crockford32 ID","required":true,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"limit_tags","in":"query","description":"Upper limit on the number of tags for the post (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"limit_taggers","in":"query","description":"Upper limit on the number of taggers per tag (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"include_attachment_metadata","in":"query","description":"Include file metadata for post attachments","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Post","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostViewDetailed"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"Post not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/post/{author_id}/{post_id}/bookmark":{"get":{"tags":["Post"],"description":"Post bookmark","operationId":"post_bookmark_handler","parameters":[{"name":"author_id","in":"path","description":"Author Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"path","description":"Post Crockford32 ID","required":true,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"Post Bookmark","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Bookmark"}}}},"404":{"description":"Post not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/post/{author_id}/{post_id}/counts":{"get":{"tags":["Post"],"description":"Post counts","operationId":"post_counts_handler","parameters":[{"name":"author_id","in":"path","description":"Author Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"path","description":"Post Crockford32 ID","required":true,"schema":{"$ref":"#/components/schemas/PostId"}}],"responses":{"200":{"description":"Post Counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostCounts"}}}},"404":{"description":"Post not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/post/{author_id}/{post_id}/details":{"get":{"tags":["Post"],"description":"Post details","operationId":"post_details_handler","parameters":[{"name":"author_id","in":"path","description":"Author Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"path","description":"Post Crockford32 ID","required":true,"schema":{"$ref":"#/components/schemas/PostId"}}],"responses":{"200":{"description":"Post Details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostDetails"}}}},"404":{"description":"Post not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/post/{author_id}/{post_id}/taggers/{label}":{"get":{"tags":["Post"],"description":"Post specific label Taggers","operationId":"post_taggers_handler","parameters":[{"name":"author_id","in":"path","description":"Author Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"label","in":"path","description":"Tag name","required":true,"schema":{"$ref":"#/components/schemas/TagLabel"}},{"name":"post_id","in":"path","description":"Post ID","required":true,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"depth","in":"query","description":"Ignored: Web of Trust filtering is not applied to taggers","required":false,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"skip","in":"query","description":"Skip N taggers (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Number of taggers to return (1–100, **default** 40)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_40_100"}}],"responses":{"200":{"description":"Post tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaggersInfoResponse"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/post/{author_id}/{post_id}/tags":{"get":{"tags":["Post"],"description":"Post tags","operationId":"post_tags_handler","parameters":[{"name":"author_id","in":"path","description":"Author Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"path","description":"Post ID","required":true,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip_tags","in":"query","description":"Skip N tags (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit_tags","in":"query","description":"Upper limit on the number of tags (1–100, **default** 5 in the global view; the WoT view returns the full trusted set by default—pass `limit_tags` for a compact view)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"limit_taggers","in":"query","description":"Upper limit on the number of taggers per tag (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"depth","in":"query","description":"WoT depth (1-3). Provide it together with `viewer_id` to filter post tags through the viewer's Web of Trust. In the WoT view `limit_tags` defaults to the full trusted set so a trusted moderation tag is not paginated out by tagger count (pass `limit_tags` for a compact view); `skip_tags`/`limit_taggers` apply as in the global view. `viewer_id` without `depth` returns the global tag view; `depth` without `viewer_id`, or an out-of-range `depth` with `viewer_id`, is rejected with 400.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Post tags","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TagDetails"}}}}},"400":{"description":"Invalid input"},"404":{"description":"Post not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/resource/by-uri":{"get":{"tags":["Resource"],"description":"Lookup resource tags by raw URI","operationId":"resource_by_uri_handler","parameters":[{"name":"uri","in":"query","description":"Raw URI to look up","required":true,"schema":{"type":"string"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip_tags","in":"query","description":"Skip N tags (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit_tags","in":"query","description":"Upper limit on the number of tags (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"limit_taggers","in":"query","description":"Upper limit on the number of taggers per tag (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}}],"responses":{"200":{"description":"Resource tags with metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceTagsResponse"}}}},"400":{"description":"Invalid URI"},"404":{"description":"Resource not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/resource/{resource_id}/tags":{"get":{"tags":["Resource"],"description":"Resource tags","operationId":"resource_tags_handler","parameters":[{"name":"resource_id","in":"path","description":"Resource ID (32-char hex)","required":true,"schema":{"$ref":"#/components/schemas/ResourceId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip_tags","in":"query","description":"Skip N tags (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit_tags","in":"query","description":"Upper limit on the number of tags (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"limit_taggers","in":"query","description":"Upper limit on the number of taggers per tag (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}}],"responses":{"200":{"description":"Resource tags with metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceTagsResponse"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"Resource not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/resource/{resource_id}/tags/{label}/taggers":{"get":{"tags":["Resource"],"description":"Resource specific label taggers","operationId":"resource_taggers_handler","parameters":[{"name":"resource_id","in":"path","description":"Resource ID (32-char hex)","required":true,"schema":{"$ref":"#/components/schemas/ResourceId"}},{"name":"label","in":"path","description":"Tag label","required":true,"schema":{"$ref":"#/components/schemas/TagLabel"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N taggers (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Limit taggers (1–100, default 40)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_40_100"}}],"responses":{"200":{"description":"Resource taggers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaggersInfoResponse"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/search/posts/by_content":{"get":{"tags":["Search"],"description":"Full-text search over post content","operationId":"search_posts_by_content_handler","parameters":[{"name":"q","in":"query","description":"Search query (2–30 characters, up to 4 terms)","required":true,"schema":{"$ref":"#/components/schemas/PostSearchQuery"}},{"name":"author","in":"query","description":"Optional author Pubky ID to scope results","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"kind","in":"query","description":"Optional post kind to filter by: short, long, image, video, link, file, collection","required":false,"schema":{"$ref":"#/components/schemas/PubkyAppPostKind"}},{"name":"skip","in":"query","description":"Skip N results (max 1000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_1000"}},{"name":"limit","in":"query","description":"Limit the number of results (1–100, default 20)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_100"}}],"responses":{"200":{"description":"Search results ordered by relevance score","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PostsByContentSearch"}}}}},"400":{"description":"Invalid query or limit parameter"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/search/posts/by_tag/{tag}":{"get":{"tags":["Search"],"description":"Search Posts by Tag","operationId":"search_posts_by_tag_handler","parameters":[{"name":"tag","in":"path","description":"Tag name","required":true,"schema":{"$ref":"#/components/schemas/TagLabel"}},{"name":"sorting","in":"query","description":"StreamSorting method","required":false,"schema":{"$ref":"#/components/schemas/StreamSorting"}},{"name":"start","in":"query","description":"The start of the stream timeframe. Posts with a timestamp greater than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}},{"name":"end","in":"query","description":"The end of the stream timeframe. Posts with a timestamp less than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}},{"name":"skip","in":"query","description":"Skip N results (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Limit the number of results (1–200, default 20)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_200"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PostsByTagSearch"}}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/search/tags/by_prefix/{prefix}":{"get":{"tags":["Search"],"description":"Search tags by prefix","operationId":"search_tags_by_prefix_handler","parameters":[{"name":"prefix","in":"path","description":"Tag name prefix","required":true,"schema":{"$ref":"#/components/schemas/TagLabel"}},{"name":"skip","in":"query","description":"Skip N results (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Limit the number of results (1–100, default 20)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_100"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/search/users/by_id/{prefix}":{"get":{"tags":["Search"],"description":"Search user IDs by ID prefix","operationId":"search_users_by_id_handler","parameters":[{"name":"prefix","in":"path","description":"User ID prefix to search for (at least 3 characters)","required":true,"schema":{"$ref":"#/components/schemas/UserIdPrefix"}},{"name":"skip","in":"query","description":"Skip N results (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Limit the number of results (1–200, default 50)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_50_200"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSearch"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/search/users/by_name/{prefix}":{"get":{"tags":["Search"],"description":"Search user id by username prefix","operationId":"search_users_by_name_handler","parameters":[{"name":"prefix","in":"path","description":"Username prefix to search for","required":true,"schema":{"$ref":"#/components/schemas/UsernamePrefix"}},{"name":"skip","in":"query","description":"Skip N results (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Limit the number of results (1–200, default 50)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_50_200"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSearch"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/search/users/by_tags":{"get":{"tags":["Search"],"description":"Search users by profile tags, scored by how many taggers applied the searched labels. Equal scores break ties by user id descending","operationId":"search_users_by_tags_handler","parameters":[{"name":"tags","in":"query","description":"Comma-separated tag labels (1-5). Users tagged with any of them are returned","required":true,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"skip","in":"query","description":"Skip N results (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Limit the number of results (1-200, default 20)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_200"}}],"responses":{"200":{"description":"Search results ordered by tagger count","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersByTagSearch"}}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/posts":{"get":{"tags":["Stream"],"description":"Stream Posts: Retrieve a stream of posts.\n\n\nThe `source` parameter determines the type of stream. Depending on the `source`, certain parameters are required:\n- *following*, *followers*, *friends*: Require **observer_id** and exclude posts authored by the observer.\n- *bookmarks*: Requires **observer_id**.\n- *post_replies*: Requires **author_id** and **post_id** to filter replies to a specific post.\n- *author*:  Requires  **author_id** to filter posts by a specific author.\n- *author_replies*:  Requires  **author_id** to filter replies by a specific author.\n- *collection*: Requires **author_id** and **post_id** of the Collection post; items are returned in curator order.\n\n- *wot*: Requires **observer_id**. Posts from users in the observer's Web of Trust (transitive follows, `depth` 1-3, default 2). Excludes the observer's own posts, including when a follow cycle reaches the observer again.\n- *wot_domain*: Requires **observer_id** and **domain_tags**. Posts by authors whom the observer's Web of Trust has tagged with any of `domain_tags`, all of those authors' posts, not only topic-tagged ones; combine with `tags=` for topic-scoped posts. With `depth=0` the trust set is the observer alone (\"Me\"): posts by authors the observer tagged directly. Includes the observer's own posts when they themselves are tagged with a matching label.\n\nEnsure that you provide the necessary parameters based on the selected `source`. If a required parameter is missing, a 400 Bad Request error will be returned.","operationId":"stream_posts_handler","parameters":[{"name":"source","in":"query","description":"Source of posts for streams with viewer (following, followers, friends, bookmarks, post_replies, author, author_replies, collection, wot, wot_domain, all). For `source=collection`: provide `author_id` + `post_id` of the Collection post; items are returned in curator order. `tags`, `kind`, `exclude_kinds`, `sorting`, `order`, `start`, `end` are all rejected with 400 (incompatible with the curator-ordered result set). Items whose underlying post is missing (deleted, not indexed) or whose URI is malformed/non-post are dropped during hydration; pages may be shorter than `limit`. Pagination via `skip`/`limit` is not stable across deletions, if an item is removed between page fetches, the same `skip` returns a different window. The FE can identify dropped items by diffing the response against the Collection envelope's `items[]`.","required":false,"schema":{"$ref":"#/components/schemas/StreamSourceKind"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"observer_id","in":"query","description":"Observer Pubky ID. The central point for streams with Reach","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"author_id","in":"query","description":"Filter posts by an specific author User ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"query","description":"This parameter is needed when we want to retrieve the replies stream for a post","required":false,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"sorting","in":"query","description":"Sort method (`timeline` or `total_engagement`). Ties are broken by post id; pagination across equal scores is best-effort.","required":false,"schema":{"$ref":"#/components/schemas/StreamSorting"}},{"name":"order","in":"query","description":"Ordering of response list. Either 'ascending' or 'descending'. Defaults to descending.","required":false,"schema":{"$ref":"#/components/schemas/SortOrder"}},{"name":"tags","in":"query","description":"Filter by a list of comma-separated tags (max 5). E.g.,`&tags=dev,free,opensource`. Only posts matching at least one of the tags will be returned.","required":false,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"depth","in":"query","description":"WoT traversal depth. For `source=wot`: 1-3, default 2. For `source=wot_domain`: 0-3, default 2, where `depth=0` is the observer-only (\"Me\") trust set (posts by authors the observer tagged directly, no follow traversal). `depth=0` is invalid for `source=wot`. Ignored for other sources.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"domain_tags","in":"query","description":"Required for `source=wot_domain`. Comma-separated tag labels (max 5); returns posts by authors tagged with any of these by the observer's WoT, or by the observer alone when `depth=0`. E.g. `&domain_tags=bitcoiner,btc-dev`. Ignored for other sources.","required":false,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"kind","in":"query","description":"Filter by post kind: short, long, image, video, link, file, collection. Mutually exclusive with `exclude_kinds`; rejected for `source=post_replies` and `source=author_replies`.","required":false,"schema":{"$ref":"#/components/schemas/PubkyAppPostKind"}},{"name":"exclude_kinds","in":"query","description":"Comma-separated post kinds to exclude server-side (1-7 items, duplicates ignored), e.g. `&exclude_kinds=collection,link`. Valid values: short, long, image, video, link, file, collection; anything else is rejected with 400. Mutually exclusive with `kind`; rejected for `source=collection`, `source=post_replies` and `source=author_replies`. Posts with a missing or unrecognized kind are never excluded.","required":false,"schema":{"$ref":"#/components/schemas/PostKinds"}},{"name":"skip","in":"query","description":"Skip N posts (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N posts (1–50, default 10)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_10_50"}},{"name":"start","in":"query","description":"The start of the stream timeframe or score. Posts with a timestamp/score greater than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}},{"name":"end","in":"query","description":"The end of the stream timeframe or score. Posts with a timestamp/score less than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}},{"name":"include_attachment_metadata","in":"query","description":"Include file metadata for post attachments","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Posts stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostStreamDetailed"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/posts/by_ids":{"post":{"tags":["Stream"],"description":"Stream post by ID. This is a POST request because we're passing a potentially large list of post IDs in the request body","operationId":"stream_posts_by_ids_handler","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostStreamByIdsRequest"}}},"required":true},"responses":{"200":{"description":"Post stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostStreamDetailed"}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/posts/keys":{"get":{"tags":["Stream"],"description":"Stream Post Keys: Retrieve a stream of post keys\n\nThe `source` parameter determines the type of stream. Depending on the `source`, certain parameters are required:\n- *following*, *followers*, *friends*: Require **observer_id** and exclude posts authored by the observer.\n- *bookmarks*: Requires **observer_id**.\n- *post_replies*: Requires **author_id** and **post_id** to filter replies to a specific post.\n- *author*:  Requires  **author_id** to filter posts by a specific author.\n- *author_replies*:  Requires  **author_id** to filter replies by a specific author.\n- *collection*: Requires **author_id** and **post_id** of the Collection post; keys are returned in curator order.\n\n- *wot*: Requires **observer_id**. Posts from users in the observer's Web of Trust (transitive follows, `depth` 1-3, default 2). Excludes the observer's own posts, including when a follow cycle reaches the observer again.\n- *wot_domain*: Requires **observer_id** and **domain_tags**. Posts by authors whom the observer's Web of Trust has tagged with any of `domain_tags`, all of those authors' posts, not only topic-tagged ones; combine with `tags=` for topic-scoped posts. With `depth=0` the trust set is the observer alone (\"Me\"): posts by authors the observer tagged directly. Includes the observer's own posts when they themselves are tagged with a matching label.\n\nEnsure that you provide the necessary parameters based on the selected `source`. If a required parameter is missing, a 400 Bad Request error will be returned.","operationId":"stream_post_keys_handler","parameters":[{"name":"source","in":"query","description":"Source of posts for streams with viewer (following, followers, friends, bookmarks, post_replies, author, author_replies, collection, wot, wot_domain, all). For `source=collection`: provide `author_id` + `post_id` of the Collection post; keys are returned in curator order. `tags`, `kind`, `exclude_kinds`, `sorting`, `order`, `start`, `end` are all rejected with 400 (incompatible with the curator-ordered result set). Like every other source, the returned keys are a best-effort snapshot, they may reference posts that have since been deleted or are not yet indexed; callers should hydrate via `GET /v0/stream/posts?source=collection&author_id=...&post_id=...` (or `POST /v0/stream/posts/by_ids`) which drops unresolved refs. Pagination via `skip`/`limit` is not stable across deletions.","required":false,"schema":{"$ref":"#/components/schemas/StreamSourceKind"}},{"name":"observer_id","in":"query","description":"Observer Pubky ID. The central point for streams with Reach","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"author_id","in":"query","description":"Filter posts by an specific author User ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"query","description":"This parameter is needed when we want to retrieve the replies stream for a post","required":false,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"sorting","in":"query","description":"Sort method (`timeline` or `total_engagement`). Ties are broken by post id; pagination across equal scores is best-effort.","required":false,"schema":{"$ref":"#/components/schemas/StreamSorting"}},{"name":"order","in":"query","description":"Ordering of response list. Either 'ascending' or 'descending'. Defaults to descending.","required":false,"schema":{"$ref":"#/components/schemas/SortOrder"}},{"name":"tags","in":"query","description":"Filter by a list of comma-separated tags (max 5). E.g.,`&tags=dev,free,opensource`. Only posts matching at least one of the tags will be returned.","required":false,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"depth","in":"query","description":"WoT traversal depth. For `source=wot`: 1-3, default 2. For `source=wot_domain`: 0-3, default 2, where `depth=0` is the observer-only (\"Me\") trust set (posts by authors the observer tagged directly, no follow traversal). `depth=0` is invalid for `source=wot`. Ignored for other sources.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"domain_tags","in":"query","description":"Required for `source=wot_domain`. Comma-separated tag labels (max 5); returns posts by authors tagged with any of these by the observer's WoT, or by the observer alone when `depth=0`. E.g. `&domain_tags=bitcoiner,btc-dev`. Ignored for other sources.","required":false,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"kind","in":"query","description":"Filter by post kind: short, long, image, video, link, file, collection. Mutually exclusive with `exclude_kinds`; rejected for `source=post_replies` and `source=author_replies`.","required":false,"schema":{"$ref":"#/components/schemas/PubkyAppPostKind"}},{"name":"exclude_kinds","in":"query","description":"Comma-separated post kinds to exclude server-side (1-7 items, duplicates ignored), e.g. `&exclude_kinds=collection,link`. Valid values: short, long, image, video, link, file, collection; anything else is rejected with 400. Mutually exclusive with `kind`; rejected for `source=collection`, `source=post_replies` and `source=author_replies`. Posts with a missing or unrecognized kind are never excluded.","required":false,"schema":{"$ref":"#/components/schemas/PostKinds"}},{"name":"skip","in":"query","description":"Skip N posts (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N posts (1–50, default 10)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_10_50"}},{"name":"start","in":"query","description":"The start of the stream timeframe or score. Posts with a timestamp/score greater than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}},{"name":"end","in":"query","description":"The end of the stream timeframe or score. Posts with a timestamp/score less than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}}],"responses":{"200":{"description":"Post key stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostKeyStream"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/resources":{"get":{"tags":["Stream"],"description":"Stream resources with app/tag filtering, returns full ResourceView objects","operationId":"stream_resources_handler","parameters":[{"name":"app","in":"query","description":"Filter by app namespace","required":false,"schema":{"type":"string"}},{"name":"tags","in":"query","description":"Comma-separated tag labels (max 5, OR logic)","required":false,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"sorting","in":"query","description":"timeline or taggers_count","required":false,"schema":{"type":"string"}},{"name":"skip","in":"query","description":"Pagination skip (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Pagination limit (1–100, default 10)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_10_100"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID for relationship checks","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"Resource stream","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ResourceView"}}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/resources/ids":{"get":{"tags":["Stream"],"description":"Stream resource IDs with app/tag filtering","operationId":"stream_resource_ids_handler","parameters":[{"name":"app","in":"query","description":"Filter by app namespace (e.g., mapky, eventky)","required":false,"schema":{"type":"string"}},{"name":"tags","in":"query","description":"Comma-separated tag labels (max 5, OR logic)","required":false,"schema":{"$ref":"#/components/schemas/Tags"}},{"name":"sorting","in":"query","description":"timeline or taggers_count","required":false,"schema":{"type":"string"}},{"name":"skip","in":"query","description":"Pagination skip (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Pagination limit (1–100, default 10)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_10_100"}}],"responses":{"200":{"description":"Resource IDs with cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceKeyStream"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/users":{"get":{"tags":["Stream"],"description":"Stream Users: Retrieve a stream of users.\n\nThe `source` parameter determines the type of stream. Depending on the `source`, certain parameters are required:\n- *following*, *followers*, *friends*, *recommended*: Requires **user_id**.\n- *influencers*: When **user_id** is provided with a **timeframe** (not 'all_time'), **reach** determines the network scope for finding influencers.The **reach** parameter can be: 'followers', 'following', 'friends', 'wot' (defaults to depth 2), or 'wot_1', 'wot_2', 'wot_3'. Defaults to 'wot_2' if not specified. If **user_id** is not provided, returns global influencers.\n- *post_replies*: Requires **author_id** and **post_id** to filter replies to a specific post.\n- *most_followed*: Does not require **user_id**.\n- *starter_pack*: Requires **tags** (1-5 comma-separated interest labels) and nothing else, so it works for a brand new account with no follows. Returns one deduplicated list ranked by the summed TrustRank of the people who tagged each candidate, either on their profile or on a post they wrote. Labels are ranked separately and interleaved in the order given, so a popular interest does not crowd out a niche one. Passing **user_id** additionally drops that user and everyone they already follow, and **viewer_id** does the same when **user_id** is absent. When both are given, **user_id** is the one excluded and **viewer_id** only shapes the relationship flags, as on every other source. An id that is not indexed yet excludes nothing. **timeframe** gates on the candidate having posted within it; the default 'all_time' only requires that they have ever posted. Moderation labels are rejected, as is a **skip** above 100, which is past the point the ranking can be paged accurately.\n\nEnsure that you provide the necessary parameters based on the selected `source`. If the required parameter is not provided, an error will be returned.","operationId":"stream_users_handler","parameters":[{"name":"source","in":"query","description":"Source of users for streams (followers, following, friends, most_followed, influencers, recommended, post_replies, starter_pack)","required":false,"schema":{"$ref":"#/components/schemas/UserStreamSource"}},{"name":"user_id","in":"query","description":"User ID to use for streams with source 'following', 'followers', 'friends', 'influencers' and 'recommended'. Optional for 'starter_pack', where it is the subject whose self and follows are excluded; 'viewer_id' stands in as that subject only when 'user_id' is absent.","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"author_id","in":"query","description":"Author ID when source is 'post_replies'","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"query","description":"Post ID when source is 'post_replies'","required":false,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"reach","in":"query","description":"The target reach of the 'influencers' source: `followers` | `following` | `friends` | `wot` | `wot_1`..`wot_3`. Bare `wot` defaults to depth 2.","required":false,"schema":{"type":"string"},"example":"wot_2"},{"name":"timeframe","in":"query","description":"Timeframe for sources supporting a range","required":false,"schema":{"$ref":"#/components/schemas/Timeframe"}},{"name":"preview","in":"query","description":"Provide a random selection of size 3 for sources supporting preview. Passing preview ignores skip and limit parameters.","required":false,"schema":{"type":"boolean"}},{"name":"depth","in":"query","description":"User trusted network depth, user following users distance. Numbers bigger than 3 will be ignored","required":false,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"tags","in":"query","description":"Comma-separated interest labels (1-5) for source 'starter_pack'. Rejected with 400 for every other source, and for moderation labels.","required":false,"schema":{"$ref":"#/components/schemas/Tags"},"example":"bitcoin,travel,music"},{"name":"skip","in":"query","description":"Skip N users (max 10000, or 100 for source 'starter_pack')","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N users (1–20, default 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_20"}}],"responses":{"200":{"description":"Users stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStream"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/users/by_ids":{"post":{"tags":["Stream"],"description":"Stream users by ID. This is a POST request because we're passing a potentially large list of user IDs in the request body.","operationId":"stream_users_by_ids_handler","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStreamByIdsRequest"}}},"required":true},"responses":{"200":{"description":"Users stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStream"}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/users/ids":{"get":{"tags":["Stream"],"description":"Stream User IDs: Retrieve a stream of user identifiers.\n\nThe `source` parameter determines the type of stream. Depending on the `source`, certain parameters are required:\n- *following*, *followers*, *friends*, *recommended*: Requires **user_id**.\n- *influencers*: When **user_id** is provided with a **timeframe** (not 'all_time'), **reach** determines the network scope for finding influencers.The **reach** parameter can be: 'followers', 'following', 'friends', 'wot' (defaults to depth 2), or 'wot_1', 'wot_2', 'wot_3'. Defaults to 'wot_2' if not specified. If **user_id** is not provided, returns global influencers.\n- *post_replies*: Requires **author_id** and **post_id** to filter replies to a specific post.\n- *most_followed*: Does not require **user_id**.\n- *starter_pack*: Requires **tags** (1-5 comma-separated interest labels) and nothing else, so it works for a brand new account with no follows. Returns one deduplicated list ranked by the summed TrustRank of the people who tagged each candidate, either on their profile or on a post they wrote. Labels are ranked separately and interleaved in the order given, so a popular interest does not crowd out a niche one. Passing **user_id** additionally drops that user and everyone they already follow, and **viewer_id** does the same when **user_id** is absent. When both are given, **user_id** is the one excluded and **viewer_id** only shapes the relationship flags, as on every other source. An id that is not indexed yet excludes nothing. **timeframe** gates on the candidate having posted within it; the default 'all_time' only requires that they have ever posted. Moderation labels are rejected, as is a **skip** above 100, which is past the point the ranking can be paged accurately.\n\nEnsure that you provide the necessary parameters based on the selected `source`. If the required parameter is not provided, an error will be returned.","operationId":"stream_user_ids_handler","parameters":[{"name":"source","in":"query","description":"Source of users for streams (followers, following, friends, most_followed, influencers, recommended, post_replies, starter_pack)","required":false,"schema":{"$ref":"#/components/schemas/UserStreamSource"}},{"name":"user_id","in":"query","description":"User ID to use for streams with source 'following', 'followers', 'friends', 'influencers' and 'recommended'. Optional for 'starter_pack', where it is the subject whose self and follows are excluded; 'viewer_id' stands in as that subject only when 'user_id' is absent.","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"author_id","in":"query","description":"Author ID when source is 'post_replies'","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"post_id","in":"query","description":"Post ID when source is 'post_replies'","required":false,"schema":{"$ref":"#/components/schemas/PostId"}},{"name":"reach","in":"query","description":"The target reach of the 'influencers' source: `followers` | `following` | `friends` | `wot` | `wot_1`..`wot_3`. Bare `wot` defaults to depth 2.","required":false,"schema":{"type":"string"},"example":"wot_2"},{"name":"timeframe","in":"query","description":"Timeframe for sources supporting a range","required":false,"schema":{"$ref":"#/components/schemas/Timeframe"}},{"name":"preview","in":"query","description":"Provide a random selection of size 3 for sources supporting preview. Passing preview ignores skip and limit parameters.","required":false,"schema":{"type":"boolean"}},{"name":"depth","in":"query","description":"User trusted network depth, user following users distance. Numbers bigger than 3 will be ignored","required":false,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"tags","in":"query","description":"Comma-separated interest labels (1-5) for source 'starter_pack'. Rejected with 400 for every other source, and for moderation labels.","required":false,"schema":{"$ref":"#/components/schemas/Tags"},"example":"bitcoin,travel,music"},{"name":"skip","in":"query","description":"Skip N users (max 10000, or 100 for source 'starter_pack')","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N users (1–20, default 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_20"}}],"responses":{"200":{"description":"User IDs stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserIdStream"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/stream/users/username":{"get":{"tags":["Stream"],"description":"Stream of user from username search result","operationId":"stream_username_search_handler","parameters":[{"name":"username","in":"query","description":"Username to search for","required":true,"schema":{"$ref":"#/components/schemas/UsernamePrefix"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N users (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N users (1–20, default 20)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_20"}}],"responses":{"200":{"description":"Username search stream","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStream"}}}},"400":{"description":"Bad Request"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/tags/hot":{"get":{"tags":["Tags"],"description":"Global Tags by reach","operationId":"hot_tags_handler","parameters":[{"name":"user_id","in":"query","description":"User Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"reach","in":"query","description":"Reach type: `followers` | `following` | `friends` | `wot` | `wot_1`..`wot_3`. To apply that, user_id is required. Bare `wot` defaults to depth 2.","required":false,"schema":{"type":"string"},"example":"wot_2"},{"name":"taggers_limit","in":"query","description":"Retrieve N user_id for each tag. Defaults to `20`","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_20"}},{"name":"skip","in":"query","description":"Skip N tags (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N tag. Defaults to `40`","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_40_40"}},{"name":"timeframe","in":"query","description":"Retrieve hot tags for this specific timeframe. Defaults to `all_time`","required":false,"schema":{"$ref":"#/components/schemas/Timeframe"}}],"responses":{"200":{"description":"Retrieve tags by reach cluster","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/HotTag"}}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/tags/taggers/{label}":{"get":{"tags":["Tags"],"description":"Global tag Taggers","operationId":"tag_taggers_handler","parameters":[{"name":"label","in":"path","description":"Tag name","required":true,"schema":{"$ref":"#/components/schemas/TagLabel"}},{"name":"reach","in":"query","description":"Reach type: `followers` | `following` | `friends` | `wot` | `wot_1`..`wot_3`. To apply that, user_id is required. Bare `wot` defaults to depth 2.","required":false,"schema":{"type":"string"},"example":"wot_2"},{"name":"user_id","in":"query","description":"User ID to base reach on","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N taggers (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N tagggers. Defaults to `20`","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_20"}},{"name":"timeframe","in":"query","description":"Retrieve taggers for this specific timeframe (not applied for reach). Defaults to `all_time`","required":false,"schema":{"$ref":"#/components/schemas/Timeframe"}}],"responses":{"200":{"description":"Taggers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Vec"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/tags/{tagger_id}/{tag_id}":{"get":{"tags":["Tag"],"description":"Tag view","operationId":"tag_view_handler","parameters":[{"name":"tagger_id","in":"path","description":"Tagger Pubky ID","required":true,"schema":{"type":"string"}},{"name":"tag_id","in":"path","description":"Tag Pubky ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagView"}}}},"404":{"description":"Tag not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}":{"get":{"tags":["User"],"description":"User profile.\n\n**social_graph_status** says how established the account is in the follow graph, from a seeded ranking recomputed on a schedule. `null` means no ranking is available and the badge should be hidden, which is not the same as `new`. It is not an endorsement: a high value means an account is expensive to fake, not that it is trustworthy.","operationId":"user_view_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"depth","in":"query","description":"WoT depth (1-3) for filtering the profile's tags through the viewer's network. Requires `viewer_id`; a value outside 1-3 (or `depth` without `viewer_id`) returns 400","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"User Profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserView"}}}},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/counts":{"get":{"tags":["User"],"description":"User counts","operationId":"user_counts_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"User counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCounts"}}}},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/details":{"get":{"tags":["User"],"description":"User details","operationId":"user_details_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"User details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDetails"}}}},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/followers":{"get":{"tags":["User"],"description":"List user's follower IDs","operationId":"user_followers_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N followers (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N followers (1–200, default 50)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_50_200"}}],"responses":{"200":{"description":"User followers list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Followers"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/following":{"get":{"tags":["User"],"description":"List user's following IDs","operationId":"user_following_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N following (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N following (1–200, default 50)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_50_200"}}],"responses":{"200":{"description":"User following list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Following"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/friends":{"get":{"tags":["User"],"description":"List user's friend IDs","operationId":"user_friends_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N friends (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N friends (1–200, default 50)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_50_200"}}],"responses":{"200":{"description":"User friends list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Friends"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/notifications":{"get":{"tags":["User"],"description":"List of user notifications","operationId":"list_notifications_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip","in":"query","description":"Skip N notifications (max 10000)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Retrieve N notifications (1–100, default 20)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_20_100"}},{"name":"start","in":"query","description":"The start of the notifications timeframe. Notifications with a timestamp greater than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}},{"name":"end","in":"query","description":"The end of the notifications timeframe. Notifications with a timestamp less than this value will be excluded from the results","required":false,"schema":{"type":"number","format":"double"}}],"responses":{"200":{"description":"List of notifications","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Notification"}}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/relationship/{viewer_id}":{"get":{"tags":["User"],"description":"User <> Viewer Relationship","operationId":"user_relationship_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"viewer_id","in":"path","description":"Viewer Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}}],"responses":{"200":{"description":"User relationship","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Relationship"}}}},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/taggers/{label}":{"get":{"tags":["User"],"description":"User label taggers","operationId":"user_taggers_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"label","in":"path","description":"Tag name","required":true,"schema":{"$ref":"#/components/schemas/TagLabel"}},{"name":"skip","in":"query","description":"Skip N taggers (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit","in":"query","description":"Number of taggers to return for pagination (1–100, **default** 40)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_40_100"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"depth","in":"query","description":"WoT depth (1-3). When provided with `viewer_id`, taggers are filtered through the viewer's Web of Trust. `depth` without `viewer_id`, or an out-of-range `depth` with `viewer_id`, is rejected with 400.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"User tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaggersInfoResponse"}}}},"400":{"description":"Invalid parameters"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}},"/v0/user/{user_id}/tags":{"get":{"tags":["User"],"description":"User Tags","operationId":"user_tags_handler","parameters":[{"name":"user_id","in":"path","description":"User Pubky ID","required":true,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"skip_tags","in":"query","description":"Skip N tags (0–10 000, **default** 0)","required":false,"schema":{"$ref":"#/components/schemas/BoundedSkip_10000"}},{"name":"limit_tags","in":"query","description":"Upper limit on the number of tags for the user (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"limit_taggers","in":"query","description":"Upper limit on the number of taggers per tag (1–100, **default** 5)","required":false,"schema":{"$ref":"#/components/schemas/BoundedLimit_5_100"}},{"name":"viewer_id","in":"query","description":"Viewer Pubky ID","required":false,"schema":{"$ref":"#/components/schemas/PubkyId"}},{"name":"depth","in":"query","description":"WoT depth (1-3). When provided with `viewer_id`, tags are filtered through the viewer's Web of Trust. `depth` without `viewer_id`, or an out-of-range `depth` with `viewer_id`, is rejected with 400.","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"User tags","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TagDetails"}}}}},"400":{"description":"Invalid parameters"},"404":{"description":"User not found"},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","format":"int64","minimum":0},"description":"Seconds until retry"}}},"500":{"description":"Internal server error"}}}}},"components":{"schemas":{"Bookmark":{"type":"object","required":["id","indexed_at"],"properties":{"id":{"type":"string"},"indexed_at":{"type":"integer","format":"int64"}}},"Bootstrap":{"type":"object","required":["users","posts","files","ids","indexed","notifications"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/FileDetails"},"description":"File metadata for all attachments referenced in posts and replies"},"ids":{"$ref":"#/components/schemas/BootstrapIds","description":"IDs of objects shown to this user on the home page of the FE"},"indexed":{"type":"boolean","description":"Whether or not this user is already indexed"},"notifications":{"type":"array","items":{"$ref":"#/components/schemas/Notification"},"description":"Latest notifications"},"posts":{"$ref":"#/components/schemas/PostStream","description":"The posts objects shown to the given user ID"},"users":{"$ref":"#/components/schemas/UserStream","description":"The user objects shown to the given user ID"}}},"BootstrapIds":{"type":"object","description":"IDs of objects relevant to the bootstrap payload, for example\nthe lists shown on the right panel of the FE.\n\nGiven as IDs because the full referenced objects might already\nbe trasferred in the streams of this Bootstrap payload.","required":["stream","influencers","recommended","hot_tags"],"properties":{"hot_tags":{"type":"array","items":{"$ref":"#/components/schemas/HotTag"}},"influencers":{"type":"array","items":{"type":"string"}},"recommended":{"type":"array","items":{"type":"string"},"description":"Recommended users for the given user ID"},"stream":{"type":"array","items":{"type":"string"},"description":"Post stream"}}},"BoundedLimit_10_100":{"type":"integer","default":10,"maximum":100,"minimum":1},"BoundedLimit_10_50":{"type":"integer","default":10,"maximum":50,"minimum":1},"BoundedLimit_20_100":{"type":"integer","default":20,"maximum":100,"minimum":1},"BoundedLimit_20_20":{"type":"integer","default":20,"maximum":20,"minimum":1},"BoundedLimit_20_200":{"type":"integer","default":20,"maximum":200,"minimum":1},"BoundedLimit_40_100":{"type":"integer","default":40,"maximum":100,"minimum":1},"BoundedLimit_40_40":{"type":"integer","default":40,"maximum":40,"minimum":1},"BoundedLimit_500_1000":{"type":"integer","default":500,"maximum":1000,"minimum":1},"BoundedLimit_50_200":{"type":"integer","default":50,"maximum":200,"minimum":1},"BoundedLimit_5_100":{"type":"integer","default":5,"maximum":100,"minimum":1},"BoundedLimit_5_20":{"type":"integer","default":5,"maximum":20,"minimum":1},"BoundedSkip_1000":{"type":"integer","default":0,"maximum":1000,"minimum":0},"BoundedSkip_10000":{"type":"integer","default":0,"maximum":10000,"minimum":0},"FileDetails":{"type":"object","description":"Represents a file and its metadata, including links to the actual binary of the file.","required":["id","uri","owner_id","indexed_at","created_at","src","name","size","content_type","urls"],"properties":{"content_type":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"id":{"type":"string"},"indexed_at":{"type":"integer","format":"int64"},"metadata":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string"},"owner_id":{"type":"string"},"size":{"type":"integer","format":"int64"},"src":{"type":"string"},"uri":{"type":"string"},"urls":{"$ref":"#/components/schemas/FileUrls"}}},"FileUris":{"type":"array","items":{"type":"string"},"description":"JSON array of file URI strings (min=1, max=100)."},"FileUrls":{"type":"object","required":["main"],"properties":{"feed":{"type":["string","null"]},"main":{"type":"string"},"small":{"type":["string","null"]}}},"FilesByIdsBody":{"type":"object","required":["uris"],"properties":{"uris":{"$ref":"#/components/schemas/FileUris"}}},"Followers":{"type":"array","items":{"type":"string"}},"Following":{"type":"array","items":{"type":"string"}},"Friends":{"type":"array","items":{"type":"string"}},"GlobalPostId":{"type":"string","description":"Composite post identifier in the format `{PubkyId}:{PostId}`.","example":"operrr8wsbpr3ue9d4qj41ge1kcc6r7fdiy6o3ugjrrhi4y77rdo:00000039YD9DP"},"GlobalPostIds":{"type":"array","items":{"$ref":"#/components/schemas/GlobalPostId"},"description":"JSON array of `GlobalPostId` values (min=1, max=100)."},"HotTag":{"type":"object","required":["label","taggers_id","tagged_count","taggers_count"],"properties":{"label":{"type":"string"},"tagged_count":{"type":"integer","format":"int64","minimum":0},"taggers_count":{"type":"integer","minimum":0},"taggers_id":{"$ref":"#/components/schemas/Taggers"}}},"HotTags":{"type":"array","items":{"$ref":"#/components/schemas/HotTag"}},"Notification":{"type":"object","required":["timestamp","body"],"properties":{"body":{"$ref":"#/components/schemas/NotificationBody"},"timestamp":{"type":"integer","format":"int64"}}},"NotificationBody":{"oneOf":[{"type":"object","required":["followed_by","type"],"properties":{"followed_by":{"type":"string"},"type":{"type":"string","enum":["follow"]}}},{"type":"object","required":["followed_by","type"],"properties":{"followed_by":{"type":"string"},"type":{"type":"string","enum":["new_friend"]}}},{"type":"object","required":["unfollowed_by","type"],"properties":{"type":{"type":"string","enum":["lost_friend"]},"unfollowed_by":{"type":"string"}}},{"type":"object","required":["tagged_by","tag_label","post_uri","type"],"properties":{"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"post_uri":{"type":"string"},"tag_label":{"type":"string"},"tagged_by":{"type":"string"},"type":{"type":"string","enum":["tag_post"]}}},{"type":"object","required":["tagged_by","tag_label","type"],"properties":{"tag_label":{"type":"string"},"tagged_by":{"type":"string"},"type":{"type":"string","enum":["tag_profile"]}}},{"type":"object","required":["untagged_by","tag_label","post_uri","type"],"properties":{"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"post_uri":{"type":"string"},"tag_label":{"type":"string"},"type":{"type":"string","enum":["untag_post"]},"untagged_by":{"type":"string"}}},{"type":"object","required":["untagged_by","tag_label","type"],"properties":{"tag_label":{"type":"string"},"type":{"type":"string","enum":["untag_profile"]},"untagged_by":{"type":"string"}}},{"type":"object","required":["replied_by","parent_post_uri","reply_uri","type"],"properties":{"parent_post_uri":{"type":"string"},"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"replied_by":{"type":"string"},"reply_uri":{"type":"string"},"type":{"type":"string","enum":["reply"]}}},{"type":"object","required":["reposted_by","embed_uri","repost_uri","type"],"properties":{"embed_uri":{"type":"string"},"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"repost_uri":{"type":"string"},"reposted_by":{"type":"string"},"type":{"type":"string","enum":["repost"]}}},{"type":"object","required":["mentioned_by","post_uri","type"],"properties":{"mentioned_by":{"type":"string"},"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"post_uri":{"type":"string"},"type":{"type":"string","enum":["mention"]}}},{"type":"object","required":["delete_source","deleted_by","deleted_uri","linked_uri","type"],"properties":{"delete_source":{"$ref":"#/components/schemas/PostChangedSource"},"deleted_by":{"type":"string"},"deleted_uri":{"type":"string"},"linked_uri":{"type":"string"},"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"type":{"type":"string","enum":["post_deleted"]}}},{"type":"object","required":["edit_source","edited_by","edited_uri","linked_uri","type"],"properties":{"edit_source":{"$ref":"#/components/schemas/PostChangedSource"},"edited_by":{"type":"string"},"edited_uri":{"type":"string"},"linked_uri":{"type":"string"},"post_kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"type":{"type":"string","enum":["post_edited"]}}}]},"PostChangedSource":{"type":"string","enum":["reply","repost","bookmark","reply_parent","repost_embed","tagged_post"]},"PostCounts":{"type":"object","description":"Represents total counts of relationships of a user.","required":["tags","unique_tags","replies","reposts"],"properties":{"replies":{"type":"integer","format":"int32","minimum":0},"reposts":{"type":"integer","format":"int32","minimum":0},"tags":{"type":"integer","format":"int32","minimum":0},"unique_tags":{"type":"integer","format":"int32","minimum":0}}},"PostDetails":{"type":"object","description":"Represents post data with content, bio, image, links, and status.","required":["content","id","indexed_at","author","kind","uri"],"properties":{"attachments":{"type":["array","null"],"items":{"type":"string"}},"author":{"type":"string"},"content":{"type":"string"},"id":{"type":"string"},"indexed_at":{"type":"integer","format":"int64"},"kind":{"$ref":"#/components/schemas/PubkyAppPostKind"},"lock":{"type":["string","null"],"description":"`pubky://` URL of the lock server; `None` when the post is unlocked.\n`default` keeps pre-lock cached JSON (no `lock` key) deserializing."},"uri":{"type":"string"}}},"PostId":{"type":"string","description":"13-character Crockford Base32-encoded post ID.","example":"00000039YD9DP"},"PostKeyStream":{"type":"object","required":["post_keys"],"properties":{"last_post_score":{"type":["integer","null"],"format":"int64","minimum":0},"post_keys":{"type":"array","items":{"type":"string"}}}},"PostKinds":{"type":"string","description":"Comma-separated list of post kinds (min=1, max=7 tokens; duplicates are\ndropped, order preserved). Parsing is strict: values outside the known\nkinds (short, long, image, video, link, file, collection) are rejected,\nunlike the lenient single `kind` param which falls back to `Unknown`.","example":"collection,link"},"PostRelationships":{"type":"object","required":["mentioned"],"properties":{"mentioned":{"type":"array","items":{"$ref":"#/components/schemas/PubkyId"},"description":"List of user IDs mentioned in this post"},"replied":{"type":["string","null"],"description":"If set, URI of the post this is a reply to"},"reposted":{"type":["string","null"],"description":"If set, URI of the post this post is reposting"}}},"PostSearchQuery":{"type":"string","description":"Post content search query (2–30 characters, up to 4 terms).","example":"bitcoin"},"PostStream":{"type":"array","items":{"$ref":"#/components/schemas/PostView"}},"PostStreamByIdsRequest":{"type":"object","required":["post_ids"],"properties":{"include_attachment_metadata":{"type":"boolean"},"post_ids":{"$ref":"#/components/schemas/GlobalPostIds"},"viewer_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PubkyId"}]}}},"PostStreamDetailed":{"type":"array","items":{"$ref":"#/components/schemas/PostViewDetailed"}},"PostView":{"type":"object","description":"Represents a Pubky user with relational data including tags, counts, and relationship with a viewer.","required":["details","counts","tags","relationships"],"properties":{"bookmark":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Bookmark"}]},"counts":{"$ref":"#/components/schemas/PostCounts"},"details":{"$ref":"#/components/schemas/PostDetails"},"relationships":{"$ref":"#/components/schemas/PostRelationships"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagDetails"}}}},"PostViewDetailed":{"allOf":[{"$ref":"#/components/schemas/PostView"},{"type":"object","properties":{"attachments_metadata":{"type":"array","items":{"$ref":"#/components/schemas/FileDetails"}}}}]},"PostsByContentSearch":{"type":"object","required":["post_key","score"],"properties":{"post_key":{"type":"string"},"score":{"type":"number","format":"double"}}},"PostsByTagSearch":{"type":"object","description":"Represents a single search result of a \"posts by tag\" search, returning the post keys (`author_id:post_id`) and score","required":["post_key","score"],"properties":{"post_key":{"type":"string"},"score":{"type":"integer","minimum":0}}},"PubkyAppPostKind":{"type":"string","description":"Represents the type of pubky-app posted data\nUsed primarily to best display the content in UI","enum":["short","long","image","video","link","file","collection","unknown"]},"PubkyAppUserLink":{"type":"object","description":"Represents a user's single link with a title and URL.","required":["title","url"],"properties":{"title":{"type":"string"},"url":{"type":"string"}}},"PubkyId":{"type":"string"},"Relationship":{"type":"object","description":"Represents the relationship of the user that views and user being viewed.","required":["following","followed_by"],"properties":{"followed_by":{"type":"boolean"},"following":{"type":"boolean"}}},"ResourceDetails":{"type":"object","required":["id","uri","scheme","indexed_at"],"properties":{"id":{"type":"string"},"indexed_at":{"type":"integer","format":"int64"},"scheme":{"type":"string"},"uri":{"type":"string"}}},"ResourceId":{"type":"string","description":"32-character lowercase hex resource identifier.","example":"0123456789abcdef0123456789abcdef"},"ResourceKeyStream":{"type":"object","required":["resource_ids"],"properties":{"last_score":{"type":["integer","null"],"format":"int64","description":"Score of the last entry, usable as a cursor for the next page.\nSet to `Some(score)` when served from Redis sorted sets (score-based pagination).\nSet to `None` when served from Neo4j graph fallback (use skip/limit pagination instead).","minimum":0},"resource_ids":{"type":"array","items":{"type":"string"}}}},"ResourceTagsResponse":{"type":"object","description":"Response envelope for resource tag endpoints, matching spec Section 9.1.","required":["resource","tags"],"properties":{"resource":{"$ref":"#/components/schemas/ResourceDetails"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagDetails"}}}},"ResourceView":{"type":"object","required":["details","tags","taggers_count"],"properties":{"details":{"$ref":"#/components/schemas/ResourceDetails"},"taggers_count":{"type":"integer","minimum":0},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagDetails"}}}},"ServerInfo":{"type":"object","required":["description","homepage","license","name","repository","version","commit_hash","last_index_snapshot","base_file_url"],"properties":{"base_file_url":{"type":"string"},"commit_hash":{"type":"string"},"description":{"type":"string"},"homepage":{"type":"string"},"last_index_snapshot":{"type":"string"},"license":{"type":"string"},"name":{"type":"string"},"repository":{"type":"string"},"version":{"type":"string"}}},"SocialGraphStatus":{"type":"string","description":"How established an account is in the follow graph, derived from the seeded\nPageRank trust ranking.\n\nDescribes position in the graph, not character: it says an account is\nexpensive to fake, never that it is trustworthy.","enum":["new","networked","established"]},"SortOrder":{"type":"string","enum":["ascending","descending"]},"StreamReach":{"oneOf":[{"type":"string","enum":["Followers"]},{"type":"string","enum":["Following"]},{"type":"string","enum":["Friends"]},{"type":"object","required":["Wot"],"properties":{"Wot":{"$ref":"#/components/schemas/WotDepth"}}}]},"StreamSorting":{"type":"string","enum":["timeline","total_engagement"]},"StreamSourceKind":{"type":"string","description":"Discriminant for the source of posts in a stream.\nMirrors the variant structure of StreamSource but does not carry ID payloads,\nsince the actual IDs are validated at the API boundary via dedicated query params.","enum":["post_replies","following","followers","friends","bookmarks","author","author_replies","collection","wot","wot_domain","all"]},"String":{"type":"object","required":["cursor","events"],"properties":{"cursor":{"type":"integer","format":"int64","minimum":0},"events":{"type":"array","items":{"type":"string"}}}},"TagDetails":{"type":"object","required":["label","taggers","taggers_count"],"properties":{"label":{"type":"string"},"relationship":{"type":"boolean"},"taggers":{"type":"array","items":{"type":"string"}},"taggers_count":{"type":"integer","minimum":0}}},"TagLabel":{"type":"string","description":"Tag label (1-20 characters, lowercased and trimmed; no commas, colons, or whitespace).","example":"rust"},"TagPost":{"type":"array","items":{"type":"string"}},"TagView":{"type":"object","description":"Represents a Pubky tag with uri, label, indexed at timestamp.","required":["uri","label","indexed_at"],"properties":{"indexed_at":{"type":"integer","format":"int64"},"label":{"type":"string"},"uri":{"type":"string"}}},"Taggers":{"$ref":"#/components/schemas/Vec"},"TaggersInfoResponse":{"type":"object","required":["users","relationship"],"properties":{"relationship":{"type":"boolean"},"users":{"$ref":"#/components/schemas/Vec"}}},"Tags":{"type":"string","description":"Comma-separated list of tag labels (min=1, max=5). Each label is validated and sanitized.","example":"dev,free,opensource"},"Timeframe":{"type":"string","enum":["today","this_week","this_month","all_time"]},"UserCounts":{"type":"object","description":"Represents total counts of relationships of a user.","required":["tagged","tags","unique_tags","posts","replies","following","followers","friends","bookmarks"],"properties":{"bookmarks":{"type":"integer","format":"int32","minimum":0},"collections":{"type":"integer","format":"int32","minimum":0},"followers":{"type":"integer","format":"int32","minimum":0},"following":{"type":"integer","format":"int32","minimum":0},"friends":{"type":"integer","format":"int32","minimum":0},"posts":{"type":"integer","format":"int32","minimum":0},"replies":{"type":"integer","format":"int32","minimum":0},"tagged":{"type":"integer","format":"int32","minimum":0},"tags":{"type":"integer","format":"int32","minimum":0},"unique_tags":{"type":"integer","format":"int32","minimum":0}}},"UserDetails":{"type":"object","description":"Represents user data with name, bio, image, links, and status.","required":["name","id","indexed_at"],"properties":{"bio":{"type":["string","null"]},"id":{"$ref":"#/components/schemas/PubkyId"},"image":{"type":["string","null"]},"indexed_at":{"type":"integer","format":"int64"},"links":{"type":["array","null"],"items":{"$ref":"#/components/schemas/PubkyAppUserLink"}},"name":{"type":"string"},"status":{"type":["string","null"]}}},"UserIdPrefix":{"type":"string","description":"User-ID search prefix (minimum 3 characters).","example":"ope"},"UserIdStream":{"type":"array","items":{"type":"string"}},"UserIds":{"type":"array","items":{"$ref":"#/components/schemas/PubkyId"},"description":"JSON array of `PubkyId` values (min=1, max=100)."},"UserSearch":{"type":"array","items":{"type":"string"},"description":"List of user IDs"},"UserStream":{"type":"array","items":{"$ref":"#/components/schemas/UserView"}},"UserStreamByIdsRequest":{"type":"object","required":["user_ids"],"properties":{"depth":{"type":["integer","null"],"format":"int32","minimum":0},"user_ids":{"$ref":"#/components/schemas/UserIds"},"viewer_id":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PubkyId"}]}}},"UserStreamSource":{"type":"string","enum":["followers","following","friends","most_followed","influencers","recommended","post_replies","starter_pack"]},"UserView":{"type":"object","description":"Represents a Pubky user with relational data including tags, counts, bookmark and relationship with other posts.","required":["details","counts","tags","relationship"],"properties":{"counts":{"$ref":"#/components/schemas/UserCounts"},"details":{"$ref":"#/components/schemas/UserDetails"},"relationship":{"$ref":"#/components/schemas/Relationship"},"social_graph_status":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SocialGraphStatus","description":"How established the account is in the follow graph. `None` when no\nranking is available, which is not the same as ranking as new."}]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagDetails"}}}},"UsernamePrefix":{"type":"string","description":"Username search prefix (must be non-empty).","example":"alice"},"UsersByTagSearch":{"type":"object","description":"Represents a single result of a \"users by tags\" search: a user whose profile\ncarries at least one of the searched tag labels, and how many distinct\ntaggers applied them (summed across the searched labels).","required":["user_id","score"],"properties":{"score":{"type":"integer","minimum":0},"user_id":{"type":"string"}}},"Vec":{"type":"array","items":{"type":"string"}},"WotDepth":{"type":"integer","format":"int32","description":"Web of Trust traversal depth, validated to `1..=3` at construction. The\n`FOLLOWS*1..n` graph traversals are expensive, so the query builders only\naccept this type, keeping the bound enforced for every caller (web, tests,\nbenches, internal) rather than at the web layer alone.","minimum":0}}}}