Skip to main content

Avatar Hub: API

Integrate your SecondMe AI avatar into any third-party application — Feishu bots, customer service systems, or any custom app.

Overview

The Avatar Open API provides a single authentication endpoint. After authentication, you use the same endpoints as the SecondMe mobile app — no custom API to learn.

Your App → /open/avatar/auth (API Key → visitor token)
→ Standard SecondMe endpoints (same as mobile app)
→ WebSocket for real-time AI responses

What You Can Build

  • Feishu / DingTalk / Slack bots — Users chat with your avatar through messaging platforms
  • Website chat widget — Embed avatar conversations on your website
  • Customer service — Let your avatar handle inquiries 24/7
  • Any custom integration — Anything that can make HTTP requests and connect WebSocket

How It Works

  1. You create an API Key for your avatar in the SecondMe app
  2. Your app calls /auth with the API Key to get a visitor token
  3. Your app uses the visitor token to call standard SecondMe APIs
  4. AI responses are pushed back through WebSocket in real-time
  5. You (the avatar owner) can view all conversations and take over from the app

Prerequisites

  1. A SecondMe account with at least one avatar created
  2. An API Key created from Avatar Hub → Avatar Detail → API Key Management
  3. Your API Key (starts with sk-, shown only once at creation — save it securely)

Environment

EnvironmentBase URL
Productionhttps://mindos.mindverse.ai/gate/in
Pre-releasehttps://mindos-prek8s.mindverse.ai/gate/in

Quick Start

Step 0: Authenticate

Exchange your API Key for a visitor token. Each end-user needs a unique visitorId.

visitorId format: {platform}_{uuid}

Examples: feishu_550e8400-e29b-41d4-a716-446655440000, web_6ba7b810-9dad-11d1-80b4-00c04fd430c8

tip

Generate a unique visitorId per end-user and persist it. Same visitorId = same visitor = can reuse existing sessions.

curl -X POST $BASE_URL/rest/open/avatar/auth \
-H "Authorization: Bearer sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"visitorId": "feishu_550e8400-e29b-41d4-a716-446655440000",
"visitorName": "John Doe",
"channel": "feishu"
}'
FieldRequiredDescription
visitorIdYesFormat: {platform}_{uuid}
visitorNameNoDisplay name, shown to avatar owner. e.g. "张三"
channelNoChannel identifier, appended to name as "张三(feishu)". e.g. "feishu", "dingtalk", "web"

Response:

{
"code": 0,
"data": {
"visitorToken": "bb857435f640c8b2...",
"visitorUserId": "del3p",
"visitorMindId": "487569763543990272",
"avatarShareCode": "ebe251793d69",
"avatarName": "My Assistant",
"ownerUserId": "de4fh"
}
}
FieldDescriptionUsed In
visitorTokenAuth token for all subsequent requeststoken header
visitorUserIdEncoded visitor user IDws/create, message/send
visitorMindIdVisitor's mind ID (numeric)session/create
avatarShareCodeAvatar's share codechat/init
ownerUserIdAvatar owner's encoded IDsession/create memberUserIds
caution

All subsequent requests require two headers:

  • token: {visitorToken}
  • Fp: {visitorId}

Step 1: Initialize Chat

Stores the avatar's context (persona, materials) in cache. Expires after 10 minutes.

curl -X POST $BASE_URL/rest/os/avatar/chat/init \
-H "token: $VISITOR_TOKEN" \
-H "Fp: $VISITOR_ID" \
-H "Content-Type: application/json" \
-d '{"shareCode": "ebe251793d69"}'

Response:

{
"code": 0,
"data": {
"mindId": "3m24e99h3mbp",
"avatarName": "My Assistant",
"ownerUserId": "de4fh",
"opening": "Hello! 👋"
}
}
tip

Save mindId from this response — you'll need it in Step 6 (Send Messages). This is an encoded string (not the numeric visitorMindId from Step 0).

Step 2: Create WebSocket

curl -X POST $BASE_URL/rest/general/ws/create \
-H "token: $VISITOR_TOKEN" \
-H "Fp: $VISITOR_ID" \
-H "Content-Type: application/json" \
-d '{
"userId": "del3p",
"channel": ["ALL"],
"apiVersion": "1.3.0",
"sdkVersion": "1.0.0"
}'

Returns a WebSocket address. Must connect within 60 seconds.

Step 3: Create Session

curl -X POST $BASE_URL/rest/general/session/create \
-H "token: $VISITOR_TOKEN" \
-H "Fp: $VISITOR_ID" \
-H "Content-Type: application/json" \
-d '{
"mindId": 487569763543990272,
"mindType": "shadow",
"mode": "PERSONAL",
"sessionType": "SHARE",
"memberUserIds": ["de4fh"]
}'
Critical Parameters

Both mindId and memberUserIds are required. Without them:

  • AI won't know the avatar's persona
  • Avatar owner cannot reply from the app ("not a member" error)
ParameterValueSource
mindIdNumeric IDStep 0 visitorMindId
memberUserIds["ownerUserId"]Step 0 ownerUserId
sessionType"SHARE"Fixed

Step 4: Bind Session to Avatar

Makes the conversation visible in the owner's Avatar Hub.

# First, get the avatar's numeric ID
curl -X GET "$BASE_URL/rest/os/avatar/public/ebe251793d69" \
-H "token: $VISITOR_TOKEN"
# Response: data.id = avatarId (e.g. 67)

# Then bind
curl -X POST $BASE_URL/rest/os/avatar/chat/start \
-H "token: $VISITOR_TOKEN" \
-H "Fp: $VISITOR_ID" \
-H "Content-Type: application/json" \
-d '{"avatarId": 67, "sessionId": "your-session-id"}'

Step 5: Connect WebSocket

Connect to the address from Step 2. Maintain a heartbeat every 15 seconds.

const ws = new WebSocket(address);

// Heartbeat every 15s
setInterval(() => {
ws.send(JSON.stringify({ type: 'ping', wsId: wsId }));
}, 15000);

Step 6: Send Messages

Messages are sent via HTTP. AI responses arrive via WebSocket.

curl -X POST $BASE_URL/rest/general/message/send \
-H "token: $VISITOR_TOKEN" \
-H "Fp: $VISITOR_ID" \
-H "Content-Type: application/json" \
-d '{
"timestamp": 1774580000000,
"seqId": "12345_____1774580000000",
"sessionId": "your-session-id",
"userId": "del3p",
"messageId": "12345_____1774580000000",
"mindId": "3m24e99h3mbp",
"index": 0,
"sendUserId": "del3p",
"dataType": "text",
"sender": "client",
"type": "msg",
"wsId": "ws:260327...",
"data": {"content": "Hello, tell me about yourself"}
}'
ParameterValueSource
timestampCurrent time in msDate.now()
seqId{random}_____${timestamp}Unique per message
sessionIdSession IDStep 3 response
userIdVisitor encoded IDStep 0 visitorUserId
messageIdSame as seqId
mindIdEncoded string (not numeric)Step 1 response mindId
sendUserIdSame as userId
wsIdWebSocket IDStep 2 response wsId
data.contentMessage text
mindId confusion

Step 6 uses the encoded string mindId from Step 1 (e.g. "3m24e99h3mbp"). This is different from the numeric visitorMindId in Step 0 (e.g. "487569763543990272") used in Step 3.

WebSocket Messages

AI Reply

{
"sender": "umm",
"multipleData": [{ "modal": { "answer": "Hello! I'm..." } }]
}

Owner Takeover Reply

When the avatar owner responds manually from the SecondMe app:

{
"sender": "client",
"sendUserId": "de4fh",
"multipleData": [{ "modal": { "answer": "Hi, this is the real me..." } }]
}

Distinguishing Message Types

sendersendUserIdMeaning
ummAI avatar reply
clientequals your visitorUserIdEcho of your own message (ignore)
clientdifferent from your visitorUserIdOwner takeover reply

Error Codes

CodeDescription
open.api.unauthorizedMissing Authorization header
open.api.key.not.foundInvalid API Key
open.api.key.disabledAPI Key is disabled
open.api.rate.limitedRate limit exceeded (60/min per key)
open.api.avatar.not.foundAvatar not found
open.api.invalid.visitor.idInvalid visitorId format
session.not.memberNot a session member (check memberUserIds)

Important Notes

  1. Surface payload expires in 10 minutes — Complete Step 3 within 10 minutes of Step 1
  2. WebSocket address expires in 60 seconds — Connect immediately after Step 2
  3. Heartbeat required — Send ping every 15 seconds or the connection will drop
  4. Messages via HTTP, responses via WebSocket — This is by design, same as the mobile app
  5. One visitorId can have multiple sessions — Each session/create call creates a new conversation
  6. Rate limit — 60 requests per minute per API Key