DingTalk¶
Overview¶
The DingTalk channel communicates with the DingTalk Open Platform via Stream Mode. Stream Mode uses a callback registration + WebSocket long-polling mechanism, requiring no public-facing endpoint. This makes it ideal for deployments behind NAT, firewalls, or without a fixed public IP.
The channel supports both 1:1 (direct) and group chat message types, automatically distinguishing between them via conversation_type metadata and routing to the appropriate send API.
Tip
Stream Mode is DingTalk's recommended bot integration approach, eliminating the complexity of webhook callback URL configuration and SSL certificate management.
Configuration Example¶
channels:
dingtalk:
enabled: true
app_key: "your-app-key"
app_secret: "your-app-secret"
robot_code: "your-robot-code"
allow_from:
- "user1"
- "user2"
| Field | Required | Description |
|---|---|---|
app_key |
Yes | AppKey of the Enterprise Internal App |
app_secret |
Yes | AppSecret of the Enterprise Internal App |
robot_code |
Yes | Unique robot identifier code |
allow_from |
No | Allowlist of user IDs permitted to interact; empty means no restriction |
Credential Setup¶
- Log in to the DingTalk Open Platform
- Navigate to "App Development" → "Enterprise Internal Apps" → click "Create App"
- On the app info page, obtain the AppKey and AppSecret
- Go to the "Robot & Message Push" configuration page
- Enable the robot feature and obtain the robot_code
- In robot settings, enable Stream Mode (set message receiving mode to "Stream Mode")
Warning
The AppSecret is displayed only once at creation time. Store it securely. If lost, you must regenerate it, which immediately invalidates the old key.
Callback / Webhook Setup¶
Stream Mode requires no public callback URL. The connection flow is:
- On startup, the app registers a callback with DingTalk API using AppKey + AppSecret
- DingTalk returns a WebSocket connection endpoint
- The app establishes a persistent WebSocket connection to receive message pushes
- Automatic reconnection on disconnection
┌─────────┐ Register ┌──────────────┐
│ Agent │ ──────────────→ │ DingTalk API │
│ │ ←────────────── │ │
│ │ WS endpoint │ │
│ │ ═════════════════ │ │
│ │ WebSocket long connection │
└─────────┘ └──────────────┘
Tip
Since it uses outbound WebSocket connections, services deployed behind NAT or firewalls work without issue. Only outbound HTTPS/WSS traffic (port 443) needs to be allowed.
Capability Matrix¶
| Capability | Supported | Notes |
|---|---|---|
| Message editing | ❌ | DingTalk API does not support modifying sent messages |
| Reactions | ❌ | Not supported |
| File sending | ❌ | Not currently implemented |
| Real-time messages | ✅ | Stream Mode WebSocket push |
| Group chat | ✅ | Routed via openConversationId |
| Direct chat | ✅ | Routed via staffId |
Send API distinction:
- Direct messages:
POST /v1.0/robot/oToMessages/batchSend - Group messages:
POST /v1.0/robot/groupMessages/send(requiresopenConversationId)
Authentication¶
DingTalk uses AppKey + AppSecret to obtain an access_token:
POST https://api.dingtalk.com/v1.0/oauth2/accessToken
{
"appKey": "your-app-key",
"appSecret": "your-app-secret"
}
The token is valid for 2 hours. The channel layer handles automatic refresh — no manual management required.
FAQ¶
Where does the group conversation ID come from?
No extra API call and no separate permission are involved. The conversation ID is read straight off the inbound callback's conversationId field and echoed back as openConversationId when replying.
Direct messages (conversationType of 1) use the sender ID as the conversation key; group chats use conversationId. So as long as the bot receives the message callback, it already holds the ID needed to reply.
Q: What happens when rate limits are triggered?
DingTalk imposes rate limits on bot message sending. When throttled, the channel automatically backs off (300-second backoff). No manual intervention is needed. If rate limits are triggered frequently:
- Consolidate multiple short replies into a single message
- Check for abnormal duplicate message sends
Q: Cannot connect via Stream Mode?
- Verify that AppKey / AppSecret / robot_code are all configured correctly
- Confirm Stream Mode is enabled in robot settings
- Check that outbound WSS connections are allowed (port 443)
- Look for token acquisition failures in the logs
Q: Bot doesn't respond in group chat?
- Confirm
allow_fromis not excluding the sender - Confirm the bot has been added to the target group
- Check if
conversation_typeis correctly identified as group chat - Group chat may require @mentioning the bot to trigger a response (depends on configuration)
Q: How are direct and group messages distinguished?
The channel automatically distinguishes via the conversationType field in incoming messages:
- 1 = Direct message
- 2 = Group message
Different message types are automatically routed to the corresponding send API.