> For the complete documentation index, see [llms.txt](https://docs.radfi.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.radfi.co/dev/api-endpoints/account.md).

# Account

## GET /api/account

> Admin: list accounts (paginated)

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}}},"paths":{"/api/account":{"get":{"operationId":"AccountController_paginate","summary":"Admin: list accounts (paginated)","parameters":[{"name":"page","required":false,"in":"query","description":"Page number (default: 1)","schema":{"type":"number"}},{"name":"pageSize","required":false,"in":"query","description":"Number of items per page (default: 10)","schema":{"type":"number"}},{"name":"sort","required":false,"in":"query","description":"Sort field and order. Use - prefix for descending. Example: -createdAt, createdAt","schema":{"type":"string"}},{"name":"select","required":false,"in":"query","description":"Fields to select (comma separated). Use + prefix to include hidden fields. Example: name,status,+holders","schema":{"type":"string"}},{"name":"populate","required":false,"in":"query","description":"Relations to populate (comma separated). Example: wallet,token","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["account"]}}}}
```

## GET /api/account/me

>

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/me":{"get":{"operationId":"AccountController_getMe","parameters":[],"responses":{"200":{"description":""}},"tags":["account"]}}}}
```

## Change password step 1 — get current password challenge

> Returns sessionId, salt, and serverPublic (B) to begin SRP proof of the existing password.

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/srp/change-password/init":{"post":{"operationId":"AccountController_srpChangePasswordInit","summary":"Change password step 1 — get current password challenge","description":"Returns sessionId, salt, and serverPublic (B) to begin SRP proof of the existing password.","parameters":[],"responses":{"200":{"description":"Returns sessionId, salt, and serverPublic (B)"}},"tags":["account"]}}}}
```

## Change password step 2 — verify old password and set new credentials

> Client proves knowledge of the old password via M1, then submits new salt, verifier, and encrypted blob atomically.

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/srp/change-password/verify":{"post":{"operationId":"AccountController_srpChangePasswordVerify","summary":"Change password step 2 — verify old password and set new credentials","description":"Client proves knowledge of the old password via M1, then submits new salt, verifier, and encrypted blob atomically.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordDto"}}}},"responses":{"200":{"description":"Password changed — returns serverProof (M2) for client verification"}},"tags":["account"]}}},"components":{"schemas":{"ChangePasswordDto":{"type":"object","properties":{"sessionId":{"type":"string","description":"Session ID returned by POST /auth/srp/change-password/init"},"clientPublic":{"type":"string","description":"Client ephemeral public key A = g^a mod N (base64)"},"clientProof":{"type":"string","description":"Client proof M1 = H(H(N)⊕H(g) || H(I) || salt || A || B || K) (base64)"},"newSrpSalt":{"type":"string","description":"New SRP salt generated client-side (base64, 32 bytes)"},"newSrpVerifier":{"type":"string","description":"New SRP verifier v = g^x mod N (base64)"},"newEncryptedBlob":{"type":"string","description":"Keystore blob re-encrypted with new derived key (base64, max 13708 chars)"},"newPasswordHint":{"type":"string","description":"New password hint"}},"required":["sessionId","clientPublic","clientProof","newSrpSalt","newSrpVerifier","newEncryptedBlob"]}}}}
```

## POST /api/account/2fa/setup

> Set up TOTP 2FA — generate a new secret and return the otpauth URI

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/2fa/setup":{"post":{"operationId":"AccountController_setupTotp","summary":"Set up TOTP 2FA — generate a new secret and return the otpauth URI","parameters":[],"responses":{"200":{"description":"Returns otpauthUri for QR code rendering"}},"tags":["account"]}}}}
```

## POST /api/account/2fa/toggle

> Enable or disable TOTP 2FA — requires a valid OTP code

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/2fa/toggle":{"post":{"operationId":"AccountController_toggleTotp","summary":"Enable or disable TOTP 2FA — requires a valid OTP code","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TotpToggleDto"}}}},"responses":{"200":{"description":"2FA state toggled"},"400":{"description":"Invalid OTP code or setup not completed"}},"tags":["account"]}}},"components":{"schemas":{"TotpToggleDto":{"type":"object","properties":{}}}}}
```

## PATCH /api/account/avatar

> Set an inscription as the account avatar

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/avatar":{"patch":{"operationId":"AccountController_setAvatar","summary":"Set an inscription as the account avatar","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAvatarDto"}}}},"responses":{"200":{"description":"Avatar updated"},"400":{"description":"Inscription not found or not owned by caller"}},"tags":["account"]}}},"components":{"schemas":{"SetAvatarDto":{"type":"object","properties":{"inscriptionId":{"type":"string","description":"The inscriptionId to set as avatar. Pass null or omit to remove the avatar.","nullable":true}}}}}}
```

## DELETE /api/account/default-token

> Remove a default token for a slot

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/default-token":{"delete":{"operationId":"AccountController_removeDefaultToken","summary":"Remove a default token for a slot","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveDefaultTokenDto"}}}},"responses":{"200":{"description":"Default token removed successfully"},"400":{"description":"Invalid slot or tokenId"},"401":{"description":"Unauthorized"}},"tags":["account"]}}},"components":{"schemas":{"RemoveDefaultTokenDto":{"type":"object","properties":{"slot":{"type":"string","enum":["usdc"]},"tokenId":{"type":"string"}},"required":["slot","tokenId"]}}}}
```

## PATCH /api/account/default-token

> Set a default token for a slot

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/default-token":{"patch":{"operationId":"AccountController_setDefaultToken","summary":"Set a default token for a slot","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDefaultTokenDto"}}}},"responses":{"200":{"description":"Default token set successfully"},"400":{"description":"Token not found, unsupported chain, or token invalid for slot"},"401":{"description":"Unauthorized"}},"tags":["account"]}}},"components":{"schemas":{"SetDefaultTokenDto":{"type":"object","properties":{"slot":{"type":"string","enum":["usdc"]},"tokenId":{"type":"string"}},"required":["slot","tokenId"]}}}}
```

## Initiate email change — send verification link to new address

> Queues a verification email to the new address and a notice to the current address. Returns \`{ srpSession }\` for SRP accounts or \`{ webauthnChallenge }\` for passkey accounts — only one field is present at a time.

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/change-email/init":{"post":{"operationId":"AccountController_changeEmailInit","summary":"Initiate email change — send verification link to new address","description":"Queues a verification email to the new address and a notice to the current address. Returns `{ srpSession }` for SRP accounts or `{ webauthnChallenge }` for passkey accounts — only one field is present at a time.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeEmailInitDto"}}}},"responses":{"200":{"description":"Returns srpSession (SRP accounts) or webauthnChallenge (passkey accounts)"},"400":{"description":"New email already taken or same as current email"},"429":{"description":"Rate limit exceeded"}},"tags":["account"]}}},"components":{"schemas":{"ChangeEmailInitDto":{"type":"object","properties":{"newEmail":{"type":"string","description":"New email address to associate with the account"}},"required":["newEmail"]}}}}
```

## Confirm email change using verification token

> Finalises the email update. SRP accounts: \`srpSessionId\`, \`clientPublic\`, \`clientProof\`, and \`newSrpVerifier\` are conditionally required. \`srpSession\` from the init response provides \`sessionId\`, \`salt\`, and \`serverPublic\`. Passkey accounts: \`credentialId\`, \`challengeId\`, and \`webauthnAssertion\` are conditionally required. \`webauthnChallenge\` from the init response provides \`challengeId\` and \`challenge\`.

```json
{"openapi":"3.0.0","info":{"title":"Radfi API","version":"1.0"},"servers":[{"url":"https://api.radfi.co","description":"Production"}],"paths":{"/api/account/change-email/verify":{"post":{"operationId":"AccountController_changeEmailVerify","summary":"Confirm email change using verification token","description":"Finalises the email update. SRP accounts: `srpSessionId`, `clientPublic`, `clientProof`, and `newSrpVerifier` are conditionally required. `srpSession` from the init response provides `sessionId`, `salt`, and `serverPublic`. Passkey accounts: `credentialId`, `challengeId`, and `webauthnAssertion` are conditionally required. `webauthnChallenge` from the init response provides `challengeId` and `challenge`.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeEmailVerifyDto"}}}},"responses":{"200":{"description":"Email updated successfully"},"400":{"description":"Invalid or expired token, email mismatch, or missing re-auth fields"}},"tags":["account"]}}},"components":{"schemas":{"ChangeEmailVerifyDto":{"type":"object","properties":{"token":{"type":"string","description":"Verification token from the change-email email link"},"email":{"type":"string","description":"New email address being verified (cross-verified against the token)"},"srpData":{"description":"SRP re-auth data — required when the account has an SRP keystore","allOf":[{"$ref":"#/components/schemas/ChangeEmailSrpDataDto"}]},"passkeyData":{"description":"Passkey re-auth data — required when the account has a passkey keystore","allOf":[{"$ref":"#/components/schemas/ChangeEmailPasskeyDataDto"}]}},"required":["token","email"]},"ChangeEmailSrpDataDto":{"type":"object","properties":{"newSrpVerifier":{"type":"string","description":"New SRP verifier recomputed as SRP(newEmail, currentPassword)"},"sessionId":{"type":"string","description":"SRP session ID from the init response"},"clientPublic":{"type":"string","description":"SRP client public ephemeral"},"clientProof":{"type":"string","description":"SRP client proof"}},"required":["newSrpVerifier","sessionId","clientPublic","clientProof"]},"ChangeEmailPasskeyDataDto":{"type":"object","properties":{"credentialId":{"type":"string","description":"Credential ID of the registered passkey"},"challengeId":{"type":"string","description":"Challenge ID from the init response"},"webauthnAssertion":{"description":"WebAuthn assertion from the passkey device","allOf":[{"$ref":"#/components/schemas/ChangeEmailWebAuthnAssertionDto"}]}},"required":["credentialId","challengeId","webauthnAssertion"]},"ChangeEmailWebAuthnAssertionDto":{"type":"object","properties":{"authenticatorData":{"type":"string","description":"Base64-encoded authenticator data"},"clientDataJson":{"type":"string","description":"Base64-encoded client data JSON"},"signature":{"type":"string","description":"Base64-encoded DER signature"}},"required":["authenticatorData","clientDataJson","signature"]}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.radfi.co/dev/api-endpoints/account.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
