···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.defs {
44+ model SkeletonSearchPost {
55+ @required uri: atUri;
66+ }
77+88+ model SkeletonSearchActor {
99+ @required did: did;
1010+ }
1111+1212+ model SkeletonSearchStarterPack {
1313+ @required uri: atUri;
1414+ }
1515+1616+ model TrendingTopic {
1717+ @required topic: string;
1818+ displayName?: string;
1919+ description?: string;
2020+ @required link: string;
2121+ }
2222+2323+ model SkeletonTrend {
2424+ @required topic: string;
2525+ @required displayName: string;
2626+ @required link: string;
2727+ @required startedAt: datetime;
2828+ @required postCount: integer;
2929+ status?: "hot" | string;
3030+ category?: string;
3131+ @required dids: did[];
3232+ }
3333+3434+ model TrendView {
3535+ @required topic: string;
3636+ @required displayName: string;
3737+ @required link: string;
3838+ @required startedAt: datetime;
3939+ @required postCount: integer;
4040+ status?: "hot" | string;
4141+ category?: string;
4242+ @required actors: app.bsky.actor.defs.ProfileViewBasic[];
4343+ }
4444+4545+ model ThreadItemPost {
4646+ @required post: app.bsky.feed.defs.PostView;
4747+4848+ @doc("This post has more parents that were not present in the response. This is just a boolean, without the number of parents.")
4949+ @required
5050+ moreParents: boolean;
5151+5252+ @doc("This post has more replies that were not present in the response. This is a numeric value, which is best-effort and might not be accurate.")
5353+ @required
5454+ moreReplies: integer;
5555+5656+ @doc("This post is part of a contiguous thread by the OP from the thread root. Many different OP threads can happen in the same thread.")
5757+ @required
5858+ opThread: boolean;
5959+6060+ @doc("The threadgate created by the author indicates this post as a reply to be hidden for everyone consuming the thread.")
6161+ @required
6262+ hiddenByThreadgate: boolean;
6363+6464+ @doc("This is by an account muted by the viewer requesting it.")
6565+ @required
6666+ mutedByViewer: boolean;
6767+ }
6868+6969+ model ThreadItemNoUnauthenticated {}
7070+7171+ model ThreadItemNotFound {}
7272+7373+ model ThreadItemBlocked {
7474+ @required author: app.bsky.feed.defs.BlockedAuthor;
7575+ }
7676+7777+ @doc("The computed state of the age assurance process, returned to the user in question on certain authenticated requests.")
7878+ model AgeAssuranceState {
7979+ @doc("The timestamp when this state was last updated.")
8080+ lastInitiatedAt?: datetime;
8181+8282+ @doc("The status of the age assurance process.")
8383+ @required
8484+ status: "unknown" | "pending" | "assured" | "blocked" | string;
8585+ }
8686+8787+ @doc("Object used to store age assurance data in stash.")
8888+ model AgeAssuranceEvent {
8989+ @doc("The date and time of this write operation.")
9090+ @required
9191+ createdAt: datetime;
9292+9393+ @doc("The status of the age assurance process.")
9494+ @required
9595+ status: "unknown" | "pending" | "assured" | string;
9696+9797+ @doc("The unique identifier for this instance of the age assurance flow, in UUID format.")
9898+ @required
9999+ attemptId: string;
100100+101101+ @doc("The email used for AA.")
102102+ email?: string;
103103+104104+ @doc("The IP address used when initiating the AA flow.")
105105+ initIp?: string;
106106+107107+ @doc("The user agent used when initiating the AA flow.")
108108+ initUa?: string;
109109+110110+ @doc("The IP address used when completing the AA flow.")
111111+ completeIp?: string;
112112+113113+ @doc("The user agent used when completing the AA flow.")
114114+ completeUa?: string;
115115+ }
116116+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getAgeAssuranceState {
44+ @doc("Returns the current state of the age assurance process for an account. This is used to check if the user has completed age assurance or if further action is required.")
55+ @query
66+ op main(): app.bsky.unspecced.defs.AgeAssuranceState;
77+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getOnboardingSuggestedStarterPacksSkeleton {
44+ @doc("Get a skeleton of suggested starterpacks for onboarding. Intended to be called and hydrated by app.bsky.unspecced.getOnboardingSuggestedStarterPacks")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries).")
88+ viewer?: did,
99+1010+ @minValue(1)
1111+ @maxValue(25)
1212+ limit?: int32 = 10
1313+ ): {
1414+ @required starterPacks: atUri[];
1515+ };
1616+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getPostThreadOtherV2 {
44+ @doc("(NOTE: this endpoint is under development and WILL change without notice. Don't use it until it is moved out of `unspecced` or your application WILL break) Get additional posts under a thread e.g. replies hidden by threadgate. Based on an anchor post at any depth of the tree, returns top-level replies below that anchor. It does not include ancestors nor the anchor itself. This should be called after exhausting `app.bsky.unspecced.getPostThreadV2`. Does not require auth, but additional metadata and filtering will be applied for authed requests.")
55+ @query
66+ op main(
77+ @doc("Reference (AT-URI) to post record. This is the anchor post.")
88+ @required
99+ anchor: atUri,
1010+1111+ @doc("Whether to prioritize posts from followed users. It only has effect when the user is authenticated.")
1212+ prioritizeFollowedUsers?: boolean = false
1313+ ): {
1414+ @doc("A flat list of other thread items. The depth of each item is indicated by the depth property inside the item.")
1515+ @required
1616+ thread: ThreadItem[];
1717+ };
1818+1919+ model ThreadItem {
2020+ @required uri: atUri;
2121+2222+ @doc("The nesting level of this item in the thread. Depth 0 means the anchor item. Items above have negative depths, items below have positive depths.")
2323+ @required
2424+ depth: integer;
2525+2626+ @required value: (app.bsky.unspecced.defs.ThreadItemPost | unknown);
2727+ }
2828+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getPostThreadV2 {
44+ @doc("(NOTE: this endpoint is under development and WILL change without notice. Don't use it until it is moved out of `unspecced` or your application WILL break) Get posts in a thread. It is based in an anchor post at any depth of the tree, and returns posts above it (recursively resolving the parent, without further branching to their replies) and below it (recursive replies, with branching to their replies). Does not require auth, but additional metadata and filtering will be applied for authed requests.")
55+ @query
66+ op main(
77+ @doc("Reference (AT-URI) to post record. This is the anchor post, and the thread will be built around it. It can be any post in the tree, not necessarily a root post.")
88+ @required
99+ anchor: atUri,
1010+1111+ @doc("Whether to include parents above the anchor.")
1212+ above?: boolean = true,
1313+1414+ @doc("How many levels of replies to include below the anchor.")
1515+ @minValue(0)
1616+ @maxValue(20)
1717+ below?: int32 = 6,
1818+1919+ @doc("Maximum of replies to include at each level of the thread, except for the direct replies to the anchor, which are (NOTE: currently, during unspecced phase) all returned (NOTE: later they might be paginated).")
2020+ @minValue(0)
2121+ @maxValue(100)
2222+ branchingFactor?: int32 = 10,
2323+2424+ @doc("Whether to prioritize posts from followed users. It only has effect when the user is authenticated.")
2525+ prioritizeFollowedUsers?: boolean = false,
2626+2727+ @doc("Sorting for the thread replies.")
2828+ sort?: "newest" | "oldest" | "top" | string = "oldest"
2929+ ): {
3030+ @doc("A flat list of thread items. The depth of each item is indicated by the depth property inside the item.")
3131+ @required
3232+ thread: ThreadItem[];
3333+3434+ threadgate?: app.bsky.feed.defs.ThreadgateView;
3535+3636+ @doc("Whether this thread has additional replies. If true, a call can be made to the `getPostThreadOtherV2` endpoint to retrieve them.")
3737+ @required
3838+ hasOtherReplies: boolean;
3939+ };
4040+4141+ model ThreadItem {
4242+ @required uri: atUri;
4343+4444+ @doc("The nesting level of this item in the thread. Depth 0 means the anchor item. Items above have negative depths, items below have positive depths.")
4545+ @required
4646+ depth: integer;
4747+4848+ @required
4949+ value: (
5050+ app.bsky.unspecced.defs.ThreadItemPost |
5151+ app.bsky.unspecced.defs.ThreadItemNoUnauthenticated |
5252+ app.bsky.unspecced.defs.ThreadItemNotFound |
5353+ app.bsky.unspecced.defs.ThreadItemBlocked |
5454+ unknown
5555+ );
5656+ }
5757+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getSuggestedFeedsSkeleton {
44+ @doc("Get a skeleton of suggested feeds. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedFeeds")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries).")
88+ viewer?: did,
99+1010+ @minValue(1)
1111+ @maxValue(25)
1212+ limit?: int32 = 10
1313+ ): {
1414+ @required feeds: atUri[];
1515+ };
1616+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getSuggestedStarterPacksSkeleton {
44+ @doc("Get a skeleton of suggested starterpacks. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedStarterpacks")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries).")
88+ viewer?: did,
99+1010+ @minValue(1)
1111+ @maxValue(25)
1212+ limit?: int32 = 10
1313+ ): {
1414+ @required starterPacks: atUri[];
1515+ };
1616+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getSuggestedUsersSkeleton {
44+ @doc("Get a skeleton of suggested users. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsers")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries).")
88+ viewer?: did,
99+1010+ @doc("Category of users to get suggestions for.")
1111+ category?: string,
1212+1313+ @minValue(1)
1414+ @maxValue(50)
1515+ limit?: int32 = 25
1616+ ): {
1717+ @required dids: did[];
1818+ };
1919+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getSuggestionsSkeleton {
44+ @doc("Get a skeleton of suggested actors. Intended to be called and then hydrated through app.bsky.actor.getSuggestions")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.")
88+ viewer?: did,
99+1010+ @minValue(1)
1111+ @maxValue(100)
1212+ limit?: int32 = 50,
1313+1414+ cursor?: string,
1515+1616+ @doc("DID of the account to get suggestions relative to. If not provided, suggestions will be based on the viewer.")
1717+ relativeToDid?: did
1818+ ): {
1919+ cursor?: string;
2020+ @required actors: app.bsky.unspecced.defs.SkeletonSearchActor[];
2121+2222+ @doc("DID of the account these suggestions are relative to. If this is returned undefined, suggestions are based on the viewer.")
2323+ relativeToDid?: did;
2424+2525+ @doc("Snowflake for this recommendation, use when submitting recommendation events.")
2626+ recId?: integer;
2727+ };
2828+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getTrendingTopics {
44+ @doc("Get a list of trending topics")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.")
88+ viewer?: did,
99+1010+ @minValue(1)
1111+ @maxValue(25)
1212+ limit?: int32 = 10
1313+ ): {
1414+ @required topics: app.bsky.unspecced.defs.TrendingTopic[];
1515+ @required suggested: app.bsky.unspecced.defs.TrendingTopic[];
1616+ };
1717+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.getTrendsSkeleton {
44+ @doc("Get the skeleton of trends on the network. Intended to be called and then hydrated through app.bsky.unspecced.getTrends")
55+ @query
66+ op main(
77+ @doc("DID of the account making the request (not included for public/unauthenticated queries).")
88+ viewer?: did,
99+1010+ @minValue(1)
1111+ @maxValue(25)
1212+ limit?: int32 = 10
1313+ ): {
1414+ @required trends: app.bsky.unspecced.defs.SkeletonTrend[];
1515+ };
1616+}
···11+import "@tlex/emitter";
22+33+namespace app.bsky.unspecced.initAgeAssurance {
44+ model InvalidEmail {}
55+ model DidTooLong {}
66+ model InvalidInitiation {}
77+88+ @doc("Initiate age assurance for an account. This is a one-time action that will start the process of verifying the user's age.")
99+ @procedure
1010+ @errors(InvalidEmail, DidTooLong, InvalidInitiation)
1111+ op main(input: {
1212+ @doc("The user's email address to receive assurance instructions.")
1313+ @required
1414+ email: string;
1515+1616+ @doc("The user's preferred language for communication during the assurance process.")
1717+ @required
1818+ language: string;
1919+2020+ @doc("An ISO 3166-1 alpha-2 code of the user's location.")
2121+ @required
2222+ countryCode: string;
2323+ }): app.bsky.unspecced.defs.AgeAssuranceState;
2424+}