Skip to main content

DeBox Bot Go SDK Webhook Guide

Source repository:

This document focuses on Webhook mode only.

1. Webhook vs Long Polling (strictly mutually exclusive)

There are two ways to receive bot updates:

  1. Webhook: DeBox pushes updates to your server via POST.
  2. Long Polling: your app pulls updates via getUpdates.

Strict exclusivity rule:

  • Once webhook URL is configured on platform, updates are routed to webhook as the primary and effective receiving path.
  • In that state, GetUpdates/GetUpdatesChan as a receiving path is effectively disabled (none or near-none updates).

Conclusion:

  • If you choose webhook, do not use long polling to receive messages.
  • If you want to use long polling, clear webhook config first.

2. When to use webhook

Use webhook when:

  • Your service is publicly reachable over HTTP/HTTPS
  • You need low latency and high throughput
  • You prefer push-based event flow

3. Platform configuration

Configure webhook URL in DeBox bot console, for example:

  • https://your-domain.com/bot/webhook

Also ensure:

  • App Domain is configured correctly
  • Webhook endpoint is stable and public
  • Webhook Key changes after webhook URL updates

4. SDK integration (aligned with Bot Development Overview)

This section follows the same pattern as DeBox Bot Guide:

  • Receive webhook callback on your server
  • Verify X-API-KEY header (Webhook Key)
  • Parse callback payload
  • Use Go SDK to send reply

4.1 Callback payload

DeBox sends POST application/json payload, typically like:

{
"from_user_id": "u_xxx",
"to_user_id": "u_bot",
"language": "en",
"group_id": "cc0onr82",
"mention_users": "u_bot",
"message": "hello",
"message_raw": "@bot hello"
}

4.2 Full sample (Gin + Go SDK)

package main

import (
"net/http"
"os"

"github.com/gin-gonic/gin"
boxbotapi "github.com/debox-pro/debox-chat-go-sdk/boxbotapi"
)

type WebhookPayload struct {
FromUserID string `json:"from_user_id"`
ToUserID string `json:"to_user_id"`
Language string `json:"language"`
GroupID string `json:"group_id"`
MentionUsers string `json:"mention_users"`
Message string `json:"message"`
MessageRaw string `json:"message_raw"`
}

func main() {
webhookKey := os.Getenv("DEBOX_WEBHOOK_KEY")
apiKey := os.Getenv("DEBOX_BOT_API_KEY")
apiSecret := os.Getenv("DEBOX_BOT_API_SECRET")

if webhookKey == "" || apiKey == "" {
panic("missing required env: DEBOX_WEBHOOK_KEY / DEBOX_BOT_API_KEY")
}

bot, err := boxbotapi.NewBotAPI(apiKey, apiSecret)
if err != nil {
panic(err)
}

r := gin.Default()
r.POST("/bot/webhook", func(c *gin.Context) {
// 1) Strict source verification
if c.GetHeader("X-API-KEY") != webhookKey {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid webhook key"})
return
}

// 2) Parse webhook body
var payload WebhookPayload
if err := c.ShouldBindJSON(&payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

// 3) Determine chat type and send reply via SDK
chatType := "private"
chatID := payload.FromUserID
if payload.GroupID != "" {
chatType = "group"
chatID = payload.GroupID
}

reply := boxbotapi.NewMessage(chatID, chatType, "Received: "+payload.Message)
reply.ParseMode = boxbotapi.ModeRichText
if _, err := bot.Send(reply); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"ok": true})
})

_ = r.Run(":8080")
}

5. Common pitfalls

  • Webhook configured but no updates received:
    • Check endpoint reachability, logs, and X-API-KEY verification logic.
  • Webhook and long polling both enabled:
    • Choose one path only. With webhook enabled, polling receive path is ineffective.
  • Local dev without public domain:
    • Use a tunnel to expose local webhook endpoint for testing.