API Reference

Connect RPC API — 10 services, 79 endpoints

Base URL: https://api.nexus-dev.xsyphon.comProtocol: Connect RPC

AgentService

12 endpoints

AgentService handles agent discovery, Mini App launch, and developer management of agents.

Discovery (any authenticated identity):

  • Users browse featured agents via ListFeaturedAgents.
  • Users view agent public profile via GetAgentInfo.

Mini App launch (user_only):

  • Users obtain signed initData to launch a Mini App via GetMiniAppLaunchData.

Developer management (user_only):

  • Developers create agents via CreateAgent.
  • Developers list their agents via ListMyAgents.
  • Developers view full agent profile via GetMyAgent.
  • Developers update agent config via SetAgentConfig.
  • Developers delete agents via DeleteMyAgent.
  • Developers regenerate agent token via RegenerateAgentToken.
  • Developers regenerate agent secret key via RegenerateAgentSecretKey.
  • Developers configure Mini App via SetAgentMiniApp.

Agent self-management:

  • Agents update their own config via UpdateAgentSelfConfig.

Relationship to other services:

  • Adding an agent creates a conversation (type = AGENT) visible in ConversationService.ListConversations.
  • Adding an agent to a group is handled by GroupService.AddAgent.

ListFeaturedAgents

ListFeaturedAgents returns a batch of recommended agents for the discovery page. No pagination; call again to get a different batch.

Request Body

api.v1.ListFeaturedAgentsRequest
limitrequired

Maximum results to return (default: 20, max: 50).

≥ 0≤ 50
int32

Response

api.v1.ListFeaturedAgentsResponse
agentsrequired array

Recommended agents.

POST/api.v1.AgentService/ListFeaturedAgents
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/ListFeaturedAgents \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "limit": 0
}'

GetAgentInfo

GetAgentInfo returns public profile info for a specific agent.

Error conditions:

  • NOT_FOUND: Agent does not exist or has been deleted.

Request Body

api.v1.GetAgentInfoRequest
agentUserIdrequired

Agent user ID.

> 0
int32

Response

api.v1.GetAgentInfoResponse
agentrequired

Agent public profile info.

POST/api.v1.AgentService/GetAgentInfo
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/GetAgentInfo \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0
}'

GetMiniAppLaunchData

User Only

GetMiniAppLaunchData generates signed initData for launching a Mini App.

Error conditions:

  • FAILED_PRECONDITION: Agent has not enabled Mini App.
  • PERMISSION_DENIED: User has no access to this agent or conversation_id mismatch.

Request Body

api.v1.GetMiniAppLaunchDataRequest
agentUserIdrequired

Target agent user ID.

> 0
int32
conversationIdrequired

Conversation ID (private chat or group chat). Zero means no conversation context.

int64
startParamrequired

Start parameter (from Direct Link or Card Action).

string
platformrequired

Client platform ("ios" / "android" / "desktop").

string

Response

api.v1.GetMiniAppLaunchDataResponse
initDatarequired

Signed initData query string.

string
miniAppUrlrequired

Mini App entry URL.

string
POST/api.v1.AgentService/GetMiniAppLaunchData
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/GetMiniAppLaunchData \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0,
  "conversationId": 0,
  "startParam": "string",
  "platform": "string"
}'

CreateAgent

User Only

CreateAgent creates a new agent on behalf of the authenticated user.

Side effects:

  • Establishes bidirectional contact relationship between developer and agent.
  • Auto-generates Agent Token and secret_key.

Error conditions:

  • ALREADY_EXISTS: Username is taken.
  • INVALID_ARGUMENT: Invalid username or name.

Request Body

api.v1.CreateAgentRequest
usernamerequired

Agent unique username.

len: 5..32
string
namerequired

Agent display name.

len: 1..64
string
signaturerequired

Agent signature / description.

len: 0..256
string

Response

api.v1.CreateAgentResponse
profilerequired

Full agent profile.

tokenrequiredsensitive

Generated API token (plaintext, returned only once).

string
secretKeyrequiredsensitive

Generated HMAC secret key (plaintext, returned only once).

string
POST/api.v1.AgentService/CreateAgent
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/CreateAgent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "username": "aaaaa",
  "name": "a",
  "signature": "string"
}'

ListMyAgents

User Only

ListMyAgents lists all agents created by the authenticated user.

Response

api.v1.ListMyAgentsResponse
agentsrequired array

Agent profiles (developer-visible details).

POST/api.v1.AgentService/ListMyAgents
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/ListMyAgents \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

GetMyAgent

User Only

GetMyAgent returns the full profile of an agent owned by the authenticated user.

Error conditions:

  • NOT_FOUND: Agent does not exist.
  • PERMISSION_DENIED: Caller is not the agent creator.

Request Body

api.v1.GetMyAgentRequest
agentUserIdrequired

Target agent user ID.

> 0
int32

Response

api.v1.GetMyAgentResponse
profilerequired

Agent profile (developer-visible fields, includes user info).

POST/api.v1.AgentService/GetMyAgent
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/GetMyAgent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0
}'

SetAgentConfig

User Only

SetAgentConfig updates configuration fields of an agent. Only provided fields are updated; omitted fields remain unchanged. When delivery_mode is set to WEBHOOK, webhook_url must also be provided.

Error conditions:

  • NOT_FOUND: Agent does not exist.
  • PERMISSION_DENIED: Caller is not the agent creator.
  • INVALID_ARGUMENT: Invalid field values or webhook URL.

Request Body

api.v1.SetAgentConfigRequest
agentUserIdrequired

Target agent user ID.

> 0
int32
visibility

Visibility setting.

ipWhitelistrequired array

IP whitelist (replaces existing). Pass empty list to clear.

max items: 50
string
commands

Slash commands (replaces existing, max 100). When set, replaces all commands; omit to leave commands unchanged.

deliveryMode

Event delivery mode.

webhookUrl

Webhook URL (required when delivery_mode is WEBHOOK, must be HTTPS).

len: 0..2048
string
POST/api.v1.AgentService/SetAgentConfig
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/SetAgentConfig \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0,
  "ipWhitelist": [
    "string"
  ]
}'

DeleteMyAgent

User Only

DeleteMyAgent permanently deletes an agent owned by the authenticated user.

Side effects:

  • Sets agent status to DELETED.
  • Removes the agent from all group memberships.
  • Existing conversations become read-only.

Error conditions:

  • NOT_FOUND: Agent does not exist.
  • PERMISSION_DENIED: Caller is not the agent creator.

Request Body

api.v1.DeleteMyAgentRequest
agentUserIdrequired

Target agent user ID.

> 0
int32
POST/api.v1.AgentService/DeleteMyAgent
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/DeleteMyAgent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0
}'

RegenerateAgentToken

User Only

RegenerateAgentToken regenerates the API token for an agent. The old token becomes invalid immediately.

Error conditions:

  • NOT_FOUND: Agent does not exist.
  • PERMISSION_DENIED: Caller is not the agent creator.

Request Body

api.v1.RegenerateAgentTokenRequest
agentUserIdrequired

Target agent user ID.

> 0
int32

Response

api.v1.RegenerateAgentTokenResponse
tokenrequiredsensitive

New API token (nxa_xxx format).

string
POST/api.v1.AgentService/RegenerateAgentToken
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/RegenerateAgentToken \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0
}'

RegenerateAgentSecretKey

User Only

RegenerateAgentSecretKey regenerates the HMAC secret key for an agent. The old key becomes invalid immediately.

Error conditions:

  • NOT_FOUND: Agent does not exist.
  • PERMISSION_DENIED: Caller is not the agent creator.

Request Body

api.v1.RegenerateAgentSecretKeyRequest
agentUserIdrequired

Target agent user ID.

> 0
int32

Response

api.v1.RegenerateAgentSecretKeyResponse
secretKeyrequiredsensitive

New HMAC secret key (plaintext).

string
POST/api.v1.AgentService/RegenerateAgentSecretKey
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/RegenerateAgentSecretKey \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0
}'

SetAgentMiniApp

User Only

SetAgentMiniApp configures the Mini App for an agent.

Error conditions:

  • NOT_FOUND: Agent does not exist.
  • PERMISSION_DENIED: Caller is not the agent creator.
  • INVALID_ARGUMENT: URL is not a valid HTTPS URL.

Request Body

api.v1.SetAgentMiniAppRequest
agentUserIdrequired

Target agent user ID.

> 0
int32
enabledrequired

Whether to enable Mini App.

bool
urlrequired

Mini App entry URL (must be HTTPS).

string
allowedOriginsrequired array

Allowed web origins for security validation.

string
permissionsrequired

Permission bitmask.

int32
POST/api.v1.AgentService/SetAgentMiniApp
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/SetAgentMiniApp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "agentUserId": 0,
  "enabled": false,
  "url": "string",
  "allowedOrigins": [
    "string"
  ],
  "permissions": 0
}'

UpdateAgentSelfConfig

Agent Only

UpdateAgentSelfConfig allows an authenticated agent to update its own configuration. The agent is identified by the caller's Bearer token; no agent_user_id field is required. Only agents may call this RPC.

Error conditions:

  • PERMISSION_DENIED: Caller is not an agent.
  • FAILED_PRECONDITION: Agent is not active.
  • INVALID_ARGUMENT: Invalid field values or webhook URL.

Request Body

api.v1.UpdateAgentSelfConfigRequest
commands

Slash commands (replaces existing, max 100). When set, replaces all commands; omit to leave commands unchanged.

deliveryMode

Event delivery mode.

webhookUrl

Webhook URL (required when delivery_mode is WEBHOOK, must be HTTPS).

len: 0..2048
string
POST/api.v1.AgentService/UpdateAgentSelfConfig
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AgentService/UpdateAgentSelfConfig \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

UserService

7 endpoints

UserService handles user profile, device sessions, and username resolution. Authenticated via Access Token (User or Agent).

GetProfile

GetProfile returns the current user profile.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.

Response

api.v1.GetProfileResponse
profilerequired

Current user profile.

POST/api.v1.UserService/GetProfile
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/GetProfile \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

UpdateProfile

UpdateProfile updates the current user profile fields.

Side effects:

  • If avatar_url changes, the old avatar is not deleted (clients may still cache it).
  • Delivers a UserProfileUpdatedEvent as an SnUpdate to the user's own update stream only (for multi-device sync). Contacts refresh cached profile data on demand.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • INVALID_ARGUMENT: Nickname exceeds 64 characters or signature exceeds 200 characters.

Request Body

api.v1.UpdateProfileRequest
nickname

New nickname (optional).

len: 0..64
string
signature

New signature (optional).

len: 0..200
string
avatarUrl

New avatar URL (optional).

len: 0..2048
string

Response

api.v1.UpdateProfileResponse
profilerequired

Updated user profile.

POST/api.v1.UserService/UpdateProfile
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/UpdateProfile \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

ListDevices

User Only

ListDevices returns all active device sessions.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.

Response

api.v1.ListDevicesResponse
devicesrequired array

Active device sessions.

POST/api.v1.UserService/ListDevices
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/ListDevices \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

RemoveDevice

User Only

RemoveDevice removes a specific device session.

Side effects:

  • Revokes the access and refresh tokens for the target device.
  • Closes the long connection for the target device if active.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • NOT_FOUND: Device does not exist or does not belong to the user.
  • INVALID_ARGUMENT: Cannot remove the current device (use Logout).

Request Body

api.v1.RemoveDeviceRequest
deviceIdrequired

Target device ID to remove.

len: 1..∞
string
POST/api.v1.UserService/RemoveDevice
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/RemoveDevice \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "deviceId": "a"
}'

SetUsername

User Only

SetUsername sets the username for the current user (first-time only).

Side effects:

  • Sets the username globally (unique constraint enforced).
  • The username becomes resolvable via ResolveUsername.
  • Delivers a UsernameChangedEvent as an SnUpdate to the user's own update stream only (multi-device sync).

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • FAILED_PRECONDITION: User already has a custom username set.
  • ALREADY_EXISTS: Username is already taken.
  • INVALID_ARGUMENT: Username does not match the required format (3-32 chars, lowercase alphanumeric and underscores only).

Request Body

api.v1.SetUsernameRequest
usernamerequired

Desired username (must be globally unique, 5-32 chars, lowercase alphanumeric and underscores only).

len: 5..32
string

Response

api.v1.SetUsernameResponse
profilerequired

Updated user profile with the new username.

POST/api.v1.UserService/SetUsername
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/SetUsername \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "username": "aaaaa"
}'

ResolveUsername

ResolveUsername resolves a username to public user info.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • NOT_FOUND: No user exists with this username.

Request Body

api.v1.ResolveUsernameRequest
usernamerequired

Username to resolve (without @ prefix).

len: 5..32
string

Response

api.v1.ResolveUsernameResponse
userrequired

Resolved user info.

isContactrequired

Whether the resolved user is already a contact of the current user.

bool
POST/api.v1.UserService/ResolveUsername
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/ResolveUsername \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "username": "aaaaa"
}'

BatchGetUserInfo

BatchGetUserInfo returns public user info for a batch of user IDs. Used by clients to populate user caches (e.g., conversation list, group member list, message sender info).

IDs that do not exist or belong to deleted accounts are silently omitted from the response (no error raised).

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • INVALID_ARGUMENT: user_ids is empty or exceeds 200 items.

Request Body

api.v1.BatchGetUserInfoRequest
userIdsrequired array

User IDs to look up. Max 200 items per request.

max items: 200
int32

Response

api.v1.BatchGetUserInfoResponse
usersrequired array

User info keyed by user_id. IDs not found are omitted.

POST/api.v1.UserService/BatchGetUserInfo
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.UserService/BatchGetUserInfo \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "userIds": [
    0
  ]
}'

AuthService

12 endpoints

AuthService handles authentication, token management, and password operations. Authenticated via Access Token (except where skip_auth is set).

RequestVerifyCode

User OnlyNo Auth

RequestVerifyCode sends a verification code to the given identity.

Side effects:

  • Generates a time-limited verification code and sends it via the appropriate channel (SMS for phone, email for email).
  • Creates a verification session referenced by verify_token.
  • Rate-limited: max 1 code per identity per 60 seconds.

Error conditions:

  • INVALID_ARGUMENT: Identity type or value is invalid.
  • RESOURCE_EXHAUSTED: Rate limit exceeded for this identity.

Request Body

api.v1.RequestVerifyCodeRequest
identityTyperequired

Identity type (email/phone).

identityValuerequired

Identity value (e.g. phone number or email address).

len: 1..255
string

Response

api.v1.RequestVerifyCodeResponse
verifyTokenrequiredsensitive

Opaque token to reference this verification session.

string
expiresInrequired

Token expiration in seconds.

int32
POST/api.v1.AuthService/RequestVerifyCode
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/RequestVerifyCode \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "identityType": 0,
  "identityValue": "a"
}'

VerifyCode

User OnlyNo Auth

VerifyCode validates the code and returns auth tokens.

Side effects:

  • If the identity is new, creates a user account (is_new_user=true).
  • Creates a device session and issues access + refresh tokens.
  • Invalidates the verification session (single-use).

Error conditions:

  • INVALID_ARGUMENT: Code is incorrect or verify_token is malformed.
  • NOT_FOUND: Verification session does not exist or has expired.
  • RESOURCE_EXHAUSTED: Too many failed attempts (max 5 per session).

Request Body

api.v1.VerifyCodeRequest
verifyTokenrequired

Verification session token.

len: 1..∞
string
coderequired

User-entered verification code.

len: 1..10
string
deviceInforequired

Client device information.

Response

api.v1.VerifyCodeResponse
userIdrequired

Authenticated user ID.

int32
deviceIdrequired

Device ID for this session.

string
isNewUserrequired

Whether this is a newly registered user.

bool
accessTokenrequiredsensitive

Access token.

string
refreshTokenrequiredsensitive

Refresh token for token renewal.

string
expiresInrequired

Access token expiration in seconds.

int32
user

User profile (present for new users).

POST/api.v1.AuthService/VerifyCode
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/VerifyCode \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "verifyToken": "a",
  "code": "a",
  "deviceInfo": {}
}'

LoginPassword

User OnlyNo Auth

LoginPassword authenticates with password credentials.

Side effects:

  • Creates a device session and issues access + refresh tokens.

Error conditions:

  • INVALID_ARGUMENT: Identity type or value is invalid.
  • NOT_FOUND: No account exists for this identity.
  • UNAUTHENTICATED: Password is incorrect.
  • RESOURCE_EXHAUSTED: Too many failed login attempts (account temporarily locked after 10 consecutive failures).

Request Body

api.v1.LoginPasswordRequest
identityTyperequired

Identity type (email/phone).

identityValuerequired

Identity value.

len: 1..255
string
passwordrequiredsensitive

User password.

len: 8..128
string
deviceInforequired

Client device information.

Response

api.v1.LoginPasswordResponse
userIdrequired

Authenticated user ID.

int32
deviceIdrequired

Device ID for this session.

string
accessTokenrequiredsensitive

Access token.

string
refreshTokenrequiredsensitive

Refresh token for token renewal.

string
expiresInrequired

Access token expiration in seconds.

int32
user

User profile.

POST/api.v1.AuthService/LoginPassword
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/LoginPassword \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "identityType": 0,
  "identityValue": "a",
  "password": "aaaaaaaa",
  "deviceInfo": {}
}'

RefreshToken

User OnlyNo Auth

RefreshToken exchanges a refresh token for a new access token.

Side effects:

  • Issues a new access token with a fresh expiration.

Error conditions:

  • UNAUTHENTICATED: Refresh token is invalid, expired, or revoked.

Request Body

api.v1.RefreshTokenRequest
refreshTokenrequiredsensitive

Current refresh token.

len: 1..∞
string

Response

api.v1.RefreshTokenResponse
accessTokenrequiredsensitive

New access token.

string
expiresInrequired

Access token expiration in seconds.

int32
refreshTokenrequiredsensitive

Rotated refresh token. The previous refresh token is invalidated.

string
POST/api.v1.AuthService/RefreshToken
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/RefreshToken \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "refreshToken": "a"
}'

Logout

User Only

Logout signs out the current device session.

Side effects:

  • Revokes the access and refresh tokens for the current device.
  • Closes the long connection for this device if active.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
POST/api.v1.AuthService/Logout
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/Logout \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

LogoutAll

User Only

LogoutAll signs out all device sessions for the user.

Side effects:

  • Revokes all access and refresh tokens across all devices.
  • Closes all active long connections for the user.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
POST/api.v1.AuthService/LogoutAll
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/LogoutAll \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

SetupPassword

User Only

SetupPassword sets a password for a passwordless account.

Side effects:

  • Stores the password securely for the user account.
  • Enables password-based login for this account.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • FAILED_PRECONDITION: Account already has a password set.
  • INVALID_ARGUMENT: Password does not meet complexity requirements.

Request Body

api.v1.SetupPasswordRequest
newPasswordrequiredsensitive

New password to set.

len: 8..128
string
POST/api.v1.AuthService/SetupPassword
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/SetupPassword \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "newPassword": "aaaaaaaa"
}'

ChangePassword

User Only

ChangePassword changes the current password.

Side effects:

  • Updates the stored password.
  • Revokes all other device sessions (forces re-login).

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • INVALID_ARGUMENT: New password does not meet complexity requirements.
  • UNAUTHENTICATED: Old password is incorrect.
  • FAILED_PRECONDITION: Account does not have a password set.

Request Body

api.v1.ChangePasswordRequest
oldPasswordrequiredsensitive

Current password for verification.

len: 8..128
string
newPasswordrequiredsensitive

New password to set.

len: 8..128
string
POST/api.v1.AuthService/ChangePassword
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/ChangePassword \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "oldPassword": "aaaaaaaa",
  "newPassword": "aaaaaaaa"
}'

ResetPasswordRequest

User OnlyNo Auth

ResetPasswordRequest initiates a password reset flow (step 1 of 2).

Sends a verification code to the identity and returns a verify_token. The client then calls ResetPasswordVerify to exchange the code for a one-time reset_token, and finally ResetPasswordConfirm to set the new password.

The verification code session is independent from RequestVerifyCode (login flow). They use separate sessions, so a login code cannot be used for password reset and vice versa.

Side effects:

  • Generates a verification code and sends it via SMS or email.
  • Creates a reset verification session referenced by verify_token.
  • Rate-limited: same limits as RequestVerifyCode per identity.

Error conditions:

  • INVALID_ARGUMENT: Identity type or value is invalid.
  • NOT_FOUND: No account exists for this identity.
  • RESOURCE_EXHAUSTED: Rate limit exceeded.

Request Body

api.v1.ResetPasswordRequestRequest
identityTyperequired

Identity type (email/phone).

identityValuerequired

Identity value.

len: 1..255
string

Response

api.v1.ResetPasswordRequestResponse
verifyTokenrequiredsensitive

Opaque token to reference this reset session.

string
expiresInrequired

Token expiration in seconds.

int32
POST/api.v1.AuthService/ResetPasswordRequest
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/ResetPasswordRequest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "identityType": 0,
  "identityValue": "a"
}'

ResetPasswordVerify

User OnlyNo Auth

ResetPasswordVerify validates the reset verification code (step 2 of 2a).

On success, returns a one-time reset_token (TTL 10 min) that the client uses in ResetPasswordConfirm.

Side effects:

  • Invalidates the verification session (single-use).
  • Issues a one-time reset_token (TTL 10 min).

Error conditions:

  • INVALID_ARGUMENT: Code is incorrect.
  • NOT_FOUND: Verification session does not exist or has expired.
  • RESOURCE_EXHAUSTED: Too many failed attempts (max 5 per session).

Request Body

api.v1.ResetPasswordVerifyRequest
verifyTokenrequired

Reset verification session token (from ResetPasswordRequestResponse).

len: 1..∞
string
coderequired

User-entered verification code.

len: 1..10
string

Response

api.v1.ResetPasswordVerifyResponse
resetTokenrequiredsensitive

One-time reset token (TTL 10 min). Use in ResetPasswordConfirm.

string
expiresInrequired

Reset token expiration in seconds.

int32
POST/api.v1.AuthService/ResetPasswordVerify
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/ResetPasswordVerify \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "verifyToken": "a",
  "code": "a"
}'

ResetPasswordConfirm

User OnlyNo Auth

ResetPasswordConfirm sets the new password using a reset_token (step 2 of 2b).

Side effects:

  • Updates the stored password.
  • Revokes all existing device sessions (forces re-login).
  • Invalidates the reset_token (single-use).

Error conditions:

  • INVALID_ARGUMENT: New password does not meet complexity requirements.
  • NOT_FOUND: reset_token does not exist, has expired, or was already used.

Request Body

api.v1.ResetPasswordConfirmRequest
resetTokenrequiredsensitive

One-time reset token (returned by ResetPasswordRequest after successful verification).

len: 1..∞
string
newPasswordrequiredsensitive

New password to set.

len: 8..128
string
POST/api.v1.AuthService/ResetPasswordConfirm
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/ResetPasswordConfirm \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "resetToken": "a",
  "newPassword": "aaaaaaaa"
}'

GetClientConfig

No Auth

GetClientConfig returns client-facing configuration such as gateway endpoints. Clients call this before login to discover service addresses.

Side effects: none.

Error conditions: none (always succeeds).

Response

api.v1.GetClientConfigResponse
gatewayrequired

Gateway connection endpoints.

loginrequired

Login method configuration.

POST/api.v1.AuthService/GetClientConfig
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.AuthService/GetClientConfig \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

ContactService

12 endpoints

ContactService handles friend requests, contact management, and blocklist. Authenticated via Access Token.

update stream integration: All state-changing operations in this service produce SnUpdate entries delivered to the relevant users' update stream. This ensures clients can reliably sync contact state changes via the SyncService.GetDifference mechanism.

See shared.v1 (in shared/v1/updates.proto) for the full list of contact-related event payloads.

SendFriendRequest

User Only

SendFriendRequest sends a friend request to a target user.

Side effects:

  • Creates a pending friend request record.
  • Delivers a FriendRequestReceivedEvent to the target user's update stream, containing the requester's info and greeting.
  • If the target user is online, the update is pushed in real-time via the long connection.

Error conditions:

  • ALREADY_EXISTS: A pending request already exists between the two users.
  • NOT_FOUND: Target user does not exist.
  • PERMISSION_DENIED: Either user has blocked the other.
  • FAILED_PRECONDITION: Users are already contacts.

Request Body

api.v1.SendFriendRequestRequest
targetUserIdrequired

Target user ID to send the friend request to.

> 0
int32
messagerequired

Optional greeting message (max 200 chars). Included in the FriendRequestReceivedEvent delivered to the target's update stream.

len: 0..200
string

Response

api.v1.SendFriendRequestResponse
requestIdrequired

Server-assigned friend request ID.

int64
POST/api.v1.ContactService/SendFriendRequest
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/SendFriendRequest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "targetUserId": 0,
  "message": "string"
}'

ListPendingRequests

ListPendingRequests lists pending incoming friend requests for the current user, ordered by creation time descending.

Request Body

api.v1.ListPendingRequestsRequest
beforeTime

Pagination anchor: only return requests created before this timestamp (Unix ms). Omit for the first page.

int64
limitrequired

Maximum number of items to return (default: 20, max: 100).

≥ 0≤ 100
int32

Response

api.v1.ListPendingRequestsResponse
itemsrequired array

Pending friend request items, ordered by created_at descending.

hasMorerequired

Whether there are more requests beyond this page.

bool
usersrequired array

Related user info referenced by the items (from_user_id values).

POST/api.v1.ContactService/ListPendingRequests
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/ListPendingRequests \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "limit": 0
}'

AcceptFriendRequest

User Only

AcceptFriendRequest accepts a pending friend request.

Side effects:

  • Updates the request status from PENDING to ACCEPTED.
  • Creates a mutual contact relationship between both users.
  • Delivers a FriendRequestAcceptedEvent to both parties' update stream, containing each other's brief info.
  • A PRIVATE conversation is created if one does not already exist.

Error conditions:

  • NOT_FOUND: Request does not exist.
  • FAILED_PRECONDITION: Request has already been handled (ACCEPTED/REJECTED).

Request Body

api.v1.AcceptFriendRequestRequest
requestIdrequired

Friend request ID to accept.

> 0
int64
POST/api.v1.ContactService/AcceptFriendRequest
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/AcceptFriendRequest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "requestId": 0
}'

RejectFriendRequest

User Only

RejectFriendRequest rejects a pending friend request.

Side effects:

  • Updates the request status from PENDING to REJECTED.
  • Delivers a FriendRequestRejectedEvent to the requester's update stream.

Error conditions:

  • NOT_FOUND: Request does not exist.
  • FAILED_PRECONDITION: Request has already been handled (ACCEPTED/REJECTED).

Request Body

api.v1.RejectFriendRequestRequest
requestIdrequired

Friend request ID to reject.

> 0
int64
POST/api.v1.ContactService/RejectFriendRequest
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/RejectFriendRequest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "requestId": 0
}'

AddContact

User Only

AddContact adds a contact without friend request approval. Currently supports adding public agents and private agents (creator only).

Side effects:

  • Creates bidirectional contact relationships.
  • Delivers a ContactAddedEvent SnUpdate to the caller's update stream (multi-device sync). Clients use this to create the local contact record and the PRIVATE conversation.
  • Delivers a contact.added webhook event to the agent.

Error conditions:

  • NOT_FOUND: Target user does not exist.
  • ALREADY_EXISTS: Contact relationship already exists.
  • PERMISSION_DENIED: Private agent, caller is not the creator.
  • FAILED_PRECONDITION: Target is a regular user (use SendFriendRequest).
  • FAILED_PRECONDITION: Agent status is not ACTIVE (error_code 7003).

Request Body

api.v1.AddContactRequest
targetUserIdrequired

Target user ID to add as contact.

> 0
int32
POST/api.v1.ContactService/AddContact
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/AddContact \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "targetUserId": 0
}'

ListContacts

ListContacts returns the current user's contact list.

Request Body

api.v1.ListContactsRequest
afterId

Pagination anchor: only return contacts with contact_user_id > after_id. Omit for the first page. Contacts are ordered by contact_user_id ascending.

int32
limitrequired

Maximum number of items to return (default: 50, max: 200).

≥ 0≤ 200
int32

Response

api.v1.ListContactsResponse
contactsrequired array

Contact items, ordered by contact_user_id ascending.

totalContactsrequired

Total number of contacts the user has (useful for UI display).

int32
hasMorerequired

Whether there are more contacts beyond this page.

bool
POST/api.v1.ContactService/ListContacts
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/ListContacts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "limit": 0
}'

DeleteContact

DeleteContact removes a contact from the current user's contact list. This is a single-sided operation: only the caller's contact record is removed. The other party's contact list is not affected.

Side effects:

  • Delivers a ContactDeletedEvent to the caller's own update stream (multi-device sync). The other party is not notified.
  • The private conversation is NOT deleted; it remains accessible but new messages cannot be sent until re-friended.

Error conditions:

  • NOT_FOUND: Contact relationship does not exist.

Request Body

api.v1.DeleteContactRequest
contactUserIdrequired

User ID of the contact to remove.

> 0
int32
POST/api.v1.ContactService/DeleteContact
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/DeleteContact \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "contactUserId": 0
}'

UpdateContactAlias

UpdateContactAlias sets or clears a custom alias for a contact. The alias overrides the contact's nickname in the current user's UI.

Side effects:

  • Delivers a ContactAliasUpdatedEvent to the caller's own update box (multi-device sync).

Request Body

api.v1.UpdateContactAliasRequest
contactUserIdrequired

User ID of the contact.

> 0
int32
alias

New alias. Set to empty or omit to clear the alias.

len: 0..64
string
POST/api.v1.ContactService/UpdateContactAlias
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/UpdateContactAlias \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "contactUserId": 0
}'

SearchUsers

SearchUsers searches for users and/or agents across the platform. Supports filtering by account type (USER, AGENT, or ALL).

For human users: exact match on phone, email, or username (returns at most 1 result). For agents: fuzzy match on nickname, username, and description (returns at most 10 results). Only PUBLIC + ACTIVE agents are returned.

Results exclude the current user and blocked users. No pagination — results are capped by design.

Request Body

api.v1.SearchUsersRequest
queryrequired

Search keyword (phone number, email, username, or agent name).

len: 1..255
string
accountTyperequired

Account type filter. Defaults to ALL if unset.

Response

api.v1.SearchUsersResponse
itemsrequired array

Matched users and/or agents. Does not include the current user or blocked users. UserInfo does not contain phone/email for privacy.

POST/api.v1.ContactService/SearchUsers
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/SearchUsers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "query": "a",
  "accountType": 0
}'

BlockUser

BlockUser blocks a user.

Side effects:

  • If the blocked user is a contact, the contact relationship is removed (equivalent to DeleteContact + block).
  • Delivers a UserBlockToggledEvent (is_blocked=true) to the blocker's own update stream (for multi-device sync). The blocked user is NOT notified.
  • Any pending friend requests between the two users are cancelled.
  • The blocked user can no longer send messages or friend requests to the blocker. The blocker also cannot send messages to the blocked user.

Error conditions:

  • ALREADY_EXISTS: User is already blocked.
  • NOT_FOUND: Target user does not exist.

Request Body

api.v1.BlockUserRequest
targetUserIdrequired

User ID to block.

> 0
int32
POST/api.v1.ContactService/BlockUser
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/BlockUser \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "targetUserId": 0
}'

UnblockUser

UnblockUser unblocks a previously blocked user.

Side effects:

  • Delivers a UserBlockToggledEvent (is_blocked=false) to the unblocker's own update stream (for multi-device sync). The unblocked user is NOT notified.
  • Unblocking does NOT restore the contact relationship; the user must send a new friend request.

Error conditions:

  • NOT_FOUND: User is not in the blocklist.

Request Body

api.v1.UnblockUserRequest
targetUserIdrequired

User ID to unblock.

> 0
int32
POST/api.v1.ContactService/UnblockUser
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/UnblockUser \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "targetUserId": 0
}'

ListBlocked

ListBlocked lists all blocked users for the current user.

Response

api.v1.ListBlockedResponse
blockedrequired array

Blocked user entries, ordered by blocked_at descending.

POST/api.v1.ContactService/ListBlocked
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ContactService/ListBlocked \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

ConversationService

4 endpoints

ConversationService handles conversation list retrieval, actions, and read-state management. Authenticated via Access Token.

Conversation lifecycle:

  • PRIVATE conversations are created implicitly when a friend request is accepted (via ContactService.AcceptFriendRequest), or when a user adds an agent as a contact (via ContactService.AddContact).
  • GROUP conversations are created via GroupService.CreateGroup.

Conversation list model:

  • Conversations are paginated by the `last_message_time` field descending.
  • Responses include related_users to avoid extra round-trips for rendering the conversation list UI.

GetConversation

GetConversation returns a single conversation detail by ID.

Clients should call this when they receive a message push for a conversation_id that is not in their local list (e.g., a previously deleted conversation that was auto-restored by the server).

Request Body

api.v1.GetConversationRequest
conversationIdrequired

Conversation ID.

> 0
int64

Response

api.v1.GetConversationResponse
conversationrequired

Conversation info.

POST/api.v1.ConversationService/GetConversation
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ConversationService/GetConversation \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0
}'

ListConversations

ListConversations returns conversations ordered by last_message_time descending, with cursor-based pagination.

This is also the entry point for reconnection sync: after authentication, clients pull the full conversation list, compare each conversation's last_message_id with their local value, and call MessageService.GetMessageHistory for conversations with a gap.

Note: Deleted conversations that have been auto-restored (due to a new incoming message) will appear in the results normally.

Request Body

api.v1.ListConversationsRequest
beforeTime

Pagination anchor: only return conversations with last_message_time < before_time. Omit for the first page.

int64
limitrequired

Maximum number of items to return (default: 20, max: 100).

≥ 0≤ 100
int32

Response

api.v1.ListConversationsResponse
conversationsrequired array

Conversations ordered by last_message_time descending.

relatedUsersrequired array

Related user info referenced by the conversations (private chat peers, message senders).

relatedGroupsrequired array

Related group info referenced by GROUP-type conversations.

messagesrequired array

Latest message for each conversation. One entry per conversation that has at least one message (keyed by conversation_id in the envelope). Clients use this to render the last message preview in the conversation list.

hasMorerequired

Whether there are more conversations beyond this page.

bool
POST/api.v1.ConversationService/ListConversations
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ConversationService/ListConversations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "limit": 0
}'

UpdateConversationAction

UpdateConversationAction performs a unified conversation action.

Supported actions:

  • MUTE: Mute conversation notifications.
  • UNMUTE: Restore conversation notifications.
  • DELETE: Soft-delete the conversation from the user's list.

Access control:

  • Permission is checked against the underlying relationship (contact for PRIVATE, group membership for GROUP).
  • If no per-user conversation state exists yet, it is created automatically.

DELETE behavior:

  • Sets is_deleted flag for the current user only (per-user soft-delete).
  • If clear_messages is true, also clears the user's local message history for this conversation (server-side per-user clear).
  • The conversation is automatically restored (is_deleted cleared) when a new message arrives in the conversation. There is no explicit RESTORE action; restoration is implicit and server-driven.
  • Online clients: receive the new message via long-connection push and should re-add the conversation to their list.
  • Offline clients: the next ListConversations call naturally returns the restored conversation since is_deleted has been cleared.
  • If a client receives a message for an unknown conversation_id, it should call GetConversation to fetch the full conversation info.

Side effects:

  • Delivers a ConversationActionEvent to the current user's update stream for multi-device sync. Other devices consume this event to keep conversation list state consistent.

Request Body

api.v1.UpdateConversationActionRequest
conversationIdrequired

Target conversation ID.

> 0
int64
actionrequired

Action to perform.

clearMessagesrequired

Whether to clear the user's message history for this conversation. Only used when action = DELETE. Defaults to false (keep history).

bool
POST/api.v1.ConversationService/UpdateConversationAction
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ConversationService/UpdateConversationAction \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "action": 0,
  "clearMessages": false
}'

MarkAsRead

MarkAsRead updates the current user's read position in a conversation.

Access control:

  • Same as UpdateConversationAction: checks underlying relationship, auto-creates per-user conversation state if needed.

Side effects:

  • Updates last_read_message_id in the conversation membership.
  • Produces a ReadReceiptEvent SnUpdate to the caller's own update stream (multi-device sync only; the peer is not notified).
  • The server does NOT maintain unread_count. Clients calculate it locally: unread = last_message_id - last_read_message_id.

Request Body

api.v1.MarkAsReadRequest
conversationIdrequired

Conversation ID.

> 0
int64
upToMessageIdrequired

Mark all messages up to and including this message ID as read. Must be >= current last_read_message_id (cannot go backwards).

> 0
int64
POST/api.v1.ConversationService/MarkAsRead
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.ConversationService/MarkAsRead \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "upToMessageId": 0
}'

GroupService

10 endpoints

GroupService handles group lifecycle, membership, and settings. Authenticated via Access Token.

Group lifecycle:

  • CreateGroup creates a GROUP conversation and adds the creator as owner.
  • DissolveGroup permanently removes the group (owner only).

System message integration: All state-changing operations produce GroupContent system messages delivered to the group conversation. See shared/v1/group_event.proto for the full list of event payloads:

  • Member changes: MemberJoinedEvent, MemberLeftEvent, MemberRemovedEvent.
  • Setting changes: GroupInfoChangedEvent.

CreateGroup

User Only

CreateGroup creates a new group conversation.

Side effects:

  • Creates a GROUP conversation and adds the creator as owner.
  • Delivers a single MemberJoinedEvent containing all initial members.

Error conditions:

  • INVALID_ARGUMENT: Name is empty or fewer than 2 member_ids.
  • FAILED_PRECONDITION: After filtering invalid/blocked users, total members (including creator) are fewer than 3.
  • RESOURCE_EXHAUSTED: Total members (including creator) exceed the group member limit (200).

Request Body

api.v1.CreateGroupRequest
namerequired

Group display name.

len: 1..64
string
avatarUrlrequired

Group avatar URL. Empty string uses system default avatar.

len: 0..2048
string
memberIdsrequired array

Initial member user IDs to invite (excluding the creator who is added automatically). At least 2 members required (group minimum is 3 including the creator). Max group size is 200 including the creator.

max items: 199
int32
descriptionrequired

Group description (optional).

len: 0..500
string

Response

api.v1.CreateGroupResponse
grouprequired

Created group details.

POST/api.v1.GroupService/CreateGroup
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/CreateGroup \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "name": "a",
  "avatarUrl": "string",
  "memberIds": [
    0
  ],
  "description": "string"
}'

DissolveGroup

User Only

DissolveGroup permanently dissolves a group.

Side effects:

  • Marks the group as DISSOLVED; no further messages can be sent.
  • Removes all members from the group.
  • Delivers GroupDissolvedEvent SnUpdate to every member's update stream.

Error conditions:

  • NOT_FOUND: Group does not exist.
  • FAILED_PRECONDITION: Group is already dissolved.
  • PERMISSION_DENIED: Caller is not the group owner.

Request Body

api.v1.DissolveGroupRequest
groupIdrequired

Group ID.

> 0
int32
POST/api.v1.GroupService/DissolveGroup
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/DissolveGroup \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0
}'

UpdateGroupName

User Only

UpdateGroupName updates the group display name.

Side effects:

  • Delivers GroupInfoChangedEvent (field="name") to the group conversation.

Error conditions:

  • NOT_FOUND: Group does not exist.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is not the owner.
  • INVALID_ARGUMENT: Name is empty.

Request Body

api.v1.UpdateGroupNameRequest
groupIdrequired

Group ID.

> 0
int32
namerequired

New group name.

len: 1..64
string
POST/api.v1.GroupService/UpdateGroupName
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/UpdateGroupName \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0,
  "name": "a"
}'

UpdateGroupAvatar

User Only

UpdateGroupAvatar updates the group avatar.

Side effects:

  • Delivers GroupInfoChangedEvent (field="avatar") to the group conversation.

Error conditions:

  • NOT_FOUND: Group does not exist.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is not the owner.

Request Body

api.v1.UpdateGroupAvatarRequest
groupIdrequired

Group ID.

> 0
int32
avatarUrlrequired

New avatar URL.

len: 0..2048
string
POST/api.v1.GroupService/UpdateGroupAvatar
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/UpdateGroupAvatar \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0,
  "avatarUrl": "string"
}'

UpdateGroupDescription

User Only

UpdateGroupDescription updates the group description.

Side effects:

  • Delivers GroupInfoChangedEvent (field="description") to the group conversation.

Error conditions:

  • NOT_FOUND: Group does not exist.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is not the owner.

Request Body

api.v1.UpdateGroupDescriptionRequest
groupIdrequired

Group ID.

> 0
int32
descriptionrequired

New group description.

len: 0..500
string
POST/api.v1.GroupService/UpdateGroupDescription
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/UpdateGroupDescription \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0,
  "description": "string"
}'

InviteMembers

User Only

InviteMembers invites one or more users or agents to join the group. The server auto-detects member type (user vs agent) by account_type.

Side effects:

  • Adds the invited members to the group.
  • Delivers a single MemberJoinedEvent containing all newly added members.

Error conditions:

  • NOT_FOUND: Group does not exist.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is not the owner.
  • RESOURCE_EXHAUSTED: Adding these members would exceed the group member limit or agent limit.

Skipped silently (no error):

  • User IDs that do not exist.
  • Users who have blocked the inviter (or vice versa).
  • Users/agents who are already group members.
  • Agents that are not active.

Request Body

api.v1.InviteMembersRequest
groupIdrequired

Group ID.

> 0
int32
memberIdsrequired array

User IDs to invite (can include both users and agents). Server enforces max group size and max agent count.

max items: 99
int32
POST/api.v1.GroupService/InviteMembers
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/InviteMembers \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0,
  "memberIds": [
    0
  ]
}'

RemoveMember

User Only

RemoveMember removes a member (user or agent) from the group (owner only).

Side effects:

  • Removes the target from the group.
  • Delivers MemberRemovedEvent to the group conversation.
  • Delivers RemovedFromGroupEvent SnUpdate to the removed member's update stream.

Error conditions:

  • NOT_FOUND: Group does not exist, or target is not a member.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is not the owner.
  • INVALID_ARGUMENT: Cannot remove the group owner.

Request Body

api.v1.RemoveMemberRequest
groupIdrequired

Group ID.

> 0
int32
targetIdrequired

Target member user ID (can be a user or agent).

> 0
int32
POST/api.v1.GroupService/RemoveMember
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/RemoveMember \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0,
  "targetId": 0
}'

LeaveGroup

LeaveGroup allows a member to voluntarily leave the group. The group owner cannot leave; use DissolveGroup instead.

Side effects:

  • Removes the caller from the group.
  • Delivers MemberLeftEvent to the group conversation.

Error conditions:

  • NOT_FOUND: Group does not exist, or caller is not a member.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is the group owner (must dissolve instead).

Request Body

api.v1.LeaveGroupRequest
groupIdrequired

Group ID.

> 0
int32
POST/api.v1.GroupService/LeaveGroup
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/LeaveGroup \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0
}'

GetGroupInfo

GetGroupInfo returns group details with all members and their user info.

Error conditions:

  • NOT_FOUND: Group does not exist.
  • FAILED_PRECONDITION: Group is dissolved.
  • PERMISSION_DENIED: Caller is not a member of the group.

Request Body

api.v1.GetGroupInfoRequest
groupIdrequired

Group ID.

> 0
int32

Response

api.v1.GetGroupInfoResponse
grouprequired

Group detail info.

membersrequired array

All group members (lightweight: user_id + role + joined_at).

usersrequired array

User info for all members, keyed by user_id. Clients join members[i].user_id with this list for display.

POST/api.v1.GroupService/GetGroupInfo
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/GetGroupInfo \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "groupId": 0
}'

ListGroups

ListGroups returns the current user's joined groups with cursor-based pagination.

Request Body

api.v1.ListGroupsRequest
afterId

Pagination anchor: only return groups with group_id > after_id. Omit for the first page.

int32
limitrequired

Maximum number of items to return (default: 50, max: 200).

≥ 0≤ 200
int32

Response

api.v1.ListGroupsResponse
groupsrequired array

Joined group info items.

hasMorerequired

Whether there are more groups beyond this page.

bool
POST/api.v1.GroupService/ListGroups
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.GroupService/ListGroups \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "limit": 0
}'

MediaService

5 endpoints

MediaService handles file upload and download for all media types. Authenticated via Access Token.

Upload strategies:

  • Small files (avatars, thumbnails): use UploadFile for single-request upload. Returns a permanent public URL for AVATAR/GROUP_AVATAR purpose.
  • Large files (message attachments): use InitUpload → UploadChunk → CompleteUpload for resumable chunked upload. Returns a file_id; clients obtain time-limited download URLs via GetDownloadURL.

Access control:

  • AVATAR / GROUP_AVATAR files are publicly accessible via permanent URL. No download RPC needed.
  • MESSAGE files are private. GetDownloadURL issues a time-limited signed URL.

UploadFile

UploadFile uploads a complete file in a single request. Suitable for avatars and small media (recommended < 5 MB).

Side effects:

  • Stores the file and generates metadata (dimensions, checksum).
  • For AVATAR/GROUP_AVATAR purpose, generates a permanent public URL in MediaFileInfo.public_url.
  • For MESSAGE purpose, generates a thumbnail if applicable.

Error conditions:

  • INVALID_ARGUMENT: File is empty, content_type is missing, or purpose is UNSPECIFIED.
  • RESOURCE_EXHAUSTED: File exceeds the size limit for single upload (5 MB). Use chunked upload instead.

Request Body

api.v1.UploadFileRequest
fileNamerequired

Original file name.

len: 1..255
string
contentTyperequired

MIME content type.

len: 1..255
string
purposerequired

Intended usage (determines storage visibility).

datarequiredsensitive

File binary data.

bytes

Response

api.v1.UploadFileResponse
filerequired

Uploaded file metadata. For AVATAR/GROUP_AVATAR, public_url is populated. For MESSAGE, use file_id with GetDownloadURL.

POST/api.v1.MediaService/UploadFile
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MediaService/UploadFile \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "fileName": "a",
  "contentType": "a",
  "purpose": {},
  "data": ""
}'

InitUpload

InitUpload initializes a resumable chunked upload session. Only for MESSAGE purpose files (attachments, videos, etc.).

Side effects:

  • Creates an upload session with a TTL (default 24 hours).

Error conditions:

  • INVALID_ARGUMENT: File name, content_type, or size is missing.
  • RESOURCE_EXHAUSTED: File size exceeds the maximum allowed (100 MB).

Request Body

api.v1.InitUploadRequest
fileNamerequired

Original file name.

len: 1..255
string
contentTyperequired

MIME content type.

len: 1..255
string
sizerequired

Total file size in bytes.

> 0≤ 104857600
int64

Response

api.v1.InitUploadResponse
sessionIdrequired

Upload session ID.

string
uploadedrequired

Bytes already uploaded (non-zero when resuming a previous session).

int64
createdAtrequired

Session creation time (Unix ms).

int64
POST/api.v1.MediaService/InitUpload
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MediaService/InitUpload \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "fileName": "a",
  "contentType": "a",
  "size": 0
}'

UploadChunk

UploadChunk uploads a file chunk to an active session.

Error conditions:

  • NOT_FOUND: Session does not exist or has expired.
  • INVALID_ARGUMENT: Offset does not match the expected position.
  • RESOURCE_EXHAUSTED: Chunk would exceed the declared file size.

Request Body

api.v1.UploadChunkRequest
sessionIdrequired

Upload session ID.

len: 1..∞
string
chunkrequiredsensitive

Chunk binary data.

bytes
offsetrequired

Byte offset of this chunk.

≥ 0
int64
POST/api.v1.MediaService/UploadChunk
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MediaService/UploadChunk \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "sessionId": "a",
  "chunk": "",
  "offset": 0
}'

CompleteUpload

CompleteUpload finalizes the chunked upload and returns file metadata.

Side effects:

  • Validates checksum integrity and generates metadata (dimensions, thumbnail).
  • Deletes the upload session.

Error conditions:

  • NOT_FOUND: Session does not exist or has expired.
  • FAILED_PRECONDITION: Uploaded bytes do not match declared size.

Request Body

api.v1.CompleteUploadRequest
sessionIdrequired

Upload session ID.

len: 1..∞
string

Response

api.v1.CompleteUploadResponse
filerequired

Uploaded file metadata.

POST/api.v1.MediaService/CompleteUpload
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MediaService/CompleteUpload \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "sessionId": "a"
}'

GetDownloadURL

GetDownloadURL returns a time-limited signed download URL for a private (MESSAGE purpose) file.

Access control: file_id is not enumerable, which provides sufficient protection against unauthorized access. No conversation membership check is performed.

Error conditions:

  • NOT_FOUND: File does not exist.

Request Body

api.v1.GetDownloadURLRequest
fileIdrequired

File ID to download.

len: 1..∞
string

Response

api.v1.GetDownloadURLResponse
urlrequired

Signed download URL (expires in 1 hour).

string
expiresAtrequired

URL expiration time (Unix ms).

int64
POST/api.v1.MediaService/GetDownloadURL
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MediaService/GetDownloadURL \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "fileId": "a"
}'

MessageService

12 endpoints

MessageService handles message sending, editing, deletion, recall, forwarding, and history retrieval. Authenticated via Access Token.

All message operations are performed via Connect RPC (HTTP). The long connection (WebSocket) is used exclusively for server-side push delivery (new messages, status updates, etc.).

SendMessage

SendMessage sends a message to a conversation.

Side effects:

  • Persists the message and assigns a server message_id.
  • Pushes an Update to all online conversation participants via their long connections.
  • Triggers offline push notifications for offline participants.
  • Updates the conversation's last_message_time and last_message_id.

Error conditions:

  • NOT_FOUND: Conversation does not exist.
  • PERMISSION_DENIED: User is not a member of the conversation, or the conversation is muted for this user (group mute).
  • FAILED_PRECONDITION: Conversation is a PRIVATE chat where the contact relationship has been removed.

Request Body

api.v1.SendMessageRequest
clientMessageIdrequired

Client-generated message ID (for idempotency and dedup).

> 0
int64
conversationIdrequired

Target conversation ID.

> 0
int64
bodyrequired

Message body.

replyToMessageId

Message ID to reply to (optional).

int64

Response

api.v1.SendMessageResponse
messageIdrequired

Server-assigned message ID.

int64
createdAtrequired

Message creation time (Unix ms).

int64
POST/api.v1.MessageService/SendMessage
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/SendMessage \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "clientMessageId": 0,
  "conversationId": 0,
  "body": {}
}'

EditMessage

EditMessage edits a previously sent message.

Side effects:

  • Updates the message content and sets updated_at timestamp.
  • Pushes an Update with the edited message to all online conversation participants.
  • Triggers webhook delivery for agent members.

Error conditions:

  • NOT_FOUND: Message does not exist.
  • PERMISSION_DENIED: User is not the message sender.
  • FAILED_PRECONDITION: Message has been recalled.
  • FAILED_PRECONDITION: Message was sent more than 24 hours ago.
  • INVALID_ARGUMENT: new_body.type differs from the original message type (type changes are not allowed).

Request Body

api.v1.EditMessageRequest
conversationIdrequired

Conversation ID.

> 0
int64
messageIdrequired

Message ID to edit.

> 0
int64
newBodyrequired

New message body.

Response

api.v1.EditMessageResponse
updatedAtrequired

Last content modification time (Unix ms).

int64
POST/api.v1.MessageService/EditMessage
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/EditMessage \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0,
  "newBody": {}
}'

DeleteMessages

DeleteMessages deletes messages by ID list for the current user only (local delete). Other participants are not affected.

Side effects:

  • Marks the specified messages as deleted for the current user.
  • Deleted messages are excluded from future GetMessageHistory responses for this user.
  • Delivers a MessageDeletedEvent to the caller's own update stream (multi-device sync).

Error conditions:

  • NOT_FOUND: Conversation does not exist.
  • PERMISSION_DENIED: User is not a member of the conversation.

Request Body

api.v1.DeleteMessagesRequest
conversationIdrequired

Conversation ID.

> 0
int64
messageIdsrequired array

Message IDs to delete.

max items: 200
int64

Response

api.v1.DeleteMessagesResponse
deletedCountrequired

Number of messages actually deleted.

int32
POST/api.v1.MessageService/DeleteMessages
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/DeleteMessages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageIds": [
    0
  ]
}'

DeleteHistory

DeleteHistory deletes all messages up to a given message ID for the current user only (local delete).

Side effects:

  • Marks all messages with message_id <= up_to_message_id as deleted for the current user.
  • Delivers a MessageDeletedEvent to the caller's own update stream (multi-device sync).

Error conditions:

  • NOT_FOUND: Conversation does not exist.
  • PERMISSION_DENIED: User is not a member of the conversation.

Request Body

api.v1.DeleteHistoryRequest
conversationIdrequired

Conversation ID.

> 0
int64
upToMessageIdrequired

Delete up to and including this message ID.

> 0
int64
POST/api.v1.MessageService/DeleteHistory
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/DeleteHistory \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "upToMessageId": 0
}'

RecallMessage

RecallMessage recalls a sent message (visible to all participants). The original message content is replaced with a MessageRecalledContent message in the conversation timeline.

Side effects:

  • Replaces the message body with RecalledContent (body.type becomes MESSAGE_TYPE_RECALLED).
  • Pushes an Update with the recalled message to all online conversation participants.
  • Triggers webhook delivery for agent members.

Error conditions:

  • NOT_FOUND: Message does not exist.
  • PERMISSION_DENIED: User is not the message sender.
  • FAILED_PRECONDITION: Message was sent more than 24 hours ago.
  • FAILED_PRECONDITION: Message is already recalled.

Request Body

api.v1.RecallMessageRequest
conversationIdrequired

Conversation ID.

> 0
int64
messageIdrequired

Message ID to recall.

> 0
int64
POST/api.v1.MessageService/RecallMessage
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/RecallMessage \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0
}'

GetMessage

GetMessage returns a single message by ID.

Error conditions:

  • NOT_FOUND: Message does not exist or has been deleted by this user.
  • PERMISSION_DENIED: User is not a member of the conversation.

Request Body

api.v1.GetMessageRequest
conversationIdrequired

Conversation ID.

> 0
int64
messageIdrequired

Message ID.

> 0
int64

Response

api.v1.GetMessageResponse
messagerequired

Message envelope.

POST/api.v1.MessageService/GetMessage
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/GetMessage \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0
}'

GetMessageHistory

GetMessageHistory returns message history with ID-based cursor pagination. Supports both backward (older) and forward (newer) pagination directions.

Pagination:

  • Backward (load older): set before_message_id. Returns messages with message_id < before_message_id, ordered descending. When has_more=true, use the smallest message_id in the response as the next before_message_id.
  • Forward (incremental pull): set after_message_id. Returns messages with message_id > after_message_id, ordered ascending. When has_more=true, use the largest message_id in the response as the next after_message_id.
  • Omit both for the latest messages (equivalent to backward from the conversation's last_message_id).

Error conditions:

  • NOT_FOUND: Conversation does not exist.
  • PERMISSION_DENIED: User is not a member of the conversation.

Request Body

api.v1.GetMessageHistoryRequest
conversationIdrequired

Conversation ID.

> 0
int64
beforeMessageId

Backward cursor: return messages with message_id < this value. When has_more=true, use the smallest message_id from the response.

int64
afterMessageId

Forward cursor: return messages with message_id > this value. When has_more=true, use the largest message_id from the response.

int64
limitrequired

Maximum number of messages to return (default: 50, max: 200).

≥ 0≤ 200
int32

Response

api.v1.GetMessageHistoryResponse
messagesrequired array

Messages in the requested range.

hasMorerequired

Whether there are more messages beyond this page.

bool
relatedUsersrequired array

Related user info referenced by the messages in this page. Contains UserInfo for each distinct sender_id (and reply_to.sender_id) appearing in the messages. Clients should merge these into their local users_cache for rendering sender names and avatars.

POST/api.v1.MessageService/GetMessageHistory
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/GetMessageHistory \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "limit": 0
}'

SubmitCardAction

SubmitCardAction reports an Adaptive Card Action.Submit to the server. The server forwards the action data to the agent that sent the card message.

Side effects:

  • Delivers a CardActionPayload event to the agent via webhook.
  • The agent may respond via AnswerCardAction (toast/alert) and optionally update the card via EditMessage.

Error conditions:

  • NOT_FOUND: Message does not exist.
  • PERMISSION_DENIED: User is not a member of the conversation.
  • FAILED_PRECONDITION: Message is not a CARD type message.

Request Body

api.v1.SubmitCardActionRequest
conversationIdrequired

Conversation ID containing the card message.

> 0
int64
messageIdrequired

Message ID of the card message.

> 0
int64
actionDatarequired

Action data from Action.Submit (JSON string, ≤ 4 KB). Contains the form input values and any static data defined in the Action.Submit's data property.

len: 1..4096
string
verbrequired

Action verb identifier (optional). Maps to the Action.Submit's "id" or custom "verb" property, allowing agents to distinguish between multiple submit actions on the same card.

len: 0..128
string

Response

api.v1.SubmitCardActionResponse
actionIdrequired

Server-assigned action ID.

string
POST/api.v1.MessageService/SubmitCardAction
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/SubmitCardAction \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0,
  "actionData": "a",
  "verb": "string"
}'

PushStreamDelta

Agent Only

PushStreamDelta pushes an incremental delta to a streaming message.

Error conditions:

  • NOT_FOUND: Streaming message does not exist.
  • FAILED_PRECONDITION: Stream has already ended or errored.

Request Body

api.v1.PushStreamDeltaRequest
conversationIdrequired

Conversation ID containing the streaming message.

> 0
int64
messageIdrequired

Message ID of the streaming message (from SendMessageResponse).

> 0
int64
seqrequired

Stream sequence number (agent-side auto-increment, starting from 1). Server uses this for dedup and gap detection.

> 0
int32
deltarequired

Incremental text fragment.

len: 1..∞
string
POST/api.v1.MessageService/PushStreamDelta
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/PushStreamDelta \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0,
  "seq": 0,
  "delta": "a"
}'

EndStream

Agent Only

EndStream finalizes a streaming message with the accumulated content.

Side effects:

  • Persists the final accumulated text as the message content.
  • Pushes StreamContent(phase=END) to online participants.

Error conditions:

  • NOT_FOUND: Streaming message does not exist.
  • FAILED_PRECONDITION: Stream has already ended or errored.

Request Body

api.v1.EndStreamRequest
conversationIdrequired

Conversation ID containing the streaming message.

> 0
int64
messageIdrequired

Message ID of the streaming message.

> 0
int64
accumulatedTextrequired

Final accumulated text content.

string
entitiesrequired array

Rich text entities for the accumulated text (@mentions, URLs, etc.).

POST/api.v1.MessageService/EndStream
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/EndStream \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0,
  "accumulatedText": "string",
  "entities": [
    {}
  ]
}'

ErrorStream

Agent Only

ErrorStream terminates a streaming message with an error.

Side effects:

  • Persists the error state and partial content.
  • Pushes StreamContent(phase=ERROR) to online participants.

Error conditions:

  • NOT_FOUND: Streaming message does not exist.
  • FAILED_PRECONDITION: Stream has already ended or errored.

Request Body

api.v1.ErrorStreamRequest
conversationIdrequired

Conversation ID containing the streaming message.

> 0
int64
messageIdrequired

Message ID of the streaming message.

> 0
int64
errorMessagerequired

Error message.

len: 1..1000
string
POST/api.v1.MessageService/ErrorStream
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/ErrorStream \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0,
  "errorMessage": "a"
}'

AnswerCardAction

Agent Only

AnswerCardAction responds to a card action submission.

Error conditions:

  • NOT_FOUND: Card action does not exist or has expired.

Request Body

api.v1.AnswerCardActionRequest
conversationIdrequired

Conversation ID where the card action was submitted.

> 0
int64
messageIdrequired

Card message ID that the action belongs to.

> 0
int64
actionIdrequired

Action ID from the webhook event (unique within conversation).

len: 1..∞
string
text

Response text to display.

len: 0..200
string
showAlertrequired

Whether to show as alert dialog (otherwise toast).

bool
POST/api.v1.MessageService/AnswerCardAction
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.MessageService/AnswerCardAction \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "conversationId": 0,
  "messageId": 0,
  "actionId": "a",
  "showAlert": false
}'

PushService

3 endpoints

PushService handles push notification token registration and removal. Authenticated via Access Token.

RegisterToken

User Only

RegisterToken registers a push notification token for the current device.

Side effects:

  • Stores the push token associated with the device and user.
  • If a token already exists for this device, it is replaced.
  • The device becomes eligible for push notifications.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • INVALID_ARGUMENT: Token is empty or platform is UNSPECIFIED.

Request Body

api.v1.RegisterTokenRequest
deviceIdrequired

Device ID.

len: 1..∞
string
tokenrequired

Push token string.

len: 1..∞
string
platformrequired

Push notification platform.

isSandboxrequired

Whether this is a sandbox environment token (APNs sandbox).

bool
POST/api.v1.PushService/RegisterToken
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.PushService/RegisterToken \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "deviceId": "a",
  "token": "a",
  "platform": {},
  "isSandbox": false
}'

UnregisterToken

User Only

UnregisterToken removes the push token for a device.

Side effects:

  • Deletes the push token for the specified device.
  • The device stops receiving push notifications.

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
  • NOT_FOUND: No push token registered for this device.

Request Body

api.v1.UnregisterTokenRequest
deviceIdrequired

Device ID.

len: 1..∞
string
POST/api.v1.PushService/UnregisterToken
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.PushService/UnregisterToken \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "deviceId": "a"
}'

ClearBadge

User Only

ClearBadge clears the push notification badge count for the user.

Side effects:

  • iOS: Sends a silent push with badge=0 to clear the app icon badge.
  • Android: No server-side action needed (client clears locally).

Error conditions:

  • UNAUTHENTICATED: Invalid or expired access token.
POST/api.v1.PushService/ClearBadge
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.PushService/ClearBadge \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

SyncService

2 endpoints

SyncService provides incremental state synchronization for clients. Clients maintain a local sequence number (sn) and use these RPCs to retrieve updates that occurred after their last known state. Authenticated via Access Token.

GetDifference

User Only

GetDifference returns updates since the client's last known sn. Clients call this on reconnect or when a gap is detected in the pushed update stream.

Request Body

api.v1.GetDifferenceRequest
snrequired

The client's last known sync number.

int32

Response

api.v1.GetDifferenceResponse
updatesrequired array

Ordered list of updates since the requested sn.

snrequired

The new sn after applying all returned updates.

int32
hasMorerequired

Whether more updates remain on the server. If true, the client should call GetDifference again with the returned sn.

bool
updateTooLongrequired

Whether the gap is too large for incremental sync. If true, the client should discard local state and perform a full resync.

bool
POST/api.v1.SyncService/GetDifference
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.SyncService/GetDifference \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
  "sn": 0
}'

GetCurrentState

User Only

GetCurrentState returns the server's latest sn. Used during the initial sync flow so the client can establish a baseline before fetching full state via other RPCs.

Response

api.v1.GetCurrentStateResponse
staterequired

The server's current sync state for this user.

POST/api.v1.SyncService/GetCurrentState
curl -X POST https://api.nexus-dev.xsyphon.com/api.v1.SyncService/GetCurrentState \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{}'

Schemas

Message types and enumerations used across the API

UserInfo

shared.v1.UserInfo

UserInfo is the public view of a user, used across list rendering and profile pages. Combines identity and display fields into a single reusable structure.

Online status is NOT included in this structure.

userIdrequired

User ID.

int32
usernamerequired

Username (globally unique public identifier).

string
nicknamerequired

Display nickname.

string
avatarUrlrequired

Avatar URL.

string
accountTyperequired

Account type: user or agent.

signaturerequired

Signature / bio.

string

PushTokenInfo

shared.v1.PushTokenInfo

PushTokenInfo defines structured push token information.

tokenrequired

Push token string.

len: 1..∞
string
platformrequired

Push notification platform.

isSandboxrequired

Whether this is a sandbox environment token.

bool

AgentCommandInfo

shared.v1.AgentCommandInfo

AgentCommandInfo represents a registered agent slash command.

commandrequired

Command name (e.g. "/help").

len: 1..32
string
descriptionrequired

Command description.

len: 1..256
string

AgentCommandList

shared.v1.AgentCommandList

AgentCommandList is a wrapper for serializing a list of commands as a single protobuf message.

itemsrequired array

Registered commands.

AgentInfo

shared.v1.AgentInfo

AgentInfo is the public profile view of an agent, visible to all users.

userrequired

Agent user info (user_id, username, nickname, avatar_url, account_type). The signature field in UserInfo serves as the agent description.

creatorrequired

Agent creator info.

statusrequired

Agent status (active/deleted).

visibilityrequired

Agent visibility (public/private).

isSystemAgentrequired

Whether this is a system agent (e.g. AgentRoot).

bool
commandsrequired array

Registered slash commands.

miniAppEnabledrequired

Whether Mini App is enabled for this agent.

bool
miniAppUrlrequired

Mini App entry URL (HTTPS).

string
miniAppPermissionsrequired

Mini App permission bitmask.

int32
createdAtrequired

Agent creation time (Unix ms).

int64

AgentProfile

shared.v1.AgentProfile

AgentProfile is the developer-facing full detail of an agent's profile.

userrequired

Agent user info (user_id, username, nickname, avatar_url, account_type, signature).

statusrequired

Agent status.

visibilityrequired

Agent visibility.

isSystemAgentrequired

Whether this is a system agent.

bool
deliveryModerequired

Agent event delivery mode.

tokenPrefixrequired

Agent token prefix (e.g. "nxa_xxxx") for identification.

string
secretKeyPrefixrequired

Secret key prefix for identification (e.g. "abcd1234...").

string
ipWhitelistrequired array

Allowed IP addresses for API access.

string
commandsrequired array

Registered slash commands.

miniAppEnabledrequired

Whether Mini App is enabled.

bool
miniAppUrlrequired

Mini App entry URL.

string
miniAppAllowedOriginsrequired array

Allowed web origins for Mini App security validation.

string
miniAppPermissionsrequired

Mini App permission bitmask.

int32
createdAtrequired

Agent creation time (Unix ms).

int64
updatedAtrequired

Agent last update time (Unix ms).

int64

User

api.v1.User

User represents the current user profile (self view, includes private fields). Online status is NOT included and not exposed to clients.

userIdrequired

User unique ID.

int32
usernamerequired

Username (globally unique public identifier, used for QR code and permanent link).

string
phone

Phone number (private).

string
email

Email address (private).

string
nicknamerequired

Display nickname.

string
avatarUrlrequired

Avatar URL.

string
signaturerequired

Signature.

string
hasPasswordrequired

Whether a password has been set.

bool
createdAtrequired

Account creation time (Unix ms).

int64
canChangeUsernamerequired

Whether the user can change their username. Server evaluates the change policy (e.g., first-time only, once per year) and returns a simple boolean so clients do not need to know the rules.

bool

Device

api.v1.Device

Device represents an active device session.

deviceIdrequired

Device unique ID (client-generated, persisted).

string
deviceTyperequired

Device type.

deviceNamerequired

Device name.

string
deviceModelrequired

Device model.

string
osVersionrequired

OS version.

string
appVersionrequired

App version.

string
loginIprequired

Login IP address.

string
loginAtrequired

Login time (Unix ms).

int64
lastActiveAtrequired

Last active time (Unix ms).

int64
isCurrentrequired

Whether this is the current device.

bool

UsersEntry

api.v1.BatchGetUserInfoResponse.UsersEntry
keyrequired
int32
valuerequired

DeviceInput

api.v1.DeviceInput

DeviceInput is the client-reported device info submitted during authentication.

deviceIdrequired

Device unique ID (client-generated, persisted).

len: 1..128
string
deviceTyperequired

Device type.

deviceNamerequired

Device name.

len: 0..128
string
deviceModelrequired

Device model.

len: 0..128
string
osVersionrequired

OS version.

len: 0..64
string
appVersionrequired

App version.

len: 0..64
string
pushToken

Structured push token (token, platform, sandbox flag).

LoginConfig

api.v1.LoginConfig

LoginConfig describes which login methods are enabled on this server.

emailEnabledrequired

Whether email-based login (verify code + password) is enabled.

bool
phoneEnabledrequired

Whether phone-based login (verify code + password) is enabled.

bool

GatewayEndpoints

api.v1.GatewayEndpoints

GatewayEndpoints contains the addresses clients use to connect to the gateway.

wsUrlrequired

WebSocket endpoint, e.g. "ws://host:8444/ws".

string

PendingRequestItem

shared.v1.PendingRequestItem

PendingRequestItem represents a friend request record. Used in events (FriendRequestReceivedEvent, FriendRequestAcceptedEvent) and in ListPendingRequestsResponse. User info is provided separately via related_users (in Update push) or a sibling users field (in RPC responses).

requestIdrequired

Friend request ID (server-assigned, auto-increment).

int64
fromUserIdrequired

User ID of the requester.

int32
toUserIdrequired

User ID of the target.

int32
messagerequired

Message attached to the friend request.

string
createdAtrequired

Request creation time (Unix ms).

int64

ContactItem

shared.v1.ContactItem

ContactItem represents a single contact entry in a user's or agent's contact list. For users, a contact is created when a friend request is accepted. For agents, a contact is created when a user adds the agent.

userrequired

Contact user info (user_id, username, nickname, avatar_url, account_type).

alias

Custom alias set by current user. Overrides nickname in UI when present. Only applicable for user contacts, always absent for agent contacts.

string
createdAtrequired

Contact creation time (Unix ms).

int64

BlockedUserItem

api.v1.BlockedUserItem

BlockedUserItem represents a blocked user entry. When a user is blocked:

  • Neither party can send messages or friend requests to the other.
  • If the two users are contacts, the contact relationship is removed.
  • Existing conversations are hidden but not deleted.
  • A UserBlockToggledEvent is delivered to the blocker's update stream.
userrequired

Blocked user info.

blockedAtrequired

Time when the user was blocked (Unix ms).

int64

ConversationInfo

shared.v1.ConversationInfo

ConversationInfo represents a conversation entry in a user's or agent's conversation list. Covers private and group conversation types.

Sync model: Each conversation maintains an independent message_id sequence. Clients compare their local last_message_id with the server's value to determine whether incremental message fetching is needed.

Unread count: The server does NOT return unread_count. Clients calculate it locally: unread = last_message_id - last_read_message_id

conversationIdrequired

Conversation ID (deterministic encoding, not auto-increment).

  • PRIVATE: int64(max(a,b)) << 32 | int64(min(a,b))
  • GROUP: int64(group_id)
int64
typerequired

Conversation type (PRIVATE, GROUP).

isMutedrequired

Whether notifications are muted for this conversation.

bool
lastMessageTimerequired

Timestamp of the last message (Unix ms). Only updated when a new message arrives, NOT when a message is deleted or edited. Also used as the sort key for conversation list ordering.

int64
lastMessageIdrequired

Last message ID in this conversation (for incremental sync). Clients compare this with their local max message_id to determine whether to pull new messages. Also used for client-side unread calculation: unread = last_message_id - last_read_message_id

int64
lastReadMessageIdrequired

Current user's last read message ID (read position).

int64
peerIdrequired

Peer ID. For PRIVATE conversations this is the other user's ID (including agents). For GROUP conversations this is the group_id.

int32

GroupInfo

shared.v1.GroupInfo

GroupInfo is the shared group detail structure.

groupIdrequired

Group ID. The group conversation_id equals int64(group_id).

int32
namerequired

Group display name.

string
avatarUrlrequired

Group avatar URL.

string
descriptionrequired

Group description text.

string
createdAtrequired

Group creation time (Unix ms).

int64
ownerIdrequired

Group owner user ID.

int32
statusrequired

Group lifecycle status (normal, dissolved, etc.).

MemberInfo

shared.v1.MemberInfo

MemberInfo represents a group member (lightweight). User details (nickname, avatar, etc.) are provided separately via the users list in GetGroupInfoResponse or related_users in push events.

userIdrequired

Member user ID.

int32
rolerequired

Member role (owner/member).

joinedAtrequired

Time when the member joined (Unix ms).

int64

GroupContent

shared.v1.GroupContent

GroupContent carries structured group event data as the body of a system message (MessageType = GROUP) delivered to a GROUP conversation. Each event type has its own strongly-typed payload.

The oneof field implicitly identifies the event type, so no separate enum is needed. Clients and agents switch on the oneof case to handle the appropriate in-chat system notification.

groupIdrequired

Group ID this event belongs to.

int32
oneof event
memberJoined

Members joined the group (user or agent).

memberLeft

A member voluntarily left the group.

memberRemoved

A member was removed from the group by the owner.

groupInfoChanged

Group metadata was changed (name, avatar, description, etc.).

MemberJoinedEvent

shared.v1.MemberJoinedEvent

MemberJoinedEvent is produced when members (users or agents) join a group. Supports batch joins: group creation and multi-invite produce a single event containing all member info, so clients render one "A, B, C joined" message instead of multiple individual messages. Delivered as a system message to the group conversation.

membersrequired array

Members who joined in this batch.

inviterrequired

The inviter who added these members (absent for group creation).

MemberLeftEvent

shared.v1.MemberLeftEvent

MemberLeftEvent is produced when a member voluntarily leaves a group. Delivered as a system message to the group conversation.

memberrequired

The member who left.

MemberRemovedEvent

shared.v1.MemberRemovedEvent

MemberRemovedEvent is produced when a member (user or agent) is removed by the group owner.

Delivery:

  • GROUP conversation: visible to all remaining members.
  • Removed member: receives a RemovedFromGroupEvent SnUpdate.
memberrequired

The member who was removed.

operatorrequired

The owner who performed the removal.

GroupInfoChangedEvent

shared.v1.GroupInfoChangedEvent

GroupInfoChangedEvent is produced when group metadata is updated (name, avatar, description, or other settings). Delivered as a system message to the group conversation. Clients obtain the latest values from related_groups in the push event.

operatorrequired

The operator who made the change.

fieldrequired

Changed field identifier (e.g. "name", "avatar", "description").

string

MessageEntity

shared.v1.MessageEntity

MessageEntity represents a rich text annotation using offset + length.

typerequired

Entity type.

offsetrequired

Start offset in characters.

int32
lengthrequired

Length in characters.

int32
oneof data
mention

@mention entity.

url

URL link entity.

phone

Phone number entity.

hashtag

Hashtag entity.

MentionEntity

shared.v1.MentionEntity

MentionEntity carries @mention data.

userIdrequired

Mentioned user ID.

int32
isAllrequired

Whether this is an @all (mention everyone).

bool

UrlEntity

shared.v1.UrlEntity

UrlEntity carries URL link data.

urlrequired

URL address.

string
displayText

Display text override (optional).

string

PhoneEntity

shared.v1.PhoneEntity

PhoneEntity carries phone number data.

phoneNumberrequired

Phone number.

string

HashtagEntity

shared.v1.HashtagEntity

HashtagEntity carries hashtag data.

tagrequired

Tag content (without # prefix).

string

MessageBody

shared.v1.MessageBody

MessageBody carries the message type and polymorphic content. All message content variants are included, enabling both users and agents to receive and parse every message type.

typerequired

Message type discriminator.

oneof content
text

Plain text content.

image

Image content.

audio

Audio/voice content.

video

Video content.

file

File attachment content.

markdown

Markdown formatted content.

card

Interactive card content.

stream

Streaming content.

group

Group event content (delivered to group conversations).

recalled

Message recalled notification content.

RecalledContent
customPayload

Custom binary payload for extensibility.

bytes

TextContent

shared.v1.TextContent

TextContent carries plain text message data.

textrequired

Text content.

len: 1..10000
string
entitiesrequired array

Rich text entities (@mentions, URLs, phone numbers, etc.).

ImageContent

shared.v1.ImageContent

ImageContent carries image message data.

fileIdrequired

Original image file ID.

len: 1..∞
string
thumbnailFileIdrequired

Thumbnail file ID.

string
widthrequired

Image width in pixels.

int32
heightrequired

Image height in pixels.

int32
sizeBytesrequired

File size in bytes.

int64
formatrequired

Image format (jpg/png/gif/webp).

string

AudioContent

shared.v1.AudioContent

AudioContent carries audio/voice message data.

fileIdrequired

Audio file ID.

len: 1..∞
string
durationMsrequired

Audio duration in milliseconds.

≥ 0
int32
sizeBytesrequired

File size in bytes.

int64
transcript

Speech-to-text transcript (optional).

string

VideoContent

shared.v1.VideoContent

VideoContent carries video message data.

fileIdrequired

Video file ID.

len: 1..∞
string
thumbnailFileIdrequired

Video thumbnail file ID.

string
durationMsrequired

Video duration in milliseconds.

int32
widthrequired

Video width in pixels.

int32
heightrequired

Video height in pixels.

int32
sizeBytesrequired

File size in bytes.

int64

FileContent

shared.v1.FileContent

FileContent carries file attachment message data.

fileIdrequired

File ID.

len: 1..∞
string
filenamerequired

File name.

len: 1..255
string
sizeBytesrequired

File size in bytes.

int64
mimeTyperequired

MIME type.

string
checksumSha256

SHA256 checksum (optional).

string

MarkdownContent

shared.v1.MarkdownContent

MarkdownContent carries markdown formatted message data.

rawMarkdownrequired

Raw markdown text (rendered by client).

len: 1..20000
string
entitiesrequired array

Extracted entities (@mentions, URLs, etc.).

CardContent

shared.v1.CardContent

CardContent carries an Adaptive Card message payload. The card_json field contains a valid Adaptive Card JSON conforming to https://adaptivecards.io/schemas/adaptive-card.json

Server validates JSON syntax and enforces a 50 KB size limit, but does NOT validate against the Adaptive Card schema. Rendering is entirely the client's responsibility.

Interaction:

  • Action.OpenUrl: handled client-side (open browser/webview).
  • Action.Submit: client sends SubmitCardAction RPC with the action's data payload, which is forwarded to the agent.
  • Action.ShowCard / Action.ToggleVisibility: handled client-side.
cardJsonrequired

Adaptive Card JSON payload. Must be valid JSON and ≤ 50 KB.

len: 2..51200
string
fallbackTextrequired

Plain text fallback for clients that cannot render Adaptive Cards.

len: 0..1000
string

StreamContent

shared.v1.StreamContent

StreamContent carries streaming message data (e.g. agent real-time generation). Delivered via Update push on the long connection.

The stream is uniquely identified by message_id (assigned when the agent calls SendMessage with type=STREAM). Each delta carries a seq number for dedup and ordering.

Lifecycle: 1. START: A new streaming message is created (message_id assigned), StreamContent with phase=START is pushed. No text content yet. 2. DELTA: Incremental text fragments are pushed via Update. Deltas are ephemeral push-only payloads. 3. END: The final accumulated text is committed and phase=END is pushed with the complete content. 4. ERROR: Generation failed; the error state is committed.

Recovery after disconnect / app restart: Clients must track locally which stream messages have not reached a terminal phase (END or ERROR). On reconnect, call MessageService.GetMessage for each incomplete stream. The returned StreamContent reflects the current server-side state:

  • phase=END + accumulated_text: generation finished while offline.
  • phase=ERROR: generation failed.
  • phase=DELTA: still generating; client resumes receiving deltas from the long connection. Use accumulated_text as the baseline and append subsequent deltas.
phaserequired

Current lifecycle phase.

seqrequired

Delta sequence number (agent-side auto-increment, starting from 1). Used for dedup and ordering. Only meaningful in DELTA phase pushes; 0 for START/END/ERROR.

int32
deltarequired

Incremental text fragment. Only meaningful in DELTA pushes.

string
contentTyperequired

Content MIME type (e.g. "text/plain", "text/markdown").

string
accumulatedTextrequired

Accumulated full text up to this point. Populated in: Empty in real-time DELTA pushes (clients accumulate locally).

  • END phase: the complete final content.
  • ERROR phase: partial content generated before the error.
  • HTTP query (GetMessage): current accumulated content regardless of phase, enabling clients to recover after disconnect.
string
entitiesrequired array

Rich text entities (@mentions, URLs, etc.) for the accumulated text. Only populated in END phase and HTTP query responses. Empty in START, DELTA, and ERROR phases.

errorMessagerequired

Error description. Only populated in ERROR phase.

string

ReplyContext

shared.v1.ReplyContext

ReplyContext defines the context of a replied message.

messageIdrequired

Replied message ID.

int64
senderIdrequired

Replied message sender ID.

int32
senderNicknamerequired

Replied message sender nickname.

string
contentPreviewrequired

Content preview of the replied message (first 100 chars).

string

MessageEnvelope

shared.v1.MessageEnvelope

MessageEnvelope is the unified message representation.

messageIdrequired

Message ID (auto-increment within conversation).

int64
conversationIdrequired

Conversation ID.

int64
senderIdrequired

Sender ID (user_id or agent_user_id). For group event messages (GROUP), sender_id is 0. For recalled messages, sender_id remains the original sender.

int32
bodyrequired

Message body.

replyTo

Reply context (quoted message reference).

metadatarequired array

Extensible metadata key-value pairs.

createdAtrequired

Message creation time (Unix ms).

int64
updatedAt

Last content modification time (Unix ms). Set on edit or recall.

int64
editedrequired

Whether the message has been edited. Not set for recalls.

bool
clientMessageIdrequired

Client-generated message ID for idempotency and dedup. Echoed from SendMessageRequest.client_message_id. Zero for system-generated messages (greetings, group events).

int64

MetadataEntry

shared.v1.MessageEnvelope.MetadataEntry
keyrequired
string
valuerequired
string

ErrorDetail

shared.v1.ErrorDetail

ErrorDetail is the standard error payload attached to connect.Error details. It is the sole mechanism for clients to identify and handle errors.

errorCoderequired

Numeric business error code. Client uses this for programmatic handling.

int32
errorNamerequired

Error name (readable identifier, e.g. "INVALID_TOKEN"). For logging.

string
metadatarequired array

Optional metadata (e.g. retry_after, attempts_remaining).

MetadataEntry

shared.v1.ErrorDetail.MetadataEntry
keyrequired
string
valuerequired
string

SnUpdate

shared.v1.SnUpdate

SnUpdate is a sequenced update delivered to a user's update stream. Each update carries a monotonically increasing sn. Clients detect gaps by comparing received sn with local_sn + 1.

snrequired

Sequence number in the user's update stream.

int32
oneof update
messageEnvelope

New or edited message.

friendRequestReceived

A friend request was received.

friendRequestAccepted

A friend request was accepted.

friendRequestRejected

A friend request was rejected.

contactDeleted

A contact was deleted (unfriended).

userBlockToggled

A user was blocked or unblocked.

userProfileUpdated

A user's profile was updated.

conversationAction

A conversation action was performed (mute, unmute, delete).

readReceipt

A read receipt update for multi-device sync.

agentStatusChanged

An agent's status changed (deleted).

friendRequestSent

A friend request was sent by the current user (multi-device sync).

contactAliasUpdated

A contact alias was updated (multi-device sync).

usernameChanged

A username was changed.

removedFromGroup

A member (user or agent) was removed from a group by the owner.

groupDissolved

Field 15 was KickedFromGroupEvent (removed, unified into RemovedFromGroupEvent). A group was dissolved by its owner.

messageDeleted

Messages were deleted locally (multi-device sync).

contactAdded

A contact was added directly (agent via AddContact).

NonSnUpdate

shared.v1.NonSnUpdate

NonSnUpdate is a non-sequenced, ephemeral update pushed in real time. Clients and agents do not track sn for these. Used for:

  • Stream DELTA (real-time text generation push)
  • CardActionAnswer (agent's toast/alert response to a card action)
  • CardActionPayload (user's card action submission, delivered to agent)
oneof update
messageEnvelope

Streaming message delta (real-time push only).

cardActionAnswer

Card action answer (toast/alert from agent, ephemeral).

cardAction

Card action submission from a user (delivered to agent, ephemeral).

CardActionAnswer

shared.v1.CardActionAnswer

CardActionAnswer carries the agent's response to a card action. Pushed as NonSnUpdate to the user who submitted the action.

actionIdrequired

Server-assigned action ID (matches CardActionPayload.action_id).

string
conversationIdrequired

Conversation where the card action was submitted.

int64
messageIdrequired

Card message ID that the action belongs to.

int64
agentUserIdrequired

Agent user ID that produced this answer.

int32
textrequired

Response text to display.

string
showAlertrequired

Whether to show as alert dialog (true) or toast (false).

bool

CardActionPayload

shared.v1.CardActionPayload

CardActionPayload contains an Adaptive Card Action.Submit event. Pushed as NonSnUpdate to the agent that owns the card. This is an ephemeral event — not sequenced and not persisted.

actionIdrequired

Server-assigned action ID (use in AnswerCardAction).

string
conversationIdrequired

Conversation ID.

int64
messageIdrequired

Card message ID.

int64
senderIdrequired

User who submitted the action.

int32
actionDatarequired

Action data (JSON string from Action.Submit).

string
verbrequired

Action verb identifier.

string

UpdateState

shared.v1.UpdateState

UpdateState holds the server's current sync state for a user.

latestSnrequired

The latest sn in the user's update stream.

int32

FriendRequestReceivedEvent

shared.v1.FriendRequestReceivedEvent

FriendRequestReceivedEvent is produced when a friend request is sent. Delivered as an SnUpdate to the target user's update stream. User info for from_user_id is provided via related_users in the Update wrapper.

requestrequired

The friend request details.

FriendRequestAcceptedEvent

shared.v1.FriendRequestAcceptedEvent

FriendRequestAcceptedEvent is produced when a friend request is accepted. Delivered as an SnUpdate to both parties' update stream. User info for the peer is provided via related_users in the Update wrapper.

requestrequired

The original friend request details.

FriendRequestRejectedEvent

shared.v1.FriendRequestRejectedEvent

FriendRequestRejectedEvent is produced when a friend request is rejected. Delivered as an SnUpdate to both parties' update stream.

requestIdrequired

Friend request ID.

int64
rejectorIdrequired

User ID of the rejector.

int32

FriendRequestSentEvent

shared.v1.FriendRequestSentEvent

FriendRequestSentEvent is produced when the current user sends a friend request. Delivered to the sender's own update stream (multi-device sync).

requestIdrequired

Friend request ID.

int64
targetUserIdrequired

Target user ID.

int32

ContactAliasUpdatedEvent

shared.v1.ContactAliasUpdatedEvent

ContactAliasUpdatedEvent is produced when a contact alias is changed. Delivered as an SnUpdate to the caller's own update stream only (multi-device sync).

contactUserIdrequired

Contact user ID whose alias was changed.

int32
newAliasrequired

New alias value. Empty means alias was cleared.

string

UsernameChangedEvent

shared.v1.UsernameChangedEvent

UsernameChangedEvent is produced when a user sets their username. Delivered as an SnUpdate to the user's own update stream only (multi-device sync). Contacts learn the new username on demand.

userIdrequired

User ID whose username changed.

int32
newUsernamerequired

New username.

string

ContactDeletedEvent

shared.v1.ContactDeletedEvent

ContactDeletedEvent is produced when a contact is removed. Single-sided: delivered as an SnUpdate to the caller's own update stream only (multi-device sync). The other party is NOT notified.

peerUserIdrequired

User ID of the removed contact.

int32

ContactAddedEvent

shared.v1.ContactAddedEvent

ContactAddedEvent is produced when a user adds an agent as a contact via AddContact. Delivered to the caller's own update stream (multi-device sync).

peerUserIdrequired

User ID of the added agent.

int32

UserBlockToggledEvent

shared.v1.UserBlockToggledEvent

UserBlockToggledEvent is produced when a user blocks or unblocks another. Delivered as an SnUpdate to the operator's own update stream only (for multi-device sync). The target user is NOT notified.

targetUserIdrequired

User ID of the target user.

int32
isBlockedrequired

True if blocked, false if unblocked.

bool

UserProfileUpdatedEvent

shared.v1.UserProfileUpdatedEvent

UserProfileUpdatedEvent is produced when a user updates their profile. Delivered as an SnUpdate to the user's own update stream only (multi-device sync). Contacts refresh cached profile data on demand.

userIdrequired

User ID whose profile was updated.

int32
newNickname

Changed fields and their new values. Only changed fields are included.

string
newAvatarUrl

New avatar URL (present only if avatar was changed).

string
newSignature

New signature (present only if signature was changed).

string

ConversationActionEvent

shared.v1.ConversationActionEvent

ConversationActionEvent is produced when a user performs a conversation management action (mute, unmute, delete). Delivered as an SnUpdate to the operator's own update stream only (for multi-device sync). Other participants are NOT notified.

conversationIdrequired

Target conversation ID.

int64
actionrequired

Action that was performed (MUTE, UNMUTE, DELETE).

clearMessagesrequired

Whether message history was cleared. Only present when action = DELETE.

bool

MessageDeletedEvent

shared.v1.MessageDeletedEvent

MessageDeletedEvent is produced when a user deletes messages locally (DeleteMessages or DeleteHistory). Delivered as an SnUpdate to the operator's own update stream only (for multi-device sync). Other participants are NOT notified.

conversationIdrequired

Target conversation ID.

int64
messageIdsrequired array

Deleted message IDs. Empty when up_to_message_id is set.

int64
upToMessageIdrequired

Delete all messages up to and including this ID. Zero when message_ids is set.

int64

ReadReceiptEvent

shared.v1.ReadReceiptEvent

ReadReceiptEvent is produced when a user marks messages as read. Delivered as an SnUpdate to the reader's own update stream only (for multi-device sync). The peer is NOT notified.

conversationIdrequired

Conversation ID where messages were read.

int64
readerUserIdrequired

User ID of the reader.

int32
lastReadMessageIdrequired

Read up to this message ID (inclusive).

int64
readAtrequired

Timestamp when the read occurred (Unix ms).

int64

RemovedFromGroupEvent

shared.v1.RemovedFromGroupEvent

RemovedFromGroupEvent is delivered as an SnUpdate to the removed member's (user or agent) update stream when they are removed from a group by the owner. Unified event for both user kicks and agent removals.

groupIdrequired

Group ID the member was removed from.

int32
operatorIdrequired

User ID of the operator who performed the removal.

int32

GroupDissolvedEvent

shared.v1.GroupDissolvedEvent

GroupDissolvedEvent is produced when the group owner dissolves the group. Delivered as an SnUpdate to every member's update stream.

operatorIdrequired

User ID of the owner who dissolved the group.

int32
groupIdrequired

Group ID that was dissolved.

int32

AgentStatusChangedEvent

shared.v1.AgentStatusChangedEvent

AgentStatusChangedEvent is produced when an agent is deleted by its developer. Delivered as an SnUpdate to all users who have added this agent as a contact.

agentUserIdrequired

Agent user ID.

int32
newStatusrequired

New agent status.

ClientFrame

api.v1.ClientFrame

ClientFrame is the transport-agnostic upstream envelope used by both users and agents. The long connection is a push-only channel — clients send only authentication and heartbeat frames upstream. All business requests go through Connect RPC (HTTP).

requestIdrequired

Client-generated correlation ID. The server echoes this ID in the corresponding ServerFrame response so the client can match them.

int64
typerequired

Frame type discriminator.

oneof payload
authRequest

Connection authentication. Server responds with ServerFrame.auth_response. Users send nxs_-prefixed tokens; agents send nxa_-prefixed tokens.

heartbeatPing

Heartbeat ping. Server responds with ServerFrame.heartbeat_pong.

HeartbeatPing

ServerFrame

api.v1.ServerFrame

ServerFrame is the transport-agnostic downstream envelope used by both users and agents. Every message sent by the server on the long connection is wrapped in a ServerFrame.

For response frames (auth_response, heartbeat_pong), the request_id matches the originating ClientFrame.request_id. For push frames (update, error), the server generates a unique request_id.

requestIdrequired

Correlation ID. Echoed from ClientFrame.request_id for responses, server-generated for pushes.

int64
typerequired

Frame type discriminator.

oneof payload
authResponse

Authentication result. Response to ClientFrame.auth_request.

update

Update push (SnUpdate or NonSnUpdate with related entity info).

heartbeatPong

Heartbeat pong. Response to ClientFrame.heartbeat_ping.

error

Error response or connection-level error push.

Update

api.v1.Update

Update wraps an SnUpdate or NonSnUpdate with related entity info for client-side rendering without extra lookups.

usersrequired array

Related user info referenced by the update (sender, peer, operator, etc.).

groupsrequired array

Related group info referenced by the update (for group events).

oneof update
snUpdate

Sequenced update.

nonSnUpdate

Non-sequenced update (ephemeral, e.g. stream deltas, card actions).

HeartbeatPong

api.v1.HeartbeatPong

HeartbeatPong is the server response to a HeartbeatPing.

serverTimerequired

Server timestamp (Unix ms). Clients can use this for clock drift estimation.

int64

GatewayErrorFrame

api.v1.GatewayErrorFrame

GatewayErrorFrame carries connection-level error information.

errorrequired

Structured error detail with error_code and error_name.

fatalrequired

Whether the client should close the connection after this error.

bool

MediaFileInfo

shared.v1.MediaFileInfo

MediaFileInfo contains file metadata returned after upload completion.

fileIdrequired

Unique file ID.

string
fileNamerequired

Original file name.

string
contentTyperequired

MIME content type.

string
sizerequired

File size in bytes.

int64
checksumrequired

File checksum (SHA256).

string
widthrequired

Image/video width in pixels (0 if not applicable).

int32
heightrequired

Image/video height in pixels (0 if not applicable).

int32
durationMsrequired

Audio/video duration in milliseconds (0 if not applicable).

int64
thumbnailFileIdrequired

Thumbnail file ID (empty if not generated).

string
publicUrlrequired

Permanent public URL. Only populated when purpose is AVATAR or GROUP_AVATAR. Empty for MESSAGE purpose files.

string

AccountType

shared.v1.AccountType

AccountType distinguishes human users from agent accounts.

ValueNumberDescription
ACCOUNT_TYPE_UNSPECIFIED0Unspecified.
ACCOUNT_TYPE_USER1Human user.
ACCOUNT_TYPE_AGENT2Agent.

DeviceType

shared.v1.DeviceType

DeviceType defines client device platforms.

ValueNumberDescription
DEVICE_TYPE_UNSPECIFIED0Unspecified.
DEVICE_TYPE_IOS1iOS device.
DEVICE_TYPE_ANDROID2Android device.
DEVICE_TYPE_WEB3Web browser.
DEVICE_TYPE_DESKTOP4Desktop application.
DEVICE_TYPE_CLI5CLI / TUI terminal client.

PushPlatform

shared.v1.PushPlatform

PushPlatform defines push notification platforms. Only APNs and FCM are supported in the current version. Desktop clients (Tauri) rely on the in-app long connection.

ValueNumberDescription
PUSH_PLATFORM_UNSPECIFIED0Unspecified.
PUSH_PLATFORM_APNS1Apple Push Notification service.
PUSH_PLATFORM_FCM2Firebase Cloud Messaging.

AgentStatus

shared.v1.AgentStatus

AgentStatus defines agent lifecycle states.

ValueNumberDescription
AGENT_STATUS_UNSPECIFIED0Unspecified.
AGENT_STATUS_ACTIVE1Agent is active and operational.
AGENT_STATUS_DELETED2Agent has been permanently deleted (soft-delete).

AgentVisibility

shared.v1.AgentVisibility

AgentVisibility defines agent discoverability and addability.

ValueNumberDescription
AGENT_VISIBILITY_UNSPECIFIED0Unspecified.
AGENT_VISIBILITY_PUBLIC1Agent is publicly listed in the directory. Any user can search and add.
AGENT_VISIBILITY_PRIVATE2Agent is private. Only the creator can use it (auto-added on creation).

AgentDeliveryMode

shared.v1.AgentDeliveryMode

AgentDeliveryMode defines the event delivery mode for an agent.

ValueNumberDescription
AGENT_DELIVERY_MODE_UNSPECIFIED0Unspecified.
AGENT_DELIVERY_MODE_WEBHOOK1Events delivered via Webhook HTTP POST.
AGENT_DELIVERY_MODE_WEBSOCKET2Events delivered via WebSocket push.

IdentityType

api.v1.IdentityType

IdentityType defines authentication identity types.

ValueNumberDescription
IDENTITY_TYPE_UNSPECIFIED0Unspecified.
IDENTITY_TYPE_EMAIL1Email address.
IDENTITY_TYPE_PHONE2Phone number.

FriendRequestStatus

shared.v1.FriendRequestStatus

FriendRequestStatus defines friend request lifecycle states.

ValueNumberDescription
FRIEND_REQUEST_STATUS_UNSPECIFIED0Unspecified.
FRIEND_REQUEST_STATUS_PENDING1Request is pending review.
FRIEND_REQUEST_STATUS_ACCEPTED2Request has been accepted.
FRIEND_REQUEST_STATUS_REJECTED3Request has been rejected.

SearchAccountType

api.v1.SearchAccountType

SearchAccountType specifies which account types to include in search.

ValueNumberDescription
SEARCH_ACCOUNT_TYPE_UNSPECIFIED0Unspecified. Searches all account types (users and agents).
SEARCH_ACCOUNT_TYPE_USER1Search only human users.
SEARCH_ACCOUNT_TYPE_AGENT2Search only agents.

ConversationType

shared.v1.ConversationType

ConversationType defines conversation types.

ValueNumberDescription
CONVERSATION_TYPE_UNSPECIFIED0Unspecified.
CONVERSATION_TYPE_PRIVATE1Private one-on-one chat.
CONVERSATION_TYPE_GROUP2Group chat.

ConversationActionType

shared.v1.ConversationActionType

ConversationActionType defines conversation management actions.

ValueNumberDescription
CONVERSATION_ACTION_TYPE_UNSPECIFIED0Unspecified.
CONVERSATION_ACTION_TYPE_MUTE1Mute conversation notifications.
CONVERSATION_ACTION_TYPE_UNMUTE2Unmute conversation notifications.
CONVERSATION_ACTION_TYPE_DELETE3Soft-delete conversation from the user's list. See UpdateConversationAction RPC for the full delete lifecycle.

MemberRole

shared.v1.MemberRole

MemberRole defines group member roles.

ValueNumberDescription
MEMBER_ROLE_UNSPECIFIED0Unspecified.
MEMBER_ROLE_OWNER1Group owner.
MEMBER_ROLE_MEMBER2Regular member.

GroupStatus

shared.v1.GroupStatus

GroupStatus defines group lifecycle states.

ValueNumberDescription
GROUP_STATUS_UNSPECIFIED0Unspecified.
GROUP_STATUS_NORMAL1Group is active and operational.
GROUP_STATUS_DISSOLVED2Group has been dissolved.

MessageType

shared.v1.MessageType

MessageType defines message content types.

ValueNumberDescription
MESSAGE_TYPE_UNSPECIFIED0Unspecified.
MESSAGE_TYPE_TEXT1Plain text message.
MESSAGE_TYPE_IMAGE2Image message.
MESSAGE_TYPE_AUDIO3Audio/voice message.
MESSAGE_TYPE_VIDEO4Video message.
MESSAGE_TYPE_FILE5File attachment message.
MESSAGE_TYPE_MARKDOWN6Markdown formatted message.
MESSAGE_TYPE_CARD7Interactive card message.
MESSAGE_TYPE_STREAM8Streaming message.
MESSAGE_TYPE_GROUP10Group event message (delivered to group conversation).
MESSAGE_TYPE_RECALLED11Message recalled notification.

MessageEntityType

shared.v1.MessageEntityType

MessageEntityType defines rich text annotation types.

ValueNumberDescription
MESSAGE_ENTITY_TYPE_UNSPECIFIED0Unspecified.
MESSAGE_ENTITY_TYPE_MENTION1@mention.
MESSAGE_ENTITY_TYPE_URL2URL link.
MESSAGE_ENTITY_TYPE_PHONE3Phone number.
MESSAGE_ENTITY_TYPE_HASHTAG4Hashtag.
MESSAGE_ENTITY_TYPE_EMAIL5Email address.
MESSAGE_ENTITY_TYPE_BOLD6Bold text.
MESSAGE_ENTITY_TYPE_ITALIC7Italic text.
MESSAGE_ENTITY_TYPE_CODE8Code span.

StreamPhase

shared.v1.StreamPhase

StreamPhase defines streaming message lifecycle phases.

ValueNumberDescription
STREAM_PHASE_UNSPECIFIED0Unspecified.
STREAM_PHASE_START1Stream started.
STREAM_PHASE_DELTA2Incremental delta.
STREAM_PHASE_END3Stream completed.
STREAM_PHASE_ERROR4Stream error.

ClientFrameType

api.v1.ClientFrameType

ClientFrameType enumerates upstream frame types.

ValueNumberDescription
CLIENT_FRAME_TYPE_UNSPECIFIED0Unspecified.
CLIENT_FRAME_TYPE_AUTH_REQUEST1Connection authentication.
CLIENT_FRAME_TYPE_HEARTBEAT_PING2Heartbeat ping.

ServerFrameType

api.v1.ServerFrameType

ServerFrameType enumerates downstream frame types.

ValueNumberDescription
SERVER_FRAME_TYPE_UNSPECIFIED0Unspecified.
SERVER_FRAME_TYPE_AUTH_RESPONSE1Authentication result.
SERVER_FRAME_TYPE_UPDATE2Update push (sequenced or non-sequenced).
SERVER_FRAME_TYPE_HEARTBEAT_PONG3Heartbeat pong.
SERVER_FRAME_TYPE_ERROR4Error.

MediaPurpose

shared.v1.MediaPurpose

MediaPurpose defines the intended usage of an uploaded file, which determines storage visibility and URL generation strategy.

ValueNumberDescription
MEDIA_PURPOSE_UNSPECIFIED0Unspecified.
MEDIA_PURPOSE_AVATAR1User avatar (public, permanent URL).
MEDIA_PURPOSE_GROUP_AVATAR2Group avatar (public, permanent URL).
MEDIA_PURPOSE_MESSAGE3Message attachment (private, time-limited URL with conversation-level access control).