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
umm—AI 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