···11+engine: nixery
22+when:
33+ - event: ["push", "pull_request"]
44+ branch: ["main"]
55+66+dependencies:
77+ nixpkgs:
88+ - nodejs
99+ - gnused
1010+1111+steps:
1212+ - name: install and build
1313+ command: |
1414+ npx pnpm install
1515+ cd packages/emitter && npx pnpm run build
1616+ cd ../website && npx pnpm run build
1717+ cd ../playground && npx pnpm run build
1818+ - name: deploy playground
1919+ command: |
2020+ cd packages/playground
2121+ npx --yes wrangler pages deploy --branch main --project-name typelex-playground ./dist/
2222+ - name: deploy website
2323+ command: |
2424+ cd packages/website
2525+ npx --yes wrangler pages deploy --branch main --project-name typelex ./dist/
+23
CHANGELOG.md
···11+### 0.2.0
22+33+- Add `@external` support
44+55+### 0.1.6
66+77+- Rebuild
88+99+### 0.1.5
1010+1111+- Allow tokens in string unions
1212+1313+### 0.1.4
1414+1515+- Fix some namespaces failing to emit
1616+1717+### 0.1.3
1818+1919+- Fix some namespaces failing to emit
2020+2121+### 0.1.2
2222+2323+- Disallow mixing `@required` with `?:`
+11-34
CLAUDE.md
···11-you're working on a TypeSpec emitter for atproto lexicons. you have these commands: `pnpm run build` builds the example (you can inspect the generated lexicons in the `packages/example/lexicon`) and `pnpm test` runs tests (they are in `packages/emitter/test/`).
11+you're working on a TypeSpec emitter for atproto Lexicons. the goal is to make a more comfortable language for writing lexicons, kind of like "coffeescript for lexicons" (however terrible that may be). one may imagine it getting supplanted by a proper atproto IDL someday. however, we're staying within what TypeSpec offers, which means we want to stay idiomatic both to atproto and TypeSpec, or rather, to try to translate atproto idioms into TypeSpec idioms as closely as we can.
2233-what i want you to do is to gradually keep adding features to typelex so that in the end it's possible to express all Lexicon code with that language. you have the following resources:
33+you have the following resources you're encouraged to explore on your own whenever they seem relevant to the task:
4455-- read `DOCS.md`!!! it's the main guideline
55+- `DOCS.md` is a must-read. it gives you an intro to typelex and how its conventions map to atproto. it also gives you a sense of the project philosophy.
66+- `../atproto-website/` has a Lexicon spec (look for `lexicon/en.mdx`) which you'll want to consult
77+- `../typespec/` is the TypeSpec repo. you can consult the source code of other emitters (in `packages`, e.g. `packages/protobuf` and `packages/json-schema`) and `website` folder for documentation of TypeSpec syntax and idioms.
6877-- `../typespec/packages` has a bunch of other emitters (so you can check how they're implemented and common patterns)
99+as a part of your workflow, you will:
81099-- `../typespec/website/src/content` has typescpec docs (which you might find very useful)
1111+- run `pnpm test` whenever you make changes to verify no regressions. note a few test suites: an `atproto` test suite with definitions from upstream (`.tsp` files produce expected `.json` files), `lexicon-examples` suite with third party lexicons, and `spec` with a more focused suite. use checked-in `*.tsp` files liberally to learn typelex conventions. we have a LOT of them!
10121111-- `../atproto-website/src/app/[locale]/specs/lexicon` contains lexicon spec (where we want to reach feature parity), and most importantly
1313+- if you're working on `packages/example`, use `pnpm run build` to run it and observe the output. you may also want to look at codegen output (it's hooked up to atproto codegen).
12141313-- `test/scenarios/atproto/output` contains a TON of lexicon definitions which i want you to translate to typespec one by one. for each atproto lexicon you're porting, your job is to create the corresponding "`input`s" for them (and fix bugs or add missing features along the way).
1515+- we also have a playground in `packages/playground` and website in `packages/website`.
14161515-the goal is to end up with a language that feels nice and concise, not some weird interop thing. so try to do things "typespec" way as you go through each lexicon. and try to respect atproto too. this should feel like a *language for atproto*. consider whether your design is elegant. and make sure to look at other typespec emitters for design ideas!
1616-1717-remember NOT to change the output to fit the input -- your job is to make the input MATCH the output. if some lexicon is too hard, you can give up on it and try another one. good luck!
1818-1919-the workflow is: pick some new lexicons, create the input files, figure out missing features / bugs, and try to get tests to pass. repeat. when you make nontrivial progress, you'll want to prepare a commit.
2020-2121-before you want to make a commit, make sure `pnpm test` and `pnpm run build` passes and, ideally, inspect the `example` app output (and maybe add the features you've just implemented there for parity). then stop and notify me.
2222-2323-ps. be mindful of the code style. we only put decorators on same line if it's `@required` alone; otherwise, put each on newline and add a newline after. see existing files for a hint.
1717+you'll approach the project thoughtfully. while `playground` and `website` are more vibey and can be garbage code, it's essential to keep the `emitter` making sense. this doesn't just mean always verifying the tests pass (that's a given), but also making each decision *based on the spec* and a good understanding of atproto semantics. always think: is this the simplest solution? does it still make sense if you forget the code that exists now and think from first principles? don't hesitate to pause and ask or rethink if something actually doesn't make sense.
24182519good luck! i believe in you
26202727-2828----
2929-3030-whenever you get stuck (try `npm test`) because you don't have a convention for how to define some pattern yetm i want you to read these sources
3131-3232- - `../typespec/packages` has a bunch of other emitters (so you can check how they're implemented and common patterns)
3333-3434- - `../typespec/website/src/content` has typescpec docs (which you might find very useful)
3535-3636- - `../atproto-website/src/app/[locale]/specs/lexicon` contains lexicon spec
3737-3838- and ultrathink about what's the most appropriate way to define defs like you want would be in this typespec translation of atproto. you can research these sources for what feels most idiomatic to define that syntax, and how to make
3939- the formatter understand that convention and emit the JSON we want.
4040-4141- also note that you can always look at generated atproto lexicons in ../atproto/lexicons -- use these!! look at the TS types there for corresponding
4242- models to inspire how you represent things in tsp syntax.
4343-4444- - read `DOCS.md`!!! it's the main guideline2121+and read the `DOCS.md` (and `*.tsp` files in this repo)!!! they're your most important sources of information.
+711-395
DOCS.md
···11-# Typelex Docs
11+# typelex docs
22+33+Typelex is a [TypeSpec](https://typespec.io/) emitter that outputs [AT Lexicon](https://atproto.com/specs/lexicon) JSON files.
44+55+## Introduction
66+77+### What's Lexicon?
88+99+[Lexicon](https://atproto.com/specs/lexicon) is a schema format used by [AT](https://atproto.com/) applications. Here's a small example:
1010+1111+```json
1212+{
1313+ "lexicon": 1,
1414+ "id": "app.bsky.bookmark.defs",
1515+ "defs": {
1616+ "listItemView": {
1717+ "type": "object",
1818+ "properties": {
1919+ "uri": { "type": "string", "format": "at-uri" }
2020+ },
2121+ "required": ["uri"]
2222+ }
2323+ }
2424+}
2525+```
22633-This maps [atproto Lexicon](https://atproto.com/specs/lexicon) JSON syntax to typelex (which is a [TypeSpec](https://typespec.io/) emitter). It assumes you're familiar with Lexicon and want to understand how to express it in TypeSpec. Consult [TypeSpec docs](https://typespec.io/) on details of TypeSpec syntax.
2727+This schema is then used to generate code for parsing of these objects, their validation, and their types.
42855-This page was mostly written by Claude based on the test fixtures from this repo (which are [deployed in the playground](https://playground.typelex.org/)). I hope it's mostly correct and comprehensible. When in doubt, refer to those fixtures.
2929+### What's TypeSpec?
63077-## Playground
3131+[TypeSpec](https://typespec.io/) is a TypeScript-like language for writing schemas for data and API calls. It offers flexible syntax and tooling (like LSP), but doesn't specify output formatโthat's what *emitters* do. For example, there's a [JSON Schema emitter](https://typespec.io/docs/emitters/json-schema/reference/) and a [Protobuf emitter](https://typespec.io/docs/emitters/protobuf/reference/).
83299-Go to https://playground.typelex.org/ to play with a bunch of lexicons.
3333+### What's typelex?
3434+3535+Typelex is a TypeSpec emitter targeting Lexicon. Here's the same schema in TypeSpec:
3636+3737+```typescript
3838+import "@typelex/emitter";
3939+4040+namespace app.bsky.bookmark.defs {
4141+ model ListItemView {
4242+ @required uri: atUri;
4343+ }
4444+}
4545+```
4646+4747+Run the compiler, and it generates Lexicon JSON for you.
4848+4949+The JSON is what you'll publishโtypelex just makes authoring easier. Think of it as "CoffeeScript for Lexicon" (however terrible that may be).
5050+5151+Typelex tries to stay faithful to both TypeSpec idioms and Lexicon concepts, which is a tricky balance. Since we can't add keywords to TypeSpec, decorators fill the gapsโyou'll write `@procedure op` instead of `procedure`, or `model` for what Lexicon calls a "def". One downside of this approach is you'll need to learn both Lexicon *and* TypeSpec to know what you're doing. Scan the [TypeSpec language overview](https://typespec.io/docs/language-basics/overview/) to get a feel for it.
5252+5353+Personally, I find JSON Lexicons hard to read and author, so the tradeoff works for me.
5454+5555+### Playground
5656+5757+[Open Playground](https://playground.typelex.org/) to play with a bunch of lexicons and to see how typelex code translates to Lexicon JSON.
5858+5959+If you already know Lexicon, you can learn the syntax by just opening the Lexicons you're familiar with.
10601161## Quick Start
12621313-Every TypeSpec file starts with an import and namespace:
6363+### Namespaces
6464+6565+A namespace corresponds to a Lexicon file:
14661567```typescript
1668import "@typelex/emitter";
17691818-/** Common definitions used by other lexicons */
1919-namespace com.example.defs {
2020- // definitions here
7070+namespace app.bsky.feed.defs {
7171+ model PostView {
7272+ // ...
7373+ }
2174}
2275```
23762424-**Maps to:**
7777+This emits `app/bsky/feed/defs.json`:
7878+2579```json
2680{
2781 "lexicon": 1,
2828- "id": "com.example.defs",
2929- "description": "Common definitions used by other lexicons",
8282+ "id": "app.bsky.feed.defs",
3083 "defs": { ... }
3184}
3285```
33863434-Use `/** */` doc comments for descriptions (or `@doc()` decorator as alternative).
8787+[Try it in the playground](https://playground.typelex.org/?c=aW1wb3J0ICJAdHlwZWxleC9lbWl0dGVyIjsKCm5hbWVzcGFjZSBhcHAuYnNreS5mZWVkLmRlZnMgewogIG1vZGVsIFBvc3RWaWV3xRMgIHJlcGx5Q291bnQ%2FOiBpbnRlZ2VyO8gab3N01RtsaWtl0xl9Cn0K&e=%40typelex%2Femitter&options=%7B%7D&vs=%7B%7D).
35883636-## Top-Level Lexicon Types
8989+If TypeSpec complains about reserved words in namespaces, use backticks:
9090+9191+```typescript
9292+import "@typelex/emitter";
9393+9494+namespace app.bsky.feed.post.`record` { }
9595+namespace `pub`.blocks.blockquote { }
9696+```
37973838-### Query (XRPC Query)
9898+You can define multiple namespaces in one file:
399940100```typescript
4141-namespace com.example.getRecord {
4242- /** Retrieve a record by ID */
4343- @query
4444- op main(
4545- /** The record identifier */
4646- @required id: string
4747- ): {
4848- @required record: com.example.record.Main;
4949- };
101101+import "@typelex/emitter";
102102+103103+namespace com.example.foo {
104104+ model Main { /* ... */ }
105105+}
106106+107107+namespace com.example.bar {
108108+ model Main { /* ... */ }
50109}
51110```
521115353-**Maps to:** `{"type": "query", ...}` with `parameters` and `output`
112112+This emits two files: `com/example/foo.json` and `com/example/bar.json`.
113113+114114+You can `import` other `.tsp` files to reuse definitions. Output structure is determined solely by namespaces, not by source file organization.
541155555-### Procedure (XRPC Procedure)
116116+## Models
117117+118118+By default, **every `model` becomes a Lexicon definition**:
5611957120```typescript
5858-namespace com.example.createRecord {
5959- /** Create a new record */
6060- @procedure
6161- op main(input: {
6262- @required text: string;
6363- }): {
6464- @required uri: atUri;
6565- @required cid: cid;
6666- };
121121+import "@typelex/emitter";
122122+123123+namespace app.bsky.feed.defs {
124124+ model PostView { /* ... */ }
125125+ model ViewerState { /* ... */ }
126126+}
127127+```
128128+129129+Model names convert PascalCase โ camelCase. For example, `PostView` becomes `postView`:
130130+131131+```json
132132+{
133133+ "id": "app.bsky.feed.defs",
134134+ "defs": {
135135+ "postView": { /* ... */ },
136136+ "viewerState": { /* ... */ }
137137+ }
138138+ // ...
67139}
68140```
691417070-**Maps to:** `{"type": "procedure", ...}` with `input` and `output`
142142+Models in the same namespace can be in separate `namespace` blocks or even different files (via [`import`](https://typespec.io/docs/language-basics/imports/)). TypeSpec bundles them all into one Lexicon file per namespace.
143143+144144+### Namespace Conventions: `.defs` vs `Main`
711457272-### Subscription (XRPC Subscription)
146146+By convention, a namespace must either end with `.defs` or have a `Main` model.
147147+148148+Use `.defs` for a grabbag of reusable definitions:
7314974150```typescript
7575-namespace com.example.subscribeRecords {
7676- /** Subscribe to record updates */
7777- @subscription
7878- op main(cursor?: integer): (Record | Delete);
151151+import "@typelex/emitter";
152152+153153+namespace app.bsky.feed.defs {
154154+ model PostView { /* ... */ }
155155+ model ViewerState { /* ... */ }
156156+}
157157+```
158158+159159+For a Lexicon about one main concept, add a `Main` model instead:
791608080- model Record {
8181- @required uri: atUri;
8282- @required record: com.example.record.Main;
8383- }
161161+```typescript
162162+import "@typelex/emitter";
841638585- model Delete {
8686- @required uri: atUri;
8787- }
164164+namespace app.bsky.embed.video {
165165+ model Main { /* ... */ }
166166+ model Caption { /* ... */ }
88167}
89168```
901699191-**Maps to:** `{"type": "subscription", ...}` with `message` containing union
170170+Pick one or the otherโthe compiler will error if you don't.
171171+172172+### References
921739393-### Record
174174+Models can reference other models:
9417595176```typescript
9696-namespace com.example.post {
9797- @rec("tid")
9898- /** A post record */
177177+import "@typelex/emitter";
178178+179179+namespace app.bsky.embed.video {
99180 model Main {
100100- @required text: string;
101101- @required createdAt: datetime;
181181+ captions?: Caption[];
102182 }
183183+ model Caption { /* ... */ }
103184}
104185```
105186106106-**Maps to:** `{"type": "record", "key": "tid", "record": {...}}`
187187+This becomes a `ref` to the `caption` definition in the same file:
107188108108-**Record key types:** `@rec("tid")`, `@rec("any")`, `@rec("nsid")`
189189+```json
190190+// ...
191191+"defs": {
192192+ "main": {
193193+ // ...
194194+ "properties": {
195195+ "captions": {
196196+ // ...
197197+ "items": { "type": "ref", "ref": "#caption" }
198198+ }
199199+ }
200200+ },
201201+ "caption": {
202202+ "type": "object",
203203+ "properties": {}
204204+ }
205205+// ...
206206+```
109207110110-### Object (Plain Definition)
208208+You can also reference models from other namespaces:
111209112210```typescript
113113-namespace com.example.defs {
114114- /** User metadata */
115115- model Metadata {
116116- version?: integer = 1;
117117- tags?: string[];
211211+import "@typelex/emitter";
212212+213213+namespace app.bsky.actor.profile {
214214+ model Main {
215215+ labels?: (com.atproto.label.defs.SelfLabels | unknown);
118216 }
119217}
218218+219219+namespace com.atproto.label.defs {
220220+ model SelfLabels { /* ... */ }
221221+}
120222```
121223122122-**Maps to:** `{"type": "object", "properties": {...}}`
224224+This becomes a fully qualified reference to another Lexicon:
123225124124-## Reserved Keywords
226226+```json
227227+// ...
228228+"labels": {
229229+ "type": "union",
230230+ "refs": ["com.atproto.label.defs#selfLabels"]
231231+}
232232+// ...
233233+```
125234126126-Use backticks for TypeScript/TypeSpec reserved words:
235235+([See it in the Playground](https://playground.typelex.org/?c=aW1wb3J0ICJAdHlwZWxleC9lbWl0dGVyIjsKCm5hbWVzcGFjZSBhcHAuYnNreS5hY3Rvci5wcm9maWxlIHsKICBAcmVjKCJsaXRlcmFsOnNlbGYiKQogIG1vZGVsIE1haW7FJiAgZGlzcGxheU5hbWU%2FOiBzdHJpbmc7xRpsYWJlbHM%2FOiAoY29tLmF0cHJvdG8uxRYuZGVmcy5TZWxmTMUlIHwgdW5rbm93binEPH0KfewAptY%2F5QCA5gCPy0nEFSAgLy8gLi4uxko%3D&e=%40typelex%2Femitter&options=%7B%7D&vs=%7B%7D).)
127236128128-```typescript
129129-namespace app.bsky.feed.post.`record` { ... }
130130-namespace `pub`.leaflet.subscription { ... }
131131-```
237237+This works across files tooโjust remember to `import` the file with the definition.
132238133133-## Inline vs Definitions
239239+### External Stubs
134240135135-**By default, models become separate defs.** Use `@inline` to prevent this:
241241+If you don't have TypeSpec definitions for external Lexicons, you can stub them out using the `@external` decorator:
136242137243```typescript
138138-// Without @inline - becomes separate def "statusEnum"
139139-union StatusEnum {
140140- "active",
141141- "inactive",
244244+import "@typelex/emitter";
245245+246246+namespace app.bsky.actor.profile {
247247+ model Main {
248248+ labels?: (com.atproto.label.defs.SelfLabels | unknown);
249249+ }
142250}
143251144144-// With @inline - inlined where used
145145-@inline
146146-union StatusEnum {
147147- "active",
148148- "inactive",
252252+// Empty stub (like .d.ts in TypeScript)
253253+@external
254254+namespace com.atproto.label.defs {
255255+ model SelfLabels { }
149256}
150257```
151258152152-Use `@inline` when you want the type directly embedded rather than referenced.
259259+The `@external` decorator tells the emitter to skip JSON output for that namespace. This is useful when referencing definitions from other Lexicons that you don't want to re-emit.
260260+261261+You could collect external stubs in one file and import them:
262262+263263+```typescript
264264+import "@typelex/emitter";
265265+import "../atproto-stubs.tsp";
153266154154-## Optional vs Required Fields
267267+namespace app.bsky.actor.profile {
268268+ model Main {
269269+ labels?: (com.atproto.label.defs.SelfLabels | unknown);
270270+ }
271271+}
272272+```
155273156156-**In lexicons, optional fields are the norm.** Required fields are discouraged and need explicit `@required`:
274274+Then in `atproto-stubs.tsp`:
157275158276```typescript
159159-model Post {
160160- text?: string; // optional (common)
161161- @required createdAt: datetime; // required (discouraged, needs decorator)
277277+import "@typelex/emitter";
278278+279279+@external
280280+namespace com.atproto.label.defs {
281281+ model SelfLabels { }
162282}
163163-```
164283165165-**Maps to:**
166166-```json
167167-{
168168- "type": "object",
169169- "required": ["createdAt"],
170170- "properties": {
171171- "text": {"type": "string"},
172172- "createdAt": {"type": "string", "format": "datetime"}
173173- }
284284+@external
285285+namespace com.atproto.repo.defs {
286286+ model StrongRef { }
287287+ @token model SomeToken { } // Note: Tokens still need @token
174288}
289289+// ... more stubs
175290```
176291177177-## Primitive Types
292292+You'll want to ensure the real JSON for external Lexicons is available before running codegen.
178293179179-| TypeSpec | Lexicon JSON |
180180-|----------|--------------|
181181-| `boolean` | `{"type": "boolean"}` |
182182-| `integer` | `{"type": "integer"}` |
183183-| `string` | `{"type": "string"}` |
184184-| `bytes` | `{"type": "bytes"}` |
185185-| `cidLink` | `{"type": "cid-link"}` |
186186-| `unknown` | `{"type": "unknown"}` |
294294+### Inline Models
187295188188-## Format Types
296296+By default, every `model` becomes a top-level def:
189297190190-Specialized string formats:
191191-192192-| TypeSpec | Lexicon Format |
193193-|----------|----------------|
194194-| `atIdentifier` | `at-identifier` - Handle or DID |
195195-| `atUri` | `at-uri` - AT Protocol URI |
196196-| `cid` | `cid` - Content ID |
197197-| `datetime` | `datetime` - ISO 8601 datetime |
198198-| `did` | `did` - DID identifier |
199199-| `handle` | `handle` - Handle identifier |
200200-| `nsid` | `nsid` - Namespaced ID |
201201-| `tid` | `tid` - Timestamp ID |
202202-| `recordKey` | `record-key` - Record key |
203203-| `uri` | `uri` - Generic URI |
204204-| `language` | `language` - Language tag |
298298+```typescript
299299+import "@typelex/emitter";
205300206206-## Unions
301301+namespace app.bsky.embed.video {
302302+ model Main {
303303+ captions?: Caption[];
304304+ }
305305+ model Caption { /* ... */ }
306306+}
307307+```
207308208208-### Open Unions (Common Pattern)
309309+This creates two defs: `main` and `caption`.
209310210210-**Open unions are the default and preferred in lexicons.** Add `unknown` to mark as open:
311311+Use `@inline` to expand a model inline instead:
211312212313```typescript
213213-model Main {
214214- /** Can be any of these types or future additions */
215215- @required item: TypeA | TypeB | TypeC | unknown;
216216-}
314314+import "@typelex/emitter";
217315218218-model TypeA {
219219- @readOnly @required kind: string = "a";
220220- @required valueA: string;
316316+namespace app.bsky.embed.video {
317317+ model Main {
318318+ captions?: Caption[];
319319+ }
320320+321321+ @inline
322322+ model Caption {
323323+ text?: string
324324+ }
221325}
222326```
223327224224-**Maps to:**
328328+Now `Caption` is expanded inline:
329329+225330```json
226226-{
227227- "properties": {
228228- "item": {
229229- "type": "union",
230230- "refs": ["#typeA", "#typeB", "#typeC"]
231231- }
331331+// ...
332332+"captions": {
333333+ "type": "array",
334334+ "items": {
335335+ "type": "object",
336336+ "properties": { "text": { "type": "string" } }
232337 }
233338}
339339+// ...
234340```
235341236236-The `unknown` makes it open but doesn't appear in refs.
342342+Note that `Caption` won't exist as a separate defโthe abstraction is erased in the output.
343343+344344+## Top-Level Lexicon Types
345345+346346+TypeSpec uses `model` for almost everything. Decorators specify what kind of Lexicon type it becomes.
237347238238-### Known Values (Open String Enum)
348348+### Objects
239349240240-Suggest values but allow others:
350350+A plain `model` becomes a Lexicon object:
241351242352```typescript
243243-model Main {
244244- /** Language - suggests common values but allows any */
245245- lang?: "en" | "es" | "fr" | string;
353353+import "@typelex/emitter";
354354+355355+namespace com.example.post {
356356+ model Main { /* ... */ }
246357}
247358```
248359249249-**Maps to:**
360360+Output:
361361+250362```json
251251-{
252252- "properties": {
253253- "lang": {
254254- "type": "string",
255255- "knownValues": ["en", "es", "fr"]
256256- }
257257- }
363363+// ...
364364+"main": {
365365+ "type": "object",
366366+ "properties": { /* ... */ }
258367}
368368+// ...
259369```
260370261261-### Closed Unions (Discouraged)
371371+### Records
262372263263-**โ ๏ธ Closed unions are discouraged in lexicons** as they prevent future additions. Use only when absolutely necessary:
373373+Use `@rec` to make a model a Lexicon record:
264374265375```typescript
266266-@closed
267267-@inline
268268-union Action {
269269- Create,
270270- Update,
271271- Delete,
272272-}
376376+import "@typelex/emitter";
273377274274-model Main {
275275- @required action: Action;
378378+namespace com.example.post {
379379+ @rec("tid")
380380+ model Main { /* ... */ }
276381}
277382```
278383279279-**Maps to:**
384384+Output:
385385+280386```json
281281-{
282282- "properties": {
283283- "action": {
284284- "type": "union",
285285- "refs": ["#create", "#update", "#delete"],
286286- "closed": true
287287- }
288288- }
387387+// ...
388388+"main": {
389389+ "type": "record",
390390+ "key": "tid",
391391+ "record": { "type": "object", "properties": { /* ... */ } }
289392}
393393+// ...
290394```
291395292292-### Closed Enums (Discouraged)
396396+You can pass any [Record Key Type](https://atproto.com/specs/record-key): `@rec("tid")`, `@rec("nsid")`, `@rec("literal:self")`, etc.
397397+398398+(It's `@rec` not `@record` because "record" is reserved in TypeSpec.)
399399+400400+### Queries
293401294294-**โ ๏ธ Closed enums are also discouraged.** Use `@closed @inline union` for fixed value sets:
402402+In TypeSpec, use [`op`](https://typespec.io/docs/language-basics/operations/) for functions. Mark with `@query` for queries:
295403296404```typescript
297297-@closed
298298-@inline
299299-union Status {
300300- "active",
301301- "inactive",
302302- "pending",
405405+import "@typelex/emitter";
406406+407407+namespace com.atproto.repo.getRecord {
408408+ @query
409409+ op main(
410410+ @required repo: atIdentifier,
411411+ @required collection: nsid,
412412+ @required rkey: recordKey,
413413+ cid?: cid
414414+ ): {
415415+ @required uri: atUri;
416416+ cid?: cid;
417417+ };
303418}
304419```
305420306306-**Maps to:**
421421+Arguments become `parameters`, return type becomes `output`:
422422+307423```json
308308-{
309309- "type": "string",
310310- "enum": ["active", "inactive", "pending"]
424424+// ...
425425+"main": {
426426+ "type": "query",
427427+ "parameters": {
428428+ "type": "params",
429429+ "properties": {
430430+ "repo": { /* ... */ },
431431+ "collection": { /* ... */ },
432432+ // ...
433433+ },
434434+ "required": ["repo", "collection", "rkey"]
435435+ },
436436+ "output": {
437437+ "encoding": "application/json",
438438+ "schema": {
439439+ "type": "object",
440440+ "properties": {
441441+ "uri": { /* ... */ },
442442+ "cid": { /* ... */ }
443443+ },
444444+ "required": ["uri"]
445445+ }
446446+ }
311447}
448448+// ...
312449```
313450314314-Integer enums work the same way:
451451+`encoding` defaults to `"application/json"`. Override with `@encoding("foo/bar")` on the `op`.
452452+453453+Declare errors with `@errors`:
315454316455```typescript
317317-@closed
318318-@inline
319319-union Fibonacci {
320320- 1, 2, 3, 5, 8,
456456+import "@typelex/emitter";
457457+458458+namespace com.atproto.repo.getRecord {
459459+ @query
460460+ @errors(FooError, BarError)
461461+ op main(/* ... */): { /* ... */ };
462462+463463+ model FooError {}
464464+ model BarError {}
321465}
322466```
323467324324-## Arrays
468468+You can extract the `{ /* ... */ }` output type to a separate `@inline` model if you prefer.
469469+470470+### Procedures
325471326326-Use `[]` suffix:
472472+Use `@procedure` for procedures. The first argument must be called `input`:
327473328474```typescript
329329-model Main {
330330- /** Array of strings */
331331- stringArray?: string[];
475475+import "@typelex/emitter";
332476333333- /** Array with size constraints */
334334- @minItems(1)
335335- @maxItems(10)
336336- limitedArray?: integer[];
477477+namespace com.example.createRecord {
478478+ @procedure
479479+ op main(input: {
480480+ @required text: string;
481481+ }): {
482482+ @required uri: atUri;
483483+ @required cid: cid;
484484+ };
485485+}
486486+```
337487338338- /** Array of references */
339339- items?: Item[];
488488+Output:
340489341341- /** Array of union types */
342342- mixed?: (TypeA | TypeB | unknown)[];
490490+```json
491491+// ...
492492+"main": {
493493+ "type": "procedure",
494494+ "input": {
495495+ "encoding": "application/json",
496496+ "schema": {
497497+ "type": "object",
498498+ "properties": { "text": { "type": "string" } },
499499+ "required": ["text"]
500500+ }
501501+ },
502502+ "output": {
503503+ "encoding": "application/json",
504504+ "schema": {
505505+ "type": "object",
506506+ "properties": {
507507+ "uri": { /* ... */ },
508508+ "cid": { /* ... */ }
509509+ },
510510+ "required": ["uri", "cid"]
511511+ }
512512+ }
343513}
514514+// ...
344515```
345516346346-**Maps to:** `{"type": "array", "items": {...}}`
517517+Procedures can also receive parameters (rarely used): `op main(input: {}, parameters: {})`.
518518+519519+Use `: void` for no output, or `: never` with `@encoding()` on the `op` for output with encoding but no schema.
347520348348-**Note:** `@minItems`/`@maxItems` in TypeSpec map to `minLength`/`maxLength` in JSON.
521521+### Subscriptions
349522350350-## Blobs
523523+Use `@subscription` for subscriptions:
351524352525```typescript
353353-model Main {
354354- /** Basic blob */
355355- file?: Blob;
526526+import "@typelex/emitter";
356527357357- /** Image up to 5MB */
358358- image?: Blob<#["image/*"], 5000000>;
528528+namespace com.atproto.sync.subscribeRepos {
529529+ @subscription
530530+ @errors(FutureCursor, ConsumerTooSlow)
531531+ op main(cursor?: integer): Commit | Sync | unknown;
359532360360- /** Specific types up to 2MB */
361361- photo?: Blob<#["image/png", "image/jpeg"], 2000000>;
533533+ model Commit { /* ... */ }
534534+ model Sync { /* ... */ }
535535+ model FutureCursor {}
536536+ model ConsumerTooSlow {}
362537}
363538```
364539365365-**Maps to:**
540540+Output:
541541+366542```json
367367-{
368368- "file": {"type": "blob"},
369369- "image": {
370370- "type": "blob",
371371- "accept": ["image/*"],
372372- "maxSize": 5000000
373373- }
543543+// ...
544544+"main": {
545545+ "type": "subscription",
546546+ "parameters": {
547547+ "type": "params",
548548+ "properties": { "cursor": { /* ... */ } }
549549+ },
550550+ "message": {
551551+ "schema": {
552552+ "type": "union",
553553+ "refs": ["#commit", "#sync"]
554554+ }
555555+ },
556556+ "errors": [{ "name": "FutureCursor" }, { "name": "ConsumerTooSlow" }]
374557}
558558+// ...
375559```
376560377377-## References
561561+### Tokens
378562379379-### Local References
563563+Use `@token` for empty token models:
380564381381-Same namespace, uses `#`:
565565+```typescript
566566+namespace com.example.moderation.defs {
567567+ @token
568568+ model ReasonSpam {}
382569383383-```typescript
384384-model Main {
385385- metadata?: Metadata;
570570+ @token
571571+ model ReasonViolation {}
572572+573573+ model Report {
574574+ @required reason: (ReasonSpam | ReasonViolation | unknown);
575575+ }
386576}
577577+```
387578388388-model Metadata {
389389- @required key: string;
579579+Output:
580580+581581+```json
582582+// ...
583583+"reasonSpam": { "type": "token" },
584584+"reasonViolation": { "type": "token" },
585585+"report": {
586586+ "type": "object",
587587+ "properties": {
588588+ "reason": {
589589+ "type": "union",
590590+ "refs": ["#reasonSpam", "#reasonViolation"]
591591+ }
592592+ },
593593+ "required": ["reason"]
390594}
595595+// ...
391596```
392597393393-**Maps to:** `{"type": "ref", "ref": "#metadata"}`
598598+## Data Types
599599+600600+All [Lexicon data types](https://atproto.com/specs/lexicon#overview-of-types) are supported.
601601+602602+### Primitive Types
603603+604604+| TypeSpec | Lexicon JSON |
605605+|----------|--------------|
606606+| `boolean` | `{"type": "boolean"}` |
607607+| `integer` | `{"type": "integer"}` |
608608+| `string` | `{"type": "string"}` |
609609+| `bytes` | `{"type": "bytes"}` |
610610+| `cidLink` | `{"type": "cid-link"}` |
611611+| `unknown` | `{"type": "unknown"}` |
612612+613613+### Format Types
614614+615615+Specialized string formats:
616616+617617+| TypeSpec | Lexicon Format |
618618+|----------|----------------|
619619+| `atIdentifier` | `at-identifier` - Handle or DID |
620620+| `atUri` | `at-uri` - AT Protocol URI |
621621+| `cid` | `cid` - Content ID |
622622+| `datetime` | `datetime` - ISO 8601 datetime |
623623+| `did` | `did` - DID identifier |
624624+| `handle` | `handle` - Handle identifier |
625625+| `nsid` | `nsid` - Namespaced ID |
626626+| `tid` | `tid` - Timestamp ID |
627627+| `recordKey` | `record-key` - Record key |
628628+| `uri` | `uri` - Generic URI |
629629+| `language` | `language` - Language tag |
394630395395-### External References
631631+### Arrays
396632397397-Different namespace to specific def:
633633+Use `[]` suffix:
398634399635```typescript
400400-model Main {
401401- externalRef?: com.example.defs.Metadata;
402402-}
403403-```
636636+import "@typelex/emitter";
404637405405-**Maps to:** `{"type": "ref", "ref": "com.example.defs#metadata"}`
638638+namespace com.example.arrays {
639639+ model Main {
640640+ stringArray?: string[];
406641407407-Different namespace to main def (no fragment):
642642+ @minItems(1)
643643+ @maxItems(10)
644644+ limitedArray?: integer[];
408645409409-```typescript
410410-model Main {
411411- mainRef?: com.example.post.Main;
646646+ items?: Item[];
647647+ mixed?: (TypeA | TypeB | unknown)[];
648648+ }
649649+ // ...
412650}
413651```
414652415415-**Maps to:** `{"type": "ref", "ref": "com.example.post"}`
653653+Output: `{ "type": "array", "items": {...} }`.
416654417417-## Tokens
655655+Note: `@minItems`/`@maxItems` map to `minLength`/`maxLength` in JSON.
418656419419-Empty models marked with `@token`:
657657+### Blobs
420658421659```typescript
422422-/** Indicates spam content */
423423-@token
424424-model ReasonSpam {}
660660+import "@typelex/emitter";
425661426426-/** Indicates policy violation */
427427-@token
428428-model ReasonViolation {}
429429-430430-model Report {
431431- @required reason: (ReasonSpam | ReasonViolation | unknown);
662662+namespace com.example.blobs {
663663+ model Main {
664664+ file?: Blob;
665665+ image?: Blob<#["image/*"], 5000000>;
666666+ photo?: Blob<#["image/png", "image/jpeg"], 2000000>;
667667+ }
432668}
433669```
434670435435-**Maps to:**
671671+Output:
672672+436673```json
437437-{
438438- "report": {
439439- "properties": {
440440- "reason": {
441441- "type": "union",
442442- "refs": ["#reasonSpam", "#reasonViolation"]
443443- }
444444- }
445445- },
446446- "reasonSpam": {
447447- "type": "token",
448448- "description": "Indicates spam content"
449449- }
674674+// ...
675675+"image": {
676676+ "type": "blob",
677677+ "accept": ["image/*"],
678678+ "maxSize": 5000000
450679}
680680+// ...
451681```
452682453453-## Operation Details
683683+## Required and Optional Fields
454684455455-### Query Parameters
685685+In Lexicon, fields are optional by default. Use `?:`:
456686457687```typescript
458458-@query
459459-op main(
460460- @required search: string,
461461- limit?: integer = 50,
462462- tags?: string[]
463463-): { ... };
688688+import "@typelex/emitter";
689689+690690+namespace tools.ozone.moderation.defs {
691691+ model SubjectStatusView {
692692+ subjectRepoHandle?: string;
693693+ }
694694+}
464695```
465696466466-Parameters can be inline with decorators before each.
697697+**Think thrice before adding required fields**โyou can't make them optional later.
467698468468-### Procedure with Input and Parameters
699699+This is why `@required` is explicit:
469700470701```typescript
471471-@procedure
472472-op main(
473473- input: {
474474- @required data: string;
475475- },
476476- parameters: {
477477- @required repo: atIdentifier;
478478- validate?: boolean = true;
702702+import "@typelex/emitter";
703703+704704+namespace tools.ozone.moderation.defs {
705705+ model SubjectStatusView {
706706+ subjectRepoHandle?: string;
707707+ @required createdAt: datetime;
479708 }
480480-): { ... };
709709+}
481710```
482711483483-Use `input:` for body, `parameters:` for query params.
712712+Output:
484713485485-### No Output
486486-487487-```typescript
488488-@procedure
489489-op main(input: {
490490- @required uri: atUri;
491491-}): void;
714714+```json
715715+// ...
716716+"required": ["createdAt"]
717717+// ...
492718```
493719494494-Use `: void` for procedures with no output.
720720+## Unions
721721+722722+### Open Unions (Recommended)
495723496496-### Output Without Schema
724724+Unions default to being *open*โallowing you to add more options later. Write `| unknown`:
497725498726```typescript
499499-@query
500500-@encoding("application/json")
501501-op main(id?: string): never;
727727+import "@typelex/emitter";
728728+729729+namespace app.bsky.feed.post {
730730+ model Main {
731731+ embed?: Images | Video | unknown;
732732+ }
733733+734734+ model Images { /* ... */ }
735735+ model Video { /* ... */ }
736736+}
502737```
503738504504-Use `: never` with `@encoding()` for output with encoding but no schema.
739739+Output:
505740506506-### Errors
741741+```json
742742+// ...
743743+"embed": {
744744+ "type": "union",
745745+ "refs": ["#images", "#video"]
746746+}
747747+// ...
748748+```
749749+750750+You can also use the `union` syntax to give it a name:
507751508752```typescript
509509-/** The provided text is invalid */
510510-model InvalidText {}
753753+import "@typelex/emitter";
754754+755755+namespace app.bsky.feed.post {
756756+ model Main {
757757+ embed?: EmbedType;
758758+ }
511759512512-/** User not found */
513513-model NotFound {}
760760+ @inline union EmbedType { Images, Video, unknown }
514761515515-@procedure
516516-@errors(InvalidText, NotFound)
517517-op main(...): ...;
762762+ model Images { /* ... */ }
763763+ model Video { /* ... */ }
764764+}
518765```
519766520520-Empty models with descriptions become error definitions.
767767+The `@inline` prevents it from becoming a separate def in the output.
521768522522-## Constraints
769769+### Known Values (Open Enums)
523770524524-### String Constraints
771771+Suggest common values but allow others with `| string`:
525772526773```typescript
527527-model Main {
528528- /** Byte length constraints */
529529- @minLength(1)
530530- @maxLength(100)
531531- text?: string;
774774+import "@typelex/emitter";
532775533533- /** Grapheme cluster length constraints */
534534- @minGraphemes(1)
535535- @maxGraphemes(50)
536536- displayName?: string;
776776+namespace com.example {
777777+ model Main {
778778+ lang?: "en" | "es" | "fr" | string;
779779+ }
537780}
538781```
539782540540-**Maps to:** `minLength`/`maxLength`, `minGraphemes`/`maxGraphemes`
783783+The `union` syntax works here too:
784784+785785+```typescript
786786+import "@typelex/emitter";
541787542542-### Integer Constraints
788788+namespace com.example {
789789+ model Main {
790790+ lang?: Languages;
791791+ }
543792544544-```typescript
545545-model Main {
546546- @minValue(1)
547547- @maxValue(100)
548548- score?: integer;
793793+ @inline union Languages { "en", "es", "fr", string }
549794}
550795```
551796552552-**Maps to:** `minimum`/`maximum`
797797+You can remove `@inline` to make it a reusable `def` accessible from other Lexicons.
798798+799799+### Closed Unions and Enums (Discouraged)
800800+801801+**Heavily discouraged** in Lexicon.
553802554554-### Bytes Constraints
803803+Marking a `union` as `@closed` lets you remove `unknown` from the list of options:
555804556805```typescript
557557-model Main {
558558- @minBytes(1)
559559- @maxBytes(1024)
560560- data?: bytes;
806806+import "@typelex/emitter";
807807+808808+namespace com.atproto.repo.applyWrites {
809809+ model Main {
810810+ @required writes: WriteAction[];
811811+ }
812812+813813+ @closed // Discouraged!
814814+ @inline
815815+ union WriteAction { Create, Update, Delete }
816816+817817+ model Create { /* ... */ }
818818+ model Update { /* ... */ }
819819+ model Delete { /* ... */ }
561820}
562821```
563822564564-**Maps to:** `minLength`/`maxLength`
823823+Output:
565824566566-**Note:** Use `@minBytes`/`@maxBytes` in TypeSpec, but they map to `minLength`/`maxLength` in JSON.
825825+```json
826826+// ...
827827+"writes": {
828828+ "type": "array",
829829+ "items": {
830830+ "type": "union",
831831+ "refs": ["#create", "#update", "#delete"],
832832+ "closed": true
833833+ }
834834+}
835835+// ...
836836+```
567837568568-### Array Constraints
838838+With strings or numbers, this becomes a closed `enum`:
569839570840```typescript
571571-model Main {
572572- @minItems(1)
573573- @maxItems(10)
574574- items?: string[];
841841+import "@typelex/emitter";
842842+843843+namespace com.atproto.repo.applyWrites {
844844+ model Main {
845845+ @required action: WriteAction;
846846+ }
847847+848848+ @closed // Discouraged!
849849+ @inline
850850+ union WriteAction { "create", "update", "delete" }
575851}
576852```
577853578578-**Maps to:** `minLength`/`maxLength`
854854+Output:
579855580580-**Note:** Use `@minItems`/`@maxItems` in TypeSpec, but they map to `minLength`/`maxLength` in JSON.
856856+```json
857857+// ...
858858+"type": "string",
859859+"enum": ["create", "update", "delete"]
860860+// ...
861861+```
581862582582-## Default and Constant Values
863863+Avoid closed unions/enums when possible.
583864584584-### Defaults
865865+## Constraints
866866+867867+### Strings
585868586869```typescript
587587-model Main {
588588- version?: integer = 1;
589589- lang?: string = "en";
870870+import "@typelex/emitter";
871871+872872+namespace com.example {
873873+ model Main {
874874+ @minLength(1)
875875+ @maxLength(100)
876876+ text?: string;
877877+878878+ @minGraphemes(1)
879879+ @maxGraphemes(50)
880880+ displayName?: string;
881881+ }
590882}
591883```
592884593593-**Maps to:** `{"default": 1}`, `{"default": "en"}`
885885+Maps to: `minLength`/`maxLength`, `minGraphemes`/`maxGraphemes`
594886595595-### Constants
887887+### Integers
596888597597-Use `@readOnly` with default value:
889889+```typescript
890890+import "@typelex/emitter";
598891599599-```typescript
600600-model Main {
601601- @readOnly status?: string = "active";
892892+namespace com.example {
893893+ model Main {
894894+ @minValue(1)
895895+ @maxValue(100)
896896+ score?: integer;
897897+ }
602898}
603899```
604900605605-**Maps to:** `{"const": "active"}`
901901+Maps to: `minimum`/`maximum`
606902607607-## Nullable Fields
903903+### Bytes
608904609609-Use `| null` for nullable fields:
905905+```typescript
906906+import "@typelex/emitter";
610907611611-```typescript
612612-model Main {
613613- @required createdAt: datetime;
614614- updatedAt?: datetime | null; // can be omitted or null
615615- deletedAt?: datetime; // can only be omitted
908908+namespace com.example {
909909+ model Main {
910910+ @minBytes(1)
911911+ @maxBytes(1024)
912912+ data?: bytes;
913913+ }
616914}
617915```
618916619619-**Maps to:**
620620-```json
621621-{
622622- "required": ["createdAt"],
623623- "nullable": ["updatedAt"],
624624- "properties": { ... }
917917+Maps to: `minLength`/`maxLength`
918918+919919+### Arrays
920920+921921+```typescript
922922+import "@typelex/emitter";
923923+924924+namespace com.example {
925925+ model Main {
926926+ @minItems(1)
927927+ @maxItems(10)
928928+ items?: string[];
929929+ }
625930}
626931```
627932628628-## Common Patterns
933933+Maps to: `minLength`/`maxLength`
629934630630-### Discriminated Unions
935935+## Defaults and Constants
631936632632-Use `@readOnly` with const for discriminator:
937937+### Defaults
633938634939```typescript
635635-model Create {
636636- @readOnly @required type: string = "create";
637637- @required data: string;
638638-}
940940+import "@typelex/emitter";
639941640640-model Update {
641641- @readOnly @required type: string = "update";
642642- @required id: string;
942942+namespace com.example {
943943+ model Main {
944944+ version?: integer = 1;
945945+ lang?: string = "en";
946946+ }
643947}
644948```
645949646646-### Nested Unions
950950+Maps to: `{"default": 1}`, `{"default": "en"}`
951951+952952+### Constants
953953+954954+Use `@readOnly` with a default:
647955648956```typescript
649649-model Container {
650650- @required id: string;
651651- @required payload: (PayloadA | PayloadB | unknown);
957957+import "@typelex/emitter";
958958+959959+namespace com.example {
960960+ model Main {
961961+ @readOnly status?: string = "active";
962962+ }
652963}
653964```
654965655655-Unions can be nested in objects and arrays.
966966+Maps to: `{"const": "active"}`
656967657657-## Naming Conventions
968968+## Nullable Fields
658969659659-Model names convert from PascalCase to camelCase in defs:
970970+Use `| null` for nullable fields:
660971661972```typescript
662662-model StatusEnum { ... } // becomes "statusEnum"
663663-model UserMetadata { ... } // becomes "userMetadata"
664664-model Main { ... } // becomes "main"
973973+import "@typelex/emitter";
974974+975975+namespace com.example {
976976+ model Main {
977977+ @required createdAt: datetime;
978978+ updatedAt?: datetime | null; // can be omitted or null
979979+ deletedAt?: datetime; // can only be omitted
980980+ }
981981+}
665982```
666983667667-## Decorator Style
984984+Output:
668985669669-- Single `@required` goes on same line: `@required text: string`
670670-- Multiple decorators go on separate lines with blank line after:
671671- ```typescript
672672- @minLength(1)
673673- @maxLength(100)
674674- text?: string;
675675- ```
986986+```json
987987+// ...
988988+"required": ["createdAt"],
989989+"nullable": ["updatedAt"]
990990+// ...
991991+```
+6-4
README.md
···2233An experimental [TypeSpec](https://typespec.io/) syntax for [Lexicon](https://atproto.com/specs/lexicon).
4455-See https://typelex.pages.dev/
66-77-**This is a hobby project but maybe somebody will find it helpful.**
55+See https://typelex.org/
8697Design is not final and might change. Ideas welcome.
108···14121513## Documentation
16141717-No "proper" docs yet. See [DOCS.md](./DOCS.md) for now.
1515+See [DOCS.md](./DOCS.md).
1616+1717+## Alternatives
1818+1919+* [MFL](https://mlf.lol/)
18201921## License
2022
···11+import "@typelex/emitter";
22+33+// Generated by typelex
44+// No external lexicons found
+15
packages/emitter/lib/decorators.tsp
···11import "../dist/tsp-index.js";
2233+using TypeSpec.Reflection;
44+35/**
46 * Specifies the maximum number of graphemes (user-perceived characters) allowed.
57 * Used alongside maxLength for proper Unicode text handling.
···159161 * ```
160162 */
161163extern dec errors(target: unknown, ...errors: unknown[]);
164164+165165+/**
166166+ * Marks a namespace as external, preventing it from emitting JSON output.
167167+ * This decorator can only be applied to namespaces.
168168+ * Useful for importing definitions from other lexicons without re-emitting them.
169169+ *
170170+ * @example
171171+ * ```typespec
172172+ * @external
173173+ * namespace com.atproto.repo.defs;
174174+ * ```
175175+ */
176176+extern dec external(target: Namespace);
···9090 @required allowSubscriptions: "followers" | "mutuals" | "none" | string;
9191 }
92929393- @doc("Metadata about the requesting account's relationship with the subject account. Only has meaningful content for authed requests.")
9393+ /** Metadata about the requesting account's relationship with the subject account. Only has meaningful content for authed requests. */
9494 model ViewerState {
9595 muted?: boolean;
9696 mutedByList?: app.bsky.graph.defs.ListViewBasic;
···100100 following?: atUri;
101101 followedBy?: atUri;
102102103103- @doc("This property is present only in selected cases, as an optimization.")
103103+ /** This property is present only in selected cases, as an optimization. */
104104 knownFollowers?: KnownFollowers;
105105106106- @doc("This property is present only in selected cases, as an optimization.")
106106+ /** This property is present only in selected cases, as an optimization. */
107107 activitySubscription?: app.bsky.notification.defs.ActivitySubscription;
108108 }
109109110110- @doc("The subject's followers whom you also follow")
110110+ /** The subject's followers whom you also follow */
111111 model KnownFollowers {
112112 @required count: integer;
113113···117117 followers: ProfileViewBasic[];
118118 }
119119120120- @doc("Represents the verification information about the user this object is attached to.")
120120+ /** Represents the verification information about the user this object is attached to. */
121121 model VerificationState {
122122- @doc("All verifications issued by trusted verifiers on behalf of this user. Verifications by untrusted verifiers are not included.")
122122+ /** All verifications issued by trusted verifiers on behalf of this user. Verifications by untrusted verifiers are not included. */
123123 @required
124124 verifications: VerificationView[];
125125126126- @doc("The user's status as a verified account.")
126126+ /** The user's status as a verified account. */
127127 @required
128128 verifiedStatus: "valid" | "invalid" | "none" | string;
129129130130- @doc("The user's status as a trusted verifier.")
130130+ /** The user's status as a trusted verifier. */
131131 @required
132132 trustedVerifierStatus: "valid" | "invalid" | "none" | string;
133133 }
134134135135- @doc("An individual verification for an associated subject.")
135135+ /** An individual verification for an associated subject. */
136136 model VerificationView {
137137- @doc("The user who issued this verification.")
137137+ /** The user who issued this verification. */
138138 @required
139139 issuer: did;
140140141141- @doc("The AT-URI of the verification record.")
141141+ /** The AT-URI of the verification record. */
142142 @required
143143 uri: atUri;
144144145145- @doc("True if the verification passes validation, otherwise false.")
145145+ /** True if the verification passes validation, otherwise false. */
146146 @required
147147 isValid: boolean;
148148149149- @doc("Timestamp when the verification was created.")
149149+ /** Timestamp when the verification was created. */
150150 @required
151151 createdAt: datetime;
152152 }
···174174 }
175175176176 model ContentLabelPref {
177177- @doc("Which labeler does this preference apply to? If undefined, applies globally.")
177177+ /** Which labeler does this preference apply to? If undefined, applies globally. */
178178 labelerDid?: did;
179179180180 @required label: string;
···199199 }
200200201201 model PersonalDetailsPref {
202202- @doc("The birth date of account owner.")
202202+ /** The birth date of account owner. */
203203 birthDate?: datetime;
204204 }
205205206206 model FeedViewPref {
207207- @doc("The URI of the feed, or an identifier which describes the feed.")
207207+ /** The URI of the feed, or an identifier which describes the feed. */
208208 @required
209209 feed: string;
210210211211- @doc("Hide replies in the feed.")
211211+ /** Hide replies in the feed. */
212212 hideReplies?: boolean;
213213214214- @doc("Hide replies in the feed if they are not by followed users.")
214214+ /** Hide replies in the feed if they are not by followed users. */
215215 hideRepliesByUnfollowed?: boolean = true;
216216217217- @doc("Hide replies in the feed if they do not have this number of likes.")
217217+ /** Hide replies in the feed if they do not have this number of likes. */
218218 hideRepliesByLikeCount?: integer;
219219220220- @doc("Hide reposts in the feed.")
220220+ /** Hide reposts in the feed. */
221221 hideReposts?: boolean;
222222223223- @doc("Hide quote posts in the feed.")
223223+ /** Hide quote posts in the feed. */
224224 hideQuotePosts?: boolean;
225225 }
226226227227 model ThreadViewPref {
228228- @doc("Sorting mode for threads.")
228228+ /** Sorting mode for threads. */
229229 sort?: "oldest" | "newest" | "most-likes" | "random" | "hotness" | string;
230230231231- @doc("Show followed users at the top of all replies.")
231231+ /** Show followed users at the top of all replies. */
232232 prioritizeFollowedUsers?: boolean;
233233 }
234234···237237 scalar InterestTag extends string;
238238239239 model InterestsPref {
240240- @doc("A list of tags which describe the account owner's interests gathered during onboarding.")
240240+ /** A list of tags which describe the account owner's interests gathered during onboarding. */
241241 @maxItems(100)
242242 @required
243243 tags: InterestTag[];
···251251 string,
252252 }
253253254254- @doc("A word that the account owner has muted.")
254254+ /** A word that the account owner has muted. */
255255 model MutedWord {
256256 id?: string;
257257258258- @doc("The muted word itself.")
258258+ /** The muted word itself. */
259259 @maxGraphemes(1000)
260260 @maxLength(10000)
261261 @required
262262 value: string;
263263264264- @doc("The intended targets of the muted word.")
264264+ /** The intended targets of the muted word. */
265265 @required
266266 targets: MutedWordTarget[];
267267268268- @doc("Groups of users to apply the muted word to. If undefined, applies to all users.")
268268+ /** Groups of users to apply the muted word to. If undefined, applies to all users. */
269269 actorTarget?: "all" | "exclude-following" | string = "all";
270270271271- @doc("The date and time at which the muted word will expire and no longer be applied.")
271271+ /** The date and time at which the muted word will expire and no longer be applied. */
272272 expiresAt?: datetime;
273273 }
274274275275 model MutedWordsPref {
276276- @doc("A list of words the account owner has muted.")
276276+ /** A list of words the account owner has muted. */
277277 @required
278278 items: MutedWord[];
279279 }
280280281281 model HiddenPostsPref {
282282- @doc("A list of URIs of posts the account owner has hidden.")
282282+ /** A list of URIs of posts the account owner has hidden. */
283283 @required
284284 items: atUri[];
285285 }
···295295 @maxLength(100)
296296 scalar NudgeToken extends string;
297297298298- @doc("A grab bag of state that's specific to the bsky.app program. Third-party apps shouldn't use this.")
298298+ /** A grab bag of state that's specific to the bsky.app program. Third-party apps shouldn't use this. */
299299 model BskyAppStatePref {
300300 activeProgressGuide?: BskyAppProgressGuide;
301301302302- @doc("An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user.")
302302+ /** An array of tokens which identify nudges (modals, popups, tours, highlight dots) that should be shown to the user. */
303303 @maxItems(1000)
304304 queuedNudges?: NudgeToken[];
305305306306- @doc("Storage for NUXs the user has encountered.")
306306+ /** Storage for NUXs the user has encountered. */
307307 @maxItems(100)
308308 nuxs?: Nux[];
309309 }
310310311311- @doc("If set, an active progress guide. Once completed, can be set to undefined. Should have unspecced fields tracking progress.")
311311+ /** If set, an active progress guide. Once completed, can be set to undefined. Should have unspecced fields tracking progress. */
312312 model BskyAppProgressGuide {
313313 @maxLength(100)
314314 @required
315315 guide: string;
316316 }
317317318318- @doc("A new user experiences (NUX) storage object")
318318+ /** A new user experiences (NUX) storage object */
319319 model Nux {
320320 @maxLength(100)
321321 @required
···323323324324 @required completed: boolean = false;
325325326326- @doc("Arbitrary data for the NUX. The structure is defined by the NUX itself. Limited to 300 characters.")
326326+ /** Arbitrary data for the NUX. The structure is defined by the NUX itself. Limited to 300 characters. */
327327 @maxGraphemes(300)
328328 @maxLength(3000)
329329 data?: string;
330330331331- @doc("The date and time at which the NUX will expire and should be considered completed.")
331331+ /** The date and time at which the NUX will expire and should be considered completed. */
332332 expiresAt?: datetime;
333333 }
334334335335- @doc("Preferences for how verified accounts appear in the app.")
335335+ /** Preferences for how verified accounts appear in the app. */
336336 model VerificationPrefs {
337337- @doc("Hide the blue check badges for verified accounts and trusted verifiers.")
337337+ /** Hide the blue check badges for verified accounts and trusted verifiers. */
338338 hideBadges?: boolean = false;
339339 }
340340341341- @doc("Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly.")
341341+ /** Default post interaction settings for the account. These values should be applied as default values when creating new posts. These refs should mirror the threadgate and postgate records exactly. */
342342 model PostInteractionSettingsPref {
343343- @doc("Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply.")
343343+ /** Matches threadgate record. List of rules defining who can reply to this users posts. If value is an empty array, no one can reply. If value is undefined, anyone can reply. */
344344 @maxItems(5)
345345 threadgateAllowRules?: (
346346 | app.bsky.feed.threadgate.MentionRule
···350350 | unknown
351351 )[];
352352353353- @doc("Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed.")
353353+ /** Matches postgate record. List of rules defining who can embed this users posts. If value is an empty array or is undefined, no particular rules apply and anyone can embed. */
354354 @maxItems(5)
355355 postgateEmbeddingRules?: (app.bsky.feed.postgate.DisableRule | unknown)[];
356356 }
357357358358 model StatusView {
359359- @doc("The status for the account.")
359359+ /** The status for the account. */
360360 @required
361361- status: "app.bsky.actor.status#live" | string;
361361+ status: app.bsky.actor.status.Live | string;
362362363363 @required record: unknown;
364364365365- @doc("An optional embed associated with the status.")
365365+ /** An optional embed associated with the status. */
366366 embed?: app.bsky.embed.external.View;
367367368368- @doc("The date when this status will expire. The application might choose to no longer return the status after expiration.")
368368+ /** The date when this status will expire. The application might choose to no longer return the status after expiration. */
369369 expiresAt?: datetime;
370370371371- @doc("True if the status is not expired, false if it is expired. Only present if expiration was set.")
371371+ /** True if the status is not expired, false if it is expired. Only present if expiration was set. */
372372 isActive?: boolean;
373373 }
374374}
375375+376376+// --- Externals ---
377377+378378+@external
379379+namespace com.atproto.label.defs {
380380+ model Label { }
381381+}
382382+383383+@external
384384+namespace app.bsky.graph.defs {
385385+ model StarterPackViewBasic { }
386386+ model ListViewBasic { }
387387+}
388388+389389+@external
390390+namespace com.atproto.repo.strongRef {
391391+ model Main { }
392392+}
393393+394394+@external
395395+namespace app.bsky.notification.defs {
396396+ model ActivitySubscription { }
397397+}
398398+399399+@external
400400+namespace app.bsky.feed.threadgate {
401401+ model MentionRule { }
402402+ model FollowerRule { }
403403+ model FollowingRule { }
404404+ model ListRule { }
405405+}
406406+407407+@external
408408+namespace app.bsky.feed.postgate {
409409+ model DisableRule { }
410410+}
411411+412412+@external
413413+namespace app.bsky.actor.status {
414414+ @token model Live { }
415415+}
416416+417417+@external
418418+namespace app.bsky.embed.external {
419419+ model View { }
420420+}
···11import "@typelex/emitter";
2233namespace app.bsky.actor.getPreferences {
44- @doc("Get private preferences attached to the current account. Expected use is synchronization between multiple devices, and import/export during account migration. Requires auth.")
44+ /** Get private preferences attached to the current account. Expected use is synchronization between multiple devices, and import/export during account migration. Requires auth. */
55 @query
66 op main(): {
77 @required preferences: app.bsky.actor.defs.Preferences;
88 };
99}
1010+1111+// --- Externals ---
1212+1313+@external
1414+namespace app.bsky.actor.defs {
1515+ model Preferences { }
1616+}
···11import "@typelex/emitter";
2233namespace app.bsky.actor.getProfile {
44- @doc("Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth.")
44+ /** Get detailed profile view of an actor. Does not require auth, but contains relevant metadata with auth. */
55 @query
66 op main(
77- @doc("Handle or DID of account to fetch profile of.")
88- actor: atIdentifier
77+ /** Handle or DID of account to fetch profile of. */
88+ @required actor: atIdentifier
99 ): app.bsky.actor.defs.ProfileViewDetailed;
1010}
1111+1212+// --- Externals ---
1313+1414+@external
1515+namespace app.bsky.actor.defs {
1616+ model ProfileViewDetailed { }
1717+}
···11import "@typelex/emitter";
2233namespace app.bsky.actor.getSuggestions {
44- @doc("Get a list of suggested actors. Expected use is discovery of accounts to follow during new account onboarding.")
44+ /** Get a list of suggested actors. Expected use is discovery of accounts to follow during new account onboarding. */
55 @query
66 op main(
77 @minValue(1)
···1515 @required
1616 actors: app.bsky.actor.defs.ProfileView[];
17171818- @doc("Snowflake for this recommendation, use when submitting recommendation events.")
1818+ /** Snowflake for this recommendation, use when submitting recommendation events. */
1919 recId?: int32;
2020 };
2121}
2222+2323+// --- Externals ---
2424+2525+@external
2626+namespace app.bsky.actor.defs {
2727+ model ProfileView { }
2828+}
···11import "@typelex/emitter";
2233namespace app.bsky.actor.searchActorsTypeahead {
44- @doc("Find actor suggestions for a prefix search term. Expected use is for auto-completion during text field entry. Does not require auth.")
44+ /** Find actor suggestions for a prefix search term. Expected use is for auto-completion during text field entry. Does not require auth. */
55 @query
66 op main(
77- @doc("DEPRECATED: use 'q' instead.")
77+ /** DEPRECATED: use 'q' instead. */
88 term?: string,
991010- @doc("Search query prefix; not a full query string.")
1010+ /** Search query prefix; not a full query string. */
1111 q?: string,
12121313 @minValue(1)
···1717 @required actors: app.bsky.actor.defs.ProfileViewBasic[];
1818 };
1919}
2020+2121+// --- Externals ---
2222+2323+@external
2424+namespace app.bsky.actor.defs {
2525+ model ProfileViewBasic { }
2626+}
···11import "@typelex/emitter";
2233namespace app.bsky.actor.status {
44- @doc("A declaration of a Bluesky account status.")
44+ /** A declaration of a Bluesky account status. */
55 @rec("literal:self")
66 model Main {
77- @doc("The status for the account.")
77+ /** The status for the account. */
88 @required
99- status: "app.bsky.actor.status#live" | string;
99+ status: Live | string;
10101111- @doc("An optional embed associated with the status.")
1111+ /** An optional embed associated with the status. */
1212 embed?: (app.bsky.embed.external.Main | unknown);
13131414- @doc("The duration of the status in minutes. Applications can choose to impose minimum and maximum limits.")
1414+ /** The duration of the status in minutes. Applications can choose to impose minimum and maximum limits. */
1515 @minValue(1)
1616 durationMinutes?: integer;
17171818 @required createdAt: datetime;
1919 }
20202121- @doc("Advertises an account as currently offering live content.")
2121+ /** Advertises an account as currently offering live content. */
2222 @token
2323 model Live {}
2424}
2525+2626+// --- Externals ---
2727+2828+@external
2929+namespace app.bsky.embed.external {
3030+ model Main { }
3131+}
···11import "@typelex/emitter";
2233namespace app.bsky.bookmark.createBookmark {
44- @doc("Creates a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication.")
44+ /** Creates a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication. */
55 @errors(UnsupportedCollection)
66 @procedure
77 op main(input: {
···99 @required cid: cid;
1010 }): void;
11111212- @doc("The URI to be bookmarked is for an unsupported collection.")
1212+ /** The URI to be bookmarked is for an unsupported collection. */
1313 model UnsupportedCollection {}
1414}
···11import "@typelex/emitter";
2233namespace app.bsky.bookmark.defs {
44- @doc("Object used to store bookmark data in stash.")
44+ /** Object used to store bookmark data in stash. */
55 model Bookmark {
66- @doc("A strong ref to the record to be bookmarked. Currently, only `app.bsky.feed.post` records are supported.")
66+ /** A strong ref to the record to be bookmarked. Currently, only `app.bsky.feed.post` records are supported. */
77 @required
88 subject: com.atproto.repo.strongRef.Main;
99 }
10101111 model BookmarkView {
1212- @doc("A strong ref to the bookmarked record.")
1212+ /** A strong ref to the bookmarked record. */
1313 @required
1414 subject: com.atproto.repo.strongRef.Main;
1515···2424 );
2525 }
2626}
2727+2828+// --- Externals ---
2929+3030+@external
3131+namespace com.atproto.repo.strongRef {
3232+ model Main { }
3333+}
3434+3535+@external
3636+namespace app.bsky.feed.defs {
3737+ model BlockedPost { }
3838+ model NotFoundPost { }
3939+ model PostView { }
4040+}
···11import "@typelex/emitter";
2233namespace app.bsky.bookmark.deleteBookmark {
44- @doc("Deletes a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication.")
44+ /** Deletes a private bookmark for the specified record. Currently, only `app.bsky.feed.post` records are supported. Requires authentication. */
55 @errors(UnsupportedCollection)
66 @procedure
77 op main(input: {
88 @required uri: atUri;
99 }): void;
10101111- @doc("The URI to be bookmarked is for an unsupported collection.")
1111+ /** The URI to be bookmarked is for an unsupported collection. */
1212 model UnsupportedCollection {}
1313}
···2233namespace app.bsky.embed.defs {
44 // Description goes on the model for defs, unlike standalone lexicons where it goes at lexicon level
55- @doc("width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit.")
55+ /** width:height represents an aspect ratio. It may be approximate, and may not correspond to absolute dimensions in any given unit. */
66 model AspectRatio {
77 @minValue(1)
88 @required
···11import "@typelex/emitter";
2233namespace app.bsky.embed.external {
44- @doc("A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post).")
44+ /** A representation of some externally linked content (eg, a URL and 'card'), embedded in a Bluesky record (eg, a post). */
55 model Main {
66 @required external: External;
77 }
···11import "@typelex/emitter";
2233-@doc("A set of images embedded in a Bluesky record (eg, a post).")
33+/** A set of images embedded in a Bluesky record (eg, a post). */
44namespace app.bsky.embed.images {
55 model Main {
66 @maxItems(4)
···1111 model Image {
1212 @required image: Blob<#["image/*"], 1000000>;
13131414- @doc("Alt text description of the image, for accessibility.")
1414+ /** Alt text description of the image, for accessibility. */
1515 @required
1616 alt: string;
1717···2525 }
26262727 model ViewImage {
2828- @doc("Fully-qualified URL where a thumbnail of the image can be fetched. For example, CDN location provided by the App View.")
2828+ /** Fully-qualified URL where a thumbnail of the image can be fetched. For example, CDN location provided by the App View. */
2929 @required
3030 thumb: uri;
31313232- @doc("Fully-qualified URL where a large version of the image can be fetched. May or may not be the exact original blob. For example, CDN location provided by the App View.")
3232+ /** Fully-qualified URL where a large version of the image can be fetched. May or may not be the exact original blob. For example, CDN location provided by the App View. */
3333 @required
3434 fullsize: uri;
35353636- @doc("Alt text description of the image, for accessibility.")
3636+ /** Alt text description of the image, for accessibility. */
3737 @required
3838 alt: string;
39394040 aspectRatio?: app.bsky.embed.defs.AspectRatio;
4141 }
4242}
4343+4444+// --- Externals ---
4545+4646+@external
4747+namespace app.bsky.embed.defs {
4848+ model AspectRatio { }
4949+}
···11import "@typelex/emitter";
2233-@doc("A representation of a record embedded in a Bluesky record (eg, a post). For example, a quote-post, or sharing a feed generator record.")
33+/** A representation of a record embedded in a Bluesky record (eg, a post). For example, a quote-post, or sharing a feed generator record. */
44namespace app.bsky.embed.`record` {
55 model Main {
66 @required record: com.atproto.repo.strongRef.Main;
···2626 @required cid: cid;
2727 @required author: app.bsky.actor.defs.ProfileViewBasic;
28282929- @doc("The record data itself.")
2929+ /** The record data itself. */
3030 @required
3131 value: unknown;
3232···7474 detached: boolean = true;
7575 }
7676}
7777+7878+// --- Externals ---
7979+8080+@external
8181+namespace com.atproto.repo.strongRef {
8282+ model Main { }
8383+}
8484+8585+@external
8686+namespace app.bsky.feed.defs {
8787+ model GeneratorView { }
8888+ model BlockedAuthor { }
8989+}
9090+9191+@external
9292+namespace app.bsky.graph.defs {
9393+ model ListView { }
9494+ model StarterPackViewBasic { }
9595+}
9696+9797+@external
9898+namespace app.bsky.labeler.defs {
9999+ model LabelerView { }
100100+}
101101+102102+@external
103103+namespace app.bsky.actor.defs {
104104+ model ProfileViewBasic { }
105105+}
106106+107107+@external
108108+namespace com.atproto.label.defs {
109109+ model Label { }
110110+}
111111+112112+@external
113113+namespace app.bsky.embed.images {
114114+ model View { }
115115+}
116116+117117+@external
118118+namespace app.bsky.embed.video {
119119+ model View { }
120120+}
121121+122122+@external
123123+namespace app.bsky.embed.external {
124124+ model View { }
125125+}
126126+127127+@external
128128+namespace app.bsky.embed.recordWithMedia {
129129+ model View { }
130130+}
···11import "@typelex/emitter";
2233-@doc("A representation of a record embedded in a Bluesky record (eg, a post), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card.")
33+/** A representation of a record embedded in a Bluesky record (eg, a post), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card. */
44namespace app.bsky.embed.recordWithMedia {
55 model Main {
66 @required record: app.bsky.embed.record.Main;
···2626 );
2727 }
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace app.bsky.embed.`record` {
3434+ model Main { }
3535+ model View { }
3636+}
3737+3838+@external
3939+namespace app.bsky.embed.images {
4040+ model Main { }
4141+ model View { }
4242+}
4343+4444+@external
4545+namespace app.bsky.embed.video {
4646+ model Main { }
4747+ model View { }
4848+}
4949+5050+@external
5151+namespace app.bsky.embed.external {
5252+ model Main { }
5353+ model View { }
5454+}
···11import "@typelex/emitter";
2233-@doc("A video embedded in a Bluesky record (eg, a post).")
33+/** A video embedded in a Bluesky record (eg, a post). */
44namespace app.bsky.embed.video {
55 model Main {
66- @doc("The mp4 video file. May be up to 100mb, formerly limited to 50mb.")
66+ /** The mp4 video file. May be up to 100mb, formerly limited to 50mb. */
77 @required
88 video: Blob<#["video/mp4"], 100000000>;
991010 @maxItems(20)
1111 captions?: Caption[];
12121313- @doc("Alt text description of the video, for accessibility.")
1313+ /** Alt text description of the video, for accessibility. */
1414 @maxGraphemes(1000)
1515 @maxLength(10000)
1616 alt?: string;
···3636 aspectRatio?: app.bsky.embed.defs.AspectRatio;
3737 }
3838}
3939+4040+// --- Externals ---
4141+4242+@external
4343+namespace app.bsky.embed.defs {
4444+ model AspectRatio { }
4545+}
···2929 threadgate?: ThreadgateView;
3030 }
31313232- @doc("Metadata about the requesting account's relationship with the subject content. Only has meaningful content for authed requests.")
3232+ /** Metadata about the requesting account's relationship with the subject content. Only has meaningful content for authed requests. */
3333 model ViewerState {
3434 repost?: atUri;
3535 like?: atUri;
···4040 pinned?: boolean;
4141 }
42424343- @doc("Metadata about this post within the context of the thread it is in.")
4343+ /** Metadata about this post within the context of the thread it is in. */
4444 model ThreadContext {
4545 rootAuthorLike?: atUri;
4646 }
···5151 reply?: ReplyRef;
5252 reason?: (ReasonRepost | ReasonPin | unknown);
53535454- @doc("Context provided by feed generator that may be passed back alongside interactions.")
5454+ /** Context provided by feed generator that may be passed back alongside interactions. */
5555 @maxLength(2000)
5656 feedContext?: string;
57575858- @doc("Unique identifier per request that may be passed back alongside interactions.")
5858+ /** Unique identifier per request that may be passed back alongside interactions. */
5959 @maxLength(100)
6060 reqId?: string;
6161 }
···6464 @required root: (PostView | NotFoundPost | BlockedPost | unknown);
6565 @required parent: (PostView | NotFoundPost | BlockedPost | unknown);
66666767- @doc("When parent is a reply to another post, this is the author of that post.")
6767+ /** When parent is a reply to another post, this is the author of that post. */
6868 grandparentAuthor?: app.bsky.actor.defs.ProfileViewBasic;
6969 }
7070···133133 acceptsInteractions?: boolean;
134134 labels?: com.atproto.label.defs.Label[];
135135 viewer?: GeneratorViewerState;
136136- contentMode?: "app.bsky.feed.defs#contentModeUnspecified" | "app.bsky.feed.defs#contentModeVideo" | string;
136136+ contentMode?: ContentModeUnspecified | ContentModeVideo | string;
137137138138 @required indexedAt: datetime;
139139 }
···147147148148 reason?: (SkeletonReasonRepost | SkeletonReasonPin | unknown);
149149150150- @doc("Context that will be passed through to client and may be passed to feed generator back alongside interactions.")
150150+ /** Context that will be passed through to client and may be passed to feed generator back alongside interactions. */
151151 @maxLength(2000)
152152 feedContext?: string;
153153 }
···167167168168 model Interaction {
169169 item?: atUri;
170170- event?: "app.bsky.feed.defs#requestLess"
171171- | "app.bsky.feed.defs#requestMore"
172172- | "app.bsky.feed.defs#clickthroughItem"
173173- | "app.bsky.feed.defs#clickthroughAuthor"
174174- | "app.bsky.feed.defs#clickthroughReposter"
175175- | "app.bsky.feed.defs#clickthroughEmbed"
176176- | "app.bsky.feed.defs#interactionSeen"
177177- | "app.bsky.feed.defs#interactionLike"
178178- | "app.bsky.feed.defs#interactionRepost"
179179- | "app.bsky.feed.defs#interactionReply"
180180- | "app.bsky.feed.defs#interactionQuote"
181181- | "app.bsky.feed.defs#interactionShare"
170170+ event?: RequestLess
171171+ | RequestMore
172172+ | ClickthroughItem
173173+ | ClickthroughAuthor
174174+ | ClickthroughReposter
175175+ | ClickthroughEmbed
176176+ | InteractionSeen
177177+ | InteractionLike
178178+ | InteractionRepost
179179+ | InteractionReply
180180+ | InteractionQuote
181181+ | InteractionShare
182182 | string;
183183184184- @doc("Context on a feed item that was originally supplied by the feed generator on getFeedSkeleton.")
184184+ /** Context on a feed item that was originally supplied by the feed generator on getFeedSkeleton. */
185185 @maxLength(2000)
186186 feedContext?: string;
187187188188- @doc("Unique identifier per request that may be passed back alongside interactions.")
188188+ /** Unique identifier per request that may be passed back alongside interactions. */
189189 @maxLength(100)
190190 reqId?: string;
191191 }
192192193193- @doc("Request that less content like the given feed item be shown in the feed")
193193+ /** Request that less content like the given feed item be shown in the feed */
194194 @token
195195 model RequestLess {}
196196197197- @doc("Request that more content like the given feed item be shown in the feed")
197197+ /** Request that more content like the given feed item be shown in the feed */
198198 @token
199199 model RequestMore {}
200200201201- @doc("User clicked through to the feed item")
201201+ /** User clicked through to the feed item */
202202 @token
203203 model ClickthroughItem {}
204204205205- @doc("User clicked through to the author of the feed item")
205205+ /** User clicked through to the author of the feed item */
206206 @token
207207 model ClickthroughAuthor {}
208208209209- @doc("User clicked through to the reposter of the feed item")
209209+ /** User clicked through to the reposter of the feed item */
210210 @token
211211 model ClickthroughReposter {}
212212213213- @doc("User clicked through to the embedded content of the feed item")
213213+ /** User clicked through to the embedded content of the feed item */
214214 @token
215215 model ClickthroughEmbed {}
216216217217- @doc("Declares the feed generator returns any types of posts.")
217217+ /** Declares the feed generator returns any types of posts. */
218218 @token
219219 model ContentModeUnspecified {}
220220221221- @doc("Declares the feed generator returns posts containing app.bsky.embed.video embeds.")
221221+ /** Declares the feed generator returns posts containing app.bsky.embed.video embeds. */
222222 @token
223223 model ContentModeVideo {}
224224225225- @doc("Feed item was seen by user")
225225+ /** Feed item was seen by user */
226226 @token
227227 model InteractionSeen {}
228228229229- @doc("User liked the feed item")
229229+ /** User liked the feed item */
230230 @token
231231 model InteractionLike {}
232232233233- @doc("User reposted the feed item")
233233+ /** User reposted the feed item */
234234 @token
235235 model InteractionRepost {}
236236237237- @doc("User replied to the feed item")
237237+ /** User replied to the feed item */
238238 @token
239239 model InteractionReply {}
240240241241- @doc("User quoted the feed item")
241241+ /** User quoted the feed item */
242242 @token
243243 model InteractionQuote {}
244244245245- @doc("User shared the feed item")
245245+ /** User shared the feed item */
246246 @token
247247 model InteractionShare {}
248248}
249249+250250+// --- Externals ---
251251+252252+@external
253253+namespace app.bsky.actor.defs {
254254+ model ProfileViewBasic { }
255255+ model ViewerState { }
256256+ model ProfileView { }
257257+}
258258+259259+@external
260260+namespace app.bsky.embed.images {
261261+ model View { }
262262+}
263263+264264+@external
265265+namespace app.bsky.embed.video {
266266+ model View { }
267267+}
268268+269269+@external
270270+namespace app.bsky.embed.external {
271271+ model View { }
272272+}
273273+274274+@external
275275+namespace app.bsky.embed.`record` {
276276+ model View { }
277277+}
278278+279279+@external
280280+namespace app.bsky.embed.recordWithMedia {
281281+ model View { }
282282+}
283283+284284+@external
285285+namespace com.atproto.label.defs {
286286+ model Label { }
287287+}
288288+289289+@external
290290+namespace app.bsky.richtext.facet {
291291+ model Main { }
292292+}
293293+294294+@external
295295+namespace app.bsky.graph.defs {
296296+ model ListViewBasic { }
297297+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.describeFeedGenerator {
44- @doc("Get information about a feed generator, including policies and offered feed URIs. Does not require auth; implemented by Feed Generator services (not App View).")
44+ /** Get information about a feed generator, including policies and offered feed URIs. Does not require auth; implemented by Feed Generator services (not App View). */
55 @query
66 op main(): {
77 @required did: did;
···11import "@typelex/emitter";
2233namespace app.bsky.feed.generator {
44- @doc("Record declaring of the existence of a feed generator, and containing metadata about it. The record can exist in any repository.")
44+ /** Record declaring of the existence of a feed generator, and containing metadata about it. The record can exist in any repository. */
55 @rec("any")
66 model Main {
77 @required did: did;
···19192020 avatar?: Blob<#["image/png", "image/jpeg"], 1000000>;
21212222- @doc("Declaration that a feed accepts feedback interactions from a client through app.bsky.feed.sendInteractions")
2222+ /** Declaration that a feed accepts feedback interactions from a client through app.bsky.feed.sendInteractions */
2323 acceptsInteractions?: boolean;
24242525- @doc("Self-label values")
2525+ /** Self-label values */
2626 labels?: (com.atproto.label.defs.SelfLabels | unknown);
27272828- contentMode?: "app.bsky.feed.defs#contentModeUnspecified" | "app.bsky.feed.defs#contentModeVideo" | string;
2828+ contentMode?: app.bsky.feed.defs.ContentModeUnspecified | app.bsky.feed.defs.ContentModeVideo | string;
29293030 @required createdAt: datetime;
3131 }
3232}
3333+3434+// --- Externals ---
3535+3636+@external
3737+namespace app.bsky.richtext.facet {
3838+ model Main { }
3939+}
4040+4141+@external
4242+namespace com.atproto.label.defs {
4343+ model SelfLabels { }
4444+}
4545+4646+@external
4747+namespace app.bsky.feed.defs {
4848+ @token model ContentModeUnspecified { }
4949+ @token model ContentModeVideo { }
5050+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getActorFeeds {
44- @doc("Get a list of feeds (feed generator records) created by the actor (in the actor's repo).")
44+ /** Get a list of feeds (feed generator records) created by the actor (in the actor's repo). */
55 @query
66 op main(
77- actor: atIdentifier,
77+ @required actor: atIdentifier,
8899 @minValue(1)
1010 @maxValue(100)
···1616 @required feeds: app.bsky.feed.defs.GeneratorView[];
1717 };
1818}
1919+2020+// --- Externals ---
2121+2222+@external
2323+namespace app.bsky.feed.defs {
2424+ model GeneratorView { }
2525+}
···44 model BlockedActor {}
55 model BlockedByActor {}
6677- @doc("Get a list of posts liked by an actor. Requires auth, actor must be the requesting account.")
77+ /** Get a list of posts liked by an actor. Requires auth, actor must be the requesting account. */
88 @query
99 @errors(BlockedActor, BlockedByActor)
1010 op main(
1111- actor: atIdentifier,
1111+ @required actor: atIdentifier,
12121313 @minValue(1)
1414 @maxValue(100)
···2020 @required feed: app.bsky.feed.defs.FeedViewPost[];
2121 };
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace app.bsky.feed.defs {
2828+ model FeedViewPost { }
2929+}
···44 model BlockedActor {}
55 model BlockedByActor {}
6677- @doc("Get a view of an actor's 'author feed' (post and reposts by the author). Does not require auth.")
77+ /** Get a view of an actor's 'author feed' (post and reposts by the author). Does not require auth. */
88 @query
99 @errors(BlockedActor, BlockedByActor)
1010 op main(
1111- actor: atIdentifier,
1111+ @required actor: atIdentifier,
12121313 @minValue(1)
1414 @maxValue(100)
···16161717 cursor?: string,
18181919- @doc("Combinations of post/repost types to include in response.")
1919+ /** Combinations of post/repost types to include in response. */
2020 filter?: "posts_with_replies" | "posts_no_replies" | "posts_with_media" | "posts_and_author_threads" | "posts_with_video" | string = "posts_with_replies",
21212222 includePins?: boolean = false
···2525 @required feed: app.bsky.feed.defs.FeedViewPost[];
2626 };
2727}
2828+2929+// --- Externals ---
3030+3131+@external
3232+namespace app.bsky.feed.defs {
3333+ model FeedViewPost { }
3434+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getFeedGenerator {
44- @doc("Get information about a feed generator. Implemented by AppView.")
44+ /** Get information about a feed generator. Implemented by AppView. */
55 @query
66 op main(
77- @doc("AT-URI of the feed generator record.")
88- feed: atUri
77+ /** AT-URI of the feed generator record. */
88+ @required feed: atUri
99 ): {
1010 @required view: app.bsky.feed.defs.GeneratorView;
11111212- @doc("Indicates whether the feed generator service has been online recently, or else seems to be inactive.")
1212+ /** Indicates whether the feed generator service has been online recently, or else seems to be inactive. */
1313 @required
1414 isOnline: boolean;
15151616- @doc("Indicates whether the feed generator service is compatible with the record declaration.")
1616+ /** Indicates whether the feed generator service is compatible with the record declaration. */
1717 @required
1818 isValid: boolean;
1919 };
2020}
2121+2222+// --- Externals ---
2323+2424+@external
2525+namespace app.bsky.feed.defs {
2626+ model GeneratorView { }
2727+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getFeedGenerators {
44- @doc("Get information about a list of feed generators.")
44+ /** Get information about a list of feed generators. */
55 @query
66 op main(
77- feeds: atUri[]
77+ @required feeds: atUri[]
88 ): {
99 @required feeds: app.bsky.feed.defs.GeneratorView[];
1010 };
1111}
1212+1313+// --- Externals ---
1414+1515+@external
1616+namespace app.bsky.feed.defs {
1717+ model GeneratorView { }
1818+}
···33namespace app.bsky.feed.getFeedSkeleton {
44 model UnknownFeed {}
5566- @doc("Get a skeleton of a feed provided by a feed generator. Auth is optional, depending on provider requirements, and provides the DID of the requester. Implemented by Feed Generator Service.")
66+ /** Get a skeleton of a feed provided by a feed generator. Auth is optional, depending on provider requirements, and provides the DID of the requester. Implemented by Feed Generator Service. */
77 @query
88 @errors(UnknownFeed)
99 op main(
1010- @doc("Reference to feed generator record describing the specific feed being requested.")
1111- feed: atUri,
1010+ /** Reference to feed generator record describing the specific feed being requested. */
1111+ @required feed: atUri,
12121313 @minValue(1)
1414 @maxValue(100)
···2121 @required
2222 feed: app.bsky.feed.defs.SkeletonFeedPost[];
23232424- @doc("Unique identifier per request that may be passed back alongside interactions.")
2424+ /** Unique identifier per request that may be passed back alongside interactions. */
2525 @maxLength(100)
2626 reqId?: string;
2727 };
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace app.bsky.feed.defs {
3434+ model SkeletonFeedPost { }
3535+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getLikes {
44- @doc("Get like records which reference a subject (by AT-URI and CID).")
44+ /** Get like records which reference a subject (by AT-URI and CID). */
55 @query
66 op main(
77- @doc("AT-URI of the subject (eg, a post record).")
88- uri: atUri,
77+ /** AT-URI of the subject (eg, a post record). */
88+ @required uri: atUri,
991010- @doc("CID of the subject record (aka, specific version of record), to filter likes.")
1010+ /** CID of the subject record (aka, specific version of record), to filter likes. */
1111 cid?: cid,
12121313 @minValue(1)
···2828 @required actor: app.bsky.actor.defs.ProfileView;
2929 }
3030}
3131+3232+// --- Externals ---
3333+3434+@external
3535+namespace app.bsky.actor.defs {
3636+ model ProfileView { }
3737+}
···33namespace app.bsky.feed.getListFeed {
44 model UnknownList {}
5566- @doc("Get a feed of recent posts from a list (posts and reposts from any actors on the list). Does not require auth.")
66+ /** Get a feed of recent posts from a list (posts and reposts from any actors on the list). Does not require auth. */
77 @query
88 @errors(UnknownList)
99 op main(
1010- @doc("Reference (AT-URI) to the list record.")
1111- list: atUri,
1010+ /** Reference (AT-URI) to the list record. */
1111+ @required list: atUri,
12121313 @minValue(1)
1414 @maxValue(100)
···2020 @required feed: app.bsky.feed.defs.FeedViewPost[];
2121 };
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace app.bsky.feed.defs {
2828+ model FeedViewPost { }
2929+}
···33namespace app.bsky.feed.getPostThread {
44 model NotFound {}
5566- @doc("Get posts in a thread. Does not require auth, but additional metadata and filtering will be applied for authed requests.")
66+ /** Get posts in a thread. Does not require auth, but additional metadata and filtering will be applied for authed requests. */
77 @query
88 @errors(NotFound)
99 op main(
1010- @doc("Reference (AT-URI) to post record.")
1111- uri: atUri,
1010+ /** Reference (AT-URI) to post record. */
1111+ @required uri: atUri,
12121313- @doc("How many levels of reply depth should be included in response.")
1313+ /** How many levels of reply depth should be included in response. */
1414 @minValue(0)
1515 @maxValue(1000)
1616 depth?: int32 = 6,
17171818- @doc("How many levels of parent (and grandparent, etc) post to include.")
1818+ /** How many levels of parent (and grandparent, etc) post to include. */
1919 @minValue(0)
2020 @maxValue(1000)
2121 parentHeight?: int32 = 80
···2626 threadgate?: app.bsky.feed.defs.ThreadgateView;
2727 };
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace app.bsky.feed.defs {
3434+ model ThreadViewPost { }
3535+ model NotFoundPost { }
3636+ model BlockedPost { }
3737+ model ThreadgateView { }
3838+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getPosts {
44- @doc("Gets post views for a specified list of posts (by AT-URI). This is sometimes referred to as 'hydrating' a 'feed skeleton'.")
44+ /** Gets post views for a specified list of posts (by AT-URI). This is sometimes referred to as 'hydrating' a 'feed skeleton'. */
55 @query
66 op main(
77- @doc("List of post AT-URIs to return hydrated views for.")
77+ /** List of post AT-URIs to return hydrated views for. */
88 @maxItems(25)
99- uris: atUri[]
99+ @required uris: atUri[]
1010 ): {
1111 @required posts: app.bsky.feed.defs.PostView[];
1212 };
1313}
1414+1515+// --- Externals ---
1616+1717+@external
1818+namespace app.bsky.feed.defs {
1919+ model PostView { }
2020+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getQuotes {
44- @doc("Get a list of quotes for a given post.")
44+ /** Get a list of quotes for a given post. */
55 @query
66 op main(
77- @doc("Reference (AT-URI) of post record")
88- uri: atUri,
77+ /** Reference (AT-URI) of post record */
88+ @required uri: atUri,
991010- @doc("If supplied, filters to quotes of specific version (by CID) of the post record.")
1010+ /** If supplied, filters to quotes of specific version (by CID) of the post record. */
1111 cid?: cid,
12121313 @minValue(1)
···2222 @required posts: app.bsky.feed.defs.PostView[];
2323 };
2424}
2525+2626+// --- Externals ---
2727+2828+@external
2929+namespace app.bsky.feed.defs {
3030+ model PostView { }
3131+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getRepostedBy {
44- @doc("Get a list of reposts for a given post.")
44+ /** Get a list of reposts for a given post. */
55 @query
66 op main(
77- @doc("Reference (AT-URI) of post record")
88- uri: atUri,
77+ /** Reference (AT-URI) of post record */
88+ @required uri: atUri,
991010- @doc("If supplied, filters to reposts of specific version (by CID) of the post record.")
1010+ /** If supplied, filters to reposts of specific version (by CID) of the post record. */
1111 cid?: cid,
12121313 @minValue(1)
···2222 @required repostedBy: app.bsky.actor.defs.ProfileView[];
2323 };
2424}
2525+2626+// --- Externals ---
2727+2828+@external
2929+namespace app.bsky.actor.defs {
3030+ model ProfileView { }
3131+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getSuggestedFeeds {
44- @doc("Get a list of suggested feeds (feed generators) for the requesting account.")
44+ /** Get a list of suggested feeds (feed generators) for the requesting account. */
55 @query
66 op main(
77 @minValue(1)
···1414 @required feeds: app.bsky.feed.defs.GeneratorView[];
1515 };
1616}
1717+1818+// --- Externals ---
1919+2020+@external
2121+namespace app.bsky.feed.defs {
2222+ model GeneratorView { }
2323+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.getTimeline {
44- @doc("Get a view of the requesting account's home timeline. This is expected to be some form of reverse-chronological feed.")
44+ /** Get a view of the requesting account's home timeline. This is expected to be some form of reverse-chronological feed. */
55 @query
66 op main(
77- @doc("Variant 'algorithm' for timeline. Implementation-specific. NOTE: most feed flexibility has been moved to feed generator mechanism.")
77+ /** Variant 'algorithm' for timeline. Implementation-specific. NOTE: most feed flexibility has been moved to feed generator mechanism. */
88 algorithm?: string,
991010 @minValue(1)
···1717 @required feed: app.bsky.feed.defs.FeedViewPost[];
1818 };
1919}
2020+2121+// --- Externals ---
2222+2323+@external
2424+namespace app.bsky.feed.defs {
2525+ model FeedViewPost { }
2626+}
···2233namespace app.bsky.feed.like {
44 @rec("tid")
55- @doc("Record declaring a 'like' of a piece of subject content.")
55+ /** Record declaring a 'like' of a piece of subject content. */
66 model Main {
77 @required
88 subject: com.atproto.repo.strongRef.Main;
···1313 via?: com.atproto.repo.strongRef.Main;
1414 }
1515}
1616+1717+// --- Externals ---
1818+1919+@external
2020+namespace com.atproto.repo.strongRef {
2121+ model Main { }
2222+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.post {
44- @doc("Record containing a Bluesky post.")
44+ /** Record containing a Bluesky post. */
55 @rec("tid")
66 model Main {
77- @doc("The primary post content. May be an empty string, if there are embeds.")
77+ /** The primary post content. May be an empty string, if there are embeds. */
88 @maxGraphemes(300)
99 @maxLength(3000)
1010 @required
1111 text: string;
12121313- @doc("DEPRECATED: replaced by app.bsky.richtext.facet.")
1313+ /** DEPRECATED: replaced by app.bsky.richtext.facet. */
1414 entities?: Entity[];
15151616- @doc("Annotations of text (mentions, URLs, hashtags, etc)")
1616+ /** Annotations of text (mentions, URLs, hashtags, etc) */
1717 facets?: app.bsky.richtext.facet.Main[];
18181919 reply?: ReplyRef;
···2727 | unknown
2828 );
29293030- @doc("Indicates human language of post primary text content.")
3030+ /** Indicates human language of post primary text content. */
3131 @maxItems(3)
3232 langs?: language[];
33333434- @doc("Self-label values for this post. Effectively content warnings.")
3434+ /** Self-label values for this post. Effectively content warnings. */
3535 labels?: (com.atproto.label.defs.SelfLabels | unknown);
36363737- @doc("Additional hashtags, in addition to any included in post text and facets.")
3737+ /** Additional hashtags, in addition to any included in post text and facets. */
3838 @maxItems(8)
3939 tags?: PostTag[];
40404141- @doc("Client-declared timestamp when this post was originally created.")
4141+ /** Client-declared timestamp when this post was originally created. */
4242 @required
4343 createdAt: datetime;
4444 }
···4848 @required parent: com.atproto.repo.strongRef.Main;
4949 }
50505151- @doc("Deprecated: use facets instead.")
5151+ /** Deprecated: use facets instead. */
5252 model Entity {
5353 @required index: TextSlice;
54545555- @doc("Expected values are 'mention' and 'link'.")
5555+ /** Expected values are 'mention' and 'link'. */
5656 @required
5757 type: string;
58585959 @required value: string;
6060 }
61616262- @doc("Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings.")
6262+ /** Deprecated. Use app.bsky.richtext instead -- A text segment. Start is inclusive, end is exclusive. Indices are for utf16-encoded strings. */
6363 model TextSlice {
6464 @minValue(0)
6565 @required
···7474@maxGraphemes(64)
7575@maxLength(640)
7676scalar PostTag extends string;
7777+7878+// --- Externals ---
7979+8080+@external
8181+namespace app.bsky.richtext.facet {
8282+ model Main { }
8383+}
8484+8585+@external
8686+namespace app.bsky.embed.images {
8787+ model Main { }
8888+}
8989+9090+@external
9191+namespace app.bsky.embed.video {
9292+ model Main { }
9393+}
9494+9595+@external
9696+namespace app.bsky.embed.external {
9797+ model Main { }
9898+}
9999+100100+@external
101101+namespace app.bsky.embed.`record` {
102102+ model Main { }
103103+}
104104+105105+@external
106106+namespace app.bsky.embed.recordWithMedia {
107107+ model Main { }
108108+}
109109+110110+@external
111111+namespace com.atproto.label.defs {
112112+ model SelfLabels { }
113113+}
114114+115115+@external
116116+namespace com.atproto.repo.strongRef {
117117+ model Main { }
118118+}
···2233namespace app.bsky.feed.postgate {
44 @rec("tid")
55- @doc("Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository.")
55+ /** Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository. */
66 model Main {
77- @doc("Reference (AT-URI) to the post record.")
77+ /** Reference (AT-URI) to the post record. */
88 @required
99 post: atUri;
10101111 @required createdAt: datetime;
12121313- @doc("List of AT-URIs embedding this post that the author has detached from.")
1313+ /** List of AT-URIs embedding this post that the author has detached from. */
1414 @maxItems(50)
1515 detachedEmbeddingUris?: atUri[];
16161717- @doc("List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed.")
1717+ /** List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed. */
1818 @maxItems(5)
1919 embeddingRules?: (DisableRule | unknown)[];
2020 }
21212222- @doc("Disables embedding of this post.")
2222+ /** Disables embedding of this post. */
2323 model DisableRule {}
2424}
···2233namespace app.bsky.feed.repost {
44 @rec("tid")
55- @doc("Record representing a 'repost' of an existing Bluesky post.")
55+ /** Record representing a 'repost' of an existing Bluesky post. */
66 model Main {
77 @required subject: com.atproto.repo.strongRef.Main;
88 @required createdAt: datetime;
99 via?: com.atproto.repo.strongRef.Main;
1010 }
1111}
1212+1313+// --- Externals ---
1414+1515+@external
1616+namespace com.atproto.repo.strongRef {
1717+ model Main { }
1818+}
···77namespace app.bsky.feed.searchPosts {
88 model BadQueryString {}
991010- @doc("Find posts matching search criteria, returning views of those posts. Note that this API endpoint may require authentication (eg, not public) for some service providers and implementations.")
1010+ /** Find posts matching search criteria, returning views of those posts. Note that this API endpoint may require authentication (eg, not public) for some service providers and implementations. */
1111 @query
1212 @errors(BadQueryString)
1313 op main(
1414- @doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
1515- q: string,
1414+ /** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
1515+ @required q: string,
16161717- @doc("Specifies the ranking order of results.")
1717+ /** Specifies the ranking order of results. */
1818 sort?: "top" | "latest" | string = "latest",
19192020- @doc("Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD).")
2020+ /** Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD). */
2121 since?: string,
22222323- @doc("Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD).")
2323+ /** Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD). */
2424 until?: string,
25252626- @doc("Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions.")
2626+ /** Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions. */
2727 mentions?: atIdentifier,
28282929- @doc("Filter to posts by the given account. Handles are resolved to DID before query-time.")
2929+ /** Filter to posts by the given account. Handles are resolved to DID before query-time. */
3030 author?: atIdentifier,
31313232- @doc("Filter to posts in the given language. Expected to be based on post language field, though server may override language detection.")
3232+ /** Filter to posts in the given language. Expected to be based on post language field, though server may override language detection. */
3333 lang?: language,
34343535- @doc("Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization.")
3535+ /** Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization. */
3636 domain?: string,
37373838- @doc("Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching.")
3838+ /** Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching. */
3939 url?: uri,
40404141- @doc("Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching.")
4141+ /** Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching. */
4242 tag?: TagString[],
43434444 @minValue(1)
4545 @maxValue(100)
4646 limit?: int32 = 25,
47474848- @doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
4848+ /** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
4949 cursor?: string
5050 ): {
5151 cursor?: string;
52525353- @doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
5353+ /** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
5454 hitsTotal?: int32;
55555656 @required posts: app.bsky.feed.defs.PostView[];
5757 };
5858}
5959+6060+// --- Externals ---
6161+6262+@external
6363+namespace app.bsky.feed.defs {
6464+ model PostView { }
6565+}
···11import "@typelex/emitter";
2233namespace app.bsky.feed.sendInteractions {
44- @doc("Send information about interactions with feed items back to the feed generator that served them.")
44+ /** Send information about interactions with feed items back to the feed generator that served them. */
55 @procedure
66 op main(input: {
77 @required interactions: app.bsky.feed.defs.Interaction[];
88 }): {};
99}
1010+1111+// --- Externals ---
1212+1313+@external
1414+namespace app.bsky.feed.defs {
1515+ model Interaction { }
1616+}
···2233namespace app.bsky.feed.threadgate {
44 @rec("tid")
55- @doc("Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository.")
55+ /** Record defining interaction gating rules for a thread (aka, reply controls). The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository. */
66 model Main {
77- @doc("Reference (AT-URI) to the post record.")
77+ /** Reference (AT-URI) to the post record. */
88 @required
99 post: atUri;
10101111- @doc("List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply.")
1111+ /** List of rules defining who can reply to this post. If value is an empty array, no one can reply. If value is undefined, anyone can reply. */
1212 @maxItems(5)
1313 allow?: (MentionRule | FollowerRule | FollowingRule | ListRule | unknown)[];
14141515 @required createdAt: datetime;
16161717- @doc("List of hidden reply URIs.")
1717+ /** List of hidden reply URIs. */
1818 @maxItems(50)
1919 hiddenReplies?: atUri[];
2020 }
21212222- @doc("Allow replies from actors mentioned in your post.")
2222+ /** Allow replies from actors mentioned in your post. */
2323 model MentionRule {}
24242525- @doc("Allow replies from actors who follow you.")
2525+ /** Allow replies from actors who follow you. */
2626 model FollowerRule {}
27272828- @doc("Allow replies from actors you follow.")
2828+ /** Allow replies from actors you follow. */
2929 model FollowingRule {}
30303131- @doc("Allow replies from actors on a list.")
3131+ /** Allow replies from actors on a list. */
3232 model ListRule {
3333 @required list: atUri;
3434 }
···2233namespace app.bsky.graph.block {
44 @rec("tid")
55- @doc("Record declaring a 'block' relationship against another account. NOTE: blocks are public in Bluesky; see blog posts for details.")
55+ /** Record declaring a 'block' relationship against another account. NOTE: blocks are public in Bluesky; see blog posts for details. */
66 model Main {
77- @doc("DID of the account to be blocked.")
77+ /** DID of the account to be blocked. */
88 @required
99 subject: did;
1010
···97979898 union ListPurpose {
9999 string,
100100-101101- Modlist: "app.bsky.graph.defs#modlist",
102102- Curatelist: "app.bsky.graph.defs#curatelist",
103103- Referencelist: "app.bsky.graph.defs#referencelist",
100100+ Modlist,
101101+ Curatelist,
102102+ Referencelist,
104103 }
105104106106- @doc("A list of actors to apply an aggregate moderation action (mute/block) on.")
105105+ /** A list of actors to apply an aggregate moderation action (mute/block) on. */
107106 @token
108107 model Modlist {}
109108110110- @doc("A list of actors used for curation purposes such as list feeds or interaction gating.")
109109+ /** A list of actors used for curation purposes such as list feeds or interaction gating. */
111110 @token
112111 model Curatelist {}
113112114114- @doc("A list of actors used for only for reference purposes such as within a starter pack.")
113113+ /** A list of actors used for only for reference purposes such as within a starter pack. */
115114 @token
116115 model Referencelist {}
117116···120119 blocked?: atUri;
121120 }
122121123123- @doc("indicates that a handle or DID could not be resolved")
122122+ /** indicates that a handle or DID could not be resolved */
124123 model NotFoundActor {
125124 @required actor: atIdentifier;
126125···129128 notFound: boolean = true;
130129 }
131130132132- @doc("lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object)")
131131+ /** lists the bi-directional graph relationships between one actor (not indicated in the object), and the target actors (the DID included in the object) */
133132 model Relationship {
134133 @required did: did;
135134136136- @doc("if the actor follows this DID, this is the AT-URI of the follow record")
135135+ /** if the actor follows this DID, this is the AT-URI of the follow record */
137136 following?: atUri;
138137139139- @doc("if the actor is followed by this DID, contains the AT-URI of the follow record")
138138+ /** if the actor is followed by this DID, contains the AT-URI of the follow record */
140139 followedBy?: atUri;
141140 }
142141}
142142+143143+// --- Externals ---
144144+145145+@external
146146+namespace com.atproto.label.defs {
147147+ model Label { }
148148+}
149149+150150+@external
151151+namespace app.bsky.actor.defs {
152152+ model ProfileView { }
153153+ model ProfileViewBasic { }
154154+}
155155+156156+@external
157157+namespace app.bsky.richtext.facet {
158158+ model Main { }
159159+}
160160+161161+@external
162162+namespace app.bsky.feed.defs {
163163+ model GeneratorView { }
164164+}
···2233namespace app.bsky.graph.follow {
44 @rec("tid")
55- @doc("Record declaring a social 'follow' relationship of another account. Duplicate follows will be ignored by the AppView.")
55+ /** Record declaring a social 'follow' relationship of another account. Duplicate follows will be ignored by the AppView. */
66 model Main {
77 @required subject: did;
88 @required createdAt: datetime;
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getActorStarterPacks {
44- @doc("Get a list of starter packs created by the actor.")
44+ /** Get a list of starter packs created by the actor. */
55 @query
66 op main(
77 @required actor: atIdentifier,
···1616 @required starterPacks: app.bsky.graph.defs.StarterPackViewBasic[];
1717 };
1818}
1919+2020+// --- Externals ---
2121+2222+@external
2323+namespace app.bsky.graph.defs {
2424+ model StarterPackViewBasic { }
2525+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getKnownFollowers {
44- @doc("Enumerates accounts which follow a specified account (actor) and are followed by the viewer.")
44+ /** Enumerates accounts which follow a specified account (actor) and are followed by the viewer. */
55 @query
66 op main(
77- actor: atIdentifier,
77+ @required actor: atIdentifier,
8899 @minValue(1)
1010 @maxValue(100)
···1717 @required followers: app.bsky.actor.defs.ProfileView[];
1818 };
1919}
2020+2121+// --- Externals ---
2222+2323+@external
2424+namespace app.bsky.actor.defs {
2525+ model ProfileView { }
2626+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getList {
44- @doc("Gets a 'view' (with additional context) of a specified list.")
44+ /** Gets a 'view' (with additional context) of a specified list. */
55 @query
66 op main(
77- @doc("Reference (AT-URI) of the list record to hydrate.")
88- list: atUri,
77+ /** Reference (AT-URI) of the list record to hydrate. */
88+ @required list: atUri,
991010 @minValue(1)
1111 @maxValue(100)
···1818 @required items: app.bsky.graph.defs.ListItemView[];
1919 };
2020}
2121+2222+// --- Externals ---
2323+2424+@external
2525+namespace app.bsky.graph.defs {
2626+ model ListView { }
2727+ model ListItemView { }
2828+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getListsWithMembership {
44- @doc("Enumerates the lists created by the session user, and includes membership information about `actor` in those lists. Only supports curation and moderation lists (no reference lists, used in starter packs). Requires auth.")
44+ /** Enumerates the lists created by the session user, and includes membership information about `actor` in those lists. Only supports curation and moderation lists (no reference lists, used in starter packs). Requires auth. */
55 @query
66 op main(
77- @doc("The account (actor) to check for membership.")
77+ /** The account (actor) to check for membership. */
88 @required
99 actor: atIdentifier,
1010···14141515 cursor?: string,
16161717- @doc("Optional filter by list purpose. If not specified, all supported types are returned.")
1717+ /** Optional filter by list purpose. If not specified, all supported types are returned. */
1818 purposes?: ("modlist" | "curatelist" | string)[]
1919 ): {
2020 cursor?: string;
2121 @required listsWithMembership: ListWithMembership[];
2222 };
23232424- @doc("A list and an optional list item indicating membership of a target user to that list.")
2424+ /** A list and an optional list item indicating membership of a target user to that list. */
2525 model ListWithMembership {
2626 @required list: app.bsky.graph.defs.ListView;
2727 listItem?: app.bsky.graph.defs.ListItemView;
2828 }
2929}
3030+3131+// --- Externals ---
3232+3333+@external
3434+namespace app.bsky.graph.defs {
3535+ model ListView { }
3636+ model ListItemView { }
3737+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getRelationships {
44- @doc("Enumerates public relationships between one account, and a list of other accounts. Does not require auth.")
44+ /** Enumerates public relationships between one account, and a list of other accounts. Does not require auth. */
55 @query
66 @errors(ActorNotFound)
77 op main(
88- @doc("Primary account requesting relationships for.")
88+ /** Primary account requesting relationships for. */
99 @required
1010 actor: atIdentifier,
11111212- @doc("List of 'other' accounts to be related back to the primary.")
1212+ /** List of 'other' accounts to be related back to the primary. */
1313 @maxItems(30)
1414 others?: atIdentifier[]
1515 ): {
···2323 )[];
2424 };
25252626- @doc("the primary actor at-identifier could not be resolved")
2626+ /** the primary actor at-identifier could not be resolved */
2727 model ActorNotFound {}
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace app.bsky.graph.defs {
3434+ model Relationship { }
3535+ model NotFoundActor { }
3636+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getStarterPacks {
44- @doc("Get views for a list of starter packs.")
44+ /** Get views for a list of starter packs. */
55 @query
66 op main(
77 @maxItems(25)
···1111 @required starterPacks: app.bsky.graph.defs.StarterPackViewBasic[];
1212 };
1313}
1414+1515+// --- Externals ---
1616+1717+@external
1818+namespace app.bsky.graph.defs {
1919+ model StarterPackViewBasic { }
2020+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getStarterPacksWithMembership {
44- @doc("Enumerates the starter packs created by the session user, and includes membership information about `actor` in those starter packs. Requires auth.")
44+ /** Enumerates the starter packs created by the session user, and includes membership information about `actor` in those starter packs. Requires auth. */
55 @query
66 op main(
77- @doc("The account (actor) to check for membership.")
77+ /** The account (actor) to check for membership. */
88 @required
99 actor: atIdentifier,
1010···1818 @required starterPacksWithMembership: StarterPackWithMembership[];
1919 };
20202121- @doc("A starter pack and an optional list item indicating membership of a target user to that starter pack.")
2121+ /** A starter pack and an optional list item indicating membership of a target user to that starter pack. */
2222 model StarterPackWithMembership {
2323 @required starterPack: app.bsky.graph.defs.StarterPackView;
2424 listItem?: app.bsky.graph.defs.ListItemView;
2525 }
2626}
2727+2828+// --- Externals ---
2929+3030+@external
3131+namespace app.bsky.graph.defs {
3232+ model StarterPackView { }
3333+ model ListItemView { }
3434+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.getSuggestedFollowsByActor {
44- @doc("Enumerates follows similar to a given account (actor). Expected use is to recommend additional accounts immediately after following one account.")
44+ /** Enumerates follows similar to a given account (actor). Expected use is to recommend additional accounts immediately after following one account. */
55 @query
66 op main(
77- actor: atIdentifier
77+ @required actor: atIdentifier
88 ): {
99 @required
1010 suggestions: app.bsky.actor.defs.ProfileView[];
11111212- @doc("If true, response has fallen-back to generic results, and is not scoped using relativeToDid")
1212+ /** If true, response has fallen-back to generic results, and is not scoped using relativeToDid */
1313 isFallback?: boolean = false;
14141515- @doc("Snowflake for this recommendation, use when submitting recommendation events.")
1515+ /** Snowflake for this recommendation, use when submitting recommendation events. */
1616 recId?: int32;
1717 };
1818}
1919+2020+// --- Externals ---
2121+2222+@external
2323+namespace app.bsky.actor.defs {
2424+ model ProfileView { }
2525+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.list {
44- @doc("Record representing a list of accounts (actors). Scope includes both moderation-oriented lists and curration-oriented lists.")
44+ /** Record representing a list of accounts (actors). Scope includes both moderation-oriented lists and curration-oriented lists. */
55 @rec("tid")
66 model Main {
77- @doc("Display name for list; can not be empty.")
77+ /** Display name for list; can not be empty. */
88 @minLength(1)
99 @maxLength(64)
1010 @required
1111 name: string;
12121313- @doc("Defines the purpose of the list (aka, moderation-oriented or curration-oriented)")
1313+ /** Defines the purpose of the list (aka, moderation-oriented or curration-oriented) */
1414 @required
1515 purpose: app.bsky.graph.defs.ListPurpose;
1616···2727 @required createdAt: datetime;
2828 }
2929}
3030+3131+// --- Externals ---
3232+3333+@external
3434+namespace app.bsky.graph.defs {
3535+ model ListPurpose { }
3636+}
3737+3838+@external
3939+namespace app.bsky.richtext.facet {
4040+ model Main { }
4141+}
4242+4343+@external
4444+namespace com.atproto.label.defs {
4545+ model SelfLabels { }
4646+}
···2233namespace app.bsky.graph.listblock {
44 @rec("tid")
55- @doc("Record representing a block relationship against an entire an entire list of accounts (actors).")
55+ /** Record representing a block relationship against an entire an entire list of accounts (actors). */
66 model Main {
77- @doc("Reference (AT-URI) to the mod list record.")
77+ /** Reference (AT-URI) to the mod list record. */
88 @required
99 subject: atUri;
1010
···2233namespace app.bsky.graph.listitem {
44 @rec("tid")
55- @doc("Record representing an account's inclusion on a specific list. The AppView will ignore duplicate listitem records.")
55+ /** Record representing an account's inclusion on a specific list. The AppView will ignore duplicate listitem records. */
66 model Main {
77- @doc("The account which is included on the list.")
77+ /** The account which is included on the list. */
88 @required
99 subject: did;
10101111- @doc("Reference (AT-URI) to the list record (app.bsky.graph.list).")
1111+ /** Reference (AT-URI) to the list record (app.bsky.graph.list). */
1212 @required
1313 list: atUri;
1414
···11import "@typelex/emitter";
2233namespace app.bsky.graph.muteActor {
44- @doc("Creates a mute relationship for the specified account. Mutes are private in Bluesky. Requires auth.")
44+ /** Creates a mute relationship for the specified account. Mutes are private in Bluesky. Requires auth. */
55 @procedure
66 op main(input: {
77 @required actor: atIdentifier;
···11import "@typelex/emitter";
2233namespace app.bsky.graph.muteActorList {
44- @doc("Creates a mute relationship for the specified list of accounts. Mutes are private in Bluesky. Requires auth.")
44+ /** Creates a mute relationship for the specified list of accounts. Mutes are private in Bluesky. Requires auth. */
55 @procedure
66 op main(input: {
77 @required list: atUri;
···11import "@typelex/emitter";
2233namespace app.bsky.graph.muteThread {
44- @doc("Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. Requires auth.")
44+ /** Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. Requires auth. */
55 @procedure
66 op main(input: {
77 @required root: atUri;
···2233namespace app.bsky.graph.starterpack {
44 @rec("tid")
55- @doc("Record defining a starter pack of actors and feeds for new users.")
55+ /** Record defining a starter pack of actors and feeds for new users. */
66 model Main {
77- @doc("Display name for starter pack; can not be empty.")
77+ /** Display name for starter pack; can not be empty. */
88 @minLength(1)
99 @maxLength(500)
1010 @maxGraphemes(50)
···17171818 descriptionFacets?: app.bsky.richtext.facet.Main[];
19192020- @doc("Reference (AT-URI) to the list record.")
2020+ /** Reference (AT-URI) to the list record. */
2121 @required
2222 list: atUri;
2323···3333 uri: atUri;
3434 }
3535}
3636+3737+// --- Externals ---
3838+3939+@external
4040+namespace app.bsky.richtext.facet {
4141+ model Main { }
4242+}
···11import "@typelex/emitter";
2233namespace app.bsky.graph.unmuteActorList {
44- @doc("Unmutes the specified list of accounts. Requires auth.")
44+ /** Unmutes the specified list of accounts. Requires auth. */
55 @procedure
66 op main(input: {
77 @required list: atUri;
···2233namespace app.bsky.graph.verification {
44 @rec("tid")
55- @doc("Record declaring a verification relationship between two accounts. Verifications are only considered valid by an app if issued by an account the app considers trusted.")
55+ /** Record declaring a verification relationship between two accounts. Verifications are only considered valid by an app if issued by an account the app considers trusted. */
66 model Main {
77- @doc("DID of the subject the verification applies to.")
77+ /** DID of the subject the verification applies to. */
88 @required
99 subject: did;
10101111- @doc("Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying.")
1111+ /** Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying. */
1212 @required
1313 handle: handle;
14141515- @doc("Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying.")
1515+ /** Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying. */
1616 @required
1717 displayName: string;
18181919- @doc("Date of when the verification was created.")
1919+ /** Date of when the verification was created. */
2020 @required
2121 createdAt: datetime;
2222 }
···31313232 labels?: com.atproto.label.defs.Label[];
33333434- @doc("The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed.")
3434+ /** The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed. */
3535 reasonTypes?: com.atproto.moderation.defs.ReasonType[];
36363737- @doc("The set of subject types (account, record, etc) this service accepts reports on.")
3737+ /** The set of subject types (account, record, etc) this service accepts reports on. */
3838 subjectTypes?: com.atproto.moderation.defs.SubjectType[];
39394040- @doc("Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type.")
4040+ /** Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type. */
4141 subjectCollections?: nsid[];
4242 }
4343···4646 }
47474848 model LabelerPolicies {
4949- @doc("The label values which this labeler publishes. May include global or custom labels.")
4949+ /** The label values which this labeler publishes. May include global or custom labels. */
5050 @required
5151 labelValues: com.atproto.label.defs.LabelValue[];
52525353- @doc("Label values created by this labeler and scoped exclusively to it. Labels defined here will override global label definitions for this labeler.")
5353+ /** Label values created by this labeler and scoped exclusively to it. Labels defined here will override global label definitions for this labeler. */
5454 labelValueDefinitions?: com.atproto.label.defs.LabelValueDefinition[];
5555 }
5656}
5757+5858+// --- Externals ---
5959+6060+@external
6161+namespace app.bsky.actor.defs {
6262+ model ProfileView { }
6363+}
6464+6565+@external
6666+namespace com.atproto.label.defs {
6767+ model Label { }
6868+ model LabelValue { }
6969+ model LabelValueDefinition { }
7070+}
7171+7272+@external
7373+namespace com.atproto.moderation.defs {
7474+ model ReasonType { }
7575+ model SubjectType { }
7676+}
···11import "@typelex/emitter";
2233namespace app.bsky.labeler.getServices {
44- @doc("Get information about a list of labeler services.")
44+ /** Get information about a list of labeler services. */
55 @query
66 op main(
77 @required dids: did[],
···1515 )[];
1616 };
1717}
1818+1919+// --- Externals ---
2020+2121+@external
2222+namespace app.bsky.labeler.defs {
2323+ model LabelerView { }
2424+ model LabelerViewDetailed { }
2525+}
···11import "@typelex/emitter";
2233namespace app.bsky.labeler.service {
44- @doc("A declaration of the existence of labeler service.")
44+ /** A declaration of the existence of labeler service. */
55 @rec("literal:self")
66 model Main {
77 @required policies: app.bsky.labeler.defs.LabelerPolicies;
···10101111 @required createdAt: datetime;
12121313- @doc("The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed.")
1313+ /** The set of report reason 'codes' which are in-scope for this service to review and action. These usually align to policy categories. If not defined (distinct from empty array), all reason types are allowed. */
1414 reasonTypes?: com.atproto.moderation.defs.ReasonType[];
15151616- @doc("The set of subject types (account, record, etc) this service accepts reports on.")
1616+ /** The set of subject types (account, record, etc) this service accepts reports on. */
1717 subjectTypes?: com.atproto.moderation.defs.SubjectType[];
18181919- @doc("Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type.")
1919+ /** Set of record types (collection NSIDs) which can be reported to this service. If not defined (distinct from empty array), default is any record type. */
2020 subjectCollections?: nsid[];
2121 }
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace app.bsky.labeler.defs {
2828+ model LabelerPolicies { }
2929+}
3030+3131+@external
3232+namespace com.atproto.label.defs {
3333+ model SelfLabels { }
3434+}
3535+3636+@external
3737+namespace com.atproto.moderation.defs {
3838+ model ReasonType { }
3939+ model SubjectType { }
4040+}
···2233namespace app.bsky.notification.declaration {
44 @rec("literal:self")
55- @doc("A declaration of the user's choices related to notifications that can be produced by them.")
55+ /** A declaration of the user's choices related to notifications that can be produced by them. */
66 model Main {
77- @doc("A declaration of the user's preference for allowing activity subscriptions from other users. Absence of a record implies 'followers'.")
77+ /** A declaration of the user's preference for allowing activity subscriptions from other users. Absence of a record implies 'followers'. */
88 @required
99 allowSubscriptions: "followers" | "mutuals" | "none" | string;
1010 }
···4040 @required reply: boolean;
4141 }
42424343- @doc("Object used to store activity subscription data in stash.")
4343+ /** Object used to store activity subscription data in stash. */
4444 model SubjectActivitySubscription {
4545 @required subject: did;
4646 @required activitySubscription: ActivitySubscription;
···11import "@typelex/emitter";
2233namespace app.bsky.notification.getUnreadCount {
44- @doc("Count the number of unread notifications for the requesting account. Requires auth.")
44+ /** Count the number of unread notifications for the requesting account. Requires auth. */
55 @query
66 op main(
77 priority?: boolean,
···11import "@typelex/emitter";
2233namespace app.bsky.notification.listActivitySubscriptions {
44- @doc("Enumerate all accounts to which the requesting account is subscribed to receive notifications for. Requires auth.")
44+ /** Enumerate all accounts to which the requesting account is subscribed to receive notifications for. Requires auth. */
55 @query
66 op main(
77 @minValue(1)
···1414 @required subscriptions: app.bsky.actor.defs.ProfileView[];
1515 };
1616}
1717+1818+// --- Externals ---
1919+2020+@external
2121+namespace app.bsky.actor.defs {
2222+ model ProfileView { }
2323+}
···11import "@typelex/emitter";
2233-@doc("A reason that matches the reason property of #notification.")
33+/** A reason that matches the reason property of #notification. */
44scalar ReasonString extends string;
5566namespace app.bsky.notification.listNotifications {
77- @doc("Enumerate notifications for the requesting account. Requires auth.")
77+ /** Enumerate notifications for the requesting account. Requires auth. */
88 @query
99 op main(
1010- @doc("Notification reasons to include in response.")
1010+ /** Notification reasons to include in response. */
1111 reasons?: ReasonString[],
12121313 @minValue(1)
···2929 @required cid: cid;
3030 @required author: app.bsky.actor.defs.ProfileView;
31313232- @doc("The reason why this notification was delivered - e.g. your post was liked, or you received a new follower.")
3232+ /** The reason why this notification was delivered - e.g. your post was liked, or you received a new follower. */
3333 @required
3434 reason: "like" | "repost" | "follow" | "mention" | "reply" | "quote" | "starterpack-joined" | "verified" | "unverified" | "like-via-repost" | "repost-via-repost" | "subscribed-post" | string;
3535···4040 labels?: com.atproto.label.defs.Label[];
4141 };
4242}
4343+4444+// --- Externals ---
4545+4646+@external
4747+namespace app.bsky.actor.defs {
4848+ model ProfileView { }
4949+}
5050+5151+@external
5252+namespace com.atproto.label.defs {
5353+ model Label { }
5454+}
···11import "@typelex/emitter";
2233namespace app.bsky.notification.putActivitySubscription {
44- @doc("Puts an activity subscription entry. The key should be omitted for creation and provided for updates. Requires auth.")
44+ /** Puts an activity subscription entry. The key should be omitted for creation and provided for updates. Requires auth. */
55 @procedure
66 op main(input: {
77 @required subject: did;
···1313 activitySubscription?: app.bsky.notification.defs.ActivitySubscription;
1414 };
1515}
1616+1717+// --- Externals ---
1818+1919+@external
2020+namespace app.bsky.notification.defs {
2121+ model ActivitySubscription { }
2222+}
···11import "@typelex/emitter";
2233namespace app.bsky.notification.registerPush {
44- @doc("Register to receive push notifications, via a specified service, for the requesting account. Requires auth.")
44+ /** Register to receive push notifications, via a specified service, for the requesting account. Requires auth. */
55 @procedure
66 op main(input: {
77 @required serviceDid: did;
···99 @required platform: "ios" | "android" | "web" | string;
1010 @required appId: string;
11111212- @doc("Set to true when the actor is age restricted")
1212+ /** Set to true when the actor is age restricted */
1313 ageRestricted?: boolean;
1414 }): void;
1515}
···11import "@typelex/emitter";
2233namespace app.bsky.notification.unregisterPush {
44- @doc("The inverse of registerPush - inform a specified service that push notifications should no longer be sent to the given token for the requesting account. Requires auth.")
44+ /** The inverse of registerPush - inform a specified service that push notifications should no longer be sent to the given token for the requesting account. Requires auth. */
55 @procedure
66 op main(input: {
77 @required serviceDid: did;
···11import "@typelex/emitter";
2233namespace app.bsky.notification.updateSeen {
44- @doc("Notify server that the requesting account has seen notifications. Requires auth.")
44+ /** Notify server that the requesting account has seen notifications. Requires auth. */
55 @procedure
66 op main(input: {
77 @required seenAt: datetime;
···11import "@typelex/emitter";
2233namespace app.bsky.richtext.facet {
44- @doc("Annotation of a sub-string within rich text.")
44+ /** Annotation of a sub-string within rich text. */
55 model Main {
66 @required index: ByteSlice;
7788 @required features: (Mention | Link | Tag | unknown)[];
99 }
10101111- @doc("Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.")
1111+ /** Facet feature for mention of another account. The text is usually a handle, including a `@` prefix, but the facet reference is a DID. */
1212 model Mention {
1313 @required did: did;
1414 }
15151616- @doc("Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.")
1616+ /** Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. */
1717 model Link {
1818 @required uri: uri;
1919 }
20202121- @doc("Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').")
2121+ /** Facet feature for a hashtag. The text usually includes a `#` prefix, but the facet reference should not (except in the case of 'double hash tags'). */
2222 model Tag {
2323 @maxLength(640)
2424 @maxGraphemes(64)
···2626 tag: string;
2727 }
28282929- @doc("Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.")
2929+ /** Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets. */
3030 model ByteSlice {
3131 @minValue(0)
3232 @required
···4545 model ThreadItemPost {
4646 @required post: app.bsky.feed.defs.PostView;
47474848- @doc("This post has more parents that were not present in the response. This is just a boolean, without the number of parents.")
4848+ /** 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;
51515252- @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.")
5252+ /** 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;
55555656- @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.")
5656+ /** 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;
59596060- @doc("The threadgate created by the author indicates this post as a reply to be hidden for everyone consuming the thread.")
6060+ /** 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;
63636464- @doc("This is by an account muted by the viewer requesting it.")
6464+ /** This is by an account muted by the viewer requesting it. */
6565 @required
6666 mutedByViewer: boolean;
6767 }
···7474 @required author: app.bsky.feed.defs.BlockedAuthor;
7575 }
76767777- @doc("The computed state of the age assurance process, returned to the user in question on certain authenticated requests.")
7777+ /** 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.")
7979+ /** The timestamp when this state was last updated. */
8080 lastInitiatedAt?: datetime;
81818282- @doc("The status of the age assurance process.")
8282+ /** The status of the age assurance process. */
8383 @required
8484 status: "unknown" | "pending" | "assured" | "blocked" | string;
8585 }
86868787- @doc("Object used to store age assurance data in stash.")
8787+ /** Object used to store age assurance data in stash. */
8888 model AgeAssuranceEvent {
8989- @doc("The date and time of this write operation.")
8989+ /** The date and time of this write operation. */
9090 @required
9191 createdAt: datetime;
92929393- @doc("The status of the age assurance process.")
9393+ /** The status of the age assurance process. */
9494 @required
9595 status: "unknown" | "pending" | "assured" | string;
96969797- @doc("The unique identifier for this instance of the age assurance flow, in UUID format.")
9797+ /** The unique identifier for this instance of the age assurance flow, in UUID format. */
9898 @required
9999 attemptId: string;
100100101101- @doc("The email used for AA.")
101101+ /** The email used for AA. */
102102 email?: string;
103103104104- @doc("The IP address used when initiating the AA flow.")
104104+ /** The IP address used when initiating the AA flow. */
105105 initIp?: string;
106106107107- @doc("The user agent used when initiating the AA flow.")
107107+ /** The user agent used when initiating the AA flow. */
108108 initUa?: string;
109109110110- @doc("The IP address used when completing the AA flow.")
110110+ /** The IP address used when completing the AA flow. */
111111 completeIp?: string;
112112113113- @doc("The user agent used when completing the AA flow.")
113113+ /** The user agent used when completing the AA flow. */
114114 completeUa?: string;
115115 }
116116}
117117+118118+// --- Externals ---
119119+120120+@external
121121+namespace app.bsky.actor.defs {
122122+ model ProfileViewBasic { }
123123+}
124124+125125+@external
126126+namespace app.bsky.feed.defs {
127127+ model PostView { }
128128+ model BlockedAuthor { }
129129+}
···11import "@typelex/emitter";
2233namespace 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.")
44+ /** 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}
88+99+// --- Externals ---
1010+1111+@external
1212+namespace app.bsky.unspecced.defs {
1313+ model AgeAssuranceState { }
1414+}
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getOnboardingSuggestedStarterPacks {
44- @doc("Get a list of suggested starterpacks for onboarding")
44+ /** Get a list of suggested starterpacks for onboarding */
55 @query
66 op main(
77 @minValue(1)
···1111 @required starterPacks: app.bsky.graph.defs.StarterPackView[];
1212 };
1313}
1414+1515+// --- Externals ---
1616+1717+@external
1818+namespace app.bsky.graph.defs {
1919+ model StarterPackView { }
2020+}
···11import "@typelex/emitter";
2233namespace 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")
44+ /** 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).")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). */
88 viewer?: did,
991010 @minValue(1)
···11import "@typelex/emitter";
2233namespace 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.")
44+ /** (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.")
77+ /** Reference (AT-URI) to post record. This is the anchor post. */
88 @required
99 anchor: atUri,
10101111- @doc("Whether to prioritize posts from followed users. It only has effect when the user is authenticated.")
1111+ /** 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.")
1414+ /** 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 };
···1919 model ThreadItem {
2020 @required uri: atUri;
21212222- @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.")
2222+ /** 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;
25252626 @required value: (app.bsky.unspecced.defs.ThreadItemPost | unknown);
2727 }
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace app.bsky.unspecced.defs {
3434+ model ThreadItemPost { }
3535+}
···11import "@typelex/emitter";
2233namespace 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.")
44+ /** (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.")
77+ /** 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,
10101111- @doc("Whether to include parents above the anchor.")
1111+ /** Whether to include parents above the anchor. */
1212 above?: boolean = true,
13131414- @doc("How many levels of replies to include below the anchor.")
1414+ /** How many levels of replies to include below the anchor. */
1515 @minValue(0)
1616 @maxValue(20)
1717 below?: int32 = 6,
18181919- @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).")
1919+ /** 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,
23232424- @doc("Whether to prioritize posts from followed users. It only has effect when the user is authenticated.")
2424+ /** Whether to prioritize posts from followed users. It only has effect when the user is authenticated. */
2525 prioritizeFollowedUsers?: boolean = false,
26262727- @doc("Sorting for the thread replies.")
2727+ /** 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.")
3030+ /** 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[];
33333434 threadgate?: app.bsky.feed.defs.ThreadgateView;
35353636- @doc("Whether this thread has additional replies. If true, a call can be made to the `getPostThreadOtherV2` endpoint to retrieve them.")
3636+ /** 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 };
···4141 model ThreadItem {
4242 @required uri: atUri;
43434444- @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.")
4444+ /** 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···5555 );
5656 }
5757}
5858+5959+// --- Externals ---
6060+6161+@external
6262+namespace app.bsky.feed.defs {
6363+ model ThreadgateView { }
6464+}
6565+6666+@external
6767+namespace app.bsky.unspecced.defs {
6868+ model ThreadItemPost { }
6969+ model ThreadItemNoUnauthenticated { }
7070+ model ThreadItemNotFound { }
7171+ model ThreadItemBlocked { }
7272+}
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getSuggestedFeedsSkeleton {
44- @doc("Get a skeleton of suggested feeds. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedFeeds")
44+ /** 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).")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). */
88 viewer?: did,
991010 @minValue(1)
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getSuggestedStarterPacksSkeleton {
44- @doc("Get a skeleton of suggested starterpacks. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedStarterpacks")
44+ /** 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).")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). */
88 viewer?: did,
991010 @minValue(1)
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getSuggestedUsers {
44- @doc("Get a list of suggested users")
44+ /** Get a list of suggested users */
55 @query
66 op main(
77- @doc("Category of users to get suggestions for.")
77+ /** Category of users to get suggestions for. */
88 category?: string,
991010 @minValue(1)
···1414 @required actors: app.bsky.actor.defs.ProfileView[];
1515 };
1616}
1717+1818+// --- Externals ---
1919+2020+@external
2121+namespace app.bsky.actor.defs {
2222+ model ProfileView { }
2323+}
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getSuggestedUsersSkeleton {
44- @doc("Get a skeleton of suggested users. Intended to be called and hydrated by app.bsky.unspecced.getSuggestedUsers")
44+ /** 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).")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). */
88 viewer?: did,
991010- @doc("Category of users to get suggestions for.")
1010+ /** Category of users to get suggestions for. */
1111 category?: string,
12121313 @minValue(1)
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getSuggestionsSkeleton {
44- @doc("Get a skeleton of suggested actors. Intended to be called and then hydrated through app.bsky.actor.getSuggestions")
44+ /** 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.")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
88 viewer?: did,
991010 @minValue(1)
···13131414 cursor?: string,
15151616- @doc("DID of the account to get suggestions relative to. If not provided, suggestions will be based on the viewer.")
1616+ /** 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[];
21212222- @doc("DID of the account these suggestions are relative to. If this is returned undefined, suggestions are based on the viewer.")
2222+ /** DID of the account these suggestions are relative to. If this is returned undefined, suggestions are based on the viewer. */
2323 relativeToDid?: did;
24242525- @doc("Snowflake for this recommendation, use when submitting recommendation events.")
2525+ /** Snowflake for this recommendation, use when submitting recommendation events. */
2626 recId?: integer;
2727 };
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace app.bsky.unspecced.defs {
3434+ model SkeletonSearchActor { }
3535+}
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getTaggedSuggestions {
44- @doc("Get a list of suggestions (feeds and users) tagged with categories")
44+ /** Get a list of suggestions (feeds and users) tagged with categories */
55 @query
66 op main(): {
77 @required suggestions: Suggestion[];
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getTrendingTopics {
44- @doc("Get a list of trending topics")
44+ /** 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.")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
88 viewer?: did,
991010 @minValue(1)
···1515 @required suggested: app.bsky.unspecced.defs.TrendingTopic[];
1616 };
1717}
1818+1919+// --- Externals ---
2020+2121+@external
2222+namespace app.bsky.unspecced.defs {
2323+ model TrendingTopic { }
2424+}
···11import "@typelex/emitter";
2233namespace app.bsky.unspecced.getTrends {
44- @doc("Get the current trends on the network")
44+ /** Get the current trends on the network */
55 @query
66 op main(
77 @minValue(1)
···1111 @required trends: app.bsky.unspecced.defs.TrendView[];
1212 };
1313}
1414+1515+// --- Externals ---
1616+1717+@external
1818+namespace app.bsky.unspecced.defs {
1919+ model TrendView { }
2020+}
···11import "@typelex/emitter";
2233namespace 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")
44+ /** 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).")
77+ /** DID of the account making the request (not included for public/unauthenticated queries). */
88 viewer?: did,
991010 @minValue(1)
···1414 @required trends: app.bsky.unspecced.defs.SkeletonTrend[];
1515 };
1616}
1717+1818+// --- Externals ---
1919+2020+@external
2121+namespace app.bsky.unspecced.defs {
2222+ model SkeletonTrend { }
2323+}
···55 model DidTooLong {}
66 model InvalidInitiation {}
7788- @doc("Initiate age assurance for an account. This is a one-time action that will start the process of verifying the user's age.")
88+ /** 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.")
1212+ /** The user's email address to receive assurance instructions. */
1313 @required
1414 email: string;
15151616- @doc("The user's preferred language for communication during the assurance process.")
1616+ /** The user's preferred language for communication during the assurance process. */
1717 @required
1818 language: string;
19192020- @doc("An ISO 3166-1 alpha-2 code of the user's location.")
2020+ /** An ISO 3166-1 alpha-2 code of the user's location. */
2121 @required
2222 countryCode: string;
2323 }): app.bsky.unspecced.defs.AgeAssuranceState;
2424}
2525+2626+// --- Externals ---
2727+2828+@external
2929+namespace app.bsky.unspecced.defs {
3030+ model AgeAssuranceState { }
3131+}
···33namespace app.bsky.unspecced.searchActorsSkeleton {
44 model BadQueryString {}
5566- @doc("Backend Actors (profile) search, returns only skeleton.")
66+ /** Backend Actors (profile) search, returns only skeleton. */
77 @query
88 @errors(BadQueryString)
99 op main(
1010- @doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax.")
1111- q: string,
1010+ /** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. For typeahead search, only simple term match is supported, not full syntax. */
1111+ @required q: string,
12121313- @doc("DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking.")
1313+ /** DID of the account making the request (not included for public/unauthenticated queries). Used to boost followed accounts in ranking. */
1414 viewer?: did,
15151616- @doc("If true, acts as fast/simple 'typeahead' query.")
1616+ /** If true, acts as fast/simple 'typeahead' query. */
1717 typeahead?: boolean,
18181919 @minValue(1)
2020 @maxValue(100)
2121 limit?: integer = 25,
22222323- @doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
2323+ /** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
2424 cursor?: string
2525 ): {
2626 cursor?: string;
27272828- @doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
2828+ /** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
2929 hitsTotal?: integer;
30303131 @required actors: app.bsky.unspecced.defs.SkeletonSearchActor[];
3232 };
3333}
3434+3535+// --- Externals ---
3636+3737+@external
3838+namespace app.bsky.unspecced.defs {
3939+ model SkeletonSearchActor { }
4040+}
···77namespace app.bsky.unspecced.searchPostsSkeleton {
88 model BadQueryString {}
991010- @doc("Backend Posts search, returns only skeleton")
1010+ /** Backend Posts search, returns only skeleton */
1111 @query
1212 @errors(BadQueryString)
1313 op main(
1414- @doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
1515- q: string,
1414+ /** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
1515+ @required q: string,
16161717- @doc("Specifies the ranking order of results.")
1717+ /** Specifies the ranking order of results. */
1818 sort?: "top" | "latest" | string = "latest",
19192020- @doc("Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD).")
2020+ /** Filter results for posts after the indicated datetime (inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYYY-MM-DD). */
2121 since?: string,
22222323- @doc("Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD).")
2323+ /** Filter results for posts before the indicated datetime (not inclusive). Expected to use 'sortAt' timestamp, which may not match 'createdAt'. Can be a datetime, or just an ISO date (YYY-MM-DD). */
2424 until?: string,
25252626- @doc("Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions.")
2626+ /** Filter to posts which mention the given account. Handles are resolved to DID before query-time. Only matches rich-text facet mentions. */
2727 mentions?: atIdentifier,
28282929- @doc("Filter to posts by the given account. Handles are resolved to DID before query-time.")
2929+ /** Filter to posts by the given account. Handles are resolved to DID before query-time. */
3030 author?: atIdentifier,
31313232- @doc("Filter to posts in the given language. Expected to be based on post language field, though server may override language detection.")
3232+ /** Filter to posts in the given language. Expected to be based on post language field, though server may override language detection. */
3333 lang?: language,
34343535- @doc("Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization.")
3535+ /** Filter to posts with URLs (facet links or embeds) linking to the given domain (hostname). Server may apply hostname normalization. */
3636 domain?: string,
37373838- @doc("Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching.")
3838+ /** Filter to posts with links (facet links or embeds) pointing to this URL. Server may apply URL normalization or fuzzy matching. */
3939 url?: uri,
40404141- @doc("Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching.")
4141+ /** Filter to posts with the given tag (hashtag), based on rich-text facet or tag field. Do not include the hash (#) prefix. Multiple tags can be specified, with 'AND' matching. */
4242 tag?: SkeletonSearchTagString[],
43434444- @doc("DID of the account making the request (not included for public/unauthenticated queries). Used for 'from:me' queries.")
4444+ /** DID of the account making the request (not included for public/unauthenticated queries). Used for 'from:me' queries. */
4545 viewer?: did,
46464747 @minValue(1)
4848 @maxValue(100)
4949 limit?: integer = 25,
50505151- @doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
5151+ /** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
5252 cursor?: string
5353 ): {
5454 cursor?: string;
55555656- @doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
5656+ /** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
5757 hitsTotal?: integer;
58585959 @required posts: app.bsky.unspecced.defs.SkeletonSearchPost[];
6060 };
6161}
6262+6363+// --- Externals ---
6464+6565+@external
6666+namespace app.bsky.unspecced.defs {
6767+ model SkeletonSearchPost { }
6868+}
···33namespace app.bsky.unspecced.searchStarterPacksSkeleton {
44 model BadQueryString {}
5566- @doc("Backend Starter Pack search, returns only skeleton.")
66+ /** Backend Starter Pack search, returns only skeleton. */
77 @query
88 @errors(BadQueryString)
99 op main(
1010- @doc("Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.")
1111- q: string,
1010+ /** Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended. */
1111+ @required q: string,
12121313- @doc("DID of the account making the request (not included for public/unauthenticated queries).")
1313+ /** DID of the account making the request (not included for public/unauthenticated queries). */
1414 viewer?: did,
15151616 @minValue(1)
1717 @maxValue(100)
1818 limit?: integer = 25,
19192020- @doc("Optional pagination mechanism; may not necessarily allow scrolling through entire result set.")
2020+ /** Optional pagination mechanism; may not necessarily allow scrolling through entire result set. */
2121 cursor?: string
2222 ): {
2323 cursor?: string;
24242525- @doc("Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits.")
2525+ /** Count of search hits. Optional, may be rounded/truncated, and may not be possible to paginate through all hits. */
2626 hitsTotal?: integer;
27272828 @required starterPacks: app.bsky.unspecced.defs.SkeletonSearchStarterPack[];
2929 };
3030}
3131+3232+// --- Externals ---
3333+3434+@external
3535+namespace app.bsky.unspecced.defs {
3636+ model SkeletonSearchStarterPack { }
3737+}
···55 @required jobId: string;
66 @required did: did;
7788- @doc("The state of the video processing job. All values not listed as a known value indicate that the job is in process.")
88+ /** The state of the video processing job. All values not listed as a known value indicate that the job is in process. */
99 @required
1010 state: "JOB_STATE_COMPLETED" | "JOB_STATE_FAILED" | string;
11111212- @doc("Progress within the current processing state.")
1212+ /** Progress within the current processing state. */
1313 @minValue(0)
1414 @maxValue(100)
1515 progress?: integer;
···11import "@typelex/emitter";
2233namespace app.bsky.video.getJobStatus {
44- @doc("Get status details for a video processing job.")
44+ /** Get status details for a video processing job. */
55 @query
66 op main(
77 @required jobId: string
···99 @required jobStatus: app.bsky.video.defs.JobStatus;
1010 };
1111}
1212+1313+// --- Externals ---
1414+1515+@external
1616+namespace app.bsky.video.defs {
1717+ model JobStatus { }
1818+}
···11import "@typelex/emitter";
2233namespace app.bsky.video.getUploadLimits {
44- @doc("Get video upload limits for the authenticated user.")
44+ /** Get video upload limits for the authenticated user. */
55 @query
66 op main(): {
77 @required canUpload: boolean;
···11import "@typelex/emitter";
2233namespace app.bsky.video.uploadVideo {
44- @doc("Upload a video to be processed then stored on the PDS.")
44+ /** Upload a video to be processed then stored on the PDS. */
55 @procedure
66 op main(
77 @encoding("video/mp4")
···1010 @required jobStatus: app.bsky.video.defs.JobStatus;
1111 };
1212}
1313+1414+// --- Externals ---
1515+1616+@external
1717+namespace app.bsky.video.defs {
1818+ model JobStatus { }
1919+}
···1414 viewer?: app.bsky.actor.defs.ViewerState;
1515 labels?: com.atproto.label.defs.Label[];
16161717- @doc("Set to true when the actor cannot actively participate in conversations")
1717+ /** Set to true when the actor cannot actively participate in conversations */
1818 chatDisabled?: boolean;
19192020 verification?: app.bsky.actor.defs.VerificationState;
2121 }
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace app.bsky.actor.defs {
2828+ model ProfileAssociated { }
2929+ model ViewerState { }
3030+ model VerificationState { }
3131+}
3232+3333+@external
3434+namespace com.atproto.label.defs {
3535+ model Label { }
3636+}
···55 op main(input: {
66 @required convoId: string;
77 }): {
88- @doc("Rev when the convo was accepted. If not present, the convo was already accepted.")
88+ /** Rev when the convo was accepted. If not present, the convo was already accepted. */
99 rev?: string;
1010 };
1111}
···11import "@typelex/emitter";
2233namespace chat.bsky.convo.addReaction {
44- @doc("Indicates that the message has been deleted and reactions can no longer be added/removed.")
44+ /** Indicates that the message has been deleted and reactions can no longer be added/removed. */
55 model ReactionMessageDeleted {}
6677- @doc("Indicates that the message has the maximum number of reactions allowed for a single user, and the requested reaction wasn't yet present. If it was already present, the request will not fail since it is idempotent.")
77+ /** Indicates that the message has the maximum number of reactions allowed for a single user, and the requested reaction wasn't yet present. If it was already present, the request will not fail since it is idempotent. */
88 model ReactionLimitReached {}
991010- @doc("Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.")
1010+ /** Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji. */
1111 model ReactionInvalidValue {}
12121313- @doc("Adds an emoji reaction to a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in a single reaction.")
1313+ /** Adds an emoji reaction to a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in a single reaction. */
1414 @procedure
1515 @errors(ReactionMessageDeleted, ReactionLimitReached, ReactionInvalidValue)
1616 op main(input: {
···2727 @required message: chat.bsky.convo.defs.MessageView;
2828 };
2929}
3030+3131+// --- Externals ---
3232+3333+@external
3434+namespace chat.bsky.convo.defs {
3535+ model MessageView { }
3636+}
···11import "@typelex/emitter";
2233namespace chat.bsky.convo.getConvoAvailability {
44- @doc("Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned.")
44+ /** Get whether the requester and the other members can chat. If an existing convo is found for these members, it is returned. */
55 @query
66 op main(
77 @minItems(1)
···1313 convo?: chat.bsky.convo.defs.ConvoView;
1414 };
1515}
1616+1717+// --- Externals ---
1818+1919+@external
2020+namespace chat.bsky.convo.defs {
2121+ model ConvoView { }
2222+}
···11import "@typelex/emitter";
2233namespace chat.bsky.convo.removeReaction {
44- @doc("Indicates that the message has been deleted and reactions can no longer be added/removed.")
44+ /** Indicates that the message has been deleted and reactions can no longer be added/removed. */
55 model ReactionMessageDeleted {}
6677- @doc("Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji.")
77+ /** Indicates the value for the reaction is not acceptable. In general, this means it is not an emoji. */
88 model ReactionInvalidValue {}
991010- @doc("Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't.")
1010+ /** Removes an emoji reaction from a message. Requires authentication. It is idempotent, so multiple calls from the same user with the same emoji result in that reaction not being present, even if it already wasn't. */
1111 @procedure
1212 @errors(ReactionMessageDeleted, ReactionInvalidValue)
1313 op main(input: {
···2424 @required message: chat.bsky.convo.defs.MessageView;
2525 };
2626}
2727+2828+// --- Externals ---
2929+3030+@external
3131+namespace chat.bsky.convo.defs {
3232+ model MessageView { }
3333+}
···33namespace chat.bsky.moderation.getMessageContext {
44 @query
55 op main(
66- @doc("Conversation that the message is from. NOTE: this field will eventually be required.")
66+ /** Conversation that the message is from. NOTE: this field will eventually be required. */
77 convoId?: string,
8899 @required messageId: string,
···2020 )[];
2121 };
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace chat.bsky.convo.defs {
2828+ model MessageView { }
2929+ model DeletedMessageView { }
3030+}
···11import "@typelex/emitter";
2233namespace com.atproto.admin.deleteAccount {
44- @doc("Delete a user account as an administrator.")
44+ /** Delete a user account as an administrator. */
55 @procedure
66 op main(input: {
77 @required did: did;
···11import "@typelex/emitter";
2233namespace com.atproto.admin.disableAccountInvites {
44- @doc("Disable an account from receiving new invite codes, but does not invalidate existing codes.")
44+ /** Disable an account from receiving new invite codes, but does not invalidate existing codes. */
55 @procedure
66 op main(input: {
77 @required account: did;
8899- @doc("Optional reason for disabled invites.")
99+ /** Optional reason for disabled invites. */
1010 note?: string;
1111 }): void;
1212}
···11import "@typelex/emitter";
2233namespace com.atproto.admin.disableInviteCodes {
44- @doc("Disable some set of codes and/or all codes associated with a set of users.")
44+ /** Disable some set of codes and/or all codes associated with a set of users. */
55 @procedure
66 op main(input: {
77 codes?: string[];
···11import "@typelex/emitter";
2233namespace com.atproto.admin.getSubjectStatus {
44- @doc("Get the service-specific admin status of a subject (account, record, or blob).")
44+ /** Get the service-specific admin status of a subject (account, record, or blob). */
55 @query
66 op main(
77 did?: did,
···2020 deactivated?: com.atproto.admin.defs.StatusAttr;
2121 };
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace com.atproto.admin.defs {
2828+ model RepoRef { }
2929+ model RepoBlobRef { }
3030+ model StatusAttr { }
3131+}
3232+3333+@external
3434+namespace com.atproto.repo.strongRef {
3535+ model Main { }
3636+}
···11import "@typelex/emitter";
2233namespace com.atproto.admin.sendEmail {
44- @doc("Send email to a user's account email address.")
44+ /** Send email to a user's account email address. */
55 @procedure
66 op main(input: {
77 @required recipientDid: did;
···99 subject?: string;
1010 @required senderDid: did;
11111212- @doc("Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers")
1212+ /** Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers */
1313 comment?: string;
1414 }): {
1515 @required sent: boolean;
···11import "@typelex/emitter";
2233namespace com.atproto.admin.updateAccountEmail {
44- @doc("Administrative action to update an account's email.")
44+ /** Administrative action to update an account's email. */
55 @procedure
66 op main(input: {
77- @doc("The handle or DID of the repo.")
77+ /** The handle or DID of the repo. */
88 @required
99 account: atIdentifier;
1010
···11import "@typelex/emitter";
2233namespace com.atproto.admin.updateAccountPassword {
44- @doc("Update the password for a user account as an administrator.")
44+ /** Update the password for a user account as an administrator. */
55 @procedure
66 op main(input: {
77 @required did: did;
···11import "@typelex/emitter";
2233namespace com.atproto.admin.updateAccountSigningKey {
44- @doc("Administrative action to update an account's signing key in their Did document.")
44+ /** Administrative action to update an account's signing key in their Did document. */
55 @procedure
66 op main(input: {
77 @required did: did;
8899- @doc("Did-key formatted public key")
99+ /** Did-key formatted public key */
1010 @required
1111 signingKey: did;
1212 }): void;
···44 model IdentityInfo {
55 @required did: did;
6677- @doc("The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document.")
77+ /** The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document. */
88 @required
99 handle: handle;
10101111- @doc("The complete DID document for the identity.")
1111+ /** The complete DID document for the identity. */
1212 @required
1313 didDoc: unknown;
1414 }
···11import "@typelex/emitter";
2233namespace com.atproto.identity.getRecommendedDidCredentials {
44- @doc("Describe the credentials that should be included in the DID doc of an account that is migrating to this service.")
44+ /** Describe the credentials that should be included in the DID doc of an account that is migrating to this service. */
55 @query
66 op main(): {
77- @doc("Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.")
77+ /** Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs. */
88 rotationKeys?: string[];
991010 alsoKnownAs?: string[];
···11import "@typelex/emitter";
2233namespace com.atproto.identity.refreshIdentity {
44- @doc("The resolution process confirmed that the handle does not resolve to any DID.")
44+ /** The resolution process confirmed that the handle does not resolve to any DID. */
55 model HandleNotFound {}
6677- @doc("The DID resolution process confirmed that there is no current DID.")
77+ /** The DID resolution process confirmed that there is no current DID. */
88 model DidNotFound {}
991010- @doc("The DID previously existed, but has been deactivated.")
1010+ /** The DID previously existed, but has been deactivated. */
1111 model DidDeactivated {}
12121313- @doc("Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server.")
1313+ /** Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server. */
1414 @procedure
1515 @errors(HandleNotFound, DidNotFound, DidDeactivated)
1616 op main(input: {
1717 @required identifier: atIdentifier;
1818 }): com.atproto.identity.defs.IdentityInfo;
1919}
2020+2121+// --- Externals ---
2222+2323+@external
2424+namespace com.atproto.identity.defs {
2525+ model IdentityInfo { }
2626+}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.requestPlcOperationSignature {
44- @doc("Request an email with a code to in order to request a signed PLC operation. Requires Auth.")
44+ /** Request an email with a code to in order to request a signed PLC operation. Requires Auth. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.resolveDid {
44- @doc("Resolves DID to DID document. Does not bi-directionally verify handle.")
44+ /** Resolves DID to DID document. Does not bi-directionally verify handle. */
55 @query
66 @errors(DidNotFound, DidDeactivated)
77 op main(
88- @doc("DID to resolve.")
88+ /** DID to resolve. */
99 @required
1010 did: did
1111 ): {
1212- @doc("The complete DID document for the identity.")
1212+ /** The complete DID document for the identity. */
1313 @required
1414 didDoc: unknown;
1515 };
16161717- @doc("The DID resolution process confirmed that there is no current DID.")
1717+ /** The DID resolution process confirmed that there is no current DID. */
1818 model DidNotFound {}
19192020- @doc("The DID previously existed, but has been deactivated.")
2020+ /** The DID previously existed, but has been deactivated. */
2121 model DidDeactivated {}
2222}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.resolveHandle {
44- @doc("Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.")
44+ /** Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document. */
55 @query
66 @errors(HandleNotFound)
77 op main(
88- @doc("The handle to resolve.")
88+ /** The handle to resolve. */
99 @required
1010 handle: handle
1111 ): {
1212 @required did: did;
1313 };
14141515- @doc("The resolution process confirmed that the handle does not resolve to any DID.")
1515+ /** The resolution process confirmed that the handle does not resolve to any DID. */
1616 model HandleNotFound {}
1717}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.resolveIdentity {
44- @doc("The resolution process confirmed that the handle does not resolve to any DID.")
44+ /** The resolution process confirmed that the handle does not resolve to any DID. */
55 model HandleNotFound {}
6677- @doc("The DID resolution process confirmed that there is no current DID.")
77+ /** The DID resolution process confirmed that there is no current DID. */
88 model DidNotFound {}
991010- @doc("The DID previously existed, but has been deactivated.")
1010+ /** The DID previously existed, but has been deactivated. */
1111 model DidDeactivated {}
12121313- @doc("Resolves an identity (DID or Handle) to a full identity (DID document and verified handle).")
1313+ /** Resolves an identity (DID or Handle) to a full identity (DID document and verified handle). */
1414 @query
1515 @errors(HandleNotFound, DidNotFound, DidDeactivated)
1616 op main(
1717- @doc("Handle or DID to resolve.")
1717+ /** Handle or DID to resolve. */
1818 @required
1919 identifier: atIdentifier
2020 ): com.atproto.identity.defs.IdentityInfo;
2121}
2222+2323+// --- Externals ---
2424+2525+@external
2626+namespace com.atproto.identity.defs {
2727+ model IdentityInfo { }
2828+}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.signPlcOperation {
44- @doc("Signs a PLC operation to update some value(s) in the requesting DID's document.")
44+ /** Signs a PLC operation to update some value(s) in the requesting DID's document. */
55 @procedure
66 op main(input: {
77- @doc("A token received through com.atproto.identity.requestPlcOperationSignature")
77+ /** A token received through com.atproto.identity.requestPlcOperationSignature */
88 token?: string;
991010 rotationKeys?: string[];
···15151616 services?: unknown;
1717 }): {
1818- @doc("A signed DID PLC operation.")
1818+ /** A signed DID PLC operation. */
1919 @required
2020 operation: unknown;
2121 };
···11import "@typelex/emitter";
2233namespace com.atproto.identity.submitPlcOperation {
44- @doc("Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry")
44+ /** Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry */
55 @procedure
66 op main(input: {
77 @required operation: unknown;
···11import "@typelex/emitter";
2233namespace com.atproto.identity.updateHandle {
44- @doc("Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth.")
44+ /** Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth. */
55 @procedure
66 op main(input: {
77- @doc("The new handle.")
77+ /** The new handle. */
88 @required
99 handle: handle;
1010 }): void;
···11import "@typelex/emitter";
2233namespace com.atproto.label.defs {
44- @doc("Metadata tag on an atproto resource (eg, repo or record).")
44+ /** Metadata tag on an atproto resource (eg, repo or record). */
55 model Label {
66- @doc("The AT Protocol version of the label object.")
66+ /** The AT Protocol version of the label object. */
77 ver?: integer;
8899- @doc("DID of the actor who created this label.")
99+ /** DID of the actor who created this label. */
1010 @required
1111 src: did;
12121313- @doc("AT URI of the record, repository (account), or other resource that this label applies to.")
1313+ /** AT URI of the record, repository (account), or other resource that this label applies to. */
1414 @required
1515 uri: uri;
16161717- @doc("Optionally, CID specifying the specific version of 'uri' resource this label applies to.")
1717+ /** Optionally, CID specifying the specific version of 'uri' resource this label applies to. */
1818 cid?: cid;
19192020- @doc("The short string name of the value or type of this label.")
2020+ /** The short string name of the value or type of this label. */
2121 @maxLength(128)
2222 @required
2323 val: string;
24242525- @doc("If true, this is a negation label, overwriting a previous label.")
2525+ /** If true, this is a negation label, overwriting a previous label. */
2626 neg?: boolean;
27272828- @doc("Timestamp when this label was created.")
2828+ /** Timestamp when this label was created. */
2929 @required
3030 cts: datetime;
31313232- @doc("Timestamp at which this label expires (no longer applies).")
3232+ /** Timestamp at which this label expires (no longer applies). */
3333 exp?: datetime;
34343535- @doc("Signature of dag-cbor encoded label.")
3535+ /** Signature of dag-cbor encoded label. */
3636 sig?: bytes;
3737 }
38383939- @doc("Metadata tags on an atproto record, published by the author within the record.")
3939+ /** Metadata tags on an atproto record, published by the author within the record. */
4040 model SelfLabels {
4141 @maxItems(10)
4242 @required
4343 values: SelfLabel[];
4444 }
45454646- @doc("Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.")
4646+ /** Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. */
4747 model SelfLabel {
4848- @doc("The short string name of the value or type of this label.")
4848+ /** The short string name of the value or type of this label. */
4949 @maxLength(128)
5050 @required
5151 val: string;
5252 }
53535454- @doc("Declares a label value and its expected interpretations and behaviors.")
5454+ /** Declares a label value and its expected interpretations and behaviors. */
5555 model LabelValueDefinition {
5656- @doc("The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).")
5656+ /** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */
5757 @maxLength(100)
5858 @maxGraphemes(100)
5959 @required
6060 identifier: string;
61616262- @doc("How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.")
6262+ /** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */
6363 @required
6464 severity: "inform" | "alert" | "none" | string;
65656666- @doc("What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.")
6666+ /** What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. */
6767 @required
6868 blurs: "content" | "media" | "none" | string;
69697070- @doc("The default setting for this label.")
7070+ /** The default setting for this label. */
7171 defaultSetting?: "ignore" | "warn" | "hide" | string = "warn";
72727373- @doc("Does the user need to have adult content enabled in order to configure this label?")
7373+ /** Does the user need to have adult content enabled in order to configure this label? */
7474 adultOnly?: boolean;
75757676 @required
7777 locales: LabelValueDefinitionStrings[];
7878 }
79798080- @doc("Strings which describe the label in the UI, localized into a specific language.")
8080+ /** Strings which describe the label in the UI, localized into a specific language. */
8181 model LabelValueDefinitionStrings {
8282- @doc("The code of the language these strings are written in.")
8282+ /** The code of the language these strings are written in. */
8383 @required
8484 lang: language;
85858686- @doc("A short human-readable name for the label.")
8686+ /** A short human-readable name for the label. */
8787 @maxGraphemes(64)
8888 @maxLength(640)
8989 @required
9090 name: string;
91919292- @doc("A longer description of what the label means and why it might be applied.")
9292+ /** A longer description of what the label means and why it might be applied. */
9393 @maxGraphemes(10000)
9494 @maxLength(100000)
9595 @required
···11import "@typelex/emitter";
2233namespace com.atproto.label.queryLabels {
44- @doc("Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth.")
44+ /** Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth. */
55 @query
66 op main(
77- @doc("List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI.")
77+ /** List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI. */
88 @required
99 uriPatterns: string[],
10101111- @doc("Optional list of label sources (DIDs) to filter on.")
1111+ /** Optional list of label sources (DIDs) to filter on. */
1212 sources?: did[],
13131414 @minValue(1)
···2121 @required labels: com.atproto.label.defs.Label[];
2222 };
2323}
2424+2525+// --- Externals ---
2626+2727+@external
2828+namespace com.atproto.label.defs {
2929+ model Label { }
3030+}
···1313 message?: string;
1414 }
15151616- @doc("Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream.")
1616+ /** Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream. */
1717 @subscription
1818 @errors(FutureCursor)
1919 op main(
2020- @doc("The last known event seq number to backfill from.")
2020+ /** The last known event seq number to backfill from. */
2121 cursor?: integer
2222 ): (Labels | Info);
2323}
2424+2525+// --- Externals ---
2626+2727+@external
2828+namespace com.atproto.label.defs {
2929+ model Label { }
3030+ model Info { }
3131+}
···11import "@typelex/emitter";
2233namespace com.atproto.lexicon.schema {
44- @doc("Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc).")
44+ /** Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc). */
55 @rec("nsid")
66 model Main {
77- @doc("Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system.")
77+ /** Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system. */
88 @required
99 lexicon: integer;
1010 }
···11import "@typelex/emitter";
2233namespace com.atproto.moderation.createReport {
44- @doc("Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth.")
44+ /** Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth. */
55 @procedure
66 op main(input: {
77- @doc("Indicates the broad category of violation the report is for.")
77+ /** Indicates the broad category of violation the report is for. */
88 @required
99 reasonType: com.atproto.moderation.defs.ReasonType;
10101111 @maxGraphemes(2000)
1212 @maxLength(20000)
1313- @doc("Additional context about the content and violation.")
1313+ /** Additional context about the content and violation. */
1414 reason?: string;
15151616 @required
···4040 @required createdAt: datetime;
4141 };
42424343- @doc("Moderation tool information for tracing the source of the action")
4343+ /** Moderation tool information for tracing the source of the action */
4444 model ModTool {
4545- @doc("Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome')")
4545+ /** Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome') */
4646 @required
4747 name: string;
48484949- @doc("Additional arbitrary metadata about the source")
4949+ /** Additional arbitrary metadata about the source */
5050 meta?: unknown;
5151 }
5252}
5353+5454+// --- Externals ---
5555+5656+@external
5757+namespace com.atproto.moderation.defs {
5858+ model ReasonType { }
5959+}
6060+6161+@external
6262+namespace com.atproto.admin.defs {
6363+ model RepoRef { }
6464+}
6565+6666+@external
6767+namespace com.atproto.repo.strongRef {
6868+ model Main { }
6969+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.applyWrites {
44- @doc("Indicates that the 'swapCommit' parameter did not match current commit.")
44+ /** Indicates that the 'swapCommit' parameter did not match current commit. */
55 model InvalidSwap {}
6677 @closed
···2020 DeleteResult,
2121 }
22222323- @doc("Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.")
2323+ /** Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS. */
2424 @procedure
2525 @errors(InvalidSwap)
2626 op main(input: {
2727- @doc("The handle or DID of the repo (aka, current account).")
2727+ /** The handle or DID of the repo (aka, current account). */
2828 @required
2929 repo: atIdentifier;
30303131- @doc("Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons.")
3131+ /** Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons. */
3232 validate?: boolean;
33333434 @required
3535 writes: WriteAction[];
36363737- @doc("If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.")
3737+ /** If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations. */
3838 swapCommit?: cid;
3939 }): {
4040 commit?: com.atproto.repo.defs.CommitMeta;
4141 results?: WriteResult[];
4242 };
43434444- @doc("Operation which creates a new record.")
4444+ /** Operation which creates a new record. */
4545 model Create {
4646 @required collection: nsid;
47474848- @doc("NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.")
4848+ /** NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility. */
4949 @maxLength(512)
5050 rkey?: recordKey;
51515252 @required value: unknown;
5353 }
54545555- @doc("Operation which updates an existing record.")
5555+ /** Operation which updates an existing record. */
5656 model Update {
5757 @required collection: nsid;
5858 @required rkey: recordKey;
5959 @required value: unknown;
6060 }
61616262- @doc("Operation which deletes an existing record.")
6262+ /** Operation which deletes an existing record. */
6363 model Delete {
6464 @required collection: nsid;
6565 @required rkey: recordKey;
···79798080 model DeleteResult {}
8181}
8282+8383+// --- Externals ---
8484+8585+@external
8686+namespace com.atproto.repo.defs {
8787+ model CommitMeta { }
8888+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.createRecord {
44- @doc("Create a single new repository record. Requires auth, implemented by PDS.")
44+ /** Create a single new repository record. Requires auth, implemented by PDS. */
55 @errors(InvalidSwap)
66 @procedure
77 op main(input: {
88- @doc("The handle or DID of the repo (aka, current account).")
88+ /** The handle or DID of the repo (aka, current account). */
99 @required
1010 repo: atIdentifier;
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid;
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @maxLength(512)
1818 rkey?: recordKey;
19192020- @doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
2020+ /** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
2121 validate?: boolean;
22222323- @doc("The record itself. Must contain a $type field.")
2323+ /** The record itself. Must contain a $type field. */
2424 @required
2525 record: unknown;
26262727- @doc("Compare and swap with the previous commit by CID.")
2727+ /** Compare and swap with the previous commit by CID. */
2828 swapCommit?: cid;
2929 }): {
3030 @required uri: atUri;
···3333 validationStatus?: "valid" | "unknown" | string;
3434 };
35353636- @doc("Indicates that 'swapCommit' didn't match current repo commit.")
3636+ /** Indicates that 'swapCommit' didn't match current repo commit. */
3737 model InvalidSwap {}
3838}
3939+4040+// --- Externals ---
4141+4242+@external
4343+namespace com.atproto.repo.defs {
4444+ model CommitMeta { }
4545+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.deleteRecord {
44- @doc("Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.")
44+ /** Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS. */
55 @errors(InvalidSwap)
66 @procedure
77 op main(input: {
88- @doc("The handle or DID of the repo (aka, current account).")
88+ /** The handle or DID of the repo (aka, current account). */
99 @required
1010 repo: atIdentifier;
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid;
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @required
1818 rkey: recordKey;
19192020- @doc("Compare and swap with the previous record by CID.")
2020+ /** Compare and swap with the previous record by CID. */
2121 swapRecord?: cid;
22222323- @doc("Compare and swap with the previous commit by CID.")
2323+ /** Compare and swap with the previous commit by CID. */
2424 swapCommit?: cid;
2525 }): {
2626 commit?: com.atproto.repo.defs.CommitMeta;
···28282929 model InvalidSwap {}
3030}
3131+3232+// --- Externals ---
3333+3434+@external
3535+namespace com.atproto.repo.defs {
3636+ model CommitMeta { }
3737+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.describeRepo {
44- @doc("Get information about an account and repository, including the list of collections. Does not require auth.")
44+ /** Get information about an account and repository, including the list of collections. Does not require auth. */
55 @query
66 op main(
77- @doc("The handle or DID of the repo.")
77+ /** The handle or DID of the repo. */
88 @required
99 repo: atIdentifier
1010 ): {
1111 @required handle: handle;
1212 @required did: did;
13131414- @doc("The complete DID document for this account.")
1414+ /** The complete DID document for this account. */
1515 @required
1616 didDoc: unknown;
17171818- @doc("List of all the collections (NSIDs) for which this repo contains at least one record.")
1818+ /** List of all the collections (NSIDs) for which this repo contains at least one record. */
1919 @required
2020 collections: nsid[];
21212222- @doc("Indicates if handle is currently valid (resolves bi-directionally)")
2222+ /** Indicates if handle is currently valid (resolves bi-directionally) */
2323 @required
2424 handleIsCorrect: boolean;
2525 };
···11import "@typelex/emitter";
2233namespace com.atproto.repo.getRecord {
44- @doc("Get a single record from a repository. Does not require auth.")
44+ /** Get a single record from a repository. Does not require auth. */
55 @query
66 @errors(RecordNotFound)
77 op main(
88- @doc("The handle or DID of the repo.")
88+ /** The handle or DID of the repo. */
99 @required
1010 repo: atIdentifier,
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid,
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @required
1818 rkey: recordKey,
19192020- @doc("The CID of the version of the record. If not specified, then return the most recent version.")
2020+ /** The CID of the version of the record. If not specified, then return the most recent version. */
2121 cid?: cid
2222 ): {
2323 @required uri: atUri;
···11import "@typelex/emitter";
2233namespace com.atproto.repo.importRepo {
44- @doc("Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.")
44+ /** Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set. */
55 @procedure
66 op main(
77 @encoding("application/vnd.ipld.car")
···11import "@typelex/emitter";
2233namespace com.atproto.repo.listMissingBlobs {
44- @doc("Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.")
44+ /** Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow. */
55 @query
66 op main(
77 @minValue(1)
···11import "@typelex/emitter";
2233namespace com.atproto.repo.listRecords {
44- @doc("List a range of records in a repository, matching a specific collection. Does not require auth.")
44+ /** List a range of records in a repository, matching a specific collection. Does not require auth. */
55 @query
66 op main(
77- @doc("The handle or DID of the repo.")
77+ /** The handle or DID of the repo. */
88 @required
99 repo: atIdentifier,
10101111- @doc("The NSID of the record type.")
1111+ /** The NSID of the record type. */
1212 @required
1313 collection: nsid,
14141515- @doc("The number of records to return.")
1515+ /** The number of records to return. */
1616 @minValue(1)
1717 @maxValue(100)
1818 limit?: int32 = 50,
19192020 cursor?: string,
21212222- @doc("Flag to reverse the order of the returned records.")
2222+ /** Flag to reverse the order of the returned records. */
2323 reverse?: boolean
2424 ): {
2525 cursor?: string;
···11import "@typelex/emitter";
2233namespace com.atproto.repo.putRecord {
44- @doc("Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.")
44+ /** Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS. */
55 @errors(InvalidSwap)
66 @procedure
77 op main(input: {
88- @doc("The handle or DID of the repo (aka, current account).")
88+ /** The handle or DID of the repo (aka, current account). */
99 @required
1010 repo: atIdentifier;
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid;
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @maxLength(512)
1818 @required
1919 rkey: recordKey;
20202121- @doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
2121+ /** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
2222 validate?: boolean;
23232424- @doc("The record to write.")
2424+ /** The record to write. */
2525 @required
2626 record: unknown;
27272828- @doc("Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation")
2828+ /** Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation */
2929 swapRecord?: cid | null;
30303131- @doc("Compare and swap with the previous commit by CID.")
3131+ /** Compare and swap with the previous commit by CID. */
3232 swapCommit?: cid;
3333 }): {
3434 @required uri: atUri;
···39394040 model InvalidSwap {}
4141}
4242+4343+// --- Externals ---
4444+4545+@external
4646+namespace com.atproto.repo.defs {
4747+ model CommitMeta { }
4848+}
···11import "@typelex/emitter";
2233-@doc("A URI with a content-hash fingerprint.")
33+/** A URI with a content-hash fingerprint. */
44namespace com.atproto.repo.strongRef {
55 model Main {
66 @required uri: atUri;
···11import "@typelex/emitter";
2233namespace com.atproto.repo.uploadBlob {
44- @doc("Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.")
44+ /** Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS. */
55 @procedure
66 op main(
77 @encoding("*/*")
···11import "@typelex/emitter";
2233namespace com.atproto.server.activateAccount {
44- @doc("Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup.")
44+ /** Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.server.checkAccountStatus {
44- @doc("Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.")
44+ /** Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself. */
55 @query
66 op main(): {
77 @required activated: boolean;
···66 model InvalidToken {}
77 model InvalidEmail {}
8899- @doc("Confirm an email using a token from com.atproto.server.requestEmailConfirmation.")
99+ /** Confirm an email using a token from com.atproto.server.requestEmailConfirmation. */
1010 @procedure
1111 @errors(AccountNotFound, ExpiredToken, InvalidToken, InvalidEmail)
1212 op main(input: {
···99 model UnresolvableDid {}
1010 model IncompatibleDidDoc {}
11111212- @doc("Account login session returned on successful account creation.")
1212+ /** Account login session returned on successful account creation. */
1313 @inline
1414 model Output {
1515 @required accessJwt: string;
1616 @required refreshJwt: string;
1717 @required handle: handle;
18181919- @doc("The DID of the new account.")
1919+ /** The DID of the new account. */
2020 @required
2121 did: did;
22222323- @doc("Complete DID document.")
2323+ /** Complete DID document. */
2424 didDoc?: unknown;
2525 }
26262727- @doc("Create an account. Implemented by PDS.")
2727+ /** Create an account. Implemented by PDS. */
2828 @procedure
2929 @errors(InvalidHandle, InvalidPassword, InvalidInviteCode, HandleNotAvailable, UnsupportedDomain, UnresolvableDid, IncompatibleDidDoc)
3030 op main(input: {
3131 email?: string;
32323333- @doc("Requested handle for the account.")
3333+ /** Requested handle for the account. */
3434 @required
3535 handle: handle;
36363737- @doc("Pre-existing atproto DID, being imported to a new account.")
3737+ /** Pre-existing atproto DID, being imported to a new account. */
3838 did?: did;
39394040 inviteCode?: string;
4141 verificationCode?: string;
4242 verificationPhone?: string;
43434444- @doc("Initial account password. May need to meet instance-specific password strength requirements.")
4444+ /** Initial account password. May need to meet instance-specific password strength requirements. */
4545 password?: string;
46464747- @doc("DID PLC rotation key (aka, recovery key) to be included in PLC creation operation.")
4747+ /** DID PLC rotation key (aka, recovery key) to be included in PLC creation operation. */
4848 recoveryKey?: string;
49495050- @doc("A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented.")
5050+ /** A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented. */
5151 plcOp?: unknown;
5252 }): Output;
5353}
···1010 privileged?: boolean;
1111 }
12121313- @doc("Create an App Password.")
1313+ /** Create an App Password. */
1414 @procedure
1515 @errors(AccountTakedown)
1616 op main(input: {
1717- @doc("A short name for the App Password, to help distinguish them.")
1717+ /** A short name for the App Password, to help distinguish them. */
1818 @required
1919 name: string;
20202121- @doc("If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients.")
2121+ /** If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients. */
2222 privileged?: boolean;
2323 }): AppPassword;
2424}
···5566 model AuthFactorTokenRequired {}
7788- @doc("Create an authentication session.")
88+ /** Create an authentication session. */
99 @procedure
1010 @errors(AccountTakedown, AuthFactorTokenRequired)
1111 op main(input: {
1212- @doc("Handle or other identifier supported by the server for the authenticating user.")
1212+ /** Handle or other identifier supported by the server for the authenticating user. */
1313 @required
1414 identifier: string;
1515···17171818 authFactorToken?: string;
19192020- @doc("When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned")
2020+ /** When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned */
2121 allowTakendown?: boolean;
2222 }): {
2323 @required accessJwt: string;
···3030 emailAuthFactor?: boolean;
3131 active?: boolean;
32323333- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
3333+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
3434 status?: "takendown" | "suspended" | "deactivated" | string;
3535 };
3636}
···11import "@typelex/emitter";
2233namespace com.atproto.server.deactivateAccount {
44- @doc("Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.")
44+ /** Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host. */
55 @procedure
66 op main(input: {
77- @doc("A recommendation to server as to how long they should hold onto the deactivated account before deleting.")
77+ /** A recommendation to server as to how long they should hold onto the deactivated account before deleting. */
88 deleteAfter?: datetime;
99 }): void;
1010}
···44 model ExpiredToken {}
55 model InvalidToken {}
6677- @doc("Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth.")
77+ /** Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth. */
88 @procedure
99 @errors(ExpiredToken, InvalidToken)
1010 op main(input: {
···11import "@typelex/emitter";
2233namespace com.atproto.server.describeServer {
44- @doc("Describes the server's account creation requirements and capabilities. Implemented by PDS.")
44+ /** Describes the server's account creation requirements and capabilities. Implemented by PDS. */
55 @query
66 op main(): {
77 @required did: did;
8899- @doc("If true, an invite code must be supplied to create an account on this instance.")
99+ /** If true, an invite code must be supplied to create an account on this instance. */
1010 inviteCodeRequired?: boolean;
11111212- @doc("If true, a phone verification token must be supplied to create an account on this instance.")
1212+ /** If true, a phone verification token must be supplied to create an account on this instance. */
1313 phoneVerificationRequired?: boolean;
14141515- @doc("List of domain suffixes that can be used in account handles.")
1515+ /** List of domain suffixes that can be used in account handles. */
1616 @required
1717 availableUserDomains: string[];
18181919- @doc("URLs of service policy documents.")
1919+ /** URLs of service policy documents. */
2020 links?: Links;
21212222- @doc("Contact information")
2222+ /** Contact information */
2323 contact?: Contact;
2424 };
2525
···33namespace com.atproto.server.getAccountInviteCodes {
44 model DuplicateCreate {}
5566- @doc("Get all invite codes for the current account. Requires auth.")
66+ /** Get all invite codes for the current account. Requires auth. */
77 @query
88 @errors(DuplicateCreate)
99 op main(
1010 includeUsed?: boolean = true,
11111212- @doc("Controls whether any new 'earned' but not 'created' invites should be created.")
1212+ /** Controls whether any new 'earned' but not 'created' invites should be created. */
1313 createAvailable?: boolean = true
1414 ): {
1515 @required codes: com.atproto.server.defs.InviteCode[];
1616 };
1717}
1818+1919+// --- Externals ---
2020+2121+@external
2222+namespace com.atproto.server.defs {
2323+ model InviteCode { }
2424+}
···11import "@typelex/emitter";
2233namespace com.atproto.server.getServiceAuth {
44- @doc("Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes.")
44+ /** Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes. */
55 model BadExpiration {}
6677- @doc("Get a signed token on behalf of the requesting DID for the requested service.")
77+ /** Get a signed token on behalf of the requesting DID for the requested service. */
88 @query
99 @errors(BadExpiration)
1010 op main(
1111- @doc("The DID of the service that the token will be used to authenticate with")
1111+ /** The DID of the service that the token will be used to authenticate with */
1212 @required
1313 aud: did,
14141515- @doc("The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope.")
1515+ /** The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope. */
1616 exp?: integer,
17171818- @doc("Lexicon (XRPC) method to bind the requested token to")
1818+ /** Lexicon (XRPC) method to bind the requested token to */
1919 lxm?: nsid
2020 ): {
2121 @required token: string;
···11import "@typelex/emitter";
2233namespace com.atproto.server.getSession {
44- @doc("Get information about the current auth session. Requires auth.")
44+ /** Get information about the current auth session. Requires auth. */
55 @query
66 op main(): {
77 @required handle: handle;
···1212 didDoc?: unknown;
1313 active?: boolean;
14141515- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
1515+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
1616 status?: "takendown" | "suspended" | "deactivated" | string;
1717 };
1818}
···33namespace com.atproto.server.refreshSession {
44 model AccountTakedown {}
5566- @doc("Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt').")
66+ /** Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt'). */
77 @procedure
88 @errors(AccountTakedown)
99 op main(): {
···1414 didDoc?: unknown;
1515 active?: boolean;
16161717- @doc("Hosting status of the account. If not specified, then assume 'active'.")
1717+ /** Hosting status of the account. If not specified, then assume 'active'. */
1818 status?: "takendown" | "suspended" | "deactivated" | string;
1919 };
2020}
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestAccountDelete {
44- @doc("Initiate a user account deletion via email.")
44+ /** Initiate a user account deletion via email. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestEmailConfirmation {
44- @doc("Request an email with a code to confirm ownership of email.")
44+ /** Request an email with a code to confirm ownership of email. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestEmailUpdate {
44- @doc("Request a token in order to update email.")
44+ /** Request a token in order to update email. */
55 @procedure
66 op main(): {
77 @required tokenRequired: boolean;
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestPasswordReset {
44- @doc("Initiate a user account password reset via email.")
44+ /** Initiate a user account password reset via email. */
55 @procedure
66 op main(input: {
77 @required email: string;
···11import "@typelex/emitter";
2233namespace com.atproto.server.reserveSigningKey {
44- @doc("Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented.")
44+ /** Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented. */
55 @procedure
66 op main(input: {
77- @doc("The DID to reserve a key for.")
77+ /** The DID to reserve a key for. */
88 did?: did;
99 }): {
1010- @doc("The public key for the reserved signing key, in did:key serialization.")
1010+ /** The public key for the reserved signing key, in did:key serialization. */
1111 @required
1212 signingKey: string;
1313 };
···44 model ExpiredToken {}
55 model InvalidToken {}
6677- @doc("Reset a user account password using a token.")
77+ /** Reset a user account password using a token. */
88 @procedure
99 @errors(ExpiredToken, InvalidToken)
1010 op main(input: {
···55 model InvalidToken {}
66 model TokenRequired {}
7788- @doc("Update an account's email.")
88+ /** Update an account's email. */
99 @procedure
1010 @errors(ExpiredToken, InvalidToken, TokenRequired)
1111 op main(input: {
1212 @required email: string;
1313 emailAuthFactor?: boolean;
14141515- @doc("Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed.")
1515+ /** Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed. */
1616 token?: string;
1717 }): void;
1818}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getBlob {
44- @doc("Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS.")
44+ /** Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS. */
55 @query
66 @encoding("*/*")
77 @errors(BlobNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the account.")
99+ /** The DID of the account. */
1010 @required
1111 did: did,
12121313- @doc("The CID of the blob to fetch")
1313+ /** The CID of the blob to fetch */
1414 @required
1515 cid: cid
1616 ): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getBlocks {
44- @doc("Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS.")
44+ /** Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS. */
55 @query
66 @encoding("application/vnd.ipld.car")
77 @errors(BlockNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the repo.")
99+ /** The DID of the repo. */
1010 @required
1111 did: did,
1212
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getCheckout {
44- @doc("DEPRECATED - please use com.atproto.sync.getRepo instead")
44+ /** DEPRECATED - please use com.atproto.sync.getRepo instead */
55 @query
66 @encoding("application/vnd.ipld.car")
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getHead {
44- @doc("DEPRECATED - please use com.atproto.sync.getLatestCommit instead")
44+ /** DEPRECATED - please use com.atproto.sync.getLatestCommit instead */
55 @query
66 @errors(HeadNotFound)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): {
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getHostStatus {
44- @doc("Returns information about a specified upstream host, as consumed by the server. Implemented by relays.")
44+ /** Returns information about a specified upstream host, as consumed by the server. Implemented by relays. */
55 @query
66 @errors(HostNotFound)
77 op main(
88- @doc("Hostname of the host (eg, PDS or relay) being queried.")
88+ /** Hostname of the host (eg, PDS or relay) being queried. */
99 @required
1010 hostname: string
1111 ): {
1212 @required hostname: string;
13131414- @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
1414+ /** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
1515 seq?: integer;
16161717- @doc("Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts.")
1717+ /** Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts. */
1818 accountCount?: integer;
19192020 status?: com.atproto.sync.defs.HostStatus;
···22222323 model HostNotFound {}
2424}
2525+2626+// --- Externals ---
2727+2828+@external
2929+namespace com.atproto.sync.defs {
3030+ model HostStatus { }
3131+}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getLatestCommit {
44- @doc("Get the current commit CID & revision of the specified repo. Does not require auth.")
44+ /** Get the current commit CID & revision of the specified repo. Does not require auth. */
55 @query
66 @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): {
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getRecord {
44- @doc("Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.")
44+ /** Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth. */
55 @query
66 @encoding("application/vnd.ipld.car")
77 @errors(RecordNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the repo.")
99+ /** The DID of the repo. */
1010 @required
1111 did: did,
12121313 @required collection: nsid,
14141515- @doc("Record Key")
1515+ /** Record Key */
1616 @required
1717 rkey: recordKey
1818 ): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getRepo {
44- @doc("Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.")
44+ /** Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS. */
55 @query
66 @encoding("application/vnd.ipld.car")
77 @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the repo.")
99+ /** The DID of the repo. */
1010 @required
1111 did: did,
12121313- @doc("The revision ('rev') of the repo to create a diff from.")
1313+ /** The revision ('rev') of the repo to create a diff from. */
1414 since?: tid
1515 ): void;
1616
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getRepoStatus {
44- @doc("Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.")
44+ /** Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay. */
55 @query
66 @errors(RepoNotFound)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): {
1212 @required did: did;
1313 @required active: boolean;
14141515- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
1515+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
1616 status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
17171818- @doc("Optional field, the current rev of the repo, if active=true")
1818+ /** Optional field, the current rev of the repo, if active=true */
1919 rev?: tid;
2020 };
2121
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listBlobs {
44- @doc("List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS.")
44+ /** List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS. */
55 @query
66 @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did,
11111212- @doc("Optional revision of the repo to list blobs since.")
1212+ /** Optional revision of the repo to list blobs since. */
1313 since?: tid,
14141515 @minValue(1)
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listHosts {
44- @doc("Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.")
44+ /** Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays. */
55 @query
66 op main(
77 @minValue(1)
···1212 ): {
1313 cursor?: string;
14141515- @doc("Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first.")
1515+ /** Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first. */
1616 @required
1717 hosts: Host[];
1818 };
19192020 model Host {
2121- @doc("hostname of server; not a URL (no scheme)")
2121+ /** hostname of server; not a URL (no scheme) */
2222 @required
2323 hostname: string;
24242525- @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
2525+ /** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
2626 seq?: integer;
27272828 accountCount?: integer;
2929 status?: com.atproto.sync.defs.HostStatus;
3030 }
3131}
3232+3333+// --- Externals ---
3434+3535+@external
3636+namespace com.atproto.sync.defs {
3737+ model HostStatus { }
3838+}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listRepos {
44- @doc("Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.")
44+ /** Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay. */
55 @query
66 op main(
77 @minValue(1)
···1717 model Repo {
1818 @required did: did;
19192020- @doc("Current repo commit CID")
2020+ /** Current repo commit CID */
2121 @required
2222 head: cid;
23232424 @required rev: tid;
2525 active?: boolean;
26262727- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
2727+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
2828 status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
2929 }
3030}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listReposByCollection {
44- @doc("Enumerates all the DIDs which have records with the given collection NSID.")
44+ /** Enumerates all the DIDs which have records with the given collection NSID. */
55 @query
66 op main(
77 @required collection: nsid,
8899- @doc("Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists.")
99+ /** Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists. */
1010 @minValue(1)
1111 @maxValue(2000)
1212 limit?: int32 = 500,
···11import "@typelex/emitter";
2233namespace com.atproto.sync.notifyOfUpdate {
44- @doc("Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl")
44+ /** Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl */
55 @procedure
66 op main(input: {
77- @doc("Hostname of the current service (usually a PDS) that is notifying of update.")
77+ /** Hostname of the current service (usually a PDS) that is notifying of update. */
88 @required
99 hostname: string;
1010 }): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.requestCrawl {
44- @doc("Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth.")
44+ /** Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth. */
55 @procedure
66 @errors(HostBanned)
77 op main(input: {
88- @doc("Hostname of the current service (eg, PDS) that is requesting to be crawled.")
88+ /** Hostname of the current service (eg, PDS) that is requesting to be crawled. */
99 @required
1010 hostname: string;
1111 }): void;
···33namespace com.atproto.sync.subscribeRepos {
44 @subscription
55 @errors(FutureCursor, ConsumerTooSlow)
66- @doc("Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay.")
66+ /** Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay. */
77 op main(
88- @doc("The last known event seq number to backfill from.")
88+ /** The last known event seq number to backfill from. */
99 cursor?: integer
1010 ): (Commit | Sync | Identity | Account | Info | unknown);
11111212 model FutureCursor {}
13131414- @doc("If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.")
1414+ /** If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection. */
1515 model ConsumerTooSlow {}
16161717- @doc("Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature.")
1717+ /** Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature. */
1818 model Commit {
1919- @doc("The stream sequence number of this message.")
1919+ /** The stream sequence number of this message. */
2020 @required
2121 seq: integer;
22222323- @doc("DEPRECATED -- unused")
2323+ /** DEPRECATED -- unused */
2424 @required
2525 rebase: boolean;
26262727- @doc("DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.")
2727+ /** DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data. */
2828 @required
2929 tooBig: boolean;
30303131- @doc("The repo this event comes from. Note that all other message types name this field 'did'.")
3131+ /** The repo this event comes from. Note that all other message types name this field 'did'. */
3232 @required
3333 repo: did;
34343535- @doc("Repo commit object CID.")
3535+ /** Repo commit object CID. */
3636 @required
3737 commit: cidLink;
38383939- @doc("The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event.")
3939+ /** The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event. */
4040 @required
4141 rev: tid;
42424343- @doc("The rev of the last emitted commit from this repo (if any).")
4343+ /** The rev of the last emitted commit from this repo (if any). */
4444 @required
4545 since: tid | null;
46464747- @doc("CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.")
4747+ /** CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list. */
4848 @maxBytes(2000000)
4949 @required
5050 blocks: bytes;
51515252 @maxItems(200)
5353 @required
5454- @doc("List of repo mutation operations in this commit (eg, records created, updated, or deleted).")
5454+ /** List of repo mutation operations in this commit (eg, records created, updated, or deleted). */
5555 ops: RepoOp[];
56565757- @doc("DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.")
5757+ /** DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit. */
5858 @required blobs: cidLink[];
59596060- @doc("The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose.")
6060+ /** The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose. */
6161 prevData?: cidLink;
62626363- @doc("Timestamp of when this message was originally broadcast.")
6363+ /** Timestamp of when this message was originally broadcast. */
6464 @required
6565 time: datetime;
6666 }
67676868- @doc("Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.")
6868+ /** Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository. */
6969 model Sync {
7070- @doc("The stream sequence number of this message.")
7070+ /** The stream sequence number of this message. */
7171 @required
7272 seq: integer;
73737474- @doc("The account this repo event corresponds to. Must match that in the commit object.")
7474+ /** The account this repo event corresponds to. Must match that in the commit object. */
7575 @required
7676 did: did;
77777878- @doc("CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.")
7878+ /** CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'. */
7979 @maxBytes(10000)
8080 @required
8181 blocks: bytes;
82828383- @doc("The rev of the commit. This value must match that in the commit object.")
8383+ /** The rev of the commit. This value must match that in the commit object. */
8484 @required
8585 rev: string;
86868787- @doc("Timestamp of when this message was originally broadcast.")
8787+ /** Timestamp of when this message was originally broadcast. */
8888 @required
8989 time: datetime;
9090 }
91919292- @doc("Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache.")
9292+ /** Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache. */
9393 model Identity {
9494 @required seq: integer;
9595 @required did: did;
9696 @required time: datetime;
97979898- @doc("The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details.")
9898+ /** The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details. */
9999 handle?: handle;
100100 }
101101102102- @doc("Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.")
102102+ /** Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active. */
103103 model Account {
104104 @required seq: integer;
105105 @required did: did;
106106 @required time: datetime;
107107108108- @doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
108108+ /** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
109109 @required
110110 active: boolean;
111111112112- @doc("If active=false, this optional field indicates a reason for why the account is not active.")
112112+ /** If active=false, this optional field indicates a reason for why the account is not active. */
113113 status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
114114 }
115115···118118 message?: string;
119119 }
120120121121- @doc("A repo operation, ie a mutation of a single record.")
121121+ /** A repo operation, ie a mutation of a single record. */
122122 model RepoOp {
123123 @required action: "create" | "update" | "delete" | string;
124124 @required path: string;
125125126126- @doc("For creates and updates, the new record CID. For deletions, null.")
126126+ /** For creates and updates, the new record CID. For deletions, null. */
127127 @required
128128 cid: cidLink | null;
129129130130- @doc("For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.")
130130+ /** For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined. */
131131 prev?: cidLink;
132132 }
133133}
···11import "@typelex/emitter";
2233namespace com.atproto.temp.addReservedHandle {
44- @doc("Add a handle to the set of reserved handles.")
44+ /** Add a handle to the set of reserved handles. */
55 @procedure
66 op main(
77 input: {
···11import "@typelex/emitter";
2233namespace com.atproto.temp.checkHandleAvailability {
44- @doc("An invalid email was provided.")
44+ /** An invalid email was provided. */
55 model InvalidEmail {}
6677- @doc("Indicates the provided handle is available.")
77+ /** Indicates the provided handle is available. */
88 model ResultAvailable {}
991010- @doc("Indicates the provided handle is unavailable and gives suggestions of available handles.")
1010+ /** Indicates the provided handle is unavailable and gives suggestions of available handles. */
1111 model ResultUnavailable {
1212- @doc("List of suggested handles based on the provided inputs.")
1212+ /** List of suggested handles based on the provided inputs. */
1313 @required
1414 suggestions: Suggestion[];
1515 }
···1717 model Suggestion {
1818 @required handle: handle;
19192020- @doc("Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics.")
2020+ /** Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics. */
2121 @required
2222 method: string;
2323 }
24242525- @doc("Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.")
2525+ /** Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions. */
2626 @query
2727 @errors(InvalidEmail)
2828 op main(
2929- @doc("Tentative handle. Will be checked for availability or used to build handle suggestions.")
3030- handle: handle,
2929+ /** Tentative handle. Will be checked for availability or used to build handle suggestions. */
3030+ @required handle: handle,
31313232- @doc("User-provided email. Might be used to build handle suggestions.")
3232+ /** User-provided email. Might be used to build handle suggestions. */
3333 email?: string,
34343535- @doc("User-provided birth date. Might be used to build handle suggestions.")
3535+ /** User-provided birth date. Might be used to build handle suggestions. */
3636 birthDate?: datetime
3737 ): {
3838- @doc("Echo of the input handle.")
3838+ /** Echo of the input handle. */
3939 @required
4040 handle: handle;
4141
···11import "@typelex/emitter";
2233namespace com.atproto.temp.fetchLabels {
44- @doc("DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.")
44+ /** DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date. */
55 @query
66 op main(
77 since?: integer,
···1313 @required labels: com.atproto.label.defs.Label[];
1414 };
1515}
1616+1717+// --- Externals ---
1818+1919+@external
2020+namespace com.atproto.label.defs {
2121+ model Label { }
2222+}
···11import "@typelex/emitter";
2233namespace com.atproto.temp.requestPhoneVerification {
44- @doc("Request a verification code to be sent to the supplied phone number")
44+ /** Request a verification code to be sent to the supplied phone number */
55 @procedure
66 op main(
77 input: {
···11import "@typelex/emitter";
2233namespace com.atproto.temp.revokeAccountCredentials {
44- @doc("Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset.")
44+ /** Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset. */
55 @procedure
66 op main(
77 input: {
···33namespace tools.ozone.communication.createTemplate {
44 model DuplicateTemplateName {}
5566- @doc("Administrative action to create a new, re-usable communication (email for now) template.")
66+ /** Administrative action to create a new, re-usable communication (email for now) template. */
77 @procedure
88 @errors(DuplicateTemplateName)
99 op main(input: {
1010- @doc("Subject of the message, used in emails.")
1010+ /** Subject of the message, used in emails. */
1111 @required
1212 subject: string;
13131414- @doc("Content of the template, markdown supported, can contain variable placeholders.")
1414+ /** Content of the template, markdown supported, can contain variable placeholders. */
1515 @required
1616 contentMarkdown: string;
17171818- @doc("Name of the template.")
1818+ /** Name of the template. */
1919 @required
2020 name: string;
21212222- @doc("Message language.")
2222+ /** Message language. */
2323 lang?: language;
24242525- @doc("DID of the user who is creating the template.")
2525+ /** DID of the user who is creating the template. */
2626 createdBy?: did;
2727 }): tools.ozone.communication.defs.TemplateView;
2828}
2929+3030+// --- Externals ---
3131+3232+@external
3333+namespace tools.ozone.communication.defs {
3434+ model TemplateView { }
3535+}
···44 model TemplateView {
55 @required id: string;
6677- @doc("Name of the template.")
77+ /** Name of the template. */
88 @required
99 name: string;
10101111- @doc("Content of the template, can contain markdown and variable placeholders.")
1111+ /** Content of the template, can contain markdown and variable placeholders. */
1212 subject?: string;
13131414- @doc("Subject of the message, used in emails.")
1414+ /** Subject of the message, used in emails. */
1515 @required
1616 contentMarkdown: string;
17171818 @required disabled: boolean;
19192020- @doc("Message language.")
2020+ /** Message language. */
2121 lang?: language;
22222323- @doc("DID of the user who last updated the template.")
2323+ /** DID of the user who last updated the template. */
2424 @required
2525 lastUpdatedBy: did;
2626
···11import "@typelex/emitter";
2233namespace tools.ozone.communication.listTemplates {
44- @doc("Get list of all communication templates.")
44+ /** Get list of all communication templates. */
55 @query
66 op main(): {
77 @required communicationTemplates: tools.ozone.communication.defs.TemplateView[];
88 };
99}
1010+1111+// --- Externals ---
1212+1313+@external
1414+namespace tools.ozone.communication.defs {
1515+ model TemplateView { }
1616+}
···33namespace tools.ozone.communication.updateTemplate {
44 model DuplicateTemplateName {}
5566- @doc("Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only.")
66+ /** Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only. */
77 @procedure
88 @errors(DuplicateTemplateName)
99 op main(input: {
1010- @doc("ID of the template to be updated.")
1010+ /** ID of the template to be updated. */
1111 @required
1212 id: string;
13131414- @doc("Name of the template.")
1414+ /** Name of the template. */
1515 name?: string;
16161717- @doc("Message language.")
1717+ /** Message language. */
1818 lang?: language;
19192020- @doc("Content of the template, markdown supported, can contain variable placeholders.")
2020+ /** Content of the template, markdown supported, can contain variable placeholders. */
2121 contentMarkdown?: string;
22222323- @doc("Subject of the message, used in emails.")
2323+ /** Subject of the message, used in emails. */
2424 subject?: string;
25252626- @doc("DID of the user who is updating the template.")
2626+ /** DID of the user who is updating the template. */
2727 updatedBy?: did;
28282929 disabled?: boolean;
3030 }): tools.ozone.communication.defs.TemplateView;
3131}
3232+3333+// --- Externals ---
3434+3535+@external
3636+namespace tools.ozone.communication.defs {
3737+ model TemplateView { }
3838+}
···11import "@typelex/emitter";
2233namespace tools.ozone.hosting.getAccountHistory {
44- @doc("Get account history, e.g. log of updated email addresses or other identity information.")
44+ /** Get account history, e.g. log of updated email addresses or other identity information. */
55 @query
66 op main(
77 @required did: did,
···9494 subjectBlobCids?: cid[];
9595 subjectRepoHandle?: string;
96969797- @doc("Timestamp referencing the first moderation status impacting event was emitted on the subject")
9797+ /** Timestamp referencing the first moderation status impacting event was emitted on the subject */
9898 @required
9999 createdAt: datetime;
100100101101- @doc("Timestamp referencing when the last update was made to the moderation status of the subject")
101101+ /** Timestamp referencing when the last update was made to the moderation status of the subject */
102102 @required
103103 updatedAt: datetime;
104104105105 @required reviewState: SubjectReviewState;
106106107107- @doc("Sticky comment on the subject.")
107107+ /** Sticky comment on the subject. */
108108 comment?: string;
109109110110- @doc("Numeric value representing the level of priority. Higher score means higher priority.")
110110+ /** Numeric value representing the level of priority. Higher score means higher priority. */
111111 @minValue(0)
112112 @maxValue(100)
113113 priorityScore?: int32;
···118118 lastReviewedAt?: datetime;
119119 lastReportedAt?: datetime;
120120121121- @doc("Timestamp referencing when the author of the subject appealed a moderation action")
121121+ /** Timestamp referencing when the author of the subject appealed a moderation action */
122122 lastAppealedAt?: datetime;
123123124124 takendown?: boolean;
125125126126- @doc("True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators.")
126126+ /** True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators. */
127127 appealed?: boolean;
128128129129 suspendUntil?: datetime;
130130 tags?: string[];
131131132132- @doc("Statistics related to the account subject")
132132+ /** Statistics related to the account subject */
133133 accountStats?: AccountStats;
134134135135- @doc("Statistics related to the record subjects authored by the subject's account")
135135+ /** Statistics related to the record subjects authored by the subject's account */
136136 recordsStats?: RecordsStats;
137137138138- @doc("Current age assurance state of the subject.")
138138+ /** Current age assurance state of the subject. */
139139 ageAssuranceState?: "pending" | "assured" | "unknown" | "reset" | "blocked" | string;
140140141141- @doc("Whether or not the last successful update to age assurance was made by the user or admin.")
141141+ /** Whether or not the last successful update to age assurance was made by the user or admin. */
142142 ageAssuranceUpdatedBy?: "admin" | "user" | string;
143143 }
144144145145- @doc("Detailed view of a subject. For record subjects, the author's repo and profile will be returned.")
145145+ /** Detailed view of a subject. For record subjects, the author's repo and profile will be returned. */
146146 model SubjectView {
147147 @required type: com.atproto.moderation.defs.SubjectType;
148148 @required subject: string;
···152152 record?: RecordViewDetail;
153153 }
154154155155- @doc("Statistics about a particular account subject")
155155+ /** Statistics about a particular account subject */
156156 model AccountStats {
157157- @doc("Total number of reports on the account")
157157+ /** Total number of reports on the account */
158158 reportCount?: int32;
159159160160- @doc("Total number of appeals against a moderation action on the account")
160160+ /** Total number of appeals against a moderation action on the account */
161161 appealCount?: int32;
162162163163- @doc("Number of times the account was suspended")
163163+ /** Number of times the account was suspended */
164164 suspendCount?: int32;
165165166166- @doc("Number of times the account was escalated")
166166+ /** Number of times the account was escalated */
167167 escalateCount?: int32;
168168169169- @doc("Number of times the account was taken down")
169169+ /** Number of times the account was taken down */
170170 takedownCount?: int32;
171171 }
172172173173- @doc("Statistics about a set of record subject items")
173173+ /** Statistics about a set of record subject items */
174174 model RecordsStats {
175175- @doc("Cumulative sum of the number of reports on the items in the set")
175175+ /** Cumulative sum of the number of reports on the items in the set */
176176 totalReports?: int32;
177177178178- @doc("Number of items that were reported at least once")
178178+ /** Number of items that were reported at least once */
179179 reportedCount?: int32;
180180181181- @doc("Number of items that were escalated at least once")
181181+ /** Number of items that were escalated at least once */
182182 escalatedCount?: int32;
183183184184- @doc("Number of items that were appealed at least once")
184184+ /** Number of items that were appealed at least once */
185185 appealedCount?: int32;
186186187187- @doc("Total number of item in the set")
187187+ /** Total number of item in the set */
188188 subjectCount?: int32;
189189190190 @doc("Number of item currently in \"reviewOpen\" or \"reviewEscalated\" state")
···193193 @doc("Number of item currently in \"reviewNone\" or \"reviewClosed\" state")
194194 processedCount?: int32;
195195196196- @doc("Number of item currently taken down")
196196+ /** Number of item currently taken down */
197197 takendownCount?: int32;
198198 }
199199200200 union SubjectReviewState {
201201- "#reviewOpen",
202202- "#reviewEscalated",
203203- "#reviewClosed",
204204- "#reviewNone",
201201+ ReviewOpen,
202202+ ReviewEscalated,
203203+ ReviewClosed,
204204+ ReviewNone,
205205 string,
206206 }
207207208208- @doc("Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator")
208208+ /** Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator */
209209 @token
210210 model ReviewOpen {}
211211212212- @doc("Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator")
212212+ /** Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator */
213213 @token
214214 model ReviewEscalated {}
215215216216- @doc("Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator")
216216+ /** Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator */
217217 @token
218218 model ReviewClosed {}
219219220220- @doc("Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it")
220220+ /** Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it */
221221 @token
222222 model ReviewNone {}
223223224224- @doc("Take down a subject permanently or temporarily")
224224+ /** Take down a subject permanently or temporarily */
225225 model ModEventTakedown {
226226 comment?: string;
227227228228- @doc("Indicates how long the takedown should be in effect before automatically expiring.")
228228+ /** Indicates how long the takedown should be in effect before automatically expiring. */
229229 durationInHours?: int32;
230230231231- @doc("If true, all other reports on content authored by this account will be resolved (acknowledged).")
231231+ /** If true, all other reports on content authored by this account will be resolved (acknowledged). */
232232 acknowledgeAccountSubjects?: boolean;
233233234234- @doc("Names/Keywords of the policies that drove the decision.")
234234+ /** Names/Keywords of the policies that drove the decision. */
235235 @maxItems(5)
236236 policies?: string[];
237237 }
238238239239- @doc("Revert take down action on a subject")
239239+ /** Revert take down action on a subject */
240240 model ModEventReverseTakedown {
241241- @doc("Describe reasoning behind the reversal.")
241241+ /** Describe reasoning behind the reversal. */
242242 comment?: string;
243243 }
244244245245- @doc("Resolve appeal on a subject")
245245+ /** Resolve appeal on a subject */
246246 model ModEventResolveAppeal {
247247- @doc("Describe resolution.")
247247+ /** Describe resolution. */
248248 comment?: string;
249249 }
250250251251- @doc("Add a comment to a subject. An empty comment will clear any previously set sticky comment.")
251251+ /** Add a comment to a subject. An empty comment will clear any previously set sticky comment. */
252252 model ModEventComment {
253253 comment?: string;
254254255255- @doc("Make the comment persistent on the subject")
255255+ /** Make the comment persistent on the subject */
256256 sticky?: boolean;
257257 }
258258259259- @doc("Report a subject")
259259+ /** Report a subject */
260260 model ModEventReport {
261261 comment?: string;
262262263263- @doc("Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject.")
263263+ /** Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject. */
264264 isReporterMuted?: boolean;
265265266266 @required reportType: com.atproto.moderation.defs.ReasonType;
267267 }
268268269269- @doc("Apply/Negate labels on a subject")
269269+ /** Apply/Negate labels on a subject */
270270 model ModEventLabel {
271271 comment?: string;
272272 @required createLabelVals: string[];
273273 @required negateLabelVals: string[];
274274275275- @doc("Indicates how long the label will remain on the subject. Only applies on labels that are being added.")
275275+ /** Indicates how long the label will remain on the subject. Only applies on labels that are being added. */
276276 durationInHours?: int32;
277277 }
278278279279- @doc("Set priority score of the subject. Higher score means higher priority.")
279279+ /** Set priority score of the subject. Higher score means higher priority. */
280280 model ModEventPriorityScore {
281281 comment?: string;
282282···286286 score: int32;
287287 }
288288289289- @doc("Age assurance info coming directly from users. Only works on DID subjects.")
289289+ /** Age assurance info coming directly from users. Only works on DID subjects. */
290290 model AgeAssuranceEvent {
291291- @doc("The date and time of this write operation.")
291291+ /** The date and time of this write operation. */
292292 @required
293293 createdAt: datetime;
294294295295- @doc("The status of the age assurance process.")
295295+ /** The status of the age assurance process. */
296296 @required
297297 status: "unknown" | "pending" | "assured" | string;
298298299299- @doc("The unique identifier for this instance of the age assurance flow, in UUID format.")
299299+ /** The unique identifier for this instance of the age assurance flow, in UUID format. */
300300 @required
301301 attemptId: string;
302302303303- @doc("The IP address used when initiating the AA flow.")
303303+ /** The IP address used when initiating the AA flow. */
304304 initIp?: string;
305305306306- @doc("The user agent used when initiating the AA flow.")
306306+ /** The user agent used when initiating the AA flow. */
307307 initUa?: string;
308308309309- @doc("The IP address used when completing the AA flow.")
309309+ /** The IP address used when completing the AA flow. */
310310 completeIp?: string;
311311312312- @doc("The user agent used when completing the AA flow.")
312312+ /** The user agent used when completing the AA flow. */
313313 completeUa?: string;
314314 }
315315316316- @doc("Age assurance status override by moderators. Only works on DID subjects.")
316316+ /** Age assurance status override by moderators. Only works on DID subjects. */
317317 model AgeAssuranceOverrideEvent {
318318- @doc("Comment describing the reason for the override.")
318318+ /** Comment describing the reason for the override. */
319319 @required
320320 comment: string;
321321322322- @doc("The status to be set for the user decided by a moderator, overriding whatever value the user had previously. Use reset to default to original state.")
322322+ /** The status to be set for the user decided by a moderator, overriding whatever value the user had previously. Use reset to default to original state. */
323323 @required
324324 status: "assured" | "reset" | "blocked" | string;
325325 }
326326327327- @doc("Account credentials revocation by moderators. Only works on DID subjects.")
327327+ /** Account credentials revocation by moderators. Only works on DID subjects. */
328328 model RevokeAccountCredentialsEvent {
329329- @doc("Comment describing the reason for the revocation.")
329329+ /** Comment describing the reason for the revocation. */
330330 @required
331331 comment: string;
332332 }
···334334 model ModEventAcknowledge {
335335 comment?: string;
336336337337- @doc("If true, all other reports on content authored by this account will be resolved (acknowledged).")
337337+ /** If true, all other reports on content authored by this account will be resolved (acknowledged). */
338338 acknowledgeAccountSubjects?: boolean;
339339 }
340340···342342 comment?: string;
343343 }
344344345345- @doc("Mute incoming reports on a subject")
345345+ /** Mute incoming reports on a subject */
346346 model ModEventMute {
347347 comment?: string;
348348349349- @doc("Indicates how long the subject should remain muted.")
349349+ /** Indicates how long the subject should remain muted. */
350350 @required
351351 durationInHours: int32;
352352 }
353353354354- @doc("Unmute action on a subject")
354354+ /** Unmute action on a subject */
355355 model ModEventUnmute {
356356- @doc("Describe reasoning behind the reversal.")
356356+ /** Describe reasoning behind the reversal. */
357357 comment?: string;
358358 }
359359360360- @doc("Mute incoming reports from an account")
360360+ /** Mute incoming reports from an account */
361361 model ModEventMuteReporter {
362362 comment?: string;
363363364364- @doc("Indicates how long the account should remain muted. Falsy value here means a permanent mute.")
364364+ /** Indicates how long the account should remain muted. Falsy value here means a permanent mute. */
365365 durationInHours?: int32;
366366 }
367367368368- @doc("Unmute incoming reports from an account")
368368+ /** Unmute incoming reports from an account */
369369 model ModEventUnmuteReporter {
370370- @doc("Describe reasoning behind the reversal.")
370370+ /** Describe reasoning behind the reversal. */
371371 comment?: string;
372372 }
373373374374- @doc("Keep a log of outgoing email to a user")
374374+ /** Keep a log of outgoing email to a user */
375375 model ModEventEmail {
376376- @doc("The subject line of the email sent to the user.")
376376+ /** The subject line of the email sent to the user. */
377377 @required
378378 subjectLine: string;
379379380380- @doc("The content of the email sent to the user.")
380380+ /** The content of the email sent to the user. */
381381 content?: string;
382382383383- @doc("Additional comment about the outgoing comm.")
383383+ /** Additional comment about the outgoing comm. */
384384 comment?: string;
385385 }
386386387387- @doc("Divert a record's blobs to a 3rd party service for further scanning/tagging")
387387+ /** Divert a record's blobs to a 3rd party service for further scanning/tagging */
388388 model ModEventDivert {
389389 comment?: string;
390390 }
391391392392- @doc("Add/Remove a tag on a subject")
392392+ /** Add/Remove a tag on a subject */
393393 model ModEventTag {
394394- @doc("Tags to be added to the subject. If already exists, won't be duplicated.")
394394+ /** Tags to be added to the subject. If already exists, won't be duplicated. */
395395 @required
396396 add: string[];
397397398398- @doc("Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated.")
398398+ /** Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated. */
399399 @required
400400 remove: string[];
401401402402- @doc("Additional comment about added/removed tags.")
402402+ /** Additional comment about added/removed tags. */
403403 comment?: string;
404404 }
405405406406- @doc("Logs account status related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking.")
406406+ /** Logs account status related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
407407 model AccountEvent {
408408 comment?: string;
409409 @required timestamp: datetime;
410410411411- @doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
411411+ /** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
412412 @required
413413 active: boolean;
414414415415 status?: "unknown" | "deactivated" | "deleted" | "takendown" | "suspended" | "tombstoned" | string;
416416 }
417417418418- @doc("Logs identity related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking.")
418418+ /** Logs identity related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
419419 model IdentityEvent {
420420 comment?: string;
421421 handle?: handle;
···424424 @required timestamp: datetime;
425425 }
426426427427- @doc("Logs lifecycle event on a record subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking.")
427427+ /** Logs lifecycle event on a record subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
428428 model RecordEvent {
429429 comment?: string;
430430 @required timestamp: datetime;
···546546 model ReporterStats {
547547 @required did: did;
548548549549- @doc("The total number of reports made by the user on accounts.")
549549+ /** The total number of reports made by the user on accounts. */
550550 @required
551551 accountReportCount: int32;
552552553553- @doc("The total number of reports made by the user on records.")
553553+ /** The total number of reports made by the user on records. */
554554 @required
555555 recordReportCount: int32;
556556557557- @doc("The total number of accounts reported by the user.")
557557+ /** The total number of accounts reported by the user. */
558558 @required
559559 reportedAccountCount: int32;
560560561561- @doc("The total number of records reported by the user.")
561561+ /** The total number of records reported by the user. */
562562 @required
563563 reportedRecordCount: int32;
564564565565- @doc("The total number of accounts taken down as a result of the user's reports.")
565565+ /** The total number of accounts taken down as a result of the user's reports. */
566566 @required
567567 takendownAccountCount: int32;
568568569569- @doc("The total number of records taken down as a result of the user's reports.")
569569+ /** The total number of records taken down as a result of the user's reports. */
570570 @required
571571 takendownRecordCount: int32;
572572573573- @doc("The total number of accounts labeled as a result of the user's reports.")
573573+ /** The total number of accounts labeled as a result of the user's reports. */
574574 @required
575575 labeledAccountCount: int32;
576576577577- @doc("The total number of records labeled as a result of the user's reports.")
577577+ /** The total number of records labeled as a result of the user's reports. */
578578 @required
579579 labeledRecordCount: int32;
580580 }
581581582582- @doc("Moderation tool information for tracing the source of the action")
582582+ /** Moderation tool information for tracing the source of the action */
583583 model ModTool {
584584- @doc("Name/identifier of the source (e.g., 'automod', 'ozone/workspace')")
584584+ /** Name/identifier of the source (e.g., 'automod', 'ozone/workspace') */
585585 @required
586586 name: string;
587587588588- @doc("Additional arbitrary metadata about the source")
588588+ /** Additional arbitrary metadata about the source */
589589 meta?: unknown;
590590 }
591591592592- @doc("Moderation event timeline event for a PLC create operation")
592592+ /** Moderation event timeline event for a PLC create operation */
593593 @token
594594 model TimelineEventPlcCreate {}
595595596596- @doc("Moderation event timeline event for generic PLC operation")
596596+ /** Moderation event timeline event for generic PLC operation */
597597 @token
598598 model TimelineEventPlcOperation {}
599599600600- @doc("Moderation event timeline event for a PLC tombstone operation")
600600+ /** Moderation event timeline event for a PLC tombstone operation */
601601 @token
602602 model TimelineEventPlcTombstone {}
603603}
604604+605605+// --- Externals ---
606606+607607+@external
608608+namespace com.atproto.admin.defs {
609609+ model RepoRef { }
610610+ model ThreatSignature { }
611611+}
612612+613613+@external
614614+namespace com.atproto.repo.strongRef {
615615+ model Main { }
616616+}
617617+618618+@external
619619+namespace chat.bsky.convo.defs {
620620+ model MessageRef { }
621621+}
622622+623623+@external
624624+namespace com.atproto.moderation.defs {
625625+ model SubjectType { }
626626+ model ReasonType { }
627627+}
628628+629629+@external
630630+namespace com.atproto.server.defs {
631631+ model InviteCode { }
632632+}
633633+634634+@external
635635+namespace com.atproto.label.defs {
636636+ model Label { }
637637+}
···33namespace tools.ozone.moderation.emitEvent {
44 model SubjectHasAction {}
5566- @doc("An event with the same external ID already exists for the subject.")
66+ /** An event with the same external ID already exists for the subject. */
77 model DuplicateExternalId {}
8899- @doc("Take a moderation action on an actor.")
99+ /** Take a moderation action on an actor. */
1010 @procedure
1111 @errors(SubjectHasAction, DuplicateExternalId)
1212 op main(input: {
···50505151 modTool?: tools.ozone.moderation.defs.ModTool;
52525353- @doc("An optional external ID for the event, used to deduplicate events from external systems. Fails when an event of same type with the same external ID exists for the same subject.")
5353+ /** An optional external ID for the event, used to deduplicate events from external systems. Fails when an event of same type with the same external ID exists for the same subject. */
5454 externalId?: string;
5555 }): tools.ozone.moderation.defs.ModEventView;
5656}
5757+5858+// --- Externals ---
5959+6060+@external
6161+namespace tools.ozone.moderation.defs {
6262+ model ModEventTakedown { }
6363+ model ModEventAcknowledge { }
6464+ model ModEventEscalate { }
6565+ model ModEventComment { }
6666+ model ModEventLabel { }
6767+ model ModEventReport { }
6868+ model ModEventMute { }
6969+ model ModEventUnmute { }
7070+ model ModEventMuteReporter { }
7171+ model ModEventUnmuteReporter { }
7272+ model ModEventReverseTakedown { }
7373+ model ModEventResolveAppeal { }
7474+ model ModEventEmail { }
7575+ model ModEventDivert { }
7676+ model ModEventTag { }
7777+ model AccountEvent { }
7878+ model IdentityEvent { }
7979+ model RecordEvent { }
8080+ model ModEventPriorityScore { }
8181+ model AgeAssuranceEvent { }
8282+ model AgeAssuranceOverrideEvent { }
8383+ model RevokeAccountCredentialsEvent { }
8484+ model ModTool { }
8585+ model ModEventView { }
8686+}
8787+8888+@external
8989+namespace com.atproto.admin.defs {
9090+ model RepoRef { }
9191+}
9292+9393+@external
9494+namespace com.atproto.repo.strongRef {
9595+ model Main { }
9696+}
···33namespace tools.ozone.moderation.getAccountTimeline {
44 model RepoNotFound {}
5566- @doc("Get timeline of all available events of an account. This includes moderation events, account history and did history.")
66+ /** Get timeline of all available events of an account. This includes moderation events, account history and did history. */
77 @query
88 @errors(RepoNotFound)
99 op main(@required did: did): {
···5555 @required count: integer;
5656 }
5757}
5858+5959+// --- Externals ---
6060+6161+@external
6262+namespace tools.ozone.moderation.defs {
6363+ model ModEventTakedown { }
6464+ model ModEventReverseTakedown { }
6565+ model ModEventComment { }
6666+ model ModEventReport { }
6767+ model ModEventLabel { }
6868+ model ModEventAcknowledge { }
6969+ model ModEventEscalate { }
7070+ model ModEventMute { }
7171+ model ModEventUnmute { }
7272+ model ModEventMuteReporter { }
7373+ model ModEventUnmuteReporter { }
7474+ model ModEventEmail { }
7575+ model ModEventResolveAppeal { }
7676+ model ModEventDivert { }
7777+ model ModEventTag { }
7878+ model AccountEvent { }
7979+ model IdentityEvent { }
8080+ model RecordEvent { }
8181+ model ModEventPriorityScore { }
8282+ model RevokeAccountCredentialsEvent { }
8383+ model AgeAssuranceEvent { }
8484+ model AgeAssuranceOverrideEvent { }
8585+ @token model TimelineEventPlcCreate { }
8686+ @token model TimelineEventPlcOperation { }
8787+ @token model TimelineEventPlcTombstone { }
8888+}
8989+9090+@external
9191+namespace tools.ozone.hosting.getAccountHistory {
9292+ model AccountCreated { }
9393+ model EmailConfirmed { }
9494+ model PasswordUpdated { }
9595+ model HandleUpdated { }
9696+}
···11import "@typelex/emitter";
2233namespace tools.ozone.moderation.getReporterStats {
44- @doc("Get reporter stats for a list of users.")
44+ /** Get reporter stats for a list of users. */
55 @query
66 op main(
77 @maxItems(100)
···1111 @required stats: tools.ozone.moderation.defs.ReporterStats[];
1212 };
1313}
1414+1515+// --- Externals ---
1616+1717+@external
1818+namespace tools.ozone.moderation.defs {
1919+ model ReporterStats { }
2020+}
···88 "desc",
99 }
10101111- @doc("List moderation events related to a subject.")
1111+ /** List moderation events related to a subject. */
1212 @query
1313 op main(
1414- @doc("The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent<name>) to filter by. If not specified, all events are returned.")
1414+ /** The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent<name>) to filter by. If not specified, all events are returned. */
1515 types?: string[],
16161717 createdBy?: did,
18181919- @doc("Sort direction for the events. Defaults to descending order of created at timestamp.")
1919+ /** Sort direction for the events. Defaults to descending order of created at timestamp. */
2020 sortDirection?: SortDirection = "desc",
21212222- @doc("Retrieve events created after a given timestamp")
2222+ /** Retrieve events created after a given timestamp */
2323 createdAfter?: datetime,
24242525- @doc("Retrieve events created before a given timestamp")
2525+ /** Retrieve events created before a given timestamp */
2626 createdBefore?: datetime,
27272828 subject?: uri,
29293030 @maxItems(20)
3131- @doc("If specified, only events where the subject belongs to the given collections will be returned. When subjectType is set to 'account', this will be ignored.")
3131+ /** If specified, only events where the subject belongs to the given collections will be returned. When subjectType is set to 'account', this will be ignored. */
3232 collections?: nsid[],
33333434- @doc("If specified, only events where the subject is of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored.")
3434+ /** If specified, only events where the subject is of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored. */
3535 subjectType?: "account" | "record" | string,
36363737- @doc("If true, events on all record types (posts, lists, profile etc.) or records from given 'collections' param, owned by the did are returned.")
3737+ /** If true, events on all record types (posts, lists, profile etc.) or records from given 'collections' param, owned by the did are returned. */
3838 includeAllUserRecords?: boolean = false,
39394040 @minValue(1)
4141 @maxValue(100)
4242 limit?: int32 = 50,
43434444- @doc("If true, only events with comments are returned")
4444+ /** If true, only events with comments are returned */
4545 hasComment?: boolean,
46464747- @doc("If specified, only events with comments containing the keyword are returned. Apply || separator to use multiple keywords and match using OR condition.")
4747+ /** If specified, only events with comments containing the keyword are returned. Apply || separator to use multiple keywords and match using OR condition. */
4848 comment?: string,
49495050- @doc("If specified, only events where all of these labels were added are returned")
5050+ /** If specified, only events where all of these labels were added are returned */
5151 addedLabels?: string[],
52525353- @doc("If specified, only events where all of these labels were removed are returned")
5353+ /** If specified, only events where all of these labels were removed are returned */
5454 removedLabels?: string[],
55555656- @doc("If specified, only events where all of these tags were added are returned")
5656+ /** If specified, only events where all of these tags were added are returned */
5757 addedTags?: string[],
58585959- @doc("If specified, only events where all of these tags were removed are returned")
5959+ /** If specified, only events where all of these tags were removed are returned */
6060 removedTags?: string[],
61616262 reportTypes?: string[],
63636464- @doc("If specified, only events where the action policies match any of the given policies are returned")
6464+ /** If specified, only events where the action policies match any of the given policies are returned */
6565 policies?: string[],
66666767- @doc("If specified, only events where the modTool name matches any of the given values are returned")
6767+ /** If specified, only events where the modTool name matches any of the given values are returned */
6868 modTool?: string[],
69697070- @doc("If specified, only events where the batchId matches the given value are returned")
7070+ /** If specified, only events where the batchId matches the given value are returned */
7171 batchId?: string,
72727373- @doc("If specified, only events where the age assurance state matches the given value are returned")
7373+ /** If specified, only events where the age assurance state matches the given value are returned */
7474 ageAssuranceState?: "pending" | "assured" | "unknown" | "reset" | "blocked" | string,
75757676 cursor?: string
···8080 @required events: tools.ozone.moderation.defs.ModEventView[];
8181 };
8282}
8383+8484+// --- Externals ---
8585+8686+@external
8787+namespace tools.ozone.moderation.defs {
8888+ model ModEventView { }
8989+}
···1818 "desc",
1919 }
20202121- @doc("View moderation statuses of subjects (record or repo).")
2121+ /** View moderation statuses of subjects (record or repo). */
2222 @query
2323 op main(
2424- @doc("Number of queues being used by moderators. Subjects will be split among all queues.")
2424+ /** Number of queues being used by moderators. Subjects will be split among all queues. */
2525 queueCount?: integer,
26262727- @doc("Index of the queue to fetch subjects from. Works only when queueCount value is specified.")
2727+ /** Index of the queue to fetch subjects from. Works only when queueCount value is specified. */
2828 queueIndex?: integer,
29293030- @doc("A seeder to shuffle/balance the queue items.")
3030+ /** A seeder to shuffle/balance the queue items. */
3131 queueSeed?: string,
32323333- @doc("All subjects, or subjects from given 'collections' param, belonging to the account specified in the 'subject' param will be returned.")
3333+ /** All subjects, or subjects from given 'collections' param, belonging to the account specified in the 'subject' param will be returned. */
3434 includeAllUserRecords?: boolean,
35353636- @doc("The subject to get the status for.")
3636+ /** The subject to get the status for. */
3737 subject?: uri,
38383939- @doc("Search subjects by keyword from comments")
3939+ /** Search subjects by keyword from comments */
4040 comment?: string,
41414242- @doc("Search subjects reported after a given timestamp")
4242+ /** Search subjects reported after a given timestamp */
4343 reportedAfter?: datetime,
44444545- @doc("Search subjects reported before a given timestamp")
4545+ /** Search subjects reported before a given timestamp */
4646 reportedBefore?: datetime,
47474848- @doc("Search subjects reviewed after a given timestamp")
4848+ /** Search subjects reviewed after a given timestamp */
4949 reviewedAfter?: datetime,
50505151- @doc("Search subjects where the associated record/account was deleted after a given timestamp")
5151+ /** Search subjects where the associated record/account was deleted after a given timestamp */
5252 hostingDeletedAfter?: datetime,
53535454- @doc("Search subjects where the associated record/account was deleted before a given timestamp")
5454+ /** Search subjects where the associated record/account was deleted before a given timestamp */
5555 hostingDeletedBefore?: datetime,
56565757- @doc("Search subjects where the associated record/account was updated after a given timestamp")
5757+ /** Search subjects where the associated record/account was updated after a given timestamp */
5858 hostingUpdatedAfter?: datetime,
59596060- @doc("Search subjects where the associated record/account was updated before a given timestamp")
6060+ /** Search subjects where the associated record/account was updated before a given timestamp */
6161 hostingUpdatedBefore?: datetime,
62626363- @doc("Search subjects by the status of the associated record/account")
6363+ /** Search subjects by the status of the associated record/account */
6464 hostingStatuses?: string[],
65656666- @doc("Search subjects reviewed before a given timestamp")
6666+ /** Search subjects reviewed before a given timestamp */
6767 reviewedBefore?: datetime,
68686969- @doc("By default, we don't include muted subjects in the results. Set this to true to include them.")
6969+ /** By default, we don't include muted subjects in the results. Set this to true to include them. */
7070 includeMuted?: boolean,
71717272- @doc("When set to true, only muted subjects and reporters will be returned.")
7272+ /** When set to true, only muted subjects and reporters will be returned. */
7373 onlyMuted?: boolean,
74747575- @doc("Specify when fetching subjects in a certain state")
7575+ /** Specify when fetching subjects in a certain state */
7676 reviewState?: string,
77777878 ignoreSubjects?: uri[],
79798080- @doc("Get all subject statuses that were reviewed by a specific moderator")
8080+ /** Get all subject statuses that were reviewed by a specific moderator */
8181 lastReviewedBy?: did,
82828383 sortField?: SortField = "lastReportedAt",
84848585 sortDirection?: SortDirection = "desc",
86868787- @doc("Get subjects that were taken down")
8787+ /** Get subjects that were taken down */
8888 takendown?: boolean,
89899090- @doc("Get subjects in unresolved appealed status")
9090+ /** Get subjects in unresolved appealed status */
9191 appealed?: boolean,
92929393 @minValue(1)
9494 @maxValue(100)
9595 limit?: int32 = 50,
96969797- @doc("Items in this array are applied with OR filters. To apply AND filter, put all tags in the same string and separate using && characters")
9797+ /** Items in this array are applied with OR filters. To apply AND filter, put all tags in the same string and separate using && characters */
9898 @maxItems(25)
9999 tags?: string[],
100100···103103 cursor?: string,
104104105105 @maxItems(20)
106106- @doc("If specified, subjects belonging to the given collections will be returned. When subjectType is set to 'account', this will be ignored.")
106106+ /** If specified, subjects belonging to the given collections will be returned. When subjectType is set to 'account', this will be ignored. */
107107 collections?: nsid[],
108108109109- @doc("If specified, subjects of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored.")
109109+ /** If specified, subjects of the given type (account or record) will be returned. When this is set to 'account' the 'collections' parameter will be ignored. When includeAllUserRecords or subject is set, this will be ignored. */
110110 subjectType?: "account" | "record" | string,
111111112112- @doc("If specified, only subjects that belong to an account that has at least this many suspensions will be returned.")
112112+ /** If specified, only subjects that belong to an account that has at least this many suspensions will be returned. */
113113 minAccountSuspendCount?: integer,
114114115115- @doc("If specified, only subjects that belong to an account that has at least this many reported records will be returned.")
115115+ /** If specified, only subjects that belong to an account that has at least this many reported records will be returned. */
116116 minReportedRecordsCount?: integer,
117117118118- @doc("If specified, only subjects that belong to an account that has at least this many taken down records will be returned.")
118118+ /** If specified, only subjects that belong to an account that has at least this many taken down records will be returned. */
119119 minTakendownRecordsCount?: integer,
120120121121 @minValue(0)
122122 @maxValue(100)
123123- @doc("If specified, only subjects that have priority score value above the given value will be returned.")
123123+ /** If specified, only subjects that have priority score value above the given value will be returned. */
124124 minPriorityScore?: integer,
125125126126- @doc("If specified, only subjects with the given age assurance state will be returned.")
126126+ /** If specified, only subjects with the given age assurance state will be returned. */
127127 ageAssuranceState?: "pending" | "assured" | "unknown" | "reset" | "blocked" | string
128128 ): {
129129 cursor?: string;
···131131 @required subjectStatuses: tools.ozone.moderation.defs.SubjectStatusView[];
132132 };
133133}
134134+135135+// --- Externals ---
136136+137137+@external
138138+namespace tools.ozone.moderation.defs {
139139+ model SubjectStatusView { }
140140+}
···11import "@typelex/emitter";
2233namespace tools.ozone.safelink.addRule {
44- @doc("The provided URL is invalid")
44+ /** The provided URL is invalid */
55 model InvalidUrl {}
6677- @doc("A rule for this URL/domain already exists")
77+ /** A rule for this URL/domain already exists */
88 model RuleAlreadyExists {}
991010- @doc("Add a new URL safety rule")
1010+ /** Add a new URL safety rule */
1111 @procedure
1212 @errors(InvalidUrl, RuleAlreadyExists)
1313 op main(input: {
1414- @doc("The URL or domain to apply the rule to")
1414+ /** The URL or domain to apply the rule to */
1515 @required
1616 url: string;
1717···21212222 @required reason: tools.ozone.safelink.defs.ReasonType;
23232424- @doc("Optional comment about the decision")
2424+ /** Optional comment about the decision */
2525 comment?: string;
26262727- @doc("Author DID. Only respected when using admin auth")
2727+ /** Author DID. Only respected when using admin auth */
2828 createdBy?: did;
2929 }): tools.ozone.safelink.defs.Event;
3030}
3131+3232+// --- Externals ---
3333+3434+@external
3535+namespace tools.ozone.safelink.defs {
3636+ model PatternType { }
3737+ model ActionType { }
3838+ model ReasonType { }
3939+ model Event { }
4040+}
···11import "@typelex/emitter";
2233namespace tools.ozone.safelink.defs {
44- @doc("An event for URL safety decisions")
44+ /** An event for URL safety decisions */
55 model Event {
66- @doc("Auto-incrementing row ID")
66+ /** Auto-incrementing row ID */
77 @required
88 id: int32;
991010 @required eventType: EventType;
11111212- @doc("The URL that this rule applies to")
1212+ /** The URL that this rule applies to */
1313 @required
1414 url: string;
1515···1717 @required action: ActionType;
1818 @required reason: ReasonType;
19192020- @doc("DID of the user who created this rule")
2020+ /** DID of the user who created this rule */
2121 @required
2222 createdBy: did;
23232424 @required createdAt: datetime;
25252626- @doc("Optional comment about the decision")
2626+ /** Optional comment about the decision */
2727 comment?: string;
2828 }
2929···5555 string,
5656 }
57575858- @doc("Input for creating a URL safety rule")
5858+ /** Input for creating a URL safety rule */
5959 model UrlRule {
6060- @doc("The URL or domain to apply the rule to")
6060+ /** The URL or domain to apply the rule to */
6161 @required
6262 url: string;
6363···6565 @required action: ActionType;
6666 @required reason: ReasonType;
67676868- @doc("Optional comment about the decision")
6868+ /** Optional comment about the decision */
6969 comment?: string;
70707171- @doc("DID of the user added the rule.")
7171+ /** DID of the user added the rule. */
7272 @required
7373 createdBy: did;
74747575- @doc("Timestamp when the rule was created")
7575+ /** Timestamp when the rule was created */
7676 @required
7777 createdAt: datetime;
78787979- @doc("Timestamp when the rule was last updated")
7979+ /** Timestamp when the rule was last updated */
8080 @required
8181 updatedAt: datetime;
8282 }
···11import "@typelex/emitter";
2233namespace tools.ozone.safelink.queryEvents {
44- @doc("Query URL safety audit events")
44+ /** Query URL safety audit events */
55 @procedure
66 op main(input: {
77- @doc("Cursor for pagination")
77+ /** Cursor for pagination */
88 cursor?: string;
991010 @minValue(1)
1111 @maxValue(100)
1212- @doc("Maximum number of results to return")
1212+ /** Maximum number of results to return */
1313 limit?: int32 = 50;
14141515- @doc("Filter by specific URLs or domains")
1515+ /** Filter by specific URLs or domains */
1616 urls?: string[];
17171818- @doc("Filter by pattern type")
1818+ /** Filter by pattern type */
1919 patternType?: string;
20202121- @doc("Sort direction")
2121+ /** Sort direction */
2222 sortDirection?: "asc" | "desc" | string = "desc";
2323 }): {
2424- @doc("Next cursor for pagination. Only present if there are more results.")
2424+ /** Next cursor for pagination. Only present if there are more results. */
2525 cursor?: string;
26262727 @required events: tools.ozone.safelink.defs.Event[];
2828 };
2929}
3030+3131+// --- Externals ---
3232+3333+@external
3434+namespace tools.ozone.safelink.defs {
3535+ model Event { }
3636+}
···11import "@typelex/emitter";
2233namespace tools.ozone.safelink.removeRule {
44- @doc("No active rule found for this URL/domain")
44+ /** No active rule found for this URL/domain */
55 model RuleNotFound {}
6677- @doc("Remove an existing URL safety rule")
77+ /** Remove an existing URL safety rule */
88 @procedure
99 @errors(RuleNotFound)
1010 op main(input: {
1111- @doc("The URL or domain to remove the rule for")
1111+ /** The URL or domain to remove the rule for */
1212 @required
1313 url: string;
14141515 @required pattern: tools.ozone.safelink.defs.PatternType;
16161717- @doc("Optional comment about why the rule is being removed")
1717+ /** Optional comment about why the rule is being removed */
1818 comment?: string;
19192020- @doc("Optional DID of the user. Only respected when using admin auth.")
2020+ /** Optional DID of the user. Only respected when using admin auth. */
2121 createdBy?: did;
2222 }): tools.ozone.safelink.defs.Event;
2323}
2424+2525+// --- Externals ---
2626+2727+@external
2828+namespace tools.ozone.safelink.defs {
2929+ model PatternType { }
3030+ model Event { }
3131+}
···11import "@typelex/emitter";
2233namespace tools.ozone.safelink.updateRule {
44- @doc("No active rule found for this URL/domain")
44+ /** No active rule found for this URL/domain */
55 model RuleNotFound {}
6677- @doc("Update an existing URL safety rule")
77+ /** Update an existing URL safety rule */
88 @procedure
99 @errors(RuleNotFound)
1010 op main(input: {
1111- @doc("The URL or domain to update the rule for")
1111+ /** The URL or domain to update the rule for */
1212 @required
1313 url: string;
1414···18181919 @required reason: tools.ozone.safelink.defs.ReasonType;
20202121- @doc("Optional comment about the update")
2121+ /** Optional comment about the update */
2222 comment?: string;
23232424- @doc("Optional DID to credit as the creator. Only respected for admin_token authentication.")
2424+ /** Optional DID to credit as the creator. Only respected for admin_token authentication. */
2525 createdBy?: did;
2626 }): tools.ozone.safelink.defs.Event;
2727}
2828+2929+// --- Externals ---
3030+3131+@external
3232+namespace tools.ozone.safelink.defs {
3333+ model PatternType { }
3434+ model ActionType { }
3535+ model ReasonType { }
3636+ model Event { }
3737+}
···11import "@typelex/emitter";
2233namespace tools.ozone.set.addValues {
44- @doc("Add values to a specific set. Attempting to add values to a set that does not exist will result in an error.")
44+ /** Add values to a specific set. Attempting to add values to a set that does not exist will result in an error. */
55 @procedure
66 op main(input: {
77- @doc("Name of the set to add values to")
77+ /** Name of the set to add values to */
88 @required
99 name: string;
10101111 @minItems(1)
1212 @maxItems(1000)
1313- @doc("Array of string values to add to the set")
1313+ /** Array of string values to add to the set */
1414 @required
1515 values: string[];
1616 }): void;
···11import "@typelex/emitter";
2233namespace tools.ozone.set.deleteSet {
44- @doc("set with the given name does not exist")
44+ /** set with the given name does not exist */
55 model SetNotFound {}
6677- @doc("Delete an entire set. Attempting to delete a set that does not exist will result in an error.")
77+ /** Delete an entire set. Attempting to delete a set that does not exist will result in an error. */
88 @procedure
99 @errors(SetNotFound)
1010 op main(input: {
1111- @doc("Name of the set to delete")
1111+ /** Name of the set to delete */
1212 @required
1313 name: string;
1414 }): {};
···11import "@typelex/emitter";
2233namespace tools.ozone.set.deleteValues {
44- @doc("set with the given name does not exist")
44+ /** set with the given name does not exist */
55 model SetNotFound {}
6677- @doc("Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error")
77+ /** Delete values from a specific set. Attempting to delete values that are not in the set will not result in an error */
88 @procedure
99 @errors(SetNotFound)
1010 op main(input: {
1111- @doc("Name of the set to delete values from")
1111+ /** Name of the set to delete values from */
1212 @required
1313 name: string;
14141515 @minItems(1)
1616- @doc("Array of string values to delete from the set")
1616+ /** Array of string values to delete from the set */
1717 @required
1818 values: string[];
1919 }): void;
···11import "@typelex/emitter";
2233namespace tools.ozone.set.getValues {
44- @doc("set with the given name does not exist")
44+ /** set with the given name does not exist */
55 model SetNotFound {}
6677- @doc("Get a specific set and its values")
77+ /** Get a specific set and its values */
88 @query
99 @errors(SetNotFound)
1010 op main(
···2323 cursor?: string;
2424 };
2525}
2626+2727+// --- Externals ---
2828+2929+@external
3030+namespace tools.ozone.set.defs {
3131+ model SetView { }
3232+}
···11import "@typelex/emitter";
2233namespace tools.ozone.signature.searchAccounts {
44- @doc("Search for accounts that match one or more threat signature values.")
44+ /** Search for accounts that match one or more threat signature values. */
55 @query
66 op main(
77 @required values: string[],
···1717 @required accounts: com.atproto.admin.defs.AccountView[];
1818 };
1919}
2020+2121+// --- Externals ---
2222+2323+@external
2424+namespace com.atproto.admin.defs {
2525+ model AccountView { }
2626+}
···11import "@typelex/emitter";
2233namespace tools.ozone.team.deleteMember {
44- @doc("The member being deleted does not exist")
44+ /** The member being deleted does not exist */
55 model MemberNotFound {}
6677- @doc("You can not delete yourself from the team")
77+ /** You can not delete yourself from the team */
88 model CannotDeleteSelf {}
991010- @doc("Delete a member from ozone team. Requires admin role.")
1010+ /** Delete a member from ozone team. Requires admin role. */
1111 @procedure
1212 @errors(MemberNotFound, CannotDeleteSelf)
1313 op main(input: {
···11import "@typelex/emitter";
2233namespace tools.ozone.team.listMembers {
44- @doc("List all members with access to the ozone service.")
44+ /** List all members with access to the ozone service. */
55 @query
66 op main(
77 q?: string,
···1818 @required members: tools.ozone.team.defs.Member[];
1919 };
2020}
2121+2222+// --- Externals ---
2323+2424+@external
2525+namespace tools.ozone.team.defs {
2626+ model Member { }
2727+}
···11import "@typelex/emitter";
2233namespace tools.ozone.verification.defs {
44- @doc("Verification data for the associated subject.")
44+ /** Verification data for the associated subject. */
55 model VerificationView {
66- @doc("The user who issued this verification.")
66+ /** The user who issued this verification. */
77 @required
88 issuer: did;
991010- @doc("The AT-URI of the verification record.")
1010+ /** The AT-URI of the verification record. */
1111 @required
1212 uri: atUri;
13131414- @doc("The subject of the verification.")
1414+ /** The subject of the verification. */
1515 @required
1616 subject: did;
17171818- @doc("Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying.")
1818+ /** Handle of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current handle matches the one at the time of verifying. */
1919 @required
2020 handle: handle;
21212222- @doc("Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying.")
2222+ /** Display name of the subject the verification applies to at the moment of verifying, which might not be the same at the time of viewing. The verification is only valid if the current displayName matches the one at the time of verifying. */
2323 @required
2424 displayName: string;
25252626- @doc("Timestamp when the verification was created.")
2626+ /** Timestamp when the verification was created. */
2727 @required
2828 createdAt: datetime;
29293030- @doc("Describes the reason for revocation, also indicating that the verification is no longer valid.")
3030+ /** Describes the reason for revocation, also indicating that the verification is no longer valid. */
3131 revokeReason?: string;
32323333- @doc("Timestamp when the verification was revoked.")
3333+ /** Timestamp when the verification was revoked. */
3434 revokedAt?: datetime;
35353636- @doc("The user who revoked this verification.")
3636+ /** The user who revoked this verification. */
3737 revokedBy?: did;
38383939 subjectProfile?: (never | unknown);
···5252 );
5353 }
5454}
5555+5656+// --- Externals ---
5757+5858+@external
5959+namespace tools.ozone.moderation.defs {
6060+ model RepoViewDetail { }
6161+ model RepoViewNotFound { }
6262+}
···11import "@typelex/emitter";
2233namespace tools.ozone.verification.grantVerifications {
44- @doc("Grant verifications to multiple subjects. Allows batch processing of up to 100 verifications at once.")
44+ /** Grant verifications to multiple subjects. Allows batch processing of up to 100 verifications at once. */
55 @procedure
66 op main(input: {
77- @doc("Array of verification requests to process")
77+ /** Array of verification requests to process */
88 @maxItems(100)
99 @required
1010 verifications: VerificationInput[];
···1414 };
15151616 model VerificationInput {
1717- @doc("The did of the subject being verified")
1717+ /** The did of the subject being verified */
1818 @required
1919 subject: did;
20202121- @doc("Handle of the subject the verification applies to at the moment of verifying.")
2121+ /** Handle of the subject the verification applies to at the moment of verifying. */
2222 @required
2323 handle: handle;
24242525- @doc("Display name of the subject the verification applies to at the moment of verifying.")
2525+ /** Display name of the subject the verification applies to at the moment of verifying. */
2626 @required
2727 displayName: string;
28282929- @doc("Timestamp for verification record. Defaults to current time when not specified.")
2929+ /** Timestamp for verification record. Defaults to current time when not specified. */
3030 createdAt?: datetime;
3131 }
32323333- @doc("Error object for failed verifications.")
3333+ /** Error object for failed verifications. */
3434 model GrantError {
3535- @doc("Error message describing the reason for failure.")
3535+ /** Error message describing the reason for failure. */
3636 @required
3737 error: string;
38383939- @doc("The did of the subject being verified")
3939+ /** The did of the subject being verified */
4040 @required
4141 subject: did;
4242 }
4343}
4444+4545+// --- Externals ---
4646+4747+@external
4848+namespace tools.ozone.verification.defs {
4949+ model VerificationView { }
5050+}
···88 "desc",
99 }
10101111- @doc("List verifications")
1111+ /** List verifications */
1212 @query
1313 op main(
1414- @doc("Pagination cursor")
1414+ /** Pagination cursor */
1515 cursor?: string,
16161717- @doc("Maximum number of results to return")
1717+ /** Maximum number of results to return */
1818 @minValue(1)
1919 @maxValue(100)
2020 limit?: int32 = 50,
21212222- @doc("Filter to verifications created after this timestamp")
2222+ /** Filter to verifications created after this timestamp */
2323 createdAfter?: datetime,
24242525- @doc("Filter to verifications created before this timestamp")
2525+ /** Filter to verifications created before this timestamp */
2626 createdBefore?: datetime,
27272828- @doc("Filter to verifications from specific issuers")
2828+ /** Filter to verifications from specific issuers */
2929 @maxItems(100)
3030 issuers?: did[],
31313232- @doc("Filter to specific verified DIDs")
3232+ /** Filter to specific verified DIDs */
3333 @maxItems(100)
3434 subjects?: did[],
35353636- @doc("Sort direction for creation date")
3636+ /** Sort direction for creation date */
3737 sortDirection?: SortDirection = "desc",
38383939- @doc("Filter to verifications that are revoked or not. By default, includes both.")
3939+ /** Filter to verifications that are revoked or not. By default, includes both. */
4040 isRevoked?: boolean
4141 ): {
4242 cursor?: string;
4343 @required verifications: tools.ozone.verification.defs.VerificationView[];
4444 };
4545}
4646+4747+// --- Externals ---
4848+4949+@external
5050+namespace tools.ozone.verification.defs {
5151+ model VerificationView { }
5252+}
···11import "@typelex/emitter";
2233namespace tools.ozone.verification.revokeVerifications {
44- @doc("Revoke previously granted verifications in batches of up to 100.")
44+ /** Revoke previously granted verifications in batches of up to 100. */
55 @procedure
66 op main(input: {
77- @doc("Array of verification record uris to revoke")
77+ /** Array of verification record uris to revoke */
88 @maxItems(100)
99 @required
1010 uris: atUri[];
11111212- @doc("Reason for revoking the verification. This is optional and can be omitted if not needed.")
1212+ /** Reason for revoking the verification. This is optional and can be omitted if not needed. */
1313 @maxLength(1000)
1414 revokeReason?: string;
1515 }): {
1616- @doc("List of verification uris successfully revoked")
1616+ /** List of verification uris successfully revoked */
1717 @required
1818 revokedVerifications: atUri[];
19192020- @doc("List of verification uris that couldn't be revoked, including failure reasons")
2020+ /** List of verification uris that couldn't be revoked, including failure reasons */
2121 @required
2222 failedRevocations: RevokeError[];
2323 };
24242525- @doc("Error object for failed revocations")
2525+ /** Error object for failed revocations */
2626 model RevokeError {
2727- @doc("The AT-URI of the verification record that failed to revoke.")
2727+ /** The AT-URI of the verification record that failed to revoke. */
2828 @required
2929 uri: atUri;
30303131- @doc("Description of the error that occurred during revocation.")
3131+ /** Description of the error that occurred during revocation. */
3232 @required
3333 error: string;
3434 }
···1616 },
1717 "mention": {
1818 "type": "object",
1919- "description": "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.",
1919+ "description": "Facet feature for mention of another account. The text is usually a handle, including a `@` prefix, but the facet reference is a DID.",
2020 "required": ["did"],
2121 "properties": {
2222 "did": { "type": "string", "format": "did" }
···3232 },
3333 "tag": {
3434 "type": "object",
3535- "description": "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').",
3535+ "description": "Facet feature for a hashtag. The text usually includes a `#` prefix, but the facet reference should not (except in the case of 'double hash tags').",
3636 "required": ["tag"],
3737 "properties": {
3838 "tag": { "type": "string", "maxLength": 640, "maxGraphemes": 64 }
···11import "@typelex/emitter";
2233namespace com.atproto.admin.deleteAccount {
44- @doc("Delete a user account as an administrator.")
44+ /** Delete a user account as an administrator. */
55 @procedure
66 op main(input: {
77 @required did: did;
···11import "@typelex/emitter";
2233namespace com.atproto.admin.disableAccountInvites {
44- @doc("Disable an account from receiving new invite codes, but does not invalidate existing codes.")
44+ /** Disable an account from receiving new invite codes, but does not invalidate existing codes. */
55 @procedure
66 op main(input: {
77 @required account: did;
8899- @doc("Optional reason for disabled invites.")
99+ /** Optional reason for disabled invites. */
1010 note?: string;
1111 }): void;
1212}
···11import "@typelex/emitter";
2233namespace com.atproto.admin.disableInviteCodes {
44- @doc("Disable some set of codes and/or all codes associated with a set of users.")
44+ /** Disable some set of codes and/or all codes associated with a set of users. */
55 @procedure
66 op main(input: {
77 codes?: string[];
···11import "@typelex/emitter";
2233namespace com.atproto.admin.getSubjectStatus {
44- @doc("Get the service-specific admin status of a subject (account, record, or blob).")
44+ /** Get the service-specific admin status of a subject (account, record, or blob). */
55 @query
66 op main(
77 did?: did,
···2020 deactivated?: com.atproto.admin.defs.StatusAttr;
2121 };
2222}
2323+2424+// --- Externals ---
2525+2626+@external
2727+namespace com.atproto.admin.defs {
2828+ model RepoRef { }
2929+ model RepoBlobRef { }
3030+ model StatusAttr { }
3131+}
3232+3333+@external
3434+namespace com.atproto.repo.strongRef {
3535+ model Main { }
3636+}
···11import "@typelex/emitter";
2233namespace com.atproto.admin.sendEmail {
44- @doc("Send email to a user's account email address.")
44+ /** Send email to a user's account email address. */
55 @procedure
66 op main(input: {
77 @required recipientDid: did;
···99 subject?: string;
1010 @required senderDid: did;
11111212- @doc("Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers")
1212+ /** Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers */
1313 comment?: string;
1414 }): {
1515 @required sent: boolean;
···11import "@typelex/emitter";
2233namespace com.atproto.admin.updateAccountEmail {
44- @doc("Administrative action to update an account's email.")
44+ /** Administrative action to update an account's email. */
55 @procedure
66 op main(input: {
77- @doc("The handle or DID of the repo.")
77+ /** The handle or DID of the repo. */
88 @required
99 account: atIdentifier;
1010
···11import "@typelex/emitter";
2233namespace com.atproto.admin.updateAccountPassword {
44- @doc("Update the password for a user account as an administrator.")
44+ /** Update the password for a user account as an administrator. */
55 @procedure
66 op main(input: {
77 @required did: did;
···11import "@typelex/emitter";
2233namespace com.atproto.admin.updateAccountSigningKey {
44- @doc("Administrative action to update an account's signing key in their Did document.")
44+ /** Administrative action to update an account's signing key in their Did document. */
55 @procedure
66 op main(input: {
77 @required did: did;
8899- @doc("Did-key formatted public key")
99+ /** Did-key formatted public key */
1010 @required
1111 signingKey: did;
1212 }): void;
···44 model IdentityInfo {
55 @required did: did;
6677- @doc("The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document.")
77+ /** The validated handle of the account; or 'handle.invalid' if the handle did not bi-directionally match the DID document. */
88 @required
99 handle: handle;
10101111- @doc("The complete DID document for the identity.")
1111+ /** The complete DID document for the identity. */
1212 @required
1313 didDoc: unknown;
1414 }
···11import "@typelex/emitter";
2233namespace com.atproto.identity.getRecommendedDidCredentials {
44- @doc("Describe the credentials that should be included in the DID doc of an account that is migrating to this service.")
44+ /** Describe the credentials that should be included in the DID doc of an account that is migrating to this service. */
55 @query
66 op main(): {
77- @doc("Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.")
77+ /** Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs. */
88 rotationKeys?: string[];
991010 alsoKnownAs?: string[];
···11import "@typelex/emitter";
2233namespace com.atproto.identity.refreshIdentity {
44- @doc("The resolution process confirmed that the handle does not resolve to any DID.")
44+ /** The resolution process confirmed that the handle does not resolve to any DID. */
55 model HandleNotFound {}
6677- @doc("The DID resolution process confirmed that there is no current DID.")
77+ /** The DID resolution process confirmed that there is no current DID. */
88 model DidNotFound {}
991010- @doc("The DID previously existed, but has been deactivated.")
1010+ /** The DID previously existed, but has been deactivated. */
1111 model DidDeactivated {}
12121313- @doc("Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server.")
1313+ /** Request that the server re-resolve an identity (DID and handle). The server may ignore this request, or require authentication, depending on the role, implementation, and policy of the server. */
1414 @procedure
1515 @errors(HandleNotFound, DidNotFound, DidDeactivated)
1616 op main(input: {
1717 @required identifier: atIdentifier;
1818 }): com.atproto.identity.defs.IdentityInfo;
1919}
2020+2121+// --- Externals ---
2222+2323+@external
2424+namespace com.atproto.identity.defs {
2525+ model IdentityInfo { }
2626+}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.requestPlcOperationSignature {
44- @doc("Request an email with a code to in order to request a signed PLC operation. Requires Auth.")
44+ /** Request an email with a code to in order to request a signed PLC operation. Requires Auth. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.resolveDid {
44- @doc("Resolves DID to DID document. Does not bi-directionally verify handle.")
44+ /** Resolves DID to DID document. Does not bi-directionally verify handle. */
55 @query
66 @errors(DidNotFound, DidDeactivated)
77 op main(
88- @doc("DID to resolve.")
88+ /** DID to resolve. */
99 @required
1010 did: did
1111 ): {
1212- @doc("The complete DID document for the identity.")
1212+ /** The complete DID document for the identity. */
1313 @required
1414 didDoc: unknown;
1515 };
16161717- @doc("The DID resolution process confirmed that there is no current DID.")
1717+ /** The DID resolution process confirmed that there is no current DID. */
1818 model DidNotFound {}
19192020- @doc("The DID previously existed, but has been deactivated.")
2020+ /** The DID previously existed, but has been deactivated. */
2121 model DidDeactivated {}
2222}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.resolveHandle {
44- @doc("Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document.")
44+ /** Resolves an atproto handle (hostname) to a DID. Does not necessarily bi-directionally verify against the the DID document. */
55 @query
66 @errors(HandleNotFound)
77 op main(
88- @doc("The handle to resolve.")
88+ /** The handle to resolve. */
99 @required
1010 handle: handle
1111 ): {
1212 @required did: did;
1313 };
14141515- @doc("The resolution process confirmed that the handle does not resolve to any DID.")
1515+ /** The resolution process confirmed that the handle does not resolve to any DID. */
1616 model HandleNotFound {}
1717}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.resolveIdentity {
44- @doc("The resolution process confirmed that the handle does not resolve to any DID.")
44+ /** The resolution process confirmed that the handle does not resolve to any DID. */
55 model HandleNotFound {}
6677- @doc("The DID resolution process confirmed that there is no current DID.")
77+ /** The DID resolution process confirmed that there is no current DID. */
88 model DidNotFound {}
991010- @doc("The DID previously existed, but has been deactivated.")
1010+ /** The DID previously existed, but has been deactivated. */
1111 model DidDeactivated {}
12121313- @doc("Resolves an identity (DID or Handle) to a full identity (DID document and verified handle).")
1313+ /** Resolves an identity (DID or Handle) to a full identity (DID document and verified handle). */
1414 @query
1515 @errors(HandleNotFound, DidNotFound, DidDeactivated)
1616 op main(
1717- @doc("Handle or DID to resolve.")
1717+ /** Handle or DID to resolve. */
1818 @required
1919 identifier: atIdentifier
2020 ): com.atproto.identity.defs.IdentityInfo;
2121}
2222+2323+// --- Externals ---
2424+2525+@external
2626+namespace com.atproto.identity.defs {
2727+ model IdentityInfo { }
2828+}
···11import "@typelex/emitter";
2233namespace com.atproto.identity.signPlcOperation {
44- @doc("Signs a PLC operation to update some value(s) in the requesting DID's document.")
44+ /** Signs a PLC operation to update some value(s) in the requesting DID's document. */
55 @procedure
66 op main(input: {
77- @doc("A token received through com.atproto.identity.requestPlcOperationSignature")
77+ /** A token received through com.atproto.identity.requestPlcOperationSignature */
88 token?: string;
991010 rotationKeys?: string[];
···15151616 services?: unknown;
1717 }): {
1818- @doc("A signed DID PLC operation.")
1818+ /** A signed DID PLC operation. */
1919 @required
2020 operation: unknown;
2121 };
···11import "@typelex/emitter";
2233namespace com.atproto.identity.submitPlcOperation {
44- @doc("Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry")
44+ /** Validates a PLC operation to ensure that it doesn't violate a service's constraints or get the identity into a bad state, then submits it to the PLC registry */
55 @procedure
66 op main(input: {
77 @required operation: unknown;
···11import "@typelex/emitter";
2233namespace com.atproto.identity.updateHandle {
44- @doc("Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth.")
44+ /** Updates the current account's handle. Verifies handle validity, and updates did:plc document if necessary. Implemented by PDS, and requires auth. */
55 @procedure
66 op main(input: {
77- @doc("The new handle.")
77+ /** The new handle. */
88 @required
99 handle: handle;
1010 }): void;
···11import "@typelex/emitter";
2233namespace com.atproto.label.defs {
44- @doc("Metadata tag on an atproto resource (eg, repo or record).")
44+ /** Metadata tag on an atproto resource (eg, repo or record). */
55 model Label {
66- @doc("The AT Protocol version of the label object.")
66+ /** The AT Protocol version of the label object. */
77 ver?: integer;
8899- @doc("DID of the actor who created this label.")
99+ /** DID of the actor who created this label. */
1010 @required
1111 src: did;
12121313- @doc("AT URI of the record, repository (account), or other resource that this label applies to.")
1313+ /** AT URI of the record, repository (account), or other resource that this label applies to. */
1414 @required
1515 uri: uri;
16161717- @doc("Optionally, CID specifying the specific version of 'uri' resource this label applies to.")
1717+ /** Optionally, CID specifying the specific version of 'uri' resource this label applies to. */
1818 cid?: cid;
19192020- @doc("The short string name of the value or type of this label.")
2020+ /** The short string name of the value or type of this label. */
2121 @maxLength(128)
2222 @required
2323 val: string;
24242525- @doc("If true, this is a negation label, overwriting a previous label.")
2525+ /** If true, this is a negation label, overwriting a previous label. */
2626 neg?: boolean;
27272828- @doc("Timestamp when this label was created.")
2828+ /** Timestamp when this label was created. */
2929 @required
3030 cts: datetime;
31313232- @doc("Timestamp at which this label expires (no longer applies).")
3232+ /** Timestamp at which this label expires (no longer applies). */
3333 exp?: datetime;
34343535- @doc("Signature of dag-cbor encoded label.")
3535+ /** Signature of dag-cbor encoded label. */
3636 sig?: bytes;
3737 }
38383939- @doc("Metadata tags on an atproto record, published by the author within the record.")
3939+ /** Metadata tags on an atproto record, published by the author within the record. */
4040 model SelfLabels {
4141 @maxItems(10)
4242 @required
4343 values: SelfLabel[];
4444 }
45454646- @doc("Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.")
4646+ /** Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. */
4747 model SelfLabel {
4848- @doc("The short string name of the value or type of this label.")
4848+ /** The short string name of the value or type of this label. */
4949 @maxLength(128)
5050 @required
5151 val: string;
5252 }
53535454- @doc("Declares a label value and its expected interpretations and behaviors.")
5454+ /** Declares a label value and its expected interpretations and behaviors. */
5555 model LabelValueDefinition {
5656- @doc("The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).")
5656+ /** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */
5757 @maxLength(100)
5858 @maxGraphemes(100)
5959 @required
6060 identifier: string;
61616262- @doc("How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.")
6262+ /** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */
6363 @required
6464 severity: "inform" | "alert" | "none" | string;
65656666- @doc("What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.")
6666+ /** What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing. */
6767 @required
6868 blurs: "content" | "media" | "none" | string;
69697070- @doc("The default setting for this label.")
7070+ /** The default setting for this label. */
7171 defaultSetting?: "ignore" | "warn" | "hide" | string = "warn";
72727373- @doc("Does the user need to have adult content enabled in order to configure this label?")
7373+ /** Does the user need to have adult content enabled in order to configure this label? */
7474 adultOnly?: boolean;
75757676 @required
7777 locales: LabelValueDefinitionStrings[];
7878 }
79798080- @doc("Strings which describe the label in the UI, localized into a specific language.")
8080+ /** Strings which describe the label in the UI, localized into a specific language. */
8181 model LabelValueDefinitionStrings {
8282- @doc("The code of the language these strings are written in.")
8282+ /** The code of the language these strings are written in. */
8383 @required
8484 lang: language;
85858686- @doc("A short human-readable name for the label.")
8686+ /** A short human-readable name for the label. */
8787 @maxGraphemes(64)
8888 @maxLength(640)
8989 @required
9090 name: string;
91919292- @doc("A longer description of what the label means and why it might be applied.")
9292+ /** A longer description of what the label means and why it might be applied. */
9393 @maxGraphemes(10000)
9494 @maxLength(100000)
9595 @required
···11import "@typelex/emitter";
2233namespace com.atproto.label.queryLabels {
44- @doc("Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth.")
44+ /** Find labels relevant to the provided AT-URI patterns. Public endpoint for moderation services, though may return different or additional results with auth. */
55 @query
66 op main(
77- @doc("List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI.")
77+ /** List of AT URI patterns to match (boolean 'OR'). Each may be a prefix (ending with '*'; will match inclusive of the string leading to '*'), or a full URI. */
88 @required
99 uriPatterns: string[],
10101111- @doc("Optional list of label sources (DIDs) to filter on.")
1111+ /** Optional list of label sources (DIDs) to filter on. */
1212 sources?: did[],
13131414 @minValue(1)
···2121 @required labels: com.atproto.label.defs.Label[];
2222 };
2323}
2424+2525+// --- Externals ---
2626+2727+@external
2828+namespace com.atproto.label.defs {
2929+ model Label { }
3030+}
···1313 message?: string;
1414 }
15151616- @doc("Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream.")
1616+ /** Subscribe to stream of labels (and negations). Public endpoint implemented by mod services. Uses same sequencing scheme as repo event stream. */
1717 @subscription
1818 @errors(FutureCursor)
1919 op main(
2020- @doc("The last known event seq number to backfill from.")
2020+ /** The last known event seq number to backfill from. */
2121 cursor?: integer
2222 ): (Labels | Info);
2323}
2424+2525+// --- Externals ---
2626+2727+@external
2828+namespace com.atproto.label.defs {
2929+ model Label { }
3030+}
···11import "@typelex/emitter";
2233namespace com.atproto.lexicon.schema {
44- @doc("Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc).")
44+ /** Representation of Lexicon schemas themselves, when published as atproto records. Note that the schema language is not defined in Lexicon; this meta schema currently only includes a single version field ('lexicon'). See the atproto specifications for description of the other expected top-level fields ('id', 'defs', etc). */
55 @rec("nsid")
66 model Main {
77- @doc("Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system.")
77+ /** Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system. */
88 @required
99 lexicon: integer;
1010 }
···11import "@typelex/emitter";
2233namespace com.atproto.moderation.createReport {
44- @doc("Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth.")
44+ /** Submit a moderation report regarding an atproto account or record. Implemented by moderation services (with PDS proxying), and requires auth. */
55 @procedure
66 op main(input: {
77- @doc("Indicates the broad category of violation the report is for.")
77+ /** Indicates the broad category of violation the report is for. */
88 @required
99 reasonType: com.atproto.moderation.defs.ReasonType;
10101111 @maxGraphemes(2000)
1212 @maxLength(20000)
1313- @doc("Additional context about the content and violation.")
1313+ /** Additional context about the content and violation. */
1414 reason?: string;
15151616 @required
···4040 @required createdAt: datetime;
4141 };
42424343- @doc("Moderation tool information for tracing the source of the action")
4343+ /** Moderation tool information for tracing the source of the action */
4444 model ModTool {
4545- @doc("Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome')")
4545+ /** Name/identifier of the source (e.g., 'bsky-app/android', 'bsky-web/chrome') */
4646 @required
4747 name: string;
48484949- @doc("Additional arbitrary metadata about the source")
4949+ /** Additional arbitrary metadata about the source */
5050 meta?: unknown;
5151 }
5252}
5353+5454+// --- Externals ---
5555+5656+@external
5757+namespace com.atproto.moderation.defs {
5858+ model ReasonType { }
5959+}
6060+6161+@external
6262+namespace com.atproto.admin.defs {
6363+ model RepoRef { }
6464+}
6565+6666+@external
6767+namespace com.atproto.repo.strongRef {
6868+ model Main { }
6969+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.applyWrites {
44- @doc("Indicates that the 'swapCommit' parameter did not match current commit.")
44+ /** Indicates that the 'swapCommit' parameter did not match current commit. */
55 model InvalidSwap {}
6677 @closed
···2020 DeleteResult,
2121 }
22222323- @doc("Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS.")
2323+ /** Apply a batch transaction of repository creates, updates, and deletes. Requires auth, implemented by PDS. */
2424 @procedure
2525 @errors(InvalidSwap)
2626 op main(input: {
2727- @doc("The handle or DID of the repo (aka, current account).")
2727+ /** The handle or DID of the repo (aka, current account). */
2828 @required
2929 repo: atIdentifier;
30303131- @doc("Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons.")
3131+ /** Can be set to 'false' to skip Lexicon schema validation of record data across all operations, 'true' to require it, or leave unset to validate only for known Lexicons. */
3232 validate?: boolean;
33333434 @required
3535 writes: WriteAction[];
36363737- @doc("If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations.")
3737+ /** If provided, the entire operation will fail if the current repo commit CID does not match this value. Used to prevent conflicting repo mutations. */
3838 swapCommit?: cid;
3939 }): {
4040 commit?: com.atproto.repo.defs.CommitMeta;
4141 results?: WriteResult[];
4242 };
43434444- @doc("Operation which creates a new record.")
4444+ /** Operation which creates a new record. */
4545 model Create {
4646 @required collection: nsid;
47474848- @doc("NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.")
4848+ /** NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility. */
4949 @maxLength(512)
5050 rkey?: recordKey;
51515252 @required value: unknown;
5353 }
54545555- @doc("Operation which updates an existing record.")
5555+ /** Operation which updates an existing record. */
5656 model Update {
5757 @required collection: nsid;
5858 @required rkey: recordKey;
5959 @required value: unknown;
6060 }
61616262- @doc("Operation which deletes an existing record.")
6262+ /** Operation which deletes an existing record. */
6363 model Delete {
6464 @required collection: nsid;
6565 @required rkey: recordKey;
···79798080 model DeleteResult {}
8181}
8282+8383+// --- Externals ---
8484+8585+@external
8686+namespace com.atproto.repo.defs {
8787+ model CommitMeta { }
8888+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.createRecord {
44- @doc("Create a single new repository record. Requires auth, implemented by PDS.")
44+ /** Create a single new repository record. Requires auth, implemented by PDS. */
55 @errors(InvalidSwap)
66 @procedure
77 op main(input: {
88- @doc("The handle or DID of the repo (aka, current account).")
88+ /** The handle or DID of the repo (aka, current account). */
99 @required
1010 repo: atIdentifier;
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid;
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @maxLength(512)
1818 rkey?: recordKey;
19192020- @doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
2020+ /** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
2121 validate?: boolean;
22222323- @doc("The record itself. Must contain a $type field.")
2323+ /** The record itself. Must contain a $type field. */
2424 @required
2525 record: unknown;
26262727- @doc("Compare and swap with the previous commit by CID.")
2727+ /** Compare and swap with the previous commit by CID. */
2828 swapCommit?: cid;
2929 }): {
3030 @required uri: atUri;
···3333 validationStatus?: "valid" | "unknown" | string;
3434 };
35353636- @doc("Indicates that 'swapCommit' didn't match current repo commit.")
3636+ /** Indicates that 'swapCommit' didn't match current repo commit. */
3737 model InvalidSwap {}
3838}
3939+4040+// --- Externals ---
4141+4242+@external
4343+namespace com.atproto.repo.defs {
4444+ model CommitMeta { }
4545+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.deleteRecord {
44- @doc("Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS.")
44+ /** Delete a repository record, or ensure it doesn't exist. Requires auth, implemented by PDS. */
55 @errors(InvalidSwap)
66 @procedure
77 op main(input: {
88- @doc("The handle or DID of the repo (aka, current account).")
88+ /** The handle or DID of the repo (aka, current account). */
99 @required
1010 repo: atIdentifier;
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid;
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @required
1818 rkey: recordKey;
19192020- @doc("Compare and swap with the previous record by CID.")
2020+ /** Compare and swap with the previous record by CID. */
2121 swapRecord?: cid;
22222323- @doc("Compare and swap with the previous commit by CID.")
2323+ /** Compare and swap with the previous commit by CID. */
2424 swapCommit?: cid;
2525 }): {
2626 commit?: com.atproto.repo.defs.CommitMeta;
···28282929 model InvalidSwap {}
3030}
3131+3232+// --- Externals ---
3333+3434+@external
3535+namespace com.atproto.repo.defs {
3636+ model CommitMeta { }
3737+}
···11import "@typelex/emitter";
2233namespace com.atproto.repo.describeRepo {
44- @doc("Get information about an account and repository, including the list of collections. Does not require auth.")
44+ /** Get information about an account and repository, including the list of collections. Does not require auth. */
55 @query
66 op main(
77- @doc("The handle or DID of the repo.")
77+ /** The handle or DID of the repo. */
88 @required
99 repo: atIdentifier
1010 ): {
1111 @required handle: handle;
1212 @required did: did;
13131414- @doc("The complete DID document for this account.")
1414+ /** The complete DID document for this account. */
1515 @required
1616 didDoc: unknown;
17171818- @doc("List of all the collections (NSIDs) for which this repo contains at least one record.")
1818+ /** List of all the collections (NSIDs) for which this repo contains at least one record. */
1919 @required
2020 collections: nsid[];
21212222- @doc("Indicates if handle is currently valid (resolves bi-directionally)")
2222+ /** Indicates if handle is currently valid (resolves bi-directionally) */
2323 @required
2424 handleIsCorrect: boolean;
2525 };
···11import "@typelex/emitter";
2233namespace com.atproto.repo.getRecord {
44- @doc("Get a single record from a repository. Does not require auth.")
44+ /** Get a single record from a repository. Does not require auth. */
55 @query
66 @errors(RecordNotFound)
77 op main(
88- @doc("The handle or DID of the repo.")
88+ /** The handle or DID of the repo. */
99 @required
1010 repo: atIdentifier,
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid,
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @required
1818 rkey: recordKey,
19192020- @doc("The CID of the version of the record. If not specified, then return the most recent version.")
2020+ /** The CID of the version of the record. If not specified, then return the most recent version. */
2121 cid?: cid
2222 ): {
2323 @required uri: atUri;
···11import "@typelex/emitter";
2233namespace com.atproto.repo.importRepo {
44- @doc("Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set.")
44+ /** Import a repo in the form of a CAR file. Requires Content-Length HTTP header to be set. */
55 @procedure
66 op main(
77 @encoding("application/vnd.ipld.car")
···11import "@typelex/emitter";
2233namespace com.atproto.repo.listMissingBlobs {
44- @doc("Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow.")
44+ /** Returns a list of missing blobs for the requesting account. Intended to be used in the account migration flow. */
55 @query
66 op main(
77 @minValue(1)
···11import "@typelex/emitter";
2233namespace com.atproto.repo.listRecords {
44- @doc("List a range of records in a repository, matching a specific collection. Does not require auth.")
44+ /** List a range of records in a repository, matching a specific collection. Does not require auth. */
55 @query
66 op main(
77- @doc("The handle or DID of the repo.")
77+ /** The handle or DID of the repo. */
88 @required
99 repo: atIdentifier,
10101111- @doc("The NSID of the record type.")
1111+ /** The NSID of the record type. */
1212 @required
1313 collection: nsid,
14141515- @doc("The number of records to return.")
1515+ /** The number of records to return. */
1616 @minValue(1)
1717 @maxValue(100)
1818 limit?: int32 = 50,
19192020 cursor?: string,
21212222- @doc("Flag to reverse the order of the returned records.")
2222+ /** Flag to reverse the order of the returned records. */
2323 reverse?: boolean
2424 ): {
2525 cursor?: string;
···11import "@typelex/emitter";
2233namespace com.atproto.repo.putRecord {
44- @doc("Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS.")
44+ /** Write a repository record, creating or updating it as needed. Requires auth, implemented by PDS. */
55 @errors(InvalidSwap)
66 @procedure
77 op main(input: {
88- @doc("The handle or DID of the repo (aka, current account).")
88+ /** The handle or DID of the repo (aka, current account). */
99 @required
1010 repo: atIdentifier;
11111212- @doc("The NSID of the record collection.")
1212+ /** The NSID of the record collection. */
1313 @required
1414 collection: nsid;
15151616- @doc("The Record Key.")
1616+ /** The Record Key. */
1717 @maxLength(512)
1818 @required
1919 rkey: recordKey;
20202121- @doc("Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons.")
2121+ /** Can be set to 'false' to skip Lexicon schema validation of record data, 'true' to require it, or leave unset to validate only for known Lexicons. */
2222 validate?: boolean;
23232424- @doc("The record to write.")
2424+ /** The record to write. */
2525 @required
2626 record: unknown;
27272828- @doc("Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation")
2828+ /** Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation */
2929 swapRecord?: cid | null;
30303131- @doc("Compare and swap with the previous commit by CID.")
3131+ /** Compare and swap with the previous commit by CID. */
3232 swapCommit?: cid;
3333 }): {
3434 @required uri: atUri;
···39394040 model InvalidSwap {}
4141}
4242+4343+// --- Externals ---
4444+4545+@external
4646+namespace com.atproto.repo.defs {
4747+ model CommitMeta { }
4848+}
···11import "@typelex/emitter";
2233-@doc("A URI with a content-hash fingerprint.")
33+/** A URI with a content-hash fingerprint. */
44namespace com.atproto.repo.strongRef {
55 model Main {
66 @required uri: atUri;
···11import "@typelex/emitter";
2233namespace com.atproto.repo.uploadBlob {
44- @doc("Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS.")
44+ /** Upload a new blob, to be referenced from a repository record. The blob will be deleted if it is not referenced within a time window (eg, minutes). Blob restrictions (mimetype, size, etc) are enforced when the reference is created. Requires auth, implemented by PDS. */
55 @procedure
66 op main(
77 @encoding("*/*")
···11import "@typelex/emitter";
2233namespace com.atproto.server.activateAccount {
44- @doc("Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup.")
44+ /** Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.server.checkAccountStatus {
44- @doc("Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself.")
44+ /** Returns the status of an account, especially as pertaining to import or recovery. Can be called many times over the course of an account migration. Requires auth and can only be called pertaining to oneself. */
55 @query
66 op main(): {
77 @required activated: boolean;
···66 model InvalidToken {}
77 model InvalidEmail {}
8899- @doc("Confirm an email using a token from com.atproto.server.requestEmailConfirmation.")
99+ /** Confirm an email using a token from com.atproto.server.requestEmailConfirmation. */
1010 @procedure
1111 @errors(AccountNotFound, ExpiredToken, InvalidToken, InvalidEmail)
1212 op main(input: {
···99 model UnresolvableDid {}
1010 model IncompatibleDidDoc {}
11111212- @doc("Account login session returned on successful account creation.")
1212+ /** Account login session returned on successful account creation. */
1313 @inline
1414 model Output {
1515 @required accessJwt: string;
1616 @required refreshJwt: string;
1717 @required handle: handle;
18181919- @doc("The DID of the new account.")
1919+ /** The DID of the new account. */
2020 @required
2121 did: did;
22222323- @doc("Complete DID document.")
2323+ /** Complete DID document. */
2424 didDoc?: unknown;
2525 }
26262727- @doc("Create an account. Implemented by PDS.")
2727+ /** Create an account. Implemented by PDS. */
2828 @procedure
2929 @errors(InvalidHandle, InvalidPassword, InvalidInviteCode, HandleNotAvailable, UnsupportedDomain, UnresolvableDid, IncompatibleDidDoc)
3030 op main(input: {
3131 email?: string;
32323333- @doc("Requested handle for the account.")
3333+ /** Requested handle for the account. */
3434 @required
3535 handle: handle;
36363737- @doc("Pre-existing atproto DID, being imported to a new account.")
3737+ /** Pre-existing atproto DID, being imported to a new account. */
3838 did?: did;
39394040 inviteCode?: string;
4141 verificationCode?: string;
4242 verificationPhone?: string;
43434444- @doc("Initial account password. May need to meet instance-specific password strength requirements.")
4444+ /** Initial account password. May need to meet instance-specific password strength requirements. */
4545 password?: string;
46464747- @doc("DID PLC rotation key (aka, recovery key) to be included in PLC creation operation.")
4747+ /** DID PLC rotation key (aka, recovery key) to be included in PLC creation operation. */
4848 recoveryKey?: string;
49495050- @doc("A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented.")
5050+ /** A signed DID PLC operation to be submitted as part of importing an existing account to this instance. NOTE: this optional field may be updated when full account migration is implemented. */
5151 plcOp?: unknown;
5252 }): Output;
5353}
···1010 privileged?: boolean;
1111 }
12121313- @doc("Create an App Password.")
1313+ /** Create an App Password. */
1414 @procedure
1515 @errors(AccountTakedown)
1616 op main(input: {
1717- @doc("A short name for the App Password, to help distinguish them.")
1717+ /** A short name for the App Password, to help distinguish them. */
1818 @required
1919 name: string;
20202121- @doc("If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients.")
2121+ /** If an app password has 'privileged' access to possibly sensitive account state. Meant for use with trusted clients. */
2222 privileged?: boolean;
2323 }): AppPassword;
2424}
···5566 model AuthFactorTokenRequired {}
7788- @doc("Create an authentication session.")
88+ /** Create an authentication session. */
99 @procedure
1010 @errors(AccountTakedown, AuthFactorTokenRequired)
1111 op main(input: {
1212- @doc("Handle or other identifier supported by the server for the authenticating user.")
1212+ /** Handle or other identifier supported by the server for the authenticating user. */
1313 @required
1414 identifier: string;
1515···17171818 authFactorToken?: string;
19192020- @doc("When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned")
2020+ /** When true, instead of throwing error for takendown accounts, a valid response with a narrow scoped token will be returned */
2121 allowTakendown?: boolean;
2222 }): {
2323 @required accessJwt: string;
···3030 emailAuthFactor?: boolean;
3131 active?: boolean;
32323333- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
3333+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
3434 status?: "takendown" | "suspended" | "deactivated" | string;
3535 };
3636}
···11import "@typelex/emitter";
2233namespace com.atproto.server.deactivateAccount {
44- @doc("Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host.")
44+ /** Deactivates a currently active account. Stops serving of repo, and future writes to repo until reactivated. Used to finalize account migration with the old host after the account has been activated on the new host. */
55 @procedure
66 op main(input: {
77- @doc("A recommendation to server as to how long they should hold onto the deactivated account before deleting.")
77+ /** A recommendation to server as to how long they should hold onto the deactivated account before deleting. */
88 deleteAfter?: datetime;
99 }): void;
1010}
···44 model ExpiredToken {}
55 model InvalidToken {}
6677- @doc("Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth.")
77+ /** Delete an actor's account with a token and password. Can only be called after requesting a deletion token. Requires auth. */
88 @procedure
99 @errors(ExpiredToken, InvalidToken)
1010 op main(input: {
···11import "@typelex/emitter";
2233namespace com.atproto.server.describeServer {
44- @doc("Describes the server's account creation requirements and capabilities. Implemented by PDS.")
44+ /** Describes the server's account creation requirements and capabilities. Implemented by PDS. */
55 @query
66 op main(): {
77 @required did: did;
8899- @doc("If true, an invite code must be supplied to create an account on this instance.")
99+ /** If true, an invite code must be supplied to create an account on this instance. */
1010 inviteCodeRequired?: boolean;
11111212- @doc("If true, a phone verification token must be supplied to create an account on this instance.")
1212+ /** If true, a phone verification token must be supplied to create an account on this instance. */
1313 phoneVerificationRequired?: boolean;
14141515- @doc("List of domain suffixes that can be used in account handles.")
1515+ /** List of domain suffixes that can be used in account handles. */
1616 @required
1717 availableUserDomains: string[];
18181919- @doc("URLs of service policy documents.")
1919+ /** URLs of service policy documents. */
2020 links?: Links;
21212222- @doc("Contact information")
2222+ /** Contact information */
2323 contact?: Contact;
2424 };
2525
···33namespace com.atproto.server.getAccountInviteCodes {
44 model DuplicateCreate {}
5566- @doc("Get all invite codes for the current account. Requires auth.")
66+ /** Get all invite codes for the current account. Requires auth. */
77 @query
88 @errors(DuplicateCreate)
99 op main(
1010 includeUsed?: boolean = true,
11111212- @doc("Controls whether any new 'earned' but not 'created' invites should be created.")
1212+ /** Controls whether any new 'earned' but not 'created' invites should be created. */
1313 createAvailable?: boolean = true
1414 ): {
1515 @required codes: com.atproto.server.defs.InviteCode[];
1616 };
1717}
1818+1919+// --- Externals ---
2020+2121+@external
2222+namespace com.atproto.server.defs {
2323+ model InviteCode { }
2424+}
···11import "@typelex/emitter";
2233namespace com.atproto.server.getServiceAuth {
44- @doc("Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes.")
44+ /** Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes. */
55 model BadExpiration {}
6677- @doc("Get a signed token on behalf of the requesting DID for the requested service.")
77+ /** Get a signed token on behalf of the requesting DID for the requested service. */
88 @query
99 @errors(BadExpiration)
1010 op main(
1111- @doc("The DID of the service that the token will be used to authenticate with")
1111+ /** The DID of the service that the token will be used to authenticate with */
1212 @required
1313 aud: did,
14141515- @doc("The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope.")
1515+ /** The time in Unix Epoch seconds that the JWT expires. Defaults to 60 seconds in the future. The service may enforce certain time bounds on tokens depending on the requested scope. */
1616 exp?: integer,
17171818- @doc("Lexicon (XRPC) method to bind the requested token to")
1818+ /** Lexicon (XRPC) method to bind the requested token to */
1919 lxm?: nsid
2020 ): {
2121 @required token: string;
···11import "@typelex/emitter";
2233namespace com.atproto.server.getSession {
44- @doc("Get information about the current auth session. Requires auth.")
44+ /** Get information about the current auth session. Requires auth. */
55 @query
66 op main(): {
77 @required handle: handle;
···1212 didDoc?: unknown;
1313 active?: boolean;
14141515- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
1515+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
1616 status?: "takendown" | "suspended" | "deactivated" | string;
1717 };
1818}
···33namespace com.atproto.server.refreshSession {
44 model AccountTakedown {}
5566- @doc("Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt').")
66+ /** Refresh an authentication session. Requires auth using the 'refreshJwt' (not the 'accessJwt'). */
77 @procedure
88 @errors(AccountTakedown)
99 op main(): {
···1414 didDoc?: unknown;
1515 active?: boolean;
16161717- @doc("Hosting status of the account. If not specified, then assume 'active'.")
1717+ /** Hosting status of the account. If not specified, then assume 'active'. */
1818 status?: "takendown" | "suspended" | "deactivated" | string;
1919 };
2020}
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestAccountDelete {
44- @doc("Initiate a user account deletion via email.")
44+ /** Initiate a user account deletion via email. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestEmailConfirmation {
44- @doc("Request an email with a code to confirm ownership of email.")
44+ /** Request an email with a code to confirm ownership of email. */
55 @procedure
66 op main(): void;
77}
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestEmailUpdate {
44- @doc("Request a token in order to update email.")
44+ /** Request a token in order to update email. */
55 @procedure
66 op main(): {
77 @required tokenRequired: boolean;
···11import "@typelex/emitter";
2233namespace com.atproto.server.requestPasswordReset {
44- @doc("Initiate a user account password reset via email.")
44+ /** Initiate a user account password reset via email. */
55 @procedure
66 op main(input: {
77 @required email: string;
···11import "@typelex/emitter";
2233namespace com.atproto.server.reserveSigningKey {
44- @doc("Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented.")
44+ /** Reserve a repo signing key, for use with account creation. Necessary so that a DID PLC update operation can be constructed during an account migraiton. Public and does not require auth; implemented by PDS. NOTE: this endpoint may change when full account migration is implemented. */
55 @procedure
66 op main(input: {
77- @doc("The DID to reserve a key for.")
77+ /** The DID to reserve a key for. */
88 did?: did;
99 }): {
1010- @doc("The public key for the reserved signing key, in did:key serialization.")
1010+ /** The public key for the reserved signing key, in did:key serialization. */
1111 @required
1212 signingKey: string;
1313 };
···44 model ExpiredToken {}
55 model InvalidToken {}
6677- @doc("Reset a user account password using a token.")
77+ /** Reset a user account password using a token. */
88 @procedure
99 @errors(ExpiredToken, InvalidToken)
1010 op main(input: {
···55 model InvalidToken {}
66 model TokenRequired {}
7788- @doc("Update an account's email.")
88+ /** Update an account's email. */
99 @procedure
1010 @errors(ExpiredToken, InvalidToken, TokenRequired)
1111 op main(input: {
1212 @required email: string;
1313 emailAuthFactor?: boolean;
14141515- @doc("Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed.")
1515+ /** Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed. */
1616 token?: string;
1717 }): void;
1818}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getBlob {
44- @doc("Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS.")
44+ /** Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS. */
55 @query
66 @encoding("*/*")
77 @errors(BlobNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the account.")
99+ /** The DID of the account. */
1010 @required
1111 did: did,
12121313- @doc("The CID of the blob to fetch")
1313+ /** The CID of the blob to fetch */
1414 @required
1515 cid: cid
1616 ): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getBlocks {
44- @doc("Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS.")
44+ /** Get data blocks from a given repo, by CID. For example, intermediate MST nodes, or records. Does not require auth; implemented by PDS. */
55 @query
66 @encoding("application/vnd.ipld.car")
77 @errors(BlockNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the repo.")
99+ /** The DID of the repo. */
1010 @required
1111 did: did,
1212
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getCheckout {
44- @doc("DEPRECATED - please use com.atproto.sync.getRepo instead")
44+ /** DEPRECATED - please use com.atproto.sync.getRepo instead */
55 @query
66 @encoding("application/vnd.ipld.car")
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getHead {
44- @doc("DEPRECATED - please use com.atproto.sync.getLatestCommit instead")
44+ /** DEPRECATED - please use com.atproto.sync.getLatestCommit instead */
55 @query
66 @errors(HeadNotFound)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): {
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getHostStatus {
44- @doc("Returns information about a specified upstream host, as consumed by the server. Implemented by relays.")
44+ /** Returns information about a specified upstream host, as consumed by the server. Implemented by relays. */
55 @query
66 @errors(HostNotFound)
77 op main(
88- @doc("Hostname of the host (eg, PDS or relay) being queried.")
88+ /** Hostname of the host (eg, PDS or relay) being queried. */
99 @required
1010 hostname: string
1111 ): {
1212 @required hostname: string;
13131414- @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
1414+ /** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
1515 seq?: integer;
16161717- @doc("Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts.")
1717+ /** Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts. */
1818 accountCount?: integer;
19192020 status?: com.atproto.sync.defs.HostStatus;
···22222323 model HostNotFound {}
2424}
2525+2626+// --- Externals ---
2727+2828+@external
2929+namespace com.atproto.sync.defs {
3030+ model HostStatus { }
3131+}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getLatestCommit {
44- @doc("Get the current commit CID & revision of the specified repo. Does not require auth.")
44+ /** Get the current commit CID & revision of the specified repo. Does not require auth. */
55 @query
66 @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): {
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getRecord {
44- @doc("Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.")
44+ /** Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth. */
55 @query
66 @encoding("application/vnd.ipld.car")
77 @errors(RecordNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the repo.")
99+ /** The DID of the repo. */
1010 @required
1111 did: did,
12121313 @required collection: nsid,
14141515- @doc("Record Key")
1515+ /** Record Key */
1616 @required
1717 rkey: recordKey
1818 ): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getRepo {
44- @doc("Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.")
44+ /** Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS. */
55 @query
66 @encoding("application/vnd.ipld.car")
77 @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88 op main(
99- @doc("The DID of the repo.")
99+ /** The DID of the repo. */
1010 @required
1111 did: did,
12121313- @doc("The revision ('rev') of the repo to create a diff from.")
1313+ /** The revision ('rev') of the repo to create a diff from. */
1414 since?: tid
1515 ): void;
1616
···11import "@typelex/emitter";
2233namespace com.atproto.sync.getRepoStatus {
44- @doc("Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.")
44+ /** Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay. */
55 @query
66 @errors(RepoNotFound)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did
1111 ): {
1212 @required did: did;
1313 @required active: boolean;
14141515- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
1515+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
1616 status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
17171818- @doc("Optional field, the current rev of the repo, if active=true")
1818+ /** Optional field, the current rev of the repo, if active=true */
1919 rev?: tid;
2020 };
2121
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listBlobs {
44- @doc("List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS.")
44+ /** List blob CIDs for an account, since some repo revision. Does not require auth; implemented by PDS. */
55 @query
66 @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
77 op main(
88- @doc("The DID of the repo.")
88+ /** The DID of the repo. */
99 @required
1010 did: did,
11111212- @doc("Optional revision of the repo to list blobs since.")
1212+ /** Optional revision of the repo to list blobs since. */
1313 since?: tid,
14141515 @minValue(1)
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listHosts {
44- @doc("Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.")
44+ /** Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays. */
55 @query
66 op main(
77 @minValue(1)
···1212 ): {
1313 cursor?: string;
14141515- @doc("Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first.")
1515+ /** Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first. */
1616 @required
1717 hosts: Host[];
1818 };
19192020 model Host {
2121- @doc("hostname of server; not a URL (no scheme)")
2121+ /** hostname of server; not a URL (no scheme) */
2222 @required
2323 hostname: string;
24242525- @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
2525+ /** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
2626 seq?: integer;
27272828 accountCount?: integer;
2929 status?: com.atproto.sync.defs.HostStatus;
3030 }
3131}
3232+3333+// --- Externals ---
3434+3535+@external
3636+namespace com.atproto.sync.defs {
3737+ model HostStatus { }
3838+}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listRepos {
44- @doc("Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.")
44+ /** Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay. */
55 @query
66 op main(
77 @minValue(1)
···1717 model Repo {
1818 @required did: did;
19192020- @doc("Current repo commit CID")
2020+ /** Current repo commit CID */
2121 @required
2222 head: cid;
23232424 @required rev: tid;
2525 active?: boolean;
26262727- @doc("If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.")
2727+ /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
2828 status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
2929 }
3030}
···11import "@typelex/emitter";
2233namespace com.atproto.sync.listReposByCollection {
44- @doc("Enumerates all the DIDs which have records with the given collection NSID.")
44+ /** Enumerates all the DIDs which have records with the given collection NSID. */
55 @query
66 op main(
77 @required collection: nsid,
8899- @doc("Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists.")
99+ /** Maximum size of response set. Recommend setting a large maximum (1000+) when enumerating large DID lists. */
1010 @minValue(1)
1111 @maxValue(2000)
1212 limit?: int32 = 500,
···11import "@typelex/emitter";
2233namespace com.atproto.sync.notifyOfUpdate {
44- @doc("Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl")
44+ /** Notify a crawling service of a recent update, and that crawling should resume. Intended use is after a gap between repo stream events caused the crawling service to disconnect. Does not require auth; implemented by Relay. DEPRECATED: just use com.atproto.sync.requestCrawl */
55 @procedure
66 op main(input: {
77- @doc("Hostname of the current service (usually a PDS) that is notifying of update.")
77+ /** Hostname of the current service (usually a PDS) that is notifying of update. */
88 @required
99 hostname: string;
1010 }): void;
···11import "@typelex/emitter";
2233namespace com.atproto.sync.requestCrawl {
44- @doc("Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth.")
44+ /** Request a service to persistently crawl hosted repos. Expected use is new PDS instances declaring their existence to Relays. Does not require auth. */
55 @procedure
66 @errors(HostBanned)
77 op main(input: {
88- @doc("Hostname of the current service (eg, PDS) that is requesting to be crawled.")
88+ /** Hostname of the current service (eg, PDS) that is requesting to be crawled. */
99 @required
1010 hostname: string;
1111 }): void;
···33namespace com.atproto.sync.subscribeRepos {
44 @subscription
55 @errors(FutureCursor, ConsumerTooSlow)
66- @doc("Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay.")
66+ /** Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay. */
77 op main(
88- @doc("The last known event seq number to backfill from.")
88+ /** The last known event seq number to backfill from. */
99 cursor?: integer
1010 ): (Commit | Sync | Identity | Account | Info | unknown);
11111212 model FutureCursor {}
13131414- @doc("If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection.")
1414+ /** If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection. */
1515 model ConsumerTooSlow {}
16161717- @doc("Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature.")
1717+ /** Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature. */
1818 model Commit {
1919- @doc("The stream sequence number of this message.")
1919+ /** The stream sequence number of this message. */
2020 @required
2121 seq: integer;
22222323- @doc("DEPRECATED -- unused")
2323+ /** DEPRECATED -- unused */
2424 @required
2525 rebase: boolean;
26262727- @doc("DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.")
2727+ /** DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data. */
2828 @required
2929 tooBig: boolean;
30303131- @doc("The repo this event comes from. Note that all other message types name this field 'did'.")
3131+ /** The repo this event comes from. Note that all other message types name this field 'did'. */
3232 @required
3333 repo: did;
34343535- @doc("Repo commit object CID.")
3535+ /** Repo commit object CID. */
3636 @required
3737 commit: cidLink;
38383939- @doc("The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event.")
3939+ /** The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event. */
4040 @required
4141 rev: tid;
42424343- @doc("The rev of the last emitted commit from this repo (if any).")
4343+ /** The rev of the last emitted commit from this repo (if any). */
4444 @required
4545 since: tid | null;
46464747- @doc("CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.")
4747+ /** CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list. */
4848 @maxBytes(2000000)
4949 @required
5050 blocks: bytes;
51515252 @maxItems(200)
5353 @required
5454- @doc("List of repo mutation operations in this commit (eg, records created, updated, or deleted).")
5454+ /** List of repo mutation operations in this commit (eg, records created, updated, or deleted). */
5555 ops: RepoOp[];
56565757- @doc("DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.")
5757+ /** DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit. */
5858 @required blobs: cidLink[];
59596060- @doc("The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose.")
6060+ /** The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose. */
6161 prevData?: cidLink;
62626363- @doc("Timestamp of when this message was originally broadcast.")
6363+ /** Timestamp of when this message was originally broadcast. */
6464 @required
6565 time: datetime;
6666 }
67676868- @doc("Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.")
6868+ /** Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository. */
6969 model Sync {
7070- @doc("The stream sequence number of this message.")
7070+ /** The stream sequence number of this message. */
7171 @required
7272 seq: integer;
73737474- @doc("The account this repo event corresponds to. Must match that in the commit object.")
7474+ /** The account this repo event corresponds to. Must match that in the commit object. */
7575 @required
7676 did: did;
77777878- @doc("CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.")
7878+ /** CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'. */
7979 @maxBytes(10000)
8080 @required
8181 blocks: bytes;
82828383- @doc("The rev of the commit. This value must match that in the commit object.")
8383+ /** The rev of the commit. This value must match that in the commit object. */
8484 @required
8585 rev: string;
86868787- @doc("Timestamp of when this message was originally broadcast.")
8787+ /** Timestamp of when this message was originally broadcast. */
8888 @required
8989 time: datetime;
9090 }
91919292- @doc("Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache.")
9292+ /** Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache. */
9393 model Identity {
9494 @required seq: integer;
9595 @required did: did;
9696 @required time: datetime;
97979898- @doc("The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details.")
9898+ /** The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details. */
9999 handle?: handle;
100100 }
101101102102- @doc("Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.")
102102+ /** Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active. */
103103 model Account {
104104 @required seq: integer;
105105 @required did: did;
106106 @required time: datetime;
107107108108- @doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
108108+ /** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
109109 @required
110110 active: boolean;
111111112112- @doc("If active=false, this optional field indicates a reason for why the account is not active.")
112112+ /** If active=false, this optional field indicates a reason for why the account is not active. */
113113 status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
114114 }
115115···118118 message?: string;
119119 }
120120121121- @doc("A repo operation, ie a mutation of a single record.")
121121+ /** A repo operation, ie a mutation of a single record. */
122122 model RepoOp {
123123 @required action: "create" | "update" | "delete" | string;
124124 @required path: string;
125125126126- @doc("For creates and updates, the new record CID. For deletions, null.")
126126+ /** For creates and updates, the new record CID. For deletions, null. */
127127 @required
128128 cid: cidLink | null;
129129130130- @doc("For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.")
130130+ /** For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined. */
131131 prev?: cidLink;
132132 }
133133}
···11import "@typelex/emitter";
2233namespace com.atproto.temp.addReservedHandle {
44- @doc("Add a handle to the set of reserved handles.")
44+ /** Add a handle to the set of reserved handles. */
55 @procedure
66 op main(
77 input: {
···11import "@typelex/emitter";
2233namespace com.atproto.temp.checkHandleAvailability {
44- @doc("An invalid email was provided.")
44+ /** An invalid email was provided. */
55 model InvalidEmail {}
6677- @doc("Indicates the provided handle is available.")
77+ /** Indicates the provided handle is available. */
88 model ResultAvailable {}
991010- @doc("Indicates the provided handle is unavailable and gives suggestions of available handles.")
1010+ /** Indicates the provided handle is unavailable and gives suggestions of available handles. */
1111 model ResultUnavailable {
1212- @doc("List of suggested handles based on the provided inputs.")
1212+ /** List of suggested handles based on the provided inputs. */
1313 @required
1414 suggestions: Suggestion[];
1515 }
···1717 model Suggestion {
1818 @required handle: handle;
19192020- @doc("Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics.")
2020+ /** Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics. */
2121 @required
2222 method: string;
2323 }
24242525- @doc("Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions.")
2525+ /** Checks whether the provided handle is available. If the handle is not available, available suggestions will be returned. Optional inputs will be used to generate suggestions. */
2626 @query
2727 @errors(InvalidEmail)
2828 op main(
2929- @doc("Tentative handle. Will be checked for availability or used to build handle suggestions.")
3030- handle: handle,
2929+ /** Tentative handle. Will be checked for availability or used to build handle suggestions. */
3030+ @required handle: handle,
31313232- @doc("User-provided email. Might be used to build handle suggestions.")
3232+ /** User-provided email. Might be used to build handle suggestions. */
3333 email?: string,
34343535- @doc("User-provided birth date. Might be used to build handle suggestions.")
3535+ /** User-provided birth date. Might be used to build handle suggestions. */
3636 birthDate?: datetime
3737 ): {
3838- @doc("Echo of the input handle.")
3838+ /** Echo of the input handle. */
3939 @required
4040 handle: handle;
4141
···11import "@typelex/emitter";
2233namespace com.atproto.temp.fetchLabels {
44- @doc("DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date.")
44+ /** DEPRECATED: use queryLabels or subscribeLabels instead -- Fetch all labels from a labeler created after a certain date. */
55 @query
66 op main(
77 since?: integer,
···1313 @required labels: com.atproto.label.defs.Label[];
1414 };
1515}
1616+1717+// --- Externals ---
1818+1919+@external
2020+namespace com.atproto.label.defs {
2121+ model Label { }
2222+}
···11import "@typelex/emitter";
2233namespace com.atproto.temp.requestPhoneVerification {
44- @doc("Request a verification code to be sent to the supplied phone number")
44+ /** Request a verification code to be sent to the supplied phone number */
55 @procedure
66 op main(
77 input: {
···11import "@typelex/emitter";
2233namespace com.atproto.temp.revokeAccountCredentials {
44- @doc("Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset.")
44+ /** Revoke sessions, password, and app passwords associated with account. May be resolved by a password reset. */
55 @procedure
66 op main(
77 input: {
···44 model Main {
55 @required image: Blob<#["image/*"], 1000000>;
6677- @doc("Alt text description of the image, for accessibility.")
77+ /** Alt text description of the image, for accessibility. */
88 alt?: string;
991010 @required aspectRatio: AspectRatio;
···11import "@typelex/emitter";
2233-@doc("A lexicon for long form rich media documents")
33+/** A lexicon for long form rich media documents */
44namespace `pub`.leaflet.document {
55- @doc("Record containing a document")
55+ /** Record containing a document */
66 @rec("tid")
77 model Main {
88 @maxGraphemes(128)
···2323 @required pages: (`pub`.leaflet.pages.linearDocument.Main | unknown)[];
2424 }
2525}
2626+2727+// --- Externals ---
2828+2929+@external
3030+namespace com.atproto.repo.strongRef {
3131+ model Main { }
3232+}
3333+3434+@external
3535+namespace `pub`.leaflet.pages.linearDocument {
3636+ model Main { }
3737+}
···11import "@typelex/emitter";
2233namespace `pub`.leaflet.graph.subscription {
44- @doc("Record declaring a subscription to a publication")
44+ /** Record declaring a subscription to a publication */
55 @rec("tid")
66 model Main {
77 @required publication: atUri;
···11import "@typelex/emitter";
2233namespace `pub`.leaflet.richtext.facet {
44- @doc("Annotation of a sub-string within rich text.")
44+ /** Annotation of a sub-string within rich text. */
55 model Main {
66 @required index: ByteSlice;
77 @required features: (Link | Code | Highlight | Underline | Strikethrough | Id | Bold | Italic | unknown)[];
88 }
991010- @doc("Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.")
1010+ /** Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets. */
1111 model ByteSlice {
1212 @minValue(0)
1313 @required
···1818 byteEnd: integer;
1919 }
20202121- @doc("Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.")
2121+ /** Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL. */
2222 model Link {
2323 @required uri: uri;
2424 }
25252626- @doc("Facet feature for inline code.")
2626+ /** Facet feature for inline code. */
2727 model Code {}
28282929- @doc("Facet feature for highlighted text.")
2929+ /** Facet feature for highlighted text. */
3030 model Highlight {}
31313232- @doc("Facet feature for underline markup")
3232+ /** Facet feature for underline markup */
3333 model Underline {}
34343535- @doc("Facet feature for strikethrough markup")
3535+ /** Facet feature for strikethrough markup */
3636 model Strikethrough {}
37373838- @doc("Facet feature for an identifier. Used for linking to a segment")
3838+ /** Facet feature for an identifier. Used for linking to a segment */
3939 model Id {
4040 id?: string;
4141 }
42424343- @doc("Facet feature for bold text")
4343+ /** Facet feature for bold text */
4444 model Bold {}
45454646- @doc("Facet feature for italic text")
4646+ /** Facet feature for italic text */
4747 model Italic {}
4848}
···11import "@typelex/emitter";
2233namespace sh.tangled.actor.profile {
44- @doc("A declaration of a Tangled account profile.")
44+ /** A declaration of a Tangled account profile. */
55 @rec("literal:self")
66 model Main {
77- @doc("Free-form profile description text.")
77+ /** Free-form profile description text. */
88 @maxGraphemes(256)
99 @maxLength(2560)
1010 description?: string;
···1717 @maxItems(2)
1818 stats?: StatValue[];
19192020- @doc("Include link to this account on Bluesky.")
2020+ /** Include link to this account on Bluesky. */
2121 @required
2222 bluesky: boolean;
23232424- @doc("Free-form location text.")
2424+ /** Free-form location text. */
2525 @maxGraphemes(40)
2626 @maxLength(400)
2727 location?: string;
28282929- @doc("Any ATURI, it is up to appviews to validate these fields.")
2929+ /** Any ATURI, it is up to appviews to validate these fields. */
3030 @minItems(0)
3131 @maxItems(6)
3232 pinnedRepositories?: atUri[];
3333 }
34343535- @doc("Any URI, intended for social profiles or websites, can be used to link DIDs/AT-URIs too.")
3535+ /** Any URI, intended for social profiles or websites, can be used to link DIDs/AT-URIs too. */
3636 @inline
3737 scalar LinkItem extends uri;
38383939- @doc("Vanity stats.")
3939+ /** Vanity stats. */
4040 @closed
4141 @inline
4242 union StatValue {
···11import "@typelex/emitter";
2233namespace sh.tangled.git.refUpdate {
44- @doc("An update to a git repository, emitted by knots.")
44+ /** An update to a git repository, emitted by knots. */
55 @rec("tid")
66 model Main {
77- @doc("Ref being updated")
77+ /** Ref being updated */
88 @maxGraphemes(256)
99 @maxLength(2560)
1010 @required
1111 ref: string;
12121313- @doc("did of the user that pushed this ref")
1313+ /** did of the user that pushed this ref */
1414 @required
1515 committerDid: did;
16161717- @doc("did of the owner of the repo")
1717+ /** did of the owner of the repo */
1818 @required
1919 repoDid: did;
20202121- @doc("name of the repo")
2121+ /** name of the repo */
2222 @required
2323 repoName: string;
24242525- @doc("old SHA of this ref")
2525+ /** old SHA of this ref */
2626 @minLength(40)
2727 @maxLength(40)
2828 @required
2929 oldSha: string;
30303131- @doc("new SHA of this ref")
3131+ /** new SHA of this ref */
3232 @minLength(40)
3333 @maxLength(40)
3434 @required
···11import "@typelex/emitter";
2233namespace sh.tangled.knot.listKeys {
44- @doc("List all public keys stored in the knot server")
44+ /** List all public keys stored in the knot server */
55 @query
66 @errors(InternalServerError)
77 op main(
88- @doc("Maximum number of keys to return")
88+ /** Maximum number of keys to return */
99 @minValue(1)
1010 @maxValue(1000)
1111 limit?: int32 = 100,
12121313- @doc("Pagination cursor")
1313+ /** Pagination cursor */
1414 cursor?: string
1515 ): {
1616 @required keys: PublicKey[];
17171818- @doc("Pagination cursor for next page")
1818+ /** Pagination cursor for next page */
1919 cursor?: string;
2020 };
21212222 model PublicKey {
2323- @doc("DID associated with the public key")
2323+ /** DID associated with the public key */
2424 @required
2525 did: did;
26262727- @doc("Public key contents")
2727+ /** Public key contents */
2828 @maxLength(4096)
2929 @required
3030 key: string;
31313232- @doc("Key upload timestamp")
3232+ /** Key upload timestamp */
3333 @required
3434 createdAt: datetime;
3535 }
36363737- @doc("Failed to retrieve public keys")
3737+ /** Failed to retrieve public keys */
3838 model InternalServerError {}
3939}
···55 model Main {
66 @required subject: did;
7788- @doc("domain that this member now belongs to")
88+ /** domain that this member now belongs to */
99 @required
1010 domain: string;
1111
···11import "@typelex/emitter";
2233namespace sh.tangled.knot.version {
44- @doc("Get the version of a knot")
44+ /** Get the version of a knot */
55 @query
66 op main(): {
77 @required version: string;
···33namespace sh.tangled.label.definition {
44 @rec("any")
55 model Main {
66- @doc("The display name of this label.")
66+ /** The display name of this label. */
77 @minGraphemes(1)
88 @maxGraphemes(40)
99 @required
1010 name: string;
11111212- @doc("The type definition of this label. Appviews may allow sorting for certain types.")
1212+ /** The type definition of this label. Appviews may allow sorting for certain types. */
1313 @required
1414 valueType: ValueType;
15151616- @doc("The areas of the repo this label may apply to, eg.: sh.tangled.repo.issue. Appviews may choose to respect this.")
1616+ /** The areas of the repo this label may apply to, eg.: sh.tangled.repo.issue. Appviews may choose to respect this. */
1717 @required
1818 scope: nsid[];
19192020- @doc("The hex value for the background color for the label. Appviews may choose to respect this.")
2020+ /** The hex value for the background color for the label. Appviews may choose to respect this. */
2121 color?: string;
22222323 @required createdAt: datetime;
24242525- @doc("Whether this label can be repeated for a given entity, eg.: [reviewer:foo, reviewer:bar]")
2525+ /** Whether this label can be repeated for a given entity, eg.: [reviewer:foo, reviewer:bar] */
2626 multiple?: boolean;
2727 }
2828···4444 }
45454646 model ValueType {
4747- @doc("The concrete type of this label's value.")
4747+ /** The concrete type of this label's value. */
4848 @required
4949 type: ConcreteType;
50505151- @doc("An optional constraint that can be applied on string concrete types.")
5151+ /** An optional constraint that can be applied on string concrete types. */
5252 @required
5353 format: FormatType;
54545555- @doc("Closed set of values that this label can take.")
5555+ /** Closed set of values that this label can take. */
5656 `enum`?: string[];
5757 }
5858}
···11+import "@typelex/emitter";
22+33+namespace sh.tangled.label.`op` {
44+ @rec("tid")
55+ model Main {
66+ @doc("The subject (task, pull or discussion) of this label. Appviews may apply a `scope` check and refuse this op.")
77+ @required
88+ subject: atUri;
99+1010+ @required
1111+ add: Operand[];
1212+1313+ @required
1414+ delete: Operand[];
1515+1616+ @required
1717+ performedAt: datetime;
1818+ }
1919+2020+ model Operand {
2121+ @doc("ATURI to the label definition")
2222+ @required
2323+ key: atUri;
2424+2525+ @doc("Stringified value of the label. This is first unstringed by appviews and then interpreted as a concrete value.")
2626+ @required
2727+ value: string;
2828+ }
2929+}
···11-import "@typelex/emitter";
22-33-namespace sh.tangled.label.`op` {
44- @rec("tid")
55- model Main {
66- @doc("The subject (task, pull or discussion) of this label. Appviews may apply a `scope` check and refuse this op.")
77- @required
88- subject: atUri;
99-1010- @required performedAt: datetime;
1111- @required add: Operand[];
1212- @required delete: Operand[];
1313- }
1414-1515- model Operand {
1616- @doc("ATURI to the label definition")
1717- @required
1818- key: atUri;
1919-2020- @doc("Stringified value of the label. This is first unstringed by appviews and then interpreted as a concrete value.")
2121- @required
2222- value: string;
2323- }
2424-}
···11import "@typelex/emitter";
2233namespace sh.tangled.owner {
44- @doc("Get the owner of a service")
44+ /** Get the owner of a service */
55 @query
66 @errors(OwnerNotFound)
77 op main(): {
88 @required owner: did;
99 };
10101111- @doc("Owner is not set for this service")
1111+ /** Owner is not set for this service */
1212 model OwnerNotFound {}
1313}
···14141515 @rec("tid")
1616 model Main {
1717- @doc("ATURI of the pipeline")
1717+ /** ATURI of the pipeline */
1818 @required
1919 pipeline: atUri;
20202121- @doc("name of the workflow within this pipeline")
2121+ /** name of the workflow within this pipeline */
2222 @required
2323 workflow: atUri;
24242525- @doc("status of the workflow")
2525+ /** status of the workflow */
2626 @required
2727 status: WorkflowStatus;
28282929- @doc("time of creation of this status update")
2929+ /** time of creation of this status update */
3030 @required
3131 createdAt: datetime;
32323333- @doc("error message if failed")
3333+ /** error message if failed */
3434 error?: string;
35353636- @doc("exit code if failed")
3636+ /** exit code if failed */
3737 exitCode?: integer;
3838 }
3939}
···11+import "@typelex/emitter";
22+33+namespace sh.tangled.repo.artifact {
44+ @rec("tid")
55+ model Main {
66+ @doc("name of the artifact")
77+ @required
88+ name: string;
99+1010+ @doc("repo that this artifact is being uploaded to")
1111+ @required
1212+ repo: atUri;
1313+1414+ @doc("hash of the tag object that this artifact is attached to (only annotated tags are supported)")
1515+ @required
1616+ @minBytes(20)
1717+ @maxBytes(20)
1818+ tag: bytes;
1919+2020+ @doc("time of creation of this artifact")
2121+ @required
2222+ createdAt: datetime;
2323+2424+ @doc("the artifact")
2525+ @required
2626+ artifact: Blob<#["*/*"], 52428800>;
2727+ }
2828+}
···11+import "@typelex/emitter";
22+33+namespace sh.tangled.repo.mergeCheck {
44+ /** Check if a merge is possible between two branches */
55+ @procedure
66+ op main(
77+ input: {
88+ /** DID of the repository owner */
99+ @required did: did,
1010+1111+ /** Name of the repository */
1212+ @required name: string,
1313+1414+ /** Patch or pull request to check for merge conflicts */
1515+ @required patch: string,
1616+1717+ /** Target branch to merge into */
1818+ @required branch: string,
1919+ }
2020+ ): {
2121+ /** Whether the merge has conflicts */
2222+ @required is_conflicted: boolean;
2323+2424+ /** List of files with merge conflicts */
2525+ conflicts?: ConflictInfo[];
2626+2727+ /** Additional message about the merge check */
2828+ message?: string;
2929+3030+ /** Error message if check failed */
3131+ error?: string;
3232+ };
3333+3434+ model ConflictInfo {
3535+ /** Name of the conflicted file */
3636+ @required filename: string;
3737+3838+ /** Reason for the conflict */
3939+ @required reason: string;
4040+ }
4141+}
···11+import "@typelex/emitter";
22+33+namespace sh.tangled.spindle.member {
44+ @rec("tid")
55+ model Main {
66+ @required
77+ subject: did;
88+99+ @doc("spindle instance that the subject is now a member of")
1010+ @required
1111+ instance: string;
1212+1313+ @required
1414+ createdAt: datetime;
1515+ }
1616+}
···11import "@typelex/emitter";
2233namespace com.example.allOptionalFields {
44- @doc("Object with all optional fields (no required)")
44+ /** Object with all optional fields (no required) */
55 model Main {
66- @doc("All fields are optional")
66+ /** All fields are optional */
77 field1?: string;
8899 field2?: integer;
···2233namespace com.example.arrayOfUnions {
44 model Main {
55- @doc("Array of open union variants")
55+ /** Array of open union variants */
66 @required
77 items: (ItemA | ItemB | ItemC | unknown)[];
8899- @doc("Array of closed union variants")
99+ /** Array of closed union variants */
1010 @maxItems(10)
1111 operations?: Operations[];
1212 }
···11import "@typelex/emitter";
2233namespace com.example.blobs {
44- @doc("Blob type examples")
44+ /** Blob type examples */
55 model Main {
66- @doc("Basic blob with no constraints")
66+ /** Basic blob with no constraints */
77 simpleBlob?: Blob;
8899- @doc("Image blob up to 5MB")
99+ /** Image blob up to 5MB */
1010 imageBlob?: Blob<#["image/*"], 5000000>;
11111212- @doc("Specific image types up to 2MB")
1212+ /** Specific image types up to 2MB */
1313 specificImages?: Blob<#["image/png", "image/jpeg", "image/gif"], 2000000>;
14141515- @doc("Video blob up to 100MB")
1515+ /** Video blob up to 100MB */
1616 videoBlob?: Blob<#["video/mp4", "video/webm"], 100000000>;
17171818- @doc("Accept any MIME type")
1818+ /** Accept any MIME type */
1919 anyBlob?: Blob<#["*/*"]>;
2020 }
2121}
···11import "@typelex/emitter";
2233namespace com.example.cidLinks {
44- @doc("CID link examples")
44+ /** CID link examples */
55 model Main {
66- @doc("A CID link to content")
66+ /** A CID link to content */
77 contentCid?: cidLink;
8899- @doc("Link to previous version")
99+ /** Link to previous version */
1010 previousVersion?: cidLink;
1111 }
1212}
···11import "@typelex/emitter";
2233namespace com.example.createRecord {
44- @doc("The provided text is invalid")
44+ /** The provided text is invalid */
55 model InvalidText {}
6677- @doc("Create a new record")
77+ /** Create a new record */
88 @procedure
99 @errors(InvalidText)
1010 op main(input: {
1111- @doc("The text content")
1111+ /** The text content */
1212 @required
1313 text: string;
1414 }): {
···11import "@typelex/emitter";
2233-@doc("Common definitions used by other lexicons")
33+/** Common definitions used by other lexicons */
44namespace com.example.defs {
55 @closed
66 union StatusEnum {
···11import "@typelex/emitter";
2233namespace com.example.deleteRecord {
44- @doc("Delete a record (no output)")
44+ /** Delete a record (no output) */
55 @procedure
66 op main(input: {
77 @required uri: atUri;
···11import "@typelex/emitter";
2233namespace com.example.eventStream {
44- @doc("Cursor is in the future")
44+ /** Cursor is in the future */
55 model FutureCursor {}
6677- @doc("Subscription with union message schema")
77+ /** Subscription with union message schema */
88 @subscription
99 @errors(FutureCursor)
1010 op main(cursor?: integer): (Commit | Identity | Account | Handle | Tombstone);
···2233namespace com.example.flexibleRecord {
44 @rec("any")
55- @doc("Record with any key type")
55+ /** Record with any key type */
66 model Main {
77 data?: string;
88 tags?: string[];
···11import "@typelex/emitter";
2233namespace com.example.getRecord {
44- @doc("Retrieve a record by ID")
44+ /** Retrieve a record by ID */
55 @query
66 op main(
77- @doc("The record identifier")
77+ /** The record identifier */
88 @required
99 id: string
1010 ): {
···11import "@typelex/emitter";
2233namespace com.example.getStatus {
44- @doc("Get system status (no parameters)")
44+ /** Get system status (no parameters) */
55 @query
66 op main(): {
77 @required status: string;
···11import "@typelex/emitter";
2233namespace com.example.nullType {
44- @doc("Demonstrates the null primitive type")
44+ /** Demonstrates the null primitive type */
55 model Main {
66- @doc("Field with explicit null type - always null")
66+ /** Field with explicit null type - always null */
77 @required
88 alwaysNull: null;
991010- @doc("Optional field that can be string or omitted, but not null")
1010+ /** Optional field that can be string or omitted, but not null */
1111 optionalString?: string;
12121313- @doc("Nullable string - can be omitted, string, or null")
1313+ /** Nullable string - can be omitted, string, or null */
1414 nullableString?: string | null;
1515 }
1616}
···11import "@typelex/emitter";
2233namespace com.example.nullableFields {
44- @doc("Demonstrates nullable field semantics")
44+ /** Demonstrates nullable field semantics */
55 model Main {
66- @doc("Required, cannot be null or omitted")
66+ /** Required, cannot be null or omitted */
77 @required
88 requiredField: string;
991010- @doc("Must be present, but can be null")
1010+ /** Must be present, but can be null */
1111 nullableRequired?: string | null;
12121313- @doc("Can be omitted, present with value, or present as null")
1313+ /** Can be omitted, present with value, or present as null */
1414 nullableOptional?: string | null;
15151616- @doc("Can be omitted or present with value, but not null")
1616+ /** Can be omitted or present with value, but not null */
1717 optionalField?: string;
1818 }
1919}
···11import "@typelex/emitter";
2233namespace com.example.objects {
44- @doc("Object with various property configurations")
44+ /** Object with various property configurations */
55 model Main {
66- @doc("This field is required")
66+ /** This field is required */
77 @required
88 requiredField: string;
991010- @doc("This field is optional")
1010+ /** This field is optional */
1111 optionalField?: string;
12121313- @doc("This field can be null")
1313+ /** This field can be null */
1414 nullableField?: string | null;
15151616 nestedObject?: Nested;
···33namespace com.example.outputWithoutSchema {
44 @query
55 @encoding("application/json")
66- @doc("Query with JSON output but no schema defined")
66+ /** Query with JSON output but no schema defined */
77 op main(id?: string): never;
88}
···2233namespace com.example.`record` {
44 @rec("tid")
55- @doc("A simple record with basic properties")
55+ /** A simple record with basic properties */
66 model Main {
77- @doc("The text content")
77+ /** The text content */
88 @required
99 text: string;
10101111- @doc("When the record was created")
1111+ /** When the record was created */
1212 @required
1313 createdAt: datetime;
1414 }
···2233namespace com.example.recordWithNsidKey {
44 @rec("nsid")
55- @doc("Record with NSID as the record key")
55+ /** Record with NSID as the record key */
66 model Main {
77- @doc("The NSID of the associated lexicon")
77+ /** The NSID of the associated lexicon */
88 @required
99 nsid: nsid;
10101111- @doc("Optional metadata")
1111+ /** Optional metadata */
1212 metadata?: string;
1313 }
1414}
···11import "@typelex/emitter";
2233namespace com.example.refs {
44- @doc("Reference examples")
44+ /** Reference examples */
55 model Main {
66- @doc("Reference to local definition")
66+ /** Reference to local definition */
77 localRef?: LocalDef;
8899- @doc("Reference to external definition")
99+ /** Reference to external definition */
1010 externalRef?: com.example.defs.Metadata;
11111212- @doc("Reference to main definition (no fragment)")
1212+ /** Reference to main definition (no fragment) */
1313 mainRef?: com.example.`record`.Main;
1414 }
1515
···11import "@typelex/emitter";
2233namespace com.example.subscriptionWithErrors {
44- @doc("Subscription with error definitions")
44+ /** Subscription with error definitions */
55 @subscription
66 @errors(ConsumerTooSlow, InvalidCursor)
77 op main(
88- @doc("Optional cursor for resuming")
88+ /** Optional cursor for resuming */
99 cursor?: integer
1010 ): (Event | Status | Info);
1111···2525 message?: string;
2626 }
27272828- @doc("Indicates the consumer is not keeping up with the event stream")
2828+ /** Indicates the consumer is not keeping up with the event stream */
2929 model ConsumerTooSlow {}
30303131- @doc("The provided cursor is invalid or expired")
3131+ /** The provided cursor is invalid or expired */
3232 model InvalidCursor {}
3333}
···2233namespace com.example.tidRecord {
44 @rec("tid")
55- @doc("Record with TID key type")
55+ /** Record with TID key type */
66 model Main {
77 @required
88 content: string;
···11import "@typelex/emitter";
2233namespace com.example.tokens {
44- @doc("Token usage example")
44+ /** Token usage example */
55 model Main {
66 @required status: Active;
77 }
8899- @doc("Indicates an active state")
99+ /** Indicates an active state */
1010 @token
1111 model Active {}
12121313- @doc("Indicates an inactive state")
1313+ /** Indicates an inactive state */
1414 @token
1515 model Inactive {}
16161717- @doc("Indicates a pending state")
1717+ /** Indicates a pending state */
1818 @token
1919 model Pending {}
2020}
···99 Delete,
1010 }
11111212- @doc("Closed union example")
1212+ /** Closed union example */
1313 model Main {
1414- @doc("Closed union - no more variants allowed")
1414+ /** Closed union - no more variants allowed */
1515 @required
1616 action: Action;
1717 }
···11import "@typelex/emitter";
2233namespace com.example.unionEmpty {
44- @doc("Empty open union (similar to unknown but requires $type)")
44+ /** Empty open union (similar to unknown but requires $type) */
55 model Main {
66- @doc("Empty open union - any object with $type allowed")
66+ /** Empty open union - any object with $type allowed */
77 data?: (never | unknown);
88 }
99}
···11import "@typelex/emitter";
2233namespace com.example.unionOpen {
44- @doc("Open union example (default)")
44+ /** Open union example (default) */
55 model Main {
66- @doc("Open union - more variants can be added in future")
66+ /** Open union - more variants can be added in future */
77 @required
88 item: TypeA | TypeB | TypeC | unknown;
99 }
···11import "@typelex/emitter";
2233namespace com.example.withErrors {
44- @doc("The provided value is invalid")
44+ /** The provided value is invalid */
55 model InvalidValue {}
6677- @doc("Too many requests")
77+ /** Too many requests */
88 model RateLimitExceeded {}
991010 model Unauthorized {}
11111212- @doc("Procedure with error definitions")
1212+ /** Procedure with error definitions */
1313 @procedure
1414 @errors(InvalidValue, RateLimitExceeded, Unauthorized)
1515 op main(input: {