Quickstart
This page builds a Go program from scratch that signs in and sends and receives messages: create a project, install the SDK, create a client, sign in with a ticket issued by your server, open the connection, receive messages and reply automatically, and shut down cleanly. You end up with a single-file program you can go run and build your own bot or integration on.
Before you start
- In the console, use the
demoapp created when you signed up, or create an app. Under "Access credentials" on the Overview, copy the AppKey (such as1575529652#demo) and the IM service address, shown as "REST endpoint" (such ashttps://im.example.com). - Connect your server to the server REST API and give it a "get IM sign-in ticket" endpoint: the program calls it as a user, and your server issues a sign-in ticket for that user and returns it, such as
{"ticket": "ult_..."}. - Install Go 1.26.5 or later.
A ticket is valid for 5 minutes and can be used once; think of it as a temporary password. The App Token and Client Secret stay on your server and must never appear in the Go program. For development and testing you can also issue a ticket for a test account with curl and paste it into the program.
Create the project and install
Install through Go modules; there's no need to download a ZIP first. In a new project, run:
mkdir imbot && cd imbot
go mod init example.com/imbot
go get github.com/DeepRespond-AI/deeprespond-im-go-sdk@v1.0.2Save the full main.go below, then run go mod tidy. The example uses the v1.0.2 module published on GitHub.
Use downloaded source
For offline development, download the v1.0.2 source ZIP, unzip it, and point your project at it with a local replace:
go mod edit -replace=github.com/DeepRespond-AI/deeprespond-im-go-sdk=/绝对路径/deeprespond-im-go-sdk-1.0.2The replace path points to the unzipped root directory, the one containing go.mod. Update the path if you move the source. To go back to the remote version, run go mod edit -dropreplace=github.com/DeepRespond-AI/deeprespond-im-go-sdk and go mod tidy. To just try the demo, you don't need to create imbot; run it from the unzipped root as described in the Demo guide.
Step 1: Create a client
cli, err := im.New(im.Config{
AppKey: "1575529652#demo", // 组织#应用,在控制台的应用详情中查看
APIURL: "https://im.example.com", // IM 服务端 REST 地址
})
if err != nil {
panic(err)
}im.New makes no network requests; it only checks the parameters and fills in defaults. For all config options, see Initialization, sign-in and connection.
Step 2: Sign in
In production, sign in with a ticket issued by your server. For development and testing, password sign-in is a shortcut:
// 生产环境:ticket 来自你的业务服务端
session, err := cli.Login(ctx, im.LoginTicket, "alice", ticket)
// 开发测试捷径:密码登录(正式分发的程序不要这样写)
// session, err := cli.Login(ctx, im.LoginPassword, "alice", "pass-123")On success you get an *im.Session (access token, refresh token, session ID, and the user's own profile). The SDK saves and renews the tokens; you never refresh them yourself.
Step 3: Subscribe to events
Once the connection is open, server events come to your OnEvent callback. To receive new messages, handle message.received:
cli.OnEvent(func(e im.Event) {
if e.Name != im.EventMessageReceived {
return
}
var m im.Message
if json.Unmarshal(e.Data, &m) != nil {
return
}
fmt.Printf("来自 %s:%s\n", m.Sender, m.TextBody())
})m.TextBody()returns a text message's text. For other types,m.BodyMap()gives the body as an object.- Events are delivered in arrival order on one goroutine, so slow work in the callback holds up later events. For slow work, start your own goroutine.
- For all events, see Events and sync.
Step 4: Connect and sync
if err := cli.ConnectWait(ctx); err != nil {
panic(err)
}ConnectWait opens the connection and blocks until the first authentication completes (waiting up to 15 seconds). You only receive events once connected, and the SDK reconnects automatically after disconnects. After signing in, a full sync is a good idea, to load the conversation list and recent messages into the in-memory cache:
n, err := cli.SyncAll(ctx)
fmt.Printf("已同步 %d 个会话\n", n)Bots that only handle live messages and never read history can skip the sync.
Step 5: Send a text message
msg, err := cli.SendText(ctx, im.ToUser("bob"), "你好", nil)
fmt.Println(msg.Seq, err)im.ToUser("bob") sends to a user and im.ToGroup("group ID") sends to a group. When the connection is up, messages go over it; otherwise the SDK falls back to REST automatically. If sending fails (returns an error), whether to retry is up to you.
Step 6: Shut down cleanly
<-ctx.Done() // 例如收到 Ctrl+C
_ = cli.Logout(context.Background()) // 退出登录:断开长连接并结束服务端会话To only close the connection and stay signed in, use cli.Disconnect(); you can Connect again later. The Go SDK has no offline send queue: when SendText returns successfully the server has the message and delivers it from there, so killing the process doesn't affect messages already sent.
Full example
Save the following as main.go. The example reads the ticket from an environment variable; in a real program, call your server's "get IM sign-in ticket" endpoint instead.
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"os/signal"
"syscall"
"time"
im "github.com/DeepRespond-AI/deeprespond-im-go-sdk"
)
// 向业务服务端获取当前用户的 IM 登录凭证。
// 实际程序中在这里调用你自己定义的接口;业务服务端校验身份后,
// 用 App Token 调 IM 服务的 REST API 为用户签发凭证并返回。
func fetchTicket() (string, error) {
t := os.Getenv("IM_TICKET")
if t == "" {
return "", fmt.Errorf("请先设置 IM_TICKET(由业务服务端签发,见文档“快速集成”)")
}
return t, nil
}
func main() {
// Ctrl+C 或 SIGTERM 时取消 ctx,触发退出
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
// 1. 创建客户端(不做网络请求)
cli, err := im.New(im.Config{
AppKey: "1575529652#demo",
APIURL: "https://im.example.com",
})
if err != nil {
panic(err)
}
// 2. 登录:生产用凭证;开发测试可用 im.LoginPassword
ticket, err := fetchTicket()
if err != nil {
panic(err)
}
if _, err := cli.Login(ctx, im.LoginTicket, "alice", ticket); err != nil {
panic(err)
}
// 3. 订阅事件:收到文本消息时打印并回复一句
cli.OnEvent(func(e im.Event) {
if e.Name != im.EventMessageReceived {
return
}
var m im.Message
if json.Unmarshal(e.Data, &m) != nil {
return
}
fmt.Printf("来自 %s:%s\n", m.Sender, m.TextBody())
go func() {
sendCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if _, err := cli.SendText(sendCtx, im.ToUser(m.Sender), "收到:"+m.TextBody(), nil); err != nil {
fmt.Println("回复失败:", err)
}
}()
})
// 4. 建立长连接并等待认证完成,然后全量同步一次
if err := cli.ConnectWait(ctx); err != nil {
panic(err)
}
fmt.Println("已连接,Ctrl+C 退出")
if n, err := cli.SyncAll(ctx); err != nil {
fmt.Println("同步失败:", err)
} else {
fmt.Printf("已同步 %d 个会话\n", n)
}
// 5. 等待退出信号,优雅退出
<-ctx.Done()
fmt.Println("退出中…")
logoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = cli.Logout(logoutCtx)
}Run it
go mod tidy
IM_TICKET=ult_xxx go run .Then send this user a message from another account (or from the Web demo). The program prints what it receives and replies automatically. Change the target to im.ToGroup("group ID") to use the bot in a group.
Password sign-in is for development only
im.LoginTicket in the example is how production programs sign in. While developing you can replace the sign-in line with cli.Login(ctx, im.LoginPassword, "alice", "pass-123") to skip issuing a ticket. Don't embed passwords in real programs.
Next steps
- Initialization, sign-in and connection: all config options, token persistence (
TokenStorage), logging (Logger), connection state and reconnects. - Events and sync: all events, the
SyncAllfull sync, and how to read theStore. - Demo: the runnable demo that ships with the SDK, covering most features, including messaging, groups, friends and device management.
