this repo has no description
1import { ok, err, type Result } from './types/result' 2import type { 3 Did, 4 Handle, 5 AccessToken, 6 RefreshToken, 7 Cid, 8 Rkey, 9 AtUri, 10 Nsid, 11 ISODateString, 12 EmailAddress, 13 InviteCode as InviteCodeBrand, 14} from './types/branded' 15import { 16 unsafeAsDid, 17 unsafeAsHandle, 18 unsafeAsAccessToken, 19 unsafeAsRefreshToken, 20 unsafeAsCid, 21 unsafeAsISODate, 22 unsafeAsEmail, 23 unsafeAsInviteCode, 24} from './types/branded' 25import type { 26 Session, 27 DidDocument, 28 AppPassword, 29 CreatedAppPassword, 30 InviteCodeInfo, 31 ServerDescription, 32 NotificationPrefs, 33 NotificationHistoryResponse, 34 ServerStats, 35 ServerConfig, 36 UploadBlobResponse, 37 ListSessionsResponse, 38 SearchAccountsResponse, 39 GetInviteCodesResponse, 40 AccountInfo, 41 RepoDescription, 42 ListRecordsResponse, 43 RecordResponse, 44 CreateRecordResponse, 45 TotpStatus, 46 TotpSecret, 47 EnableTotpResponse, 48 RegenerateBackupCodesResponse, 49 ListPasskeysResponse, 50 StartPasskeyRegistrationResponse, 51 FinishPasskeyRegistrationResponse, 52 ListTrustedDevicesResponse, 53 ReauthStatus, 54 ReauthResponse, 55 ReauthPasskeyStartResponse, 56 ReserveSigningKeyResponse, 57 RecommendedDidCredentials, 58 PasskeyAccountCreateResponse, 59 CompletePasskeySetupResponse, 60 VerifyTokenResponse, 61 ListBackupsResponse, 62 CreateBackupResponse, 63 SetBackupEnabledResponse, 64 EmailUpdateResponse, 65 LegacyLoginPreference, 66 UpdateLegacyLoginResponse, 67 UpdateLocaleResponse, 68 PasswordStatus, 69 SuccessResponse, 70 CheckEmailVerifiedResponse, 71 VerifyMigrationEmailResponse, 72 ResendMigrationVerificationResponse, 73 ListReposResponse, 74 VerificationChannel, 75 DidType, 76 ApiErrorCode, 77 VerificationMethod as VerificationMethodType, 78 CreateAccountParams, 79 CreateAccountResult, 80 ConfirmSignupResult, 81} from './types/api' 82 83const API_BASE = '/xrpc' 84 85export class ApiError extends Error { 86 public did?: Did 87 public reauthMethods?: string[] 88 constructor( 89 public status: number, 90 public error: ApiErrorCode, 91 message: string, 92 did?: string, 93 reauthMethods?: string[], 94 ) { 95 super(message) 96 this.name = 'ApiError' 97 this.did = did ? unsafeAsDid(did) : undefined 98 this.reauthMethods = reauthMethods 99 } 100} 101 102let tokenRefreshCallback: (() => Promise<string | null>) | null = null 103 104export function setTokenRefreshCallback( 105 callback: () => Promise<string | null>, 106) { 107 tokenRefreshCallback = callback 108} 109 110interface XrpcOptions { 111 method?: 'GET' | 'POST' 112 params?: Record<string, string> 113 body?: unknown 114 token?: string 115 skipRetry?: boolean 116} 117 118async function xrpc<T>(method: string, options?: XrpcOptions): Promise<T> { 119 const { method: httpMethod = 'GET', params, body, token, skipRetry } = 120 options ?? {} 121 let url = `${API_BASE}/${method}` 122 if (params) { 123 const searchParams = new URLSearchParams(params) 124 url += `?${searchParams}` 125 } 126 const headers: Record<string, string> = {} 127 if (token) { 128 headers['Authorization'] = `Bearer ${token}` 129 } 130 if (body) { 131 headers['Content-Type'] = 'application/json' 132 } 133 const res = await fetch(url, { 134 method: httpMethod, 135 headers, 136 body: body ? JSON.stringify(body) : undefined, 137 }) 138 if (!res.ok) { 139 const errData = await res.json().catch(() => ({ 140 error: 'Unknown', 141 message: res.statusText, 142 })) 143 if ( 144 res.status === 401 && 145 (errData.error === 'AuthenticationFailed' || errData.error === 'ExpiredToken') && 146 token && tokenRefreshCallback && !skipRetry 147 ) { 148 const newToken = await tokenRefreshCallback() 149 if (newToken && newToken !== token) { 150 return xrpc(method, { ...options, token: newToken, skipRetry: true }) 151 } 152 } 153 throw new ApiError( 154 res.status, 155 errData.error as ApiErrorCode, 156 errData.message, 157 errData.did, 158 errData.reauthMethods, 159 ) 160 } 161 return res.json() 162} 163 164async function xrpcResult<T>( 165 method: string, 166 options?: XrpcOptions 167): Promise<Result<T, ApiError>> { 168 try { 169 const value = await xrpc<T>(method, options) 170 return ok(value) 171 } catch (e) { 172 if (e instanceof ApiError) { 173 return err(e) 174 } 175 return err(new ApiError(0, 'Unknown', e instanceof Error ? e.message : String(e))) 176 } 177} 178 179export interface VerificationMethod { 180 id: string 181 type: string 182 publicKeyMultibase: string 183} 184 185export type { Session, DidDocument, AppPassword, InviteCodeInfo as InviteCode } 186export type { VerificationChannel, DidType, CreateAccountParams, CreateAccountResult, ConfirmSignupResult } 187 188function castSession(raw: unknown): Session { 189 const s = raw as Record<string, unknown> 190 return { 191 did: unsafeAsDid(s.did as string), 192 handle: unsafeAsHandle(s.handle as string), 193 email: s.email ? unsafeAsEmail(s.email as string) : undefined, 194 emailConfirmed: s.emailConfirmed as boolean | undefined, 195 preferredChannel: s.preferredChannel as VerificationChannel | undefined, 196 preferredChannelVerified: s.preferredChannelVerified as boolean | undefined, 197 isAdmin: s.isAdmin as boolean | undefined, 198 active: s.active as boolean | undefined, 199 status: s.status as Session['status'], 200 migratedToPds: s.migratedToPds as string | undefined, 201 migratedAt: s.migratedAt ? unsafeAsISODate(s.migratedAt as string) : undefined, 202 accessJwt: unsafeAsAccessToken(s.accessJwt as string), 203 refreshJwt: unsafeAsRefreshToken(s.refreshJwt as string), 204 } 205} 206 207export const api = { 208 async createAccount( 209 params: CreateAccountParams, 210 byodToken?: string, 211 ): Promise<CreateAccountResult> { 212 const url = `${API_BASE}/com.atproto.server.createAccount` 213 const headers: Record<string, string> = { 214 'Content-Type': 'application/json', 215 } 216 if (byodToken) { 217 headers['Authorization'] = `Bearer ${byodToken}` 218 } 219 const response = await fetch(url, { 220 method: 'POST', 221 headers, 222 body: JSON.stringify({ 223 handle: params.handle, 224 email: params.email, 225 password: params.password, 226 inviteCode: params.inviteCode, 227 didType: params.didType, 228 did: params.did, 229 signingKey: params.signingKey, 230 verificationChannel: params.verificationChannel, 231 discordId: params.discordId, 232 telegramUsername: params.telegramUsername, 233 signalNumber: params.signalNumber, 234 }), 235 }) 236 const data = await response.json() 237 if (!response.ok) { 238 throw new ApiError(response.status, data.error, data.message) 239 } 240 return data 241 }, 242 243 async createAccountWithServiceAuth( 244 serviceAuthToken: string, 245 params: { 246 did: Did 247 handle: Handle 248 email: EmailAddress 249 password: string 250 inviteCode?: string 251 }, 252 ): Promise<Session> { 253 const url = `${API_BASE}/com.atproto.server.createAccount` 254 const response = await fetch(url, { 255 method: 'POST', 256 headers: { 257 'Content-Type': 'application/json', 258 'Authorization': `Bearer ${serviceAuthToken}`, 259 }, 260 body: JSON.stringify({ 261 did: params.did, 262 handle: params.handle, 263 email: params.email, 264 password: params.password, 265 inviteCode: params.inviteCode, 266 }), 267 }) 268 const data = await response.json() 269 if (!response.ok) { 270 throw new ApiError(response.status, data.error, data.message) 271 } 272 return castSession(data) 273 }, 274 275 confirmSignup( 276 did: Did, 277 verificationCode: string, 278 ): Promise<ConfirmSignupResult> { 279 return xrpc('com.atproto.server.confirmSignup', { 280 method: 'POST', 281 body: { did, verificationCode }, 282 }) 283 }, 284 285 resendVerification(did: Did): Promise<{ success: boolean }> { 286 return xrpc('com.atproto.server.resendVerification', { 287 method: 'POST', 288 body: { did }, 289 }) 290 }, 291 292 async createSession(identifier: string, password: string): Promise<Session> { 293 const raw = await xrpc<unknown>('com.atproto.server.createSession', { 294 method: 'POST', 295 body: { identifier, password }, 296 }) 297 return castSession(raw) 298 }, 299 300 checkEmailVerified(identifier: string): Promise<{ verified: boolean }> { 301 return xrpc('_checkEmailVerified', { 302 method: 'POST', 303 body: { identifier }, 304 }) 305 }, 306 307 async getSession(token: AccessToken): Promise<Session> { 308 const raw = await xrpc<unknown>('com.atproto.server.getSession', { token }) 309 return castSession(raw) 310 }, 311 312 async refreshSession(refreshJwt: RefreshToken): Promise<Session> { 313 const raw = await xrpc<unknown>('com.atproto.server.refreshSession', { 314 method: 'POST', 315 token: refreshJwt, 316 }) 317 return castSession(raw) 318 }, 319 320 async deleteSession(token: AccessToken): Promise<void> { 321 await xrpc('com.atproto.server.deleteSession', { 322 method: 'POST', 323 token, 324 }) 325 }, 326 327 listAppPasswords(token: AccessToken): Promise<{ passwords: AppPassword[] }> { 328 return xrpc('com.atproto.server.listAppPasswords', { token }) 329 }, 330 331 createAppPassword( 332 token: AccessToken, 333 name: string, 334 scopes?: string, 335 ): Promise<CreatedAppPassword> { 336 return xrpc('com.atproto.server.createAppPassword', { 337 method: 'POST', 338 token, 339 body: { name, scopes }, 340 }) 341 }, 342 343 async revokeAppPassword(token: AccessToken, name: string): Promise<void> { 344 await xrpc('com.atproto.server.revokeAppPassword', { 345 method: 'POST', 346 token, 347 body: { name }, 348 }) 349 }, 350 351 getAccountInviteCodes(token: AccessToken): Promise<{ codes: InviteCodeInfo[] }> { 352 return xrpc('com.atproto.server.getAccountInviteCodes', { token }) 353 }, 354 355 createInviteCode( 356 token: AccessToken, 357 useCount: number = 1, 358 ): Promise<{ code: string }> { 359 return xrpc('com.atproto.server.createInviteCode', { 360 method: 'POST', 361 token, 362 body: { useCount }, 363 }) 364 }, 365 366 async requestPasswordReset(email: EmailAddress): Promise<void> { 367 await xrpc('com.atproto.server.requestPasswordReset', { 368 method: 'POST', 369 body: { email }, 370 }) 371 }, 372 373 async resetPassword(token: string, password: string): Promise<void> { 374 await xrpc('com.atproto.server.resetPassword', { 375 method: 'POST', 376 body: { token, password }, 377 }) 378 }, 379 380 requestEmailUpdate(token: AccessToken): Promise<EmailUpdateResponse> { 381 return xrpc('com.atproto.server.requestEmailUpdate', { 382 method: 'POST', 383 token, 384 }) 385 }, 386 387 async updateEmail( 388 token: AccessToken, 389 email: string, 390 emailToken?: string, 391 ): Promise<void> { 392 await xrpc('com.atproto.server.updateEmail', { 393 method: 'POST', 394 token, 395 body: { email, token: emailToken }, 396 }) 397 }, 398 399 async updateHandle(token: AccessToken, handle: Handle): Promise<void> { 400 await xrpc('com.atproto.identity.updateHandle', { 401 method: 'POST', 402 token, 403 body: { handle }, 404 }) 405 }, 406 407 async requestAccountDelete(token: AccessToken): Promise<void> { 408 await xrpc('com.atproto.server.requestAccountDelete', { 409 method: 'POST', 410 token, 411 }) 412 }, 413 414 async deleteAccount( 415 did: Did, 416 password: string, 417 deleteToken: string, 418 ): Promise<void> { 419 await xrpc('com.atproto.server.deleteAccount', { 420 method: 'POST', 421 body: { did, password, token: deleteToken }, 422 }) 423 }, 424 425 describeServer(): Promise<ServerDescription> { 426 return xrpc('com.atproto.server.describeServer') 427 }, 428 429 listRepos(limit?: number): Promise<ListReposResponse> { 430 const params: Record<string, string> = {} 431 if (limit) params.limit = String(limit) 432 return xrpc('com.atproto.sync.listRepos', { params }) 433 }, 434 435 getNotificationPrefs(token: AccessToken): Promise<NotificationPrefs> { 436 return xrpc('_account.getNotificationPrefs', { token }) 437 }, 438 439 updateNotificationPrefs(token: AccessToken, prefs: { 440 preferredChannel?: string 441 discordId?: string 442 telegramUsername?: string 443 signalNumber?: string 444 }): Promise<SuccessResponse> { 445 return xrpc('_account.updateNotificationPrefs', { 446 method: 'POST', 447 token, 448 body: prefs, 449 }) 450 }, 451 452 confirmChannelVerification( 453 token: AccessToken, 454 channel: string, 455 identifier: string, 456 code: string, 457 ): Promise<SuccessResponse> { 458 return xrpc('_account.confirmChannelVerification', { 459 method: 'POST', 460 token, 461 body: { channel, identifier, code }, 462 }) 463 }, 464 465 getNotificationHistory(token: AccessToken): Promise<NotificationHistoryResponse> { 466 return xrpc('_account.getNotificationHistory', { token }) 467 }, 468 469 getServerStats(token: AccessToken): Promise<ServerStats> { 470 return xrpc('_admin.getServerStats', { token }) 471 }, 472 473 getServerConfig(): Promise<ServerConfig> { 474 return xrpc('_server.getConfig') 475 }, 476 477 updateServerConfig( 478 token: AccessToken, 479 config: { 480 serverName?: string 481 primaryColor?: string 482 primaryColorDark?: string 483 secondaryColor?: string 484 secondaryColorDark?: string 485 logoCid?: string 486 }, 487 ): Promise<SuccessResponse> { 488 return xrpc('_admin.updateServerConfig', { 489 method: 'POST', 490 token, 491 body: config, 492 }) 493 }, 494 495 async uploadBlob(token: AccessToken, file: File): Promise<UploadBlobResponse> { 496 const res = await fetch('/xrpc/com.atproto.repo.uploadBlob', { 497 method: 'POST', 498 headers: { 499 'Authorization': `Bearer ${token}`, 500 'Content-Type': file.type, 501 }, 502 body: file, 503 }) 504 if (!res.ok) { 505 const errData = await res.json().catch(() => ({ 506 error: 'Unknown', 507 message: res.statusText, 508 })) 509 throw new ApiError(res.status, errData.error, errData.message) 510 } 511 return res.json() 512 }, 513 514 async changePassword( 515 token: AccessToken, 516 currentPassword: string, 517 newPassword: string, 518 ): Promise<void> { 519 await xrpc('_account.changePassword', { 520 method: 'POST', 521 token, 522 body: { currentPassword, newPassword }, 523 }) 524 }, 525 526 removePassword(token: AccessToken): Promise<SuccessResponse> { 527 return xrpc('_account.removePassword', { 528 method: 'POST', 529 token, 530 }) 531 }, 532 533 getPasswordStatus(token: AccessToken): Promise<PasswordStatus> { 534 return xrpc('_account.getPasswordStatus', { token }) 535 }, 536 537 getLegacyLoginPreference(token: AccessToken): Promise<LegacyLoginPreference> { 538 return xrpc('_account.getLegacyLoginPreference', { token }) 539 }, 540 541 updateLegacyLoginPreference( 542 token: AccessToken, 543 allowLegacyLogin: boolean, 544 ): Promise<UpdateLegacyLoginResponse> { 545 return xrpc('_account.updateLegacyLoginPreference', { 546 method: 'POST', 547 token, 548 body: { allowLegacyLogin }, 549 }) 550 }, 551 552 updateLocale(token: AccessToken, preferredLocale: string): Promise<UpdateLocaleResponse> { 553 return xrpc('_account.updateLocale', { 554 method: 'POST', 555 token, 556 body: { preferredLocale }, 557 }) 558 }, 559 560 listSessions(token: AccessToken): Promise<ListSessionsResponse> { 561 return xrpc('_account.listSessions', { token }) 562 }, 563 564 async revokeSession(token: AccessToken, sessionId: string): Promise<void> { 565 await xrpc('_account.revokeSession', { 566 method: 'POST', 567 token, 568 body: { sessionId }, 569 }) 570 }, 571 572 revokeAllSessions(token: AccessToken): Promise<{ revokedCount: number }> { 573 return xrpc('_account.revokeAllSessions', { 574 method: 'POST', 575 token, 576 }) 577 }, 578 579 searchAccounts(token: AccessToken, options?: { 580 handle?: string 581 cursor?: string 582 limit?: number 583 }): Promise<SearchAccountsResponse> { 584 const params: Record<string, string> = {} 585 if (options?.handle) params.handle = options.handle 586 if (options?.cursor) params.cursor = options.cursor 587 if (options?.limit) params.limit = String(options.limit) 588 return xrpc('com.atproto.admin.searchAccounts', { token, params }) 589 }, 590 591 getInviteCodes(token: AccessToken, options?: { 592 sort?: 'recent' | 'usage' 593 cursor?: string 594 limit?: number 595 }): Promise<GetInviteCodesResponse> { 596 const params: Record<string, string> = {} 597 if (options?.sort) params.sort = options.sort 598 if (options?.cursor) params.cursor = options.cursor 599 if (options?.limit) params.limit = String(options.limit) 600 return xrpc('com.atproto.admin.getInviteCodes', { token, params }) 601 }, 602 603 async disableInviteCodes( 604 token: AccessToken, 605 codes?: string[], 606 accounts?: string[], 607 ): Promise<void> { 608 await xrpc('com.atproto.admin.disableInviteCodes', { 609 method: 'POST', 610 token, 611 body: { codes, accounts }, 612 }) 613 }, 614 615 getAccountInfo(token: AccessToken, did: Did): Promise<AccountInfo> { 616 return xrpc('com.atproto.admin.getAccountInfo', { token, params: { did } }) 617 }, 618 619 async disableAccountInvites(token: AccessToken, account: Did): Promise<void> { 620 await xrpc('com.atproto.admin.disableAccountInvites', { 621 method: 'POST', 622 token, 623 body: { account }, 624 }) 625 }, 626 627 async enableAccountInvites(token: AccessToken, account: Did): Promise<void> { 628 await xrpc('com.atproto.admin.enableAccountInvites', { 629 method: 'POST', 630 token, 631 body: { account }, 632 }) 633 }, 634 635 async adminDeleteAccount(token: AccessToken, did: Did): Promise<void> { 636 await xrpc('com.atproto.admin.deleteAccount', { 637 method: 'POST', 638 token, 639 body: { did }, 640 }) 641 }, 642 643 describeRepo(token: AccessToken, repo: Did): Promise<RepoDescription> { 644 return xrpc('com.atproto.repo.describeRepo', { 645 token, 646 params: { repo }, 647 }) 648 }, 649 650 listRecords(token: AccessToken, repo: Did, collection: Nsid, options?: { 651 limit?: number 652 cursor?: string 653 reverse?: boolean 654 }): Promise<ListRecordsResponse> { 655 const params: Record<string, string> = { repo, collection } 656 if (options?.limit) params.limit = String(options.limit) 657 if (options?.cursor) params.cursor = options.cursor 658 if (options?.reverse) params.reverse = 'true' 659 return xrpc('com.atproto.repo.listRecords', { token, params }) 660 }, 661 662 getRecord( 663 token: AccessToken, 664 repo: Did, 665 collection: Nsid, 666 rkey: Rkey, 667 ): Promise<RecordResponse> { 668 return xrpc('com.atproto.repo.getRecord', { 669 token, 670 params: { repo, collection, rkey }, 671 }) 672 }, 673 674 createRecord( 675 token: AccessToken, 676 repo: Did, 677 collection: Nsid, 678 record: unknown, 679 rkey?: Rkey, 680 ): Promise<CreateRecordResponse> { 681 return xrpc('com.atproto.repo.createRecord', { 682 method: 'POST', 683 token, 684 body: { repo, collection, record, rkey }, 685 }) 686 }, 687 688 putRecord( 689 token: AccessToken, 690 repo: Did, 691 collection: Nsid, 692 rkey: Rkey, 693 record: unknown, 694 ): Promise<CreateRecordResponse> { 695 return xrpc('com.atproto.repo.putRecord', { 696 method: 'POST', 697 token, 698 body: { repo, collection, rkey, record }, 699 }) 700 }, 701 702 async deleteRecord( 703 token: AccessToken, 704 repo: Did, 705 collection: Nsid, 706 rkey: Rkey, 707 ): Promise<void> { 708 await xrpc('com.atproto.repo.deleteRecord', { 709 method: 'POST', 710 token, 711 body: { repo, collection, rkey }, 712 }) 713 }, 714 715 getTotpStatus(token: AccessToken): Promise<TotpStatus> { 716 return xrpc('com.atproto.server.getTotpStatus', { token }) 717 }, 718 719 createTotpSecret(token: AccessToken): Promise<TotpSecret> { 720 return xrpc('com.atproto.server.createTotpSecret', { 721 method: 'POST', 722 token, 723 }) 724 }, 725 726 enableTotp(token: AccessToken, code: string): Promise<EnableTotpResponse> { 727 return xrpc('com.atproto.server.enableTotp', { 728 method: 'POST', 729 token, 730 body: { code }, 731 }) 732 }, 733 734 disableTotp( 735 token: AccessToken, 736 password: string, 737 code: string, 738 ): Promise<SuccessResponse> { 739 return xrpc('com.atproto.server.disableTotp', { 740 method: 'POST', 741 token, 742 body: { password, code }, 743 }) 744 }, 745 746 regenerateBackupCodes( 747 token: AccessToken, 748 password: string, 749 code: string, 750 ): Promise<RegenerateBackupCodesResponse> { 751 return xrpc('com.atproto.server.regenerateBackupCodes', { 752 method: 'POST', 753 token, 754 body: { password, code }, 755 }) 756 }, 757 758 startPasskeyRegistration( 759 token: AccessToken, 760 friendlyName?: string, 761 ): Promise<StartPasskeyRegistrationResponse> { 762 return xrpc('com.atproto.server.startPasskeyRegistration', { 763 method: 'POST', 764 token, 765 body: { friendlyName }, 766 }) 767 }, 768 769 finishPasskeyRegistration( 770 token: AccessToken, 771 credential: unknown, 772 friendlyName?: string, 773 ): Promise<FinishPasskeyRegistrationResponse> { 774 return xrpc('com.atproto.server.finishPasskeyRegistration', { 775 method: 'POST', 776 token, 777 body: { credential, friendlyName }, 778 }) 779 }, 780 781 listPasskeys(token: AccessToken): Promise<ListPasskeysResponse> { 782 return xrpc('com.atproto.server.listPasskeys', { token }) 783 }, 784 785 async deletePasskey(token: AccessToken, id: string): Promise<void> { 786 await xrpc('com.atproto.server.deletePasskey', { 787 method: 'POST', 788 token, 789 body: { id }, 790 }) 791 }, 792 793 async updatePasskey( 794 token: AccessToken, 795 id: string, 796 friendlyName: string, 797 ): Promise<void> { 798 await xrpc('com.atproto.server.updatePasskey', { 799 method: 'POST', 800 token, 801 body: { id, friendlyName }, 802 }) 803 }, 804 805 listTrustedDevices(token: AccessToken): Promise<ListTrustedDevicesResponse> { 806 return xrpc('_account.listTrustedDevices', { token }) 807 }, 808 809 revokeTrustedDevice(token: AccessToken, deviceId: string): Promise<SuccessResponse> { 810 return xrpc('_account.revokeTrustedDevice', { 811 method: 'POST', 812 token, 813 body: { deviceId }, 814 }) 815 }, 816 817 updateTrustedDevice( 818 token: AccessToken, 819 deviceId: string, 820 friendlyName: string, 821 ): Promise<SuccessResponse> { 822 return xrpc('_account.updateTrustedDevice', { 823 method: 'POST', 824 token, 825 body: { deviceId, friendlyName }, 826 }) 827 }, 828 829 getReauthStatus(token: AccessToken): Promise<ReauthStatus> { 830 return xrpc('_account.getReauthStatus', { token }) 831 }, 832 833 reauthPassword(token: AccessToken, password: string): Promise<ReauthResponse> { 834 return xrpc('_account.reauthPassword', { 835 method: 'POST', 836 token, 837 body: { password }, 838 }) 839 }, 840 841 reauthTotp(token: AccessToken, code: string): Promise<ReauthResponse> { 842 return xrpc('_account.reauthTotp', { 843 method: 'POST', 844 token, 845 body: { code }, 846 }) 847 }, 848 849 reauthPasskeyStart(token: AccessToken): Promise<ReauthPasskeyStartResponse> { 850 return xrpc('_account.reauthPasskeyStart', { 851 method: 'POST', 852 token, 853 }) 854 }, 855 856 reauthPasskeyFinish(token: AccessToken, credential: unknown): Promise<ReauthResponse> { 857 return xrpc('_account.reauthPasskeyFinish', { 858 method: 'POST', 859 token, 860 body: { credential }, 861 }) 862 }, 863 864 reserveSigningKey(did?: Did): Promise<ReserveSigningKeyResponse> { 865 return xrpc('com.atproto.server.reserveSigningKey', { 866 method: 'POST', 867 body: { did }, 868 }) 869 }, 870 871 getRecommendedDidCredentials(token: AccessToken): Promise<RecommendedDidCredentials> { 872 return xrpc('com.atproto.identity.getRecommendedDidCredentials', { token }) 873 }, 874 875 async activateAccount(token: AccessToken): Promise<void> { 876 await xrpc('com.atproto.server.activateAccount', { 877 method: 'POST', 878 token, 879 }) 880 }, 881 882 async createPasskeyAccount(params: { 883 handle: Handle 884 email?: EmailAddress 885 inviteCode?: string 886 didType?: DidType 887 did?: Did 888 signingKey?: string 889 verificationChannel?: VerificationChannel 890 discordId?: string 891 telegramUsername?: string 892 signalNumber?: string 893 }, byodToken?: string): Promise<PasskeyAccountCreateResponse> { 894 const url = `${API_BASE}/_account.createPasskeyAccount` 895 const headers: Record<string, string> = { 896 'Content-Type': 'application/json', 897 } 898 if (byodToken) { 899 headers['Authorization'] = `Bearer ${byodToken}` 900 } 901 const res = await fetch(url, { 902 method: 'POST', 903 headers, 904 body: JSON.stringify(params), 905 }) 906 if (!res.ok) { 907 const errData = await res.json().catch(() => ({ 908 error: 'Unknown', 909 message: res.statusText, 910 })) 911 throw new ApiError(res.status, errData.error, errData.message) 912 } 913 return res.json() 914 }, 915 916 startPasskeyRegistrationForSetup( 917 did: Did, 918 setupToken: string, 919 friendlyName?: string, 920 ): Promise<StartPasskeyRegistrationResponse> { 921 return xrpc('_account.startPasskeyRegistrationForSetup', { 922 method: 'POST', 923 body: { did, setupToken, friendlyName }, 924 }) 925 }, 926 927 completePasskeySetup( 928 did: Did, 929 setupToken: string, 930 passkeyCredential: unknown, 931 passkeyFriendlyName?: string, 932 ): Promise<CompletePasskeySetupResponse> { 933 return xrpc('_account.completePasskeySetup', { 934 method: 'POST', 935 body: { did, setupToken, passkeyCredential, passkeyFriendlyName }, 936 }) 937 }, 938 939 requestPasskeyRecovery(email: EmailAddress): Promise<SuccessResponse> { 940 return xrpc('_account.requestPasskeyRecovery', { 941 method: 'POST', 942 body: { email }, 943 }) 944 }, 945 946 recoverPasskeyAccount( 947 did: Did, 948 recoveryToken: string, 949 newPassword: string, 950 ): Promise<SuccessResponse> { 951 return xrpc('_account.recoverPasskeyAccount', { 952 method: 'POST', 953 body: { did, recoveryToken, newPassword }, 954 }) 955 }, 956 957 verifyMigrationEmail(token: string, email: EmailAddress): Promise<VerifyMigrationEmailResponse> { 958 return xrpc('com.atproto.server.verifyMigrationEmail', { 959 method: 'POST', 960 body: { token, email }, 961 }) 962 }, 963 964 resendMigrationVerification(email: EmailAddress): Promise<ResendMigrationVerificationResponse> { 965 return xrpc('com.atproto.server.resendMigrationVerification', { 966 method: 'POST', 967 body: { email }, 968 }) 969 }, 970 971 verifyToken( 972 token: string, 973 identifier: string, 974 accessToken?: AccessToken, 975 ): Promise<VerifyTokenResponse> { 976 return xrpc('_account.verifyToken', { 977 method: 'POST', 978 body: { token, identifier }, 979 token: accessToken, 980 }) 981 }, 982 983 getDidDocument(token: AccessToken): Promise<DidDocument> { 984 return xrpc('_account.getDidDocument', { token }) 985 }, 986 987 updateDidDocument( 988 token: AccessToken, 989 params: { 990 verificationMethods?: VerificationMethod[] 991 alsoKnownAs?: string[] 992 serviceEndpoint?: string 993 }, 994 ): Promise<SuccessResponse> { 995 return xrpc('_account.updateDidDocument', { 996 method: 'POST', 997 token, 998 body: params, 999 }) 1000 }, 1001 1002 async deactivateAccount(token: AccessToken, deleteAfter?: string): Promise<void> { 1003 await xrpc('com.atproto.server.deactivateAccount', { 1004 method: 'POST', 1005 token, 1006 body: { deleteAfter }, 1007 }) 1008 }, 1009 1010 async getRepo(token: AccessToken, did: Did): Promise<ArrayBuffer> { 1011 const url = `${API_BASE}/com.atproto.sync.getRepo?did=${encodeURIComponent(did)}` 1012 const res = await fetch(url, { 1013 headers: { Authorization: `Bearer ${token}` }, 1014 }) 1015 if (!res.ok) { 1016 const errData = await res.json().catch(() => ({ 1017 error: 'Unknown', 1018 message: res.statusText, 1019 })) 1020 throw new ApiError(res.status, errData.error, errData.message) 1021 } 1022 return res.arrayBuffer() 1023 }, 1024 1025 listBackups(token: AccessToken): Promise<ListBackupsResponse> { 1026 return xrpc('_backup.listBackups', { token }) 1027 }, 1028 1029 async getBackup(token: AccessToken, id: string): Promise<Blob> { 1030 const url = `${API_BASE}/_backup.getBackup?id=${encodeURIComponent(id)}` 1031 const res = await fetch(url, { 1032 headers: { Authorization: `Bearer ${token}` }, 1033 }) 1034 if (!res.ok) { 1035 const errData = await res.json().catch(() => ({ 1036 error: 'Unknown', 1037 message: res.statusText, 1038 })) 1039 throw new ApiError(res.status, errData.error, errData.message) 1040 } 1041 return res.blob() 1042 }, 1043 1044 createBackup(token: AccessToken): Promise<CreateBackupResponse> { 1045 return xrpc('_backup.createBackup', { 1046 method: 'POST', 1047 token, 1048 }) 1049 }, 1050 1051 async deleteBackup(token: AccessToken, id: string): Promise<void> { 1052 await xrpc('_backup.deleteBackup', { 1053 method: 'POST', 1054 token, 1055 params: { id }, 1056 }) 1057 }, 1058 1059 setBackupEnabled(token: AccessToken, enabled: boolean): Promise<SetBackupEnabledResponse> { 1060 return xrpc('_backup.setEnabled', { 1061 method: 'POST', 1062 token, 1063 body: { enabled }, 1064 }) 1065 }, 1066 1067 async importRepo(token: AccessToken, car: Uint8Array): Promise<void> { 1068 const url = `${API_BASE}/com.atproto.repo.importRepo` 1069 const res = await fetch(url, { 1070 method: 'POST', 1071 headers: { 1072 Authorization: `Bearer ${token}`, 1073 'Content-Type': 'application/vnd.ipld.car', 1074 }, 1075 body: car, 1076 }) 1077 if (!res.ok) { 1078 const errData = await res.json().catch(() => ({ 1079 error: 'Unknown', 1080 message: res.statusText, 1081 })) 1082 throw new ApiError(res.status, errData.error, errData.message) 1083 } 1084 }, 1085} 1086 1087export const typedApi = { 1088 createSession( 1089 identifier: string, 1090 password: string 1091 ): Promise<Result<Session, ApiError>> { 1092 return xrpcResult<Session>('com.atproto.server.createSession', { 1093 method: 'POST', 1094 body: { identifier, password }, 1095 }).then(r => r.ok ? ok(castSession(r.value)) : r) 1096 }, 1097 1098 getSession(token: AccessToken): Promise<Result<Session, ApiError>> { 1099 return xrpcResult<Session>('com.atproto.server.getSession', { token }) 1100 .then(r => r.ok ? ok(castSession(r.value)) : r) 1101 }, 1102 1103 refreshSession(refreshJwt: RefreshToken): Promise<Result<Session, ApiError>> { 1104 return xrpcResult<Session>('com.atproto.server.refreshSession', { 1105 method: 'POST', 1106 token: refreshJwt, 1107 }).then(r => r.ok ? ok(castSession(r.value)) : r) 1108 }, 1109 1110 describeServer(): Promise<Result<ServerDescription, ApiError>> { 1111 return xrpcResult('com.atproto.server.describeServer') 1112 }, 1113 1114 listAppPasswords(token: AccessToken): Promise<Result<{ passwords: AppPassword[] }, ApiError>> { 1115 return xrpcResult('com.atproto.server.listAppPasswords', { token }) 1116 }, 1117 1118 createAppPassword( 1119 token: AccessToken, 1120 name: string, 1121 scopes?: string 1122 ): Promise<Result<CreatedAppPassword, ApiError>> { 1123 return xrpcResult('com.atproto.server.createAppPassword', { 1124 method: 'POST', 1125 token, 1126 body: { name, scopes }, 1127 }) 1128 }, 1129 1130 revokeAppPassword(token: AccessToken, name: string): Promise<Result<void, ApiError>> { 1131 return xrpcResult<void>('com.atproto.server.revokeAppPassword', { 1132 method: 'POST', 1133 token, 1134 body: { name }, 1135 }) 1136 }, 1137 1138 listSessions(token: AccessToken): Promise<Result<ListSessionsResponse, ApiError>> { 1139 return xrpcResult('_account.listSessions', { token }) 1140 }, 1141 1142 revokeSession(token: AccessToken, sessionId: string): Promise<Result<void, ApiError>> { 1143 return xrpcResult<void>('_account.revokeSession', { 1144 method: 'POST', 1145 token, 1146 body: { sessionId }, 1147 }) 1148 }, 1149 1150 getTotpStatus(token: AccessToken): Promise<Result<TotpStatus, ApiError>> { 1151 return xrpcResult('com.atproto.server.getTotpStatus', { token }) 1152 }, 1153 1154 createTotpSecret(token: AccessToken): Promise<Result<TotpSecret, ApiError>> { 1155 return xrpcResult('com.atproto.server.createTotpSecret', { 1156 method: 'POST', 1157 token, 1158 }) 1159 }, 1160 1161 enableTotp(token: AccessToken, code: string): Promise<Result<EnableTotpResponse, ApiError>> { 1162 return xrpcResult('com.atproto.server.enableTotp', { 1163 method: 'POST', 1164 token, 1165 body: { code }, 1166 }) 1167 }, 1168 1169 disableTotp( 1170 token: AccessToken, 1171 password: string, 1172 code: string 1173 ): Promise<Result<SuccessResponse, ApiError>> { 1174 return xrpcResult('com.atproto.server.disableTotp', { 1175 method: 'POST', 1176 token, 1177 body: { password, code }, 1178 }) 1179 }, 1180 1181 listPasskeys(token: AccessToken): Promise<Result<ListPasskeysResponse, ApiError>> { 1182 return xrpcResult('com.atproto.server.listPasskeys', { token }) 1183 }, 1184 1185 deletePasskey(token: AccessToken, id: string): Promise<Result<void, ApiError>> { 1186 return xrpcResult<void>('com.atproto.server.deletePasskey', { 1187 method: 'POST', 1188 token, 1189 body: { id }, 1190 }) 1191 }, 1192 1193 listTrustedDevices(token: AccessToken): Promise<Result<ListTrustedDevicesResponse, ApiError>> { 1194 return xrpcResult('_account.listTrustedDevices', { token }) 1195 }, 1196 1197 getReauthStatus(token: AccessToken): Promise<Result<ReauthStatus, ApiError>> { 1198 return xrpcResult('_account.getReauthStatus', { token }) 1199 }, 1200 1201 getNotificationPrefs(token: AccessToken): Promise<Result<NotificationPrefs, ApiError>> { 1202 return xrpcResult('_account.getNotificationPrefs', { token }) 1203 }, 1204 1205 updateHandle(token: AccessToken, handle: Handle): Promise<Result<void, ApiError>> { 1206 return xrpcResult<void>('com.atproto.identity.updateHandle', { 1207 method: 'POST', 1208 token, 1209 body: { handle }, 1210 }) 1211 }, 1212 1213 describeRepo(token: AccessToken, repo: Did): Promise<Result<RepoDescription, ApiError>> { 1214 return xrpcResult('com.atproto.repo.describeRepo', { 1215 token, 1216 params: { repo }, 1217 }) 1218 }, 1219 1220 listRecords( 1221 token: AccessToken, 1222 repo: Did, 1223 collection: Nsid, 1224 options?: { limit?: number; cursor?: string; reverse?: boolean } 1225 ): Promise<Result<ListRecordsResponse, ApiError>> { 1226 const params: Record<string, string> = { repo, collection } 1227 if (options?.limit) params.limit = String(options.limit) 1228 if (options?.cursor) params.cursor = options.cursor 1229 if (options?.reverse) params.reverse = 'true' 1230 return xrpcResult('com.atproto.repo.listRecords', { token, params }) 1231 }, 1232 1233 getRecord( 1234 token: AccessToken, 1235 repo: Did, 1236 collection: Nsid, 1237 rkey: Rkey 1238 ): Promise<Result<RecordResponse, ApiError>> { 1239 return xrpcResult('com.atproto.repo.getRecord', { 1240 token, 1241 params: { repo, collection, rkey }, 1242 }) 1243 }, 1244 1245 deleteRecord( 1246 token: AccessToken, 1247 repo: Did, 1248 collection: Nsid, 1249 rkey: Rkey 1250 ): Promise<Result<void, ApiError>> { 1251 return xrpcResult<void>('com.atproto.repo.deleteRecord', { 1252 method: 'POST', 1253 token, 1254 body: { repo, collection, rkey }, 1255 }) 1256 }, 1257 1258 searchAccounts( 1259 token: AccessToken, 1260 options?: { handle?: string; cursor?: string; limit?: number } 1261 ): Promise<Result<SearchAccountsResponse, ApiError>> { 1262 const params: Record<string, string> = {} 1263 if (options?.handle) params.handle = options.handle 1264 if (options?.cursor) params.cursor = options.cursor 1265 if (options?.limit) params.limit = String(options.limit) 1266 return xrpcResult('com.atproto.admin.searchAccounts', { token, params }) 1267 }, 1268 1269 getAccountInfo(token: AccessToken, did: Did): Promise<Result<AccountInfo, ApiError>> { 1270 return xrpcResult('com.atproto.admin.getAccountInfo', { token, params: { did } }) 1271 }, 1272 1273 getServerStats(token: AccessToken): Promise<Result<ServerStats, ApiError>> { 1274 return xrpcResult('_admin.getServerStats', { token }) 1275 }, 1276 1277 listBackups(token: AccessToken): Promise<Result<ListBackupsResponse, ApiError>> { 1278 return xrpcResult('_backup.listBackups', { token }) 1279 }, 1280 1281 createBackup(token: AccessToken): Promise<Result<CreateBackupResponse, ApiError>> { 1282 return xrpcResult('_backup.createBackup', { 1283 method: 'POST', 1284 token, 1285 }) 1286 }, 1287 1288 getDidDocument(token: AccessToken): Promise<Result<DidDocument, ApiError>> { 1289 return xrpcResult('_account.getDidDocument', { token }) 1290 }, 1291 1292 deleteSession(token: AccessToken): Promise<Result<void, ApiError>> { 1293 return xrpcResult<void>('com.atproto.server.deleteSession', { 1294 method: 'POST', 1295 token, 1296 }) 1297 }, 1298 1299 revokeAllSessions(token: AccessToken): Promise<Result<{ revokedCount: number }, ApiError>> { 1300 return xrpcResult('_account.revokeAllSessions', { 1301 method: 'POST', 1302 token, 1303 }) 1304 }, 1305 1306 getAccountInviteCodes(token: AccessToken): Promise<Result<{ codes: InviteCodeInfo[] }, ApiError>> { 1307 return xrpcResult('com.atproto.server.getAccountInviteCodes', { token }) 1308 }, 1309 1310 createInviteCode(token: AccessToken, useCount: number = 1): Promise<Result<{ code: string }, ApiError>> { 1311 return xrpcResult('com.atproto.server.createInviteCode', { 1312 method: 'POST', 1313 token, 1314 body: { useCount }, 1315 }) 1316 }, 1317 1318 changePassword( 1319 token: AccessToken, 1320 currentPassword: string, 1321 newPassword: string 1322 ): Promise<Result<void, ApiError>> { 1323 return xrpcResult<void>('_account.changePassword', { 1324 method: 'POST', 1325 token, 1326 body: { currentPassword, newPassword }, 1327 }) 1328 }, 1329 1330 getPasswordStatus(token: AccessToken): Promise<Result<PasswordStatus, ApiError>> { 1331 return xrpcResult('_account.getPasswordStatus', { token }) 1332 }, 1333 1334 getServerConfig(): Promise<Result<ServerConfig, ApiError>> { 1335 return xrpcResult('_server.getConfig') 1336 }, 1337 1338 getLegacyLoginPreference(token: AccessToken): Promise<Result<LegacyLoginPreference, ApiError>> { 1339 return xrpcResult('_account.getLegacyLoginPreference', { token }) 1340 }, 1341 1342 updateLegacyLoginPreference( 1343 token: AccessToken, 1344 allowLegacyLogin: boolean 1345 ): Promise<Result<UpdateLegacyLoginResponse, ApiError>> { 1346 return xrpcResult('_account.updateLegacyLoginPreference', { 1347 method: 'POST', 1348 token, 1349 body: { allowLegacyLogin }, 1350 }) 1351 }, 1352 1353 getNotificationHistory(token: AccessToken): Promise<Result<NotificationHistoryResponse, ApiError>> { 1354 return xrpcResult('_account.getNotificationHistory', { token }) 1355 }, 1356 1357 updateNotificationPrefs( 1358 token: AccessToken, 1359 prefs: { 1360 preferredChannel?: string 1361 discordId?: string 1362 telegramUsername?: string 1363 signalNumber?: string 1364 } 1365 ): Promise<Result<SuccessResponse, ApiError>> { 1366 return xrpcResult('_account.updateNotificationPrefs', { 1367 method: 'POST', 1368 token, 1369 body: prefs, 1370 }) 1371 }, 1372 1373 revokeTrustedDevice(token: AccessToken, deviceId: string): Promise<Result<SuccessResponse, ApiError>> { 1374 return xrpcResult('_account.revokeTrustedDevice', { 1375 method: 'POST', 1376 token, 1377 body: { deviceId }, 1378 }) 1379 }, 1380 1381 updateTrustedDevice( 1382 token: AccessToken, 1383 deviceId: string, 1384 friendlyName: string 1385 ): Promise<Result<SuccessResponse, ApiError>> { 1386 return xrpcResult('_account.updateTrustedDevice', { 1387 method: 'POST', 1388 token, 1389 body: { deviceId, friendlyName }, 1390 }) 1391 }, 1392 1393 reauthPassword(token: AccessToken, password: string): Promise<Result<ReauthResponse, ApiError>> { 1394 return xrpcResult('_account.reauthPassword', { 1395 method: 'POST', 1396 token, 1397 body: { password }, 1398 }) 1399 }, 1400 1401 reauthTotp(token: AccessToken, code: string): Promise<Result<ReauthResponse, ApiError>> { 1402 return xrpcResult('_account.reauthTotp', { 1403 method: 'POST', 1404 token, 1405 body: { code }, 1406 }) 1407 }, 1408 1409 reauthPasskeyStart(token: AccessToken): Promise<Result<ReauthPasskeyStartResponse, ApiError>> { 1410 return xrpcResult('_account.reauthPasskeyStart', { 1411 method: 'POST', 1412 token, 1413 }) 1414 }, 1415 1416 reauthPasskeyFinish(token: AccessToken, credential: unknown): Promise<Result<ReauthResponse, ApiError>> { 1417 return xrpcResult('_account.reauthPasskeyFinish', { 1418 method: 'POST', 1419 token, 1420 body: { credential }, 1421 }) 1422 }, 1423 1424 confirmSignup(did: Did, verificationCode: string): Promise<Result<ConfirmSignupResult, ApiError>> { 1425 return xrpcResult('com.atproto.server.confirmSignup', { 1426 method: 'POST', 1427 body: { did, verificationCode }, 1428 }) 1429 }, 1430 1431 resendVerification(did: Did): Promise<Result<{ success: boolean }, ApiError>> { 1432 return xrpcResult('com.atproto.server.resendVerification', { 1433 method: 'POST', 1434 body: { did }, 1435 }) 1436 }, 1437 1438 requestEmailUpdate(token: AccessToken): Promise<Result<EmailUpdateResponse, ApiError>> { 1439 return xrpcResult('com.atproto.server.requestEmailUpdate', { 1440 method: 'POST', 1441 token, 1442 }) 1443 }, 1444 1445 updateEmail(token: AccessToken, email: string, emailToken?: string): Promise<Result<void, ApiError>> { 1446 return xrpcResult<void>('com.atproto.server.updateEmail', { 1447 method: 'POST', 1448 token, 1449 body: { email, token: emailToken }, 1450 }) 1451 }, 1452 1453 requestAccountDelete(token: AccessToken): Promise<Result<void, ApiError>> { 1454 return xrpcResult<void>('com.atproto.server.requestAccountDelete', { 1455 method: 'POST', 1456 token, 1457 }) 1458 }, 1459 1460 deleteAccount(did: Did, password: string, deleteToken: string): Promise<Result<void, ApiError>> { 1461 return xrpcResult<void>('com.atproto.server.deleteAccount', { 1462 method: 'POST', 1463 body: { did, password, token: deleteToken }, 1464 }) 1465 }, 1466 1467 updateDidDocument( 1468 token: AccessToken, 1469 params: { 1470 verificationMethods?: VerificationMethod[] 1471 alsoKnownAs?: string[] 1472 serviceEndpoint?: string 1473 } 1474 ): Promise<Result<SuccessResponse, ApiError>> { 1475 return xrpcResult('_account.updateDidDocument', { 1476 method: 'POST', 1477 token, 1478 body: params, 1479 }) 1480 }, 1481 1482 deactivateAccount(token: AccessToken, deleteAfter?: string): Promise<Result<void, ApiError>> { 1483 return xrpcResult<void>('com.atproto.server.deactivateAccount', { 1484 method: 'POST', 1485 token, 1486 body: { deleteAfter }, 1487 }) 1488 }, 1489 1490 activateAccount(token: AccessToken): Promise<Result<void, ApiError>> { 1491 return xrpcResult<void>('com.atproto.server.activateAccount', { 1492 method: 'POST', 1493 token, 1494 }) 1495 }, 1496 1497 setBackupEnabled(token: AccessToken, enabled: boolean): Promise<Result<SetBackupEnabledResponse, ApiError>> { 1498 return xrpcResult('_backup.setEnabled', { 1499 method: 'POST', 1500 token, 1501 body: { enabled }, 1502 }) 1503 }, 1504 1505 deleteBackup(token: AccessToken, id: string): Promise<Result<void, ApiError>> { 1506 return xrpcResult<void>('_backup.deleteBackup', { 1507 method: 'POST', 1508 token, 1509 params: { id }, 1510 }) 1511 }, 1512 1513 createRecord( 1514 token: AccessToken, 1515 repo: Did, 1516 collection: Nsid, 1517 record: unknown, 1518 rkey?: Rkey 1519 ): Promise<Result<CreateRecordResponse, ApiError>> { 1520 return xrpcResult('com.atproto.repo.createRecord', { 1521 method: 'POST', 1522 token, 1523 body: { repo, collection, record, rkey }, 1524 }) 1525 }, 1526 1527 putRecord( 1528 token: AccessToken, 1529 repo: Did, 1530 collection: Nsid, 1531 rkey: Rkey, 1532 record: unknown 1533 ): Promise<Result<CreateRecordResponse, ApiError>> { 1534 return xrpcResult('com.atproto.repo.putRecord', { 1535 method: 'POST', 1536 token, 1537 body: { repo, collection, rkey, record }, 1538 }) 1539 }, 1540 1541 getInviteCodes( 1542 token: AccessToken, 1543 options?: { sort?: 'recent' | 'usage'; cursor?: string; limit?: number } 1544 ): Promise<Result<GetInviteCodesResponse, ApiError>> { 1545 const params: Record<string, string> = {} 1546 if (options?.sort) params.sort = options.sort 1547 if (options?.cursor) params.cursor = options.cursor 1548 if (options?.limit) params.limit = String(options.limit) 1549 return xrpcResult('com.atproto.admin.getInviteCodes', { token, params }) 1550 }, 1551 1552 disableAccountInvites(token: AccessToken, account: Did): Promise<Result<void, ApiError>> { 1553 return xrpcResult<void>('com.atproto.admin.disableAccountInvites', { 1554 method: 'POST', 1555 token, 1556 body: { account }, 1557 }) 1558 }, 1559 1560 enableAccountInvites(token: AccessToken, account: Did): Promise<Result<void, ApiError>> { 1561 return xrpcResult<void>('com.atproto.admin.enableAccountInvites', { 1562 method: 'POST', 1563 token, 1564 body: { account }, 1565 }) 1566 }, 1567 1568 adminDeleteAccount(token: AccessToken, did: Did): Promise<Result<void, ApiError>> { 1569 return xrpcResult<void>('com.atproto.admin.deleteAccount', { 1570 method: 'POST', 1571 token, 1572 body: { did }, 1573 }) 1574 }, 1575 1576 startPasskeyRegistration( 1577 token: AccessToken, 1578 friendlyName?: string 1579 ): Promise<Result<StartPasskeyRegistrationResponse, ApiError>> { 1580 return xrpcResult('com.atproto.server.startPasskeyRegistration', { 1581 method: 'POST', 1582 token, 1583 body: { friendlyName }, 1584 }) 1585 }, 1586 1587 finishPasskeyRegistration( 1588 token: AccessToken, 1589 credential: unknown, 1590 friendlyName?: string 1591 ): Promise<Result<FinishPasskeyRegistrationResponse, ApiError>> { 1592 return xrpcResult('com.atproto.server.finishPasskeyRegistration', { 1593 method: 'POST', 1594 token, 1595 body: { credential, friendlyName }, 1596 }) 1597 }, 1598 1599 updatePasskey( 1600 token: AccessToken, 1601 id: string, 1602 friendlyName: string 1603 ): Promise<Result<void, ApiError>> { 1604 return xrpcResult<void>('com.atproto.server.updatePasskey', { 1605 method: 'POST', 1606 token, 1607 body: { id, friendlyName }, 1608 }) 1609 }, 1610 1611 regenerateBackupCodes( 1612 token: AccessToken, 1613 password: string, 1614 code: string 1615 ): Promise<Result<RegenerateBackupCodesResponse, ApiError>> { 1616 return xrpcResult('com.atproto.server.regenerateBackupCodes', { 1617 method: 'POST', 1618 token, 1619 body: { password, code }, 1620 }) 1621 }, 1622 1623 updateLocale(token: AccessToken, preferredLocale: string): Promise<Result<UpdateLocaleResponse, ApiError>> { 1624 return xrpcResult('_account.updateLocale', { 1625 method: 'POST', 1626 token, 1627 body: { preferredLocale }, 1628 }) 1629 }, 1630 1631 confirmChannelVerification( 1632 token: AccessToken, 1633 channel: string, 1634 identifier: string, 1635 code: string 1636 ): Promise<Result<SuccessResponse, ApiError>> { 1637 return xrpcResult('_account.confirmChannelVerification', { 1638 method: 'POST', 1639 token, 1640 body: { channel, identifier, code }, 1641 }) 1642 }, 1643 1644 removePassword(token: AccessToken): Promise<Result<SuccessResponse, ApiError>> { 1645 return xrpcResult('_account.removePassword', { 1646 method: 'POST', 1647 token, 1648 }) 1649 }, 1650}