···11+import "@tylex/emitter";
22+33+namespace com.atproto.admin.disableInviteCodes {
44+ @doc("Disable some set of codes and/or all codes associated with a set of users.")
55+ @procedure
66+ op main(input: {
77+ codes?: string[];
88+ accounts?: string[];
99+ }): void;
1010+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.admin.sendEmail {
44+ @doc("Send email to a user's account email address.")
55+ @procedure
66+ op main(input: {
77+ @required recipientDid: did;
88+ @required content: string;
99+ subject?: string;
1010+ @required senderDid: did;
1111+1212+ @doc("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;
1616+ };
1717+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.admin.updateAccountPassword {
44+ @doc("Update the password for a user account as an administrator.")
55+ @procedure
66+ op main(input: {
77+ @required did: did;
88+ @required password: string;
99+ }): void;
1010+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.identity.defs {
44+ model IdentityInfo {
55+ @required did: did;
66+77+ @doc("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;
1010+1111+ @doc("The complete DID document for the identity.")
1212+ @required
1313+ didDoc: unknown;
1414+ }
1515+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @query
66+ op main(): {
77+ @doc("Recommended rotation keys for PLC dids. Should be undefined (or ignored) for did:webs.")
88+ rotationKeys?: string[];
99+1010+ alsoKnownAs?: string[];
1111+ verificationMethods?: unknown;
1212+ services?: unknown;
1313+ };
1414+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.identity.refreshIdentity {
44+ @doc("The resolution process confirmed that the handle does not resolve to any DID.")
55+ model HandleNotFound {}
66+77+ @doc("The DID resolution process confirmed that there is no current DID.")
88+ model DidNotFound {}
99+1010+ @doc("The DID previously existed, but has been deactivated.")
1111+ model DidDeactivated {}
1212+1313+ @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.")
1414+ @procedure
1515+ @errors(HandleNotFound, DidNotFound, DidDeactivated)
1616+ op main(input: {
1717+ @required identifier: atIdentifier;
1818+ }): com.atproto.identity.defs.IdentityInfo;
1919+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.identity.requestPlcOperationSignature {
44+ @doc("Request an email with a code to in order to request a signed PLC operation. Requires Auth.")
55+ @procedure
66+ op main(): void;
77+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.identity.resolveDid {
44+ @doc("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.")
99+ @required
1010+ did: did
1111+ ): {
1212+ @doc("The complete DID document for the identity.")
1313+ @required
1414+ didDoc: unknown;
1515+ };
1616+1717+ @doc("The DID resolution process confirmed that there is no current DID.")
1818+ model DidNotFound {}
1919+2020+ @doc("The DID previously existed, but has been deactivated.")
2121+ model DidDeactivated {}
2222+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @query
66+ @errors(HandleNotFound)
77+ op main(
88+ @doc("The handle to resolve.")
99+ @required
1010+ handle: handle
1111+ ): {
1212+ @required did: did;
1313+ };
1414+1515+ @doc("The resolution process confirmed that the handle does not resolve to any DID.")
1616+ model HandleNotFound {}
1717+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.identity.resolveIdentity {
44+ @doc("The resolution process confirmed that the handle does not resolve to any DID.")
55+ model HandleNotFound {}
66+77+ @doc("The DID resolution process confirmed that there is no current DID.")
88+ model DidNotFound {}
99+1010+ @doc("The DID previously existed, but has been deactivated.")
1111+ model DidDeactivated {}
1212+1313+ @doc("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.")
1818+ @required
1919+ identifier: atIdentifier
2020+ ): com.atproto.identity.defs.IdentityInfo;
2121+}
···11+import "@tylex/emitter";
22+33+namespace 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")
55+ @procedure
66+ op main(input: {
77+ @required operation: unknown;
88+ }): void;
99+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.label.defs {
44+ @doc("Metadata tag on an atproto resource (eg, repo or record).")
55+ model Label {
66+ @doc("The AT Protocol version of the label object.")
77+ ver?: integer;
88+99+ @doc("DID of the actor who created this label.")
1010+ @required
1111+ src: did;
1212+1313+ @doc("AT URI of the record, repository (account), or other resource that this label applies to.")
1414+ @required
1515+ uri: uri;
1616+1717+ @doc("Optionally, CID specifying the specific version of 'uri' resource this label applies to.")
1818+ cid?: cid;
1919+2020+ @doc("The short string name of the value or type of this label.")
2121+ @maxLength(128)
2222+ @required
2323+ val: string;
2424+2525+ @doc("If true, this is a negation label, overwriting a previous label.")
2626+ neg?: boolean;
2727+2828+ @doc("Timestamp when this label was created.")
2929+ @required
3030+ cts: datetime;
3131+3232+ @doc("Timestamp at which this label expires (no longer applies).")
3333+ exp?: datetime;
3434+3535+ @doc("Signature of dag-cbor encoded label.")
3636+ sig?: bytes;
3737+ }
3838+3939+ @doc("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+ }
4545+4646+ @doc("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.")
4949+ @maxLength(128)
5050+ @required
5151+ val: string;
5252+ }
5353+5454+ @doc("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-]+).")
5757+ @maxLength(100)
5858+ @maxGraphemes(100)
5959+ @required
6060+ identifier: string;
6161+6262+ @doc("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;
6565+6666+ @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.")
6767+ @required
6868+ blurs: "content" | "media" | "none" | string;
6969+7070+ @doc("The default setting for this label.")
7171+ defaultSetting?: "ignore" | "warn" | "hide" | string = "warn";
7272+7373+ @doc("Does the user need to have adult content enabled in order to configure this label?")
7474+ adultOnly?: boolean;
7575+7676+ @required
7777+ locales: LabelValueDefinitionStrings[];
7878+ }
7979+8080+ @doc("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.")
8383+ @required
8484+ lang: language;
8585+8686+ @doc("A short human-readable name for the label.")
8787+ @maxGraphemes(64)
8888+ @maxLength(640)
8989+ @required
9090+ name: string;
9191+9292+ @doc("A longer description of what the label means and why it might be applied.")
9393+ @maxGraphemes(10000)
9494+ @maxLength(100000)
9595+ @required
9696+ description: string;
9797+ }
9898+9999+ union LabelValue {
100100+ "!hide",
101101+ "!no-promote",
102102+ "!warn",
103103+ "!no-unauthenticated",
104104+ "dmca-violation",
105105+ "doxxing",
106106+ "porn",
107107+ "sexual",
108108+ "nudity",
109109+ "nsfl",
110110+ "gore",
111111+ string,
112112+ }
113113+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
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.")
88+ @required
99+ uriPatterns: string[],
1010+1111+ @doc("Optional list of label sources (DIDs) to filter on.")
1212+ sources?: did[],
1313+1414+ @minValue(1)
1515+ @maxValue(250)
1616+ limit?: int32 = 50,
1717+1818+ cursor?: string
1919+ ): {
2020+ cursor?: string;
2121+ @required labels: com.atproto.label.defs.Label[];
2222+ };
2323+}
···11+import "@tylex/emitter";
22+33+namespace 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).")
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.")
88+ @required
99+ lexicon: integer;
1010+ }
1111+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.applyWrites {
44+ @doc("Indicates that the 'swapCommit' parameter did not match current commit.")
55+ model InvalidSwap {}
66+77+ @closed
88+ @inline
99+ union WriteAction {
1010+ Create,
1111+ Update,
1212+ Delete,
1313+ }
1414+1515+ @closed
1616+ @inline
1717+ union WriteResult {
1818+ CreateResult,
1919+ UpdateResult,
2020+ DeleteResult,
2121+ }
2222+2323+ @doc("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).")
2828+ @required
2929+ repo: atIdentifier;
3030+3131+ @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.")
3232+ validate?: boolean;
3333+3434+ @required
3535+ writes: WriteAction[];
3636+3737+ @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.")
3838+ swapCommit?: cid;
3939+ }): {
4040+ commit?: com.atproto.repo.defs.CommitMeta;
4141+ results?: WriteResult[];
4242+ };
4343+4444+ @doc("Operation which creates a new record.")
4545+ model Create {
4646+ @required collection: nsid;
4747+4848+ @doc("NOTE: maxLength is redundant with record-key format. Keeping it temporarily to ensure backwards compatibility.")
4949+ @maxLength(512)
5050+ rkey?: recordKey;
5151+5252+ @required value: unknown;
5353+ }
5454+5555+ @doc("Operation which updates an existing record.")
5656+ model Update {
5757+ @required collection: nsid;
5858+ @required rkey: recordKey;
5959+ @required value: unknown;
6060+ }
6161+6262+ @doc("Operation which deletes an existing record.")
6363+ model Delete {
6464+ @required collection: nsid;
6565+ @required rkey: recordKey;
6666+ }
6767+6868+ model CreateResult {
6969+ @required uri: atUri;
7070+ @required cid: cid;
7171+ validationStatus?: "valid" | "unknown" | string;
7272+ }
7373+7474+ model UpdateResult {
7575+ @required uri: atUri;
7676+ @required cid: cid;
7777+ validationStatus?: "valid" | "unknown" | string;
7878+ }
7979+8080+ model DeleteResult {}
8181+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.createRecord {
44+ @doc("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).")
99+ @required
1010+ repo: atIdentifier;
1111+1212+ @doc("The NSID of the record collection.")
1313+ @required
1414+ collection: nsid;
1515+1616+ @doc("The Record Key.")
1717+ @maxLength(512)
1818+ rkey?: recordKey;
1919+2020+ @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+ validate?: boolean;
2222+2323+ @doc("The record itself. Must contain a $type field.")
2424+ @required
2525+ record: unknown;
2626+2727+ @doc("Compare and swap with the previous commit by CID.")
2828+ swapCommit?: cid;
2929+ }): {
3030+ @required uri: atUri;
3131+ @required cid: cid;
3232+ commit?: com.atproto.repo.defs.CommitMeta;
3333+ validationStatus?: "valid" | "unknown" | string;
3434+ };
3535+3636+ @doc("Indicates that 'swapCommit' didn't match current repo commit.")
3737+ model InvalidSwap {}
3838+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.deleteRecord {
44+ @doc("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).")
99+ @required
1010+ repo: atIdentifier;
1111+1212+ @doc("The NSID of the record collection.")
1313+ @required
1414+ collection: nsid;
1515+1616+ @doc("The Record Key.")
1717+ @required
1818+ rkey: recordKey;
1919+2020+ @doc("Compare and swap with the previous record by CID.")
2121+ swapRecord?: cid;
2222+2323+ @doc("Compare and swap with the previous commit by CID.")
2424+ swapCommit?: cid;
2525+ }): {
2626+ commit?: com.atproto.repo.defs.CommitMeta;
2727+ };
2828+2929+ model InvalidSwap {}
3030+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.describeRepo {
44+ @doc("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.")
88+ @required
99+ repo: atIdentifier
1010+ ): {
1111+ @required handle: handle;
1212+ @required did: did;
1313+1414+ @doc("The complete DID document for this account.")
1515+ @required
1616+ didDoc: unknown;
1717+1818+ @doc("List of all the collections (NSIDs) for which this repo contains at least one record.")
1919+ @required
2020+ collections: nsid[];
2121+2222+ @doc("Indicates if handle is currently valid (resolves bi-directionally)")
2323+ @required
2424+ handleIsCorrect: boolean;
2525+ };
2626+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.getRecord {
44+ @doc("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.")
99+ @required
1010+ repo: atIdentifier,
1111+1212+ @doc("The NSID of the record collection.")
1313+ @required
1414+ collection: nsid,
1515+1616+ @doc("The Record Key.")
1717+ @required
1818+ rkey: recordKey,
1919+2020+ @doc("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;
2424+ cid?: cid;
2525+ @required value: unknown;
2626+ };
2727+2828+ model RecordNotFound {}
2929+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.importRepo {
44+ @doc("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")
88+ input: void
99+ ): void;
1010+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.listRecords {
44+ @doc("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.")
88+ @required
99+ repo: atIdentifier,
1010+1111+ @doc("The NSID of the record type.")
1212+ @required
1313+ collection: nsid,
1414+1515+ @doc("The number of records to return.")
1616+ @minValue(1)
1717+ @maxValue(100)
1818+ limit?: int32 = 50,
1919+2020+ cursor?: string,
2121+2222+ @doc("Flag to reverse the order of the returned records.")
2323+ reverse?: boolean
2424+ ): {
2525+ cursor?: string;
2626+ @required records: Record[];
2727+ };
2828+2929+ model Record {
3030+ @required uri: atUri;
3131+ @required cid: cid;
3232+ @required value: unknown;
3333+ }
3434+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.repo.putRecord {
44+ @doc("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).")
99+ @required
1010+ repo: atIdentifier;
1111+1212+ @doc("The NSID of the record collection.")
1313+ @required
1414+ collection: nsid;
1515+1616+ @doc("The Record Key.")
1717+ @maxLength(512)
1818+ @required
1919+ rkey: recordKey;
2020+2121+ @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.")
2222+ validate?: boolean;
2323+2424+ @doc("The record to write.")
2525+ @required
2626+ record: unknown;
2727+2828+ @doc("Compare and swap with the previous record by CID. WARNING: nullable and optional field; may cause problems with golang implementation")
2929+ swapRecord?: cid | null;
3030+3131+ @doc("Compare and swap with the previous commit by CID.")
3232+ swapCommit?: cid;
3333+ }): {
3434+ @required uri: atUri;
3535+ @required cid: cid;
3636+ commit?: com.atproto.repo.defs.CommitMeta;
3737+ validationStatus?: "valid" | "unknown" | string;
3838+ };
3939+4040+ model InvalidSwap {}
4141+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @procedure
66+ op main(
77+ @encoding("*/*")
88+ input: void
99+ ): {
1010+ @required blob: Blob<#[], 0>;
1111+ };
1212+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @procedure
66+ op main(): void;
77+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @query
66+ op main(): {
77+ @required activated: boolean;
88+ @required validDid: boolean;
99+ @required repoCommit: cid;
1010+ @required repoRev: string;
1111+ @required repoBlocks: integer;
1212+ @required indexedRecords: integer;
1313+ @required privateStateValues: integer;
1414+ @required expectedBlobs: integer;
1515+ @required importedBlobs: integer;
1616+ };
1717+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.createAccount {
44+ model InvalidHandle {}
55+ model InvalidPassword {}
66+ model InvalidInviteCode {}
77+ model HandleNotAvailable {}
88+ model UnsupportedDomain {}
99+ model UnresolvableDid {}
1010+ model IncompatibleDidDoc {}
1111+1212+ @doc("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;
1818+1919+ @doc("The DID of the new account.")
2020+ @required
2121+ did: did;
2222+2323+ @doc("Complete DID document.")
2424+ didDoc?: unknown;
2525+ }
2626+2727+ @doc("Create an account. Implemented by PDS.")
2828+ @procedure
2929+ @errors(InvalidHandle, InvalidPassword, InvalidInviteCode, HandleNotAvailable, UnsupportedDomain, UnresolvableDid, IncompatibleDidDoc)
3030+ op main(input: {
3131+ email?: string;
3232+3333+ @doc("Requested handle for the account.")
3434+ @required
3535+ handle: handle;
3636+3737+ @doc("Pre-existing atproto DID, being imported to a new account.")
3838+ did?: did;
3939+4040+ inviteCode?: string;
4141+ verificationCode?: string;
4242+ verificationPhone?: string;
4343+4444+ @doc("Initial account password. May need to meet instance-specific password strength requirements.")
4545+ password?: string;
4646+4747+ @doc("DID PLC rotation key (aka, recovery key) to be included in PLC creation operation.")
4848+ recoveryKey?: string;
4949+5050+ @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.")
5151+ plcOp?: unknown;
5252+ }): Output;
5353+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.createSession {
44+ model AccountTakedown {}
55+66+ model AuthFactorTokenRequired {}
77+88+ @doc("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.")
1313+ @required
1414+ identifier: string;
1515+1616+ @required password: string;
1717+1818+ authFactorToken?: string;
1919+2020+ @doc("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;
2424+ @required refreshJwt: string;
2525+ @required handle: handle;
2626+ @required did: did;
2727+ didDoc?: unknown;
2828+ email?: string;
2929+ emailConfirmed?: boolean;
3030+ emailAuthFactor?: boolean;
3131+ active?: boolean;
3232+3333+ @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.")
3434+ status?: "takendown" | "suspended" | "deactivated" | string;
3535+ };
3636+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
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.")
88+ deleteAfter?: datetime;
99+ }): void;
1010+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.deleteAccount {
44+ model ExpiredToken {}
55+ model InvalidToken {}
66+77+ @doc("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: {
1111+ @required did: did;
1212+ @required password: string;
1313+ @required token: string;
1414+ }): void;
1515+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.describeServer {
44+ @doc("Describes the server's account creation requirements and capabilities. Implemented by PDS.")
55+ @query
66+ op main(): {
77+ @required did: did;
88+99+ @doc("If true, an invite code must be supplied to create an account on this instance.")
1010+ inviteCodeRequired?: boolean;
1111+1212+ @doc("If true, a phone verification token must be supplied to create an account on this instance.")
1313+ phoneVerificationRequired?: boolean;
1414+1515+ @doc("List of domain suffixes that can be used in account handles.")
1616+ @required
1717+ availableUserDomains: string[];
1818+1919+ @doc("URLs of service policy documents.")
2020+ links?: Links;
2121+2222+ @doc("Contact information")
2323+ contact?: Contact;
2424+ };
2525+2626+ model Links {
2727+ privacyPolicy?: uri;
2828+ termsOfService?: uri;
2929+ }
3030+3131+ model Contact {
3232+ email?: string;
3333+ }
3434+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ model BadExpiration {}
66+77+ @doc("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")
1212+ @required
1313+ aud: did,
1414+1515+ @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.")
1616+ exp?: integer,
1717+1818+ @doc("Lexicon (XRPC) method to bind the requested token to")
1919+ lxm?: nsid
2020+ ): {
2121+ @required token: string;
2222+ };
2323+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.getSession {
44+ @doc("Get information about the current auth session. Requires auth.")
55+ @query
66+ op main(): {
77+ @required handle: handle;
88+ @required did: did;
99+ email?: string;
1010+ emailConfirmed?: boolean;
1111+ emailAuthFactor?: boolean;
1212+ didDoc?: unknown;
1313+ active?: boolean;
1414+1515+ @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.")
1616+ status?: "takendown" | "suspended" | "deactivated" | string;
1717+ };
1818+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.requestAccountDelete {
44+ @doc("Initiate a user account deletion via email.")
55+ @procedure
66+ op main(): void;
77+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.server.requestEmailConfirmation {
44+ @doc("Request an email with a code to confirm ownership of email.")
55+ @procedure
66+ op main(): void;
77+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @procedure
66+ op main(input: {
77+ @doc("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.")
1111+ @required
1212+ signingKey: string;
1313+ };
1414+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @query
66+ @encoding("*/*")
77+ @errors(BlobNotFound, RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88+ op main(
99+ @doc("The DID of the account.")
1010+ @required
1111+ did: did,
1212+1313+ @doc("The CID of the blob to fetch")
1414+ @required
1515+ cid: cid
1616+ ): void;
1717+1818+ model BlobNotFound {}
1919+ model RepoNotFound {}
2020+ model RepoTakendown {}
2121+ model RepoSuspended {}
2222+ model RepoDeactivated {}
2323+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
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.")
1010+ @required
1111+ did: did,
1212+1313+ @required cids: cid[]
1414+ ): void;
1515+1616+ model BlockNotFound {}
1717+ model RepoNotFound {}
1818+ model RepoTakendown {}
1919+ model RepoSuspended {}
2020+ model RepoDeactivated {}
2121+}
···11+import "@tylex/emitter";
22+import "./defs.tsp";
33+44+namespace com.atproto.sync.getHostStatus {
55+ @doc("Returns information about a specified upstream host, as consumed by the server. Implemented by relays.")
66+ @query
77+ @errors(HostNotFound)
88+ op main(
99+ @doc("Hostname of the host (eg, PDS or relay) being queried.")
1010+ @required
1111+ hostname: string
1212+ ): {
1313+ @required hostname: string;
1414+1515+ @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
1616+ seq?: integer;
1717+1818+ @doc("Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts.")
1919+ accountCount?: integer;
2020+2121+ status?: com.atproto.sync.defs.HostStatus;
2222+ };
2323+2424+ model HostNotFound {}
2525+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.sync.getLatestCommit {
44+ @doc("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.")
99+ @required
1010+ did: did
1111+ ): {
1212+ @required cid: cid;
1313+ @required rev: tid;
1414+ };
1515+1616+ model RepoNotFound {}
1717+ model RepoTakendown {}
1818+ model RepoSuspended {}
1919+ model RepoDeactivated {}
2020+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
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.")
1010+ @required
1111+ did: did,
1212+1313+ @required collection: nsid,
1414+1515+ @doc("Record Key")
1616+ @required
1717+ rkey: recordKey
1818+ ): void;
1919+2020+ model RecordNotFound {}
2121+ model RepoNotFound {}
2222+ model RepoTakendown {}
2323+ model RepoSuspended {}
2424+ model RepoDeactivated {}
2525+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @query
66+ @encoding("application/vnd.ipld.car")
77+ @errors(RepoNotFound, RepoTakendown, RepoSuspended, RepoDeactivated)
88+ op main(
99+ @doc("The DID of the repo.")
1010+ @required
1111+ did: did,
1212+1313+ @doc("The revision ('rev') of the repo to create a diff from.")
1414+ since?: tid
1515+ ): void;
1616+1717+ model RepoNotFound {}
1818+ model RepoTakendown {}
1919+ model RepoSuspended {}
2020+ model RepoDeactivated {}
2121+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.sync.getRepoStatus {
44+ @doc("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.")
99+ @required
1010+ did: did
1111+ ): {
1212+ @required did: did;
1313+ @required active: boolean;
1414+1515+ @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.")
1616+ status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
1717+1818+ @doc("Optional field, the current rev of the repo, if active=true")
1919+ rev?: tid;
2020+ };
2121+2222+ model RepoNotFound {}
2323+}
···11+import "@tylex/emitter";
22+import "./defs.tsp";
33+44+namespace com.atproto.sync.listHosts {
55+ @doc("Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays.")
66+ @query
77+ op main(
88+ @minValue(1)
99+ @maxValue(1000)
1010+ limit?: int32 = 200,
1111+1212+ cursor?: string
1313+ ): {
1414+ cursor?: string;
1515+1616+ @doc("Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first.")
1717+ @required
1818+ hosts: Host[];
1919+ };
2020+2121+ model Host {
2222+ @doc("hostname of server; not a URL (no scheme)")
2323+ @required
2424+ hostname: string;
2525+2626+ @doc("Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor).")
2727+ seq?: integer;
2828+2929+ accountCount?: integer;
3030+ status?: com.atproto.sync.defs.HostStatus;
3131+ }
3232+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @query
66+ op main(
77+ @minValue(1)
88+ @maxValue(1000)
99+ limit?: int32 = 500,
1010+1111+ cursor?: string
1212+ ): {
1313+ cursor?: string;
1414+ @required repos: Repo[];
1515+ };
1616+1717+ model Repo {
1818+ @required did: did;
1919+2020+ @doc("Current repo commit CID")
2121+ @required
2222+ head: cid;
2323+2424+ @required rev: tid;
2525+ active?: boolean;
2626+2727+ @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.")
2828+ status?: "takendown" | "suspended" | "deleted" | "deactivated" | "desynchronized" | "throttled" | string;
2929+ }
3030+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.sync.listReposByCollection {
44+ @doc("Enumerates all the DIDs which have records with the given collection NSID.")
55+ @query
66+ op main(
77+ @required collection: nsid,
88+99+ @doc("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,
1313+1414+ cursor?: string
1515+ ): {
1616+ cursor?: string;
1717+ @required repos: Repo[];
1818+ };
1919+2020+ model Repo {
2121+ @required did: did;
2222+ }
2323+}
···11+import "@tylex/emitter";
22+33+namespace 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")
55+ @procedure
66+ op main(input: {
77+ @doc("Hostname of the current service (usually a PDS) that is notifying of update.")
88+ @required
99+ hostname: string;
1010+ }): void;
1111+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
55+ @procedure
66+ @errors(HostBanned)
77+ op main(input: {
88+ @doc("Hostname of the current service (eg, PDS) that is requesting to be crawled.")
99+ @required
1010+ hostname: string;
1111+ }): void;
1212+1313+ model HostBanned {}
1414+}
···11+import "@tylex/emitter";
22+33+namespace 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.")
77+ op main(
88+ @doc("The last known event seq number to backfill from.")
99+ cursor?: integer
1010+ ): (Commit | Sync | Identity | Account | Info | unknown);
1111+1212+ model FutureCursor {}
1313+1414+ @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.")
1515+ model ConsumerTooSlow {}
1616+1717+ @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.")
1818+ model Commit {
1919+ @doc("The stream sequence number of this message.")
2020+ @required
2121+ seq: integer;
2222+2323+ @doc("DEPRECATED -- unused")
2424+ @required
2525+ rebase: boolean;
2626+2727+ @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.")
2828+ @required
2929+ tooBig: boolean;
3030+3131+ @doc("The repo this event comes from. Note that all other message types name this field 'did'.")
3232+ @required
3333+ repo: did;
3434+3535+ @doc("Repo commit object CID.")
3636+ @required
3737+ commit: cidLink;
3838+3939+ @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.")
4040+ @required
4141+ rev: tid;
4242+4343+ @doc("The rev of the last emitted commit from this repo (if any).")
4444+ @required
4545+ since: tid | null;
4646+4747+ @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.")
4848+ @maxBytes(2000000)
4949+ @required
5050+ blocks: bytes;
5151+5252+ @maxItems(200)
5353+ @required
5454+ @doc("List of repo mutation operations in this commit (eg, records created, updated, or deleted).")
5555+ ops: RepoOp[];
5656+5757+ @doc("DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.")
5858+ @required blobs: cidLink[];
5959+6060+ @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.")
6161+ prevData?: cidLink;
6262+6363+ @doc("Timestamp of when this message was originally broadcast.")
6464+ @required
6565+ time: datetime;
6666+ }
6767+6868+ @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.")
6969+ model Sync {
7070+ @doc("The stream sequence number of this message.")
7171+ @required
7272+ seq: integer;
7373+7474+ @doc("The account this repo event corresponds to. Must match that in the commit object.")
7575+ @required
7676+ did: did;
7777+7878+ @doc("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;
8282+8383+ @doc("The rev of the commit. This value must match that in the commit object.")
8484+ @required
8585+ rev: string;
8686+8787+ @doc("Timestamp of when this message was originally broadcast.")
8888+ @required
8989+ time: datetime;
9090+ }
9191+9292+ @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.")
9393+ model Identity {
9494+ @required seq: integer;
9595+ @required did: did;
9696+ @required time: datetime;
9797+9898+ @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.")
9999+ handle?: handle;
100100+ }
101101+102102+ @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.")
103103+ model Account {
104104+ @required seq: integer;
105105+ @required did: did;
106106+ @required time: datetime;
107107+108108+ @doc("Indicates that the account has a repository which can be fetched from the host that emitted this event.")
109109+ @required
110110+ active: boolean;
111111+112112+ @doc("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+116116+ model Info {
117117+ @required name: "OutdatedCursor" | string;
118118+ message?: string;
119119+ }
120120+121121+ @doc("A repo operation, ie a mutation of a single record.")
122122+ model RepoOp {
123123+ @required action: "create" | "update" | "delete" | string;
124124+ @required path: string;
125125+126126+ @doc("For creates and updates, the new record CID. For deletions, null.")
127127+ @required
128128+ cid: cidLink | null;
129129+130130+ @doc("For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.")
131131+ prev?: cidLink;
132132+ }
133133+}
···11+import "@tylex/emitter";
22+33+namespace com.atproto.temp.checkHandleAvailability {
44+ @doc("An invalid email was provided.")
55+ model InvalidEmail {}
66+77+ @doc("Indicates the provided handle is available.")
88+ model ResultAvailable {}
99+1010+ @doc("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.")
1313+ @required
1414+ suggestions: Suggestion[];
1515+ }
1616+1717+ model Suggestion {
1818+ @required handle: handle;
1919+2020+ @doc("Method used to build this suggestion. Should be considered opaque to clients. Can be used for metrics.")
2121+ @required
2222+ method: string;
2323+ }
2424+2525+ @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.")
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,
3131+3232+ @doc("User-provided email. Might be used to build handle suggestions.")
3333+ email?: string,
3434+3535+ @doc("User-provided birth date. Might be used to build handle suggestions.")
3636+ birthDate?: datetime
3737+ ): {
3838+ @doc("Echo of the input handle.")
3939+ @required
4040+ handle: handle;
4141+4242+ @required result: ResultAvailable | ResultUnavailable;
4343+ };
4444+}
···11+import "@tylex/emitter";
22+33+namespace `pub`.leaflet.richtext.facet {
44+ @doc("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+ }
99+1010+ @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.")
1111+ model ByteSlice {
1212+ @minValue(0)
1313+ @required
1414+ byteStart: integer;
1515+1616+ @minValue(0)
1717+ @required
1818+ byteEnd: integer;
1919+ }
2020+2121+ @doc("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+ }
2525+2626+ @doc("Facet feature for inline code.")
2727+ model Code {}
2828+2929+ @doc("Facet feature for highlighted text.")
3030+ model Highlight {}
3131+3232+ @doc("Facet feature for underline markup")
3333+ model Underline {}
3434+3535+ @doc("Facet feature for strikethrough markup")
3636+ model Strikethrough {}
3737+3838+ @doc("Facet feature for an identifier. Used for linking to a segment")
3939+ model Id {
4040+ id?: string;
4141+ }
4242+4343+ @doc("Facet feature for bold text")
4444+ model Bold {}
4545+4646+ @doc("Facet feature for italic text")
4747+ model Italic {}
4848+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.identity.refreshIdentity",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "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.",
88+ "input": {
99+ "encoding": "application/json",
1010+ "schema": {
1111+ "type": "object",
1212+ "required": ["identifier"],
1313+ "properties": {
1414+ "identifier": {
1515+ "type": "string",
1616+ "format": "at-identifier"
1717+ }
1818+ }
1919+ }
2020+ },
2121+ "output": {
2222+ "encoding": "application/json",
2323+ "schema": {
2424+ "type": "ref",
2525+ "ref": "com.atproto.identity.defs#identityInfo"
2626+ }
2727+ },
2828+ "errors": [
2929+ {
3030+ "name": "HandleNotFound",
3131+ "description": "The resolution process confirmed that the handle does not resolve to any DID."
3232+ },
3333+ {
3434+ "name": "DidNotFound",
3535+ "description": "The DID resolution process confirmed that there is no current DID."
3636+ },
3737+ {
3838+ "name": "DidDeactivated",
3939+ "description": "The DID previously existed, but has been deactivated."
4040+ }
4141+ ]
4242+ }
4343+ }
4444+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.identity.requestPlcOperationSignature",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "Request an email with a code to in order to request a signed PLC operation. Requires Auth."
88+ }
99+ }
1010+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.label.defs",
44+ "defs": {
55+ "label": {
66+ "type": "object",
77+ "description": "Metadata tag on an atproto resource (eg, repo or record).",
88+ "required": ["src", "uri", "val", "cts"],
99+ "properties": {
1010+ "ver": {
1111+ "type": "integer",
1212+ "description": "The AT Protocol version of the label object."
1313+ },
1414+ "src": {
1515+ "type": "string",
1616+ "format": "did",
1717+ "description": "DID of the actor who created this label."
1818+ },
1919+ "uri": {
2020+ "type": "string",
2121+ "format": "uri",
2222+ "description": "AT URI of the record, repository (account), or other resource that this label applies to."
2323+ },
2424+ "cid": {
2525+ "type": "string",
2626+ "format": "cid",
2727+ "description": "Optionally, CID specifying the specific version of 'uri' resource this label applies to."
2828+ },
2929+ "val": {
3030+ "type": "string",
3131+ "maxLength": 128,
3232+ "description": "The short string name of the value or type of this label."
3333+ },
3434+ "neg": {
3535+ "type": "boolean",
3636+ "description": "If true, this is a negation label, overwriting a previous label."
3737+ },
3838+ "cts": {
3939+ "type": "string",
4040+ "format": "datetime",
4141+ "description": "Timestamp when this label was created."
4242+ },
4343+ "exp": {
4444+ "type": "string",
4545+ "format": "datetime",
4646+ "description": "Timestamp at which this label expires (no longer applies)."
4747+ },
4848+ "sig": {
4949+ "type": "bytes",
5050+ "description": "Signature of dag-cbor encoded label."
5151+ }
5252+ }
5353+ },
5454+ "selfLabels": {
5555+ "type": "object",
5656+ "description": "Metadata tags on an atproto record, published by the author within the record.",
5757+ "required": ["values"],
5858+ "properties": {
5959+ "values": {
6060+ "type": "array",
6161+ "items": { "type": "ref", "ref": "#selfLabel" },
6262+ "maxLength": 10
6363+ }
6464+ }
6565+ },
6666+ "selfLabel": {
6767+ "type": "object",
6868+ "description": "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel.",
6969+ "required": ["val"],
7070+ "properties": {
7171+ "val": {
7272+ "type": "string",
7373+ "maxLength": 128,
7474+ "description": "The short string name of the value or type of this label."
7575+ }
7676+ }
7777+ },
7878+ "labelValueDefinition": {
7979+ "type": "object",
8080+ "description": "Declares a label value and its expected interpretations and behaviors.",
8181+ "required": ["identifier", "severity", "blurs", "locales"],
8282+ "properties": {
8383+ "identifier": {
8484+ "type": "string",
8585+ "description": "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).",
8686+ "maxLength": 100,
8787+ "maxGraphemes": 100
8888+ },
8989+ "severity": {
9090+ "type": "string",
9191+ "description": "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.",
9292+ "knownValues": ["inform", "alert", "none"]
9393+ },
9494+ "blurs": {
9595+ "type": "string",
9696+ "description": "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.",
9797+ "knownValues": ["content", "media", "none"]
9898+ },
9999+ "defaultSetting": {
100100+ "type": "string",
101101+ "description": "The default setting for this label.",
102102+ "knownValues": ["ignore", "warn", "hide"],
103103+ "default": "warn"
104104+ },
105105+ "adultOnly": {
106106+ "type": "boolean",
107107+ "description": "Does the user need to have adult content enabled in order to configure this label?"
108108+ },
109109+ "locales": {
110110+ "type": "array",
111111+ "items": { "type": "ref", "ref": "#labelValueDefinitionStrings" }
112112+ }
113113+ }
114114+ },
115115+ "labelValueDefinitionStrings": {
116116+ "type": "object",
117117+ "description": "Strings which describe the label in the UI, localized into a specific language.",
118118+ "required": ["lang", "name", "description"],
119119+ "properties": {
120120+ "lang": {
121121+ "type": "string",
122122+ "description": "The code of the language these strings are written in.",
123123+ "format": "language"
124124+ },
125125+ "name": {
126126+ "type": "string",
127127+ "description": "A short human-readable name for the label.",
128128+ "maxGraphemes": 64,
129129+ "maxLength": 640
130130+ },
131131+ "description": {
132132+ "type": "string",
133133+ "description": "A longer description of what the label means and why it might be applied.",
134134+ "maxGraphemes": 10000,
135135+ "maxLength": 100000
136136+ }
137137+ }
138138+ },
139139+ "labelValue": {
140140+ "type": "string",
141141+ "knownValues": [
142142+ "!hide",
143143+ "!no-promote",
144144+ "!warn",
145145+ "!no-unauthenticated",
146146+ "dmca-violation",
147147+ "doxxing",
148148+ "porn",
149149+ "sexual",
150150+ "nudity",
151151+ "nsfl",
152152+ "gore"
153153+ ]
154154+ }
155155+ }
156156+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.lexicon.schema",
44+ "defs": {
55+ "main": {
66+ "type": "record",
77+ "description": "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).",
88+ "key": "nsid",
99+ "record": {
1010+ "type": "object",
1111+ "required": ["lexicon"],
1212+ "properties": {
1313+ "lexicon": {
1414+ "type": "integer",
1515+ "description": "Indicates the 'version' of the Lexicon language. Must be '1' for the current atproto/Lexicon schema system."
1616+ }
1717+ }
1818+ }
1919+ }
2020+ }
2121+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.repo.uploadBlob",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "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.",
88+ "input": {
99+ "encoding": "*/*"
1010+ },
1111+ "output": {
1212+ "encoding": "application/json",
1313+ "schema": {
1414+ "type": "object",
1515+ "required": ["blob"],
1616+ "properties": {
1717+ "blob": { "type": "blob" }
1818+ }
1919+ }
2020+ }
2121+ }
2222+ }
2323+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.server.activateAccount",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "Activates a currently deactivated account. Used to finalize account migration after the account's repo is imported and identity is setup."
88+ }
99+ }
1010+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.server.deactivateAccount",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "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.",
88+ "input": {
99+ "encoding": "application/json",
1010+ "schema": {
1111+ "type": "object",
1212+ "properties": {
1313+ "deleteAfter": {
1414+ "type": "string",
1515+ "format": "datetime",
1616+ "description": "A recommendation to server as to how long they should hold onto the deactivated account before deleting."
1717+ }
1818+ }
1919+ }
2020+ }
2121+ }
2222+ }
2323+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.server.getServiceAuth",
44+ "defs": {
55+ "main": {
66+ "type": "query",
77+ "description": "Get a signed token on behalf of the requesting DID for the requested service.",
88+ "parameters": {
99+ "type": "params",
1010+ "required": ["aud"],
1111+ "properties": {
1212+ "aud": {
1313+ "type": "string",
1414+ "format": "did",
1515+ "description": "The DID of the service that the token will be used to authenticate with"
1616+ },
1717+ "exp": {
1818+ "type": "integer",
1919+ "description": "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."
2020+ },
2121+ "lxm": {
2222+ "type": "string",
2323+ "format": "nsid",
2424+ "description": "Lexicon (XRPC) method to bind the requested token to"
2525+ }
2626+ }
2727+ },
2828+ "output": {
2929+ "encoding": "application/json",
3030+ "schema": {
3131+ "type": "object",
3232+ "required": ["token"],
3333+ "properties": {
3434+ "token": {
3535+ "type": "string"
3636+ }
3737+ }
3838+ }
3939+ },
4040+ "errors": [
4141+ {
4242+ "name": "BadExpiration",
4343+ "description": "Indicates that the requested expiration date is not a valid. May be in the past or may be reliant on the requested scopes."
4444+ }
4545+ ]
4646+ }
4747+ }
4848+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.server.reserveSigningKey",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "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.",
88+ "input": {
99+ "encoding": "application/json",
1010+ "schema": {
1111+ "type": "object",
1212+ "properties": {
1313+ "did": {
1414+ "type": "string",
1515+ "format": "did",
1616+ "description": "The DID to reserve a key for."
1717+ }
1818+ }
1919+ }
2020+ },
2121+ "output": {
2222+ "encoding": "application/json",
2323+ "schema": {
2424+ "type": "object",
2525+ "required": ["signingKey"],
2626+ "properties": {
2727+ "signingKey": {
2828+ "type": "string",
2929+ "description": "The public key for the reserved signing key, in did:key serialization."
3030+ }
3131+ }
3232+ }
3333+ }
3434+ }
3535+ }
3636+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.sync.notifyOfUpdate",
44+ "defs": {
55+ "main": {
66+ "type": "procedure",
77+ "description": "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",
88+ "input": {
99+ "encoding": "application/json",
1010+ "schema": {
1111+ "type": "object",
1212+ "required": ["hostname"],
1313+ "properties": {
1414+ "hostname": {
1515+ "type": "string",
1616+ "description": "Hostname of the current service (usually a PDS) that is notifying of update."
1717+ }
1818+ }
1919+ }
2020+ }
2121+ }
2222+ }
2323+}
···11+{
22+ "lexicon": 1,
33+ "id": "com.atproto.sync.subscribeRepos",
44+ "defs": {
55+ "main": {
66+ "type": "subscription",
77+ "description": "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.",
88+ "parameters": {
99+ "type": "params",
1010+ "properties": {
1111+ "cursor": {
1212+ "type": "integer",
1313+ "description": "The last known event seq number to backfill from."
1414+ }
1515+ }
1616+ },
1717+ "message": {
1818+ "schema": {
1919+ "type": "union",
2020+ "refs": ["#commit", "#sync", "#identity", "#account", "#info"]
2121+ }
2222+ },
2323+ "errors": [
2424+ { "name": "FutureCursor" },
2525+ {
2626+ "name": "ConsumerTooSlow",
2727+ "description": "If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection."
2828+ }
2929+ ]
3030+ },
3131+ "commit": {
3232+ "type": "object",
3333+ "description": "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.",
3434+ "required": [
3535+ "seq",
3636+ "rebase",
3737+ "tooBig",
3838+ "repo",
3939+ "commit",
4040+ "rev",
4141+ "since",
4242+ "blocks",
4343+ "ops",
4444+ "blobs",
4545+ "time"
4646+ ],
4747+ "nullable": ["since"],
4848+ "properties": {
4949+ "seq": {
5050+ "type": "integer",
5151+ "description": "The stream sequence number of this message."
5252+ },
5353+ "rebase": { "type": "boolean", "description": "DEPRECATED -- unused" },
5454+ "tooBig": {
5555+ "type": "boolean",
5656+ "description": "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."
5757+ },
5858+ "repo": {
5959+ "type": "string",
6060+ "format": "did",
6161+ "description": "The repo this event comes from. Note that all other message types name this field 'did'."
6262+ },
6363+ "commit": {
6464+ "type": "cid-link",
6565+ "description": "Repo commit object CID."
6666+ },
6767+ "rev": {
6868+ "type": "string",
6969+ "format": "tid",
7070+ "description": "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."
7171+ },
7272+ "since": {
7373+ "type": "string",
7474+ "format": "tid",
7575+ "description": "The rev of the last emitted commit from this repo (if any)."
7676+ },
7777+ "blocks": {
7878+ "type": "bytes",
7979+ "description": "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.",
8080+ "maxLength": 2000000
8181+ },
8282+ "ops": {
8383+ "type": "array",
8484+ "description": "List of repo mutation operations in this commit (eg, records created, updated, or deleted).",
8585+ "items": {
8686+ "type": "ref",
8787+ "ref": "#repoOp"
8888+ },
8989+ "maxLength": 200
9090+ },
9191+ "blobs": {
9292+ "type": "array",
9393+ "description": "DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.",
9494+ "items": {
9595+ "type": "cid-link"
9696+ }
9797+ },
9898+ "prevData": {
9999+ "type": "cid-link",
100100+ "description": "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."
101101+ },
102102+ "time": {
103103+ "type": "string",
104104+ "format": "datetime",
105105+ "description": "Timestamp of when this message was originally broadcast."
106106+ }
107107+ }
108108+ },
109109+ "sync": {
110110+ "type": "object",
111111+ "description": "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.",
112112+ "required": ["seq", "did", "blocks", "rev", "time"],
113113+ "properties": {
114114+ "seq": {
115115+ "type": "integer",
116116+ "description": "The stream sequence number of this message."
117117+ },
118118+ "did": {
119119+ "type": "string",
120120+ "format": "did",
121121+ "description": "The account this repo event corresponds to. Must match that in the commit object."
122122+ },
123123+ "blocks": {
124124+ "type": "bytes",
125125+ "description": "CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.",
126126+ "maxLength": 10000
127127+ },
128128+ "rev": {
129129+ "type": "string",
130130+ "description": "The rev of the commit. This value must match that in the commit object."
131131+ },
132132+ "time": {
133133+ "type": "string",
134134+ "format": "datetime",
135135+ "description": "Timestamp of when this message was originally broadcast."
136136+ }
137137+ }
138138+ },
139139+ "identity": {
140140+ "type": "object",
141141+ "description": "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.",
142142+ "required": ["seq", "did", "time"],
143143+ "properties": {
144144+ "seq": { "type": "integer" },
145145+ "did": { "type": "string", "format": "did" },
146146+ "time": { "type": "string", "format": "datetime" },
147147+ "handle": {
148148+ "type": "string",
149149+ "format": "handle",
150150+ "description": "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."
151151+ }
152152+ }
153153+ },
154154+ "account": {
155155+ "type": "object",
156156+ "description": "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.",
157157+ "required": ["seq", "did", "time", "active"],
158158+ "properties": {
159159+ "seq": { "type": "integer" },
160160+ "did": { "type": "string", "format": "did" },
161161+ "time": { "type": "string", "format": "datetime" },
162162+ "active": {
163163+ "type": "boolean",
164164+ "description": "Indicates that the account has a repository which can be fetched from the host that emitted this event."
165165+ },
166166+ "status": {
167167+ "type": "string",
168168+ "description": "If active=false, this optional field indicates a reason for why the account is not active.",
169169+ "knownValues": [
170170+ "takendown",
171171+ "suspended",
172172+ "deleted",
173173+ "deactivated",
174174+ "desynchronized",
175175+ "throttled"
176176+ ]
177177+ }
178178+ }
179179+ },
180180+ "info": {
181181+ "type": "object",
182182+ "required": ["name"],
183183+ "properties": {
184184+ "name": {
185185+ "type": "string",
186186+ "knownValues": ["OutdatedCursor"]
187187+ },
188188+ "message": {
189189+ "type": "string"
190190+ }
191191+ }
192192+ },
193193+ "repoOp": {
194194+ "type": "object",
195195+ "description": "A repo operation, ie a mutation of a single record.",
196196+ "required": ["action", "path", "cid"],
197197+ "nullable": ["cid"],
198198+ "properties": {
199199+ "action": {
200200+ "type": "string",
201201+ "knownValues": ["create", "update", "delete"]
202202+ },
203203+ "path": { "type": "string" },
204204+ "cid": {
205205+ "type": "cid-link",
206206+ "description": "For creates and updates, the new record CID. For deletions, null."
207207+ },
208208+ "prev": {
209209+ "type": "cid-link",
210210+ "description": "For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined."
211211+ }
212212+ }
213213+ }
214214+ }
215215+}
···11+# Tylex Website
22+33+Landing page for tylex - TypeSpec for AT Protocol Lexicons.
44+55+## Features
66+77+- **Live Examples**: TypeSpec examples are compiled during build to show real Lexicon JSON output
88+- **Syntax Highlighting**: Using Shiki for beautiful code highlighting
99+- **Interactive Playground**: Try tylex in the browser (coming soon)
1010+1111+## Development
1212+1313+```sh
1414+pnpm install
1515+pnpm run dev
1616+```
1717+1818+## Building
1919+2020+The build process automatically:
2121+1. Compiles TypeSpec examples **in memory** during the Astro build
2222+2. Reads TypeSpec source files
2323+3. Syntax-highlights and displays them side-by-side with generated JSON
2424+2525+```sh
2626+pnpm run build
2727+```
2828+2929+No intermediate files are generated - everything happens in memory!
3030+3131+## Adding Examples
3232+3333+1. Create a new `.tsp` file in `src/examples/`
3434+2. Add it to the examples array in `src/pages/index.astro`
3535+3. Run `pnpm run build` to see it on the site
3636+3737+## Commands
3838+3939+| Command | Action |
4040+| :------------------------ | :----------------------------------------------- |
4141+| `pnpm install` | Installs dependencies |
4242+| `pnpm dev` | Starts local dev server at `localhost:4321` |
4343+| `pnpm build` | Build your production site to `./dist/` |
4444+| `pnpm preview` | Preview your build locally, before deploying |
4545+4646+## Structure
4747+4848+```
4949+/
5050+├── src/
5151+│ ├── examples/ # TypeSpec examples
5252+│ │ ├── profile.tsp
5353+│ │ ├── getQuotes.tsp
5454+│ │ └── ...
5555+│ ├── pages/
5656+│ │ └── index.astro # Landing page
5757+│ ├── components/
5858+│ │ └── Playground.tsx
5959+│ └── utils/
6060+│ └── compile.ts # In-memory TypeSpec compiler
6161+└── package.json
6262+```
+11
packages/website/astro.config.mjs
···11+// @ts-check
22+import { defineConfig } from 'astro/config';
33+import react from '@astrojs/react';
44+55+// https://astro.build/config
66+export default defineConfig({
77+ integrations: [react()],
88+ vite: {
99+ // Vite config accessible for future playground tweaks
1010+ }
1111+});