Skip to main content

Overview

The HTTP POST webhook (HTTP Client) allows NapCat to push events to your server via HTTP POST requests. This is a one-way communication method where NapCat sends events to your endpoint.

Configuration

Configure the HTTP client in your OneBot config:
{
  "network": {
    "httpClients": [
      {
        "name": "http-client",
        "enable": true,
        "url": "http://localhost:8080",
        "messagePostFormat": "array",
        "reportSelfMessage": false,
        "token": "your_secret_token",
        "debug": false
      }
    ]
  }
}

Configuration Options

OptionTypeDefaultDescription
enablebooleanfalseEnable HTTP POST webhook
urlstringhttp://localhost:8080Target URL for event delivery
tokenstring""Secret token for HMAC signature
messagePostFormatstringarrayMessage format (array or string)
reportSelfMessagebooleanfalseReport messages sent by bot itself
debugbooleanfalseEnable debug logging

Event Delivery

Request Format

NapCat sends POST requests with the following headers:
POST / HTTP/1.1
Host: localhost:8080
Content-Type: application/json
X-Self-ID: 123456789
X-Signature: sha1=abcdef1234567890
User-Agent: NapCat

Request Body

The request body contains the event data:
{
  "time": 1234567890,
  "self_id": 123456789,
  "post_type": "message",
  "message_type": "private",
  "sub_type": "friend",
  "message_id": 12345,
  "user_id": 87654321,
  "message": "Hello!",
  "raw_message": "Hello!",
  "font": 0,
  "sender": {
    "user_id": 87654321,
    "nickname": "Friend"
  }
}

Security and Authentication

HMAC Signature Verification

NapCat signs each request using HMAC-SHA1. Verify the signature to ensure requests are authentic:
const crypto = require('crypto');
const express = require('express');
const app = express();

const SECRET_TOKEN = 'your_secret_token';

app.post('/', express.json(), (req, res) => {
  const signature = req.headers['x-signature'];
  const body = JSON.stringify(req.body);
  
  // Calculate expected signature
  const hmac = crypto.createHmac('sha1', SECRET_TOKEN);
  hmac.update(body);
  const expectedSignature = 'sha1=' + hmac.digest('hex');
  
  // Verify signature
  if (signature !== expectedSignature) {
    return res.status(403).json({ error: 'Invalid signature' });
  }
  
  // Process event
  console.log('Event received:', req.body);
  res.json({ message: 'Event received' });
});

app.listen(8080, () => {
  console.log('Webhook server listening on port 8080');
});

Python Example

import hmac
import hashlib
import json
from flask import Flask, request, jsonify

app = Flask(__name__)
SECRET_TOKEN = 'your_secret_token'

@app.route('/', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature', '')
    body = request.get_data()
    
    # Calculate expected signature
    expected = 'sha1=' + hmac.new(
        SECRET_TOKEN.encode('utf-8'),
        body,
        hashlib.sha1
    ).hexdigest()
    
    # Verify signature
    if not hmac.compare_digest(signature, expected):
        return jsonify({'error': 'Invalid signature'}), 403
    
    # Process event
    event = request.json
    print(f'Event received: {event}')
    
    return jsonify({'message': 'Event received'})

if __name__ == '__main__':
    app.run(port=8080)

Quick Actions

You can return quick actions in the webhook response to perform immediate operations:
app.post('/', express.json(), (req, res) => {
  const event = req.body;
  
  if (event.post_type === 'message' && event.message === 'ping') {
    // Quick reply
    return res.json({
      reply: 'pong!'
    });
  }
  
  if (event.post_type === 'message' && event.message.includes('bad word')) {
    // Delete message and kick user
    return res.json({
      delete: true,
      kick: true
    });
  }
  
  res.json({});
});

Available Quick Actions

ActionTypeDescription
replystring/arraySend a reply message
reply_atbooleanInclude @mention in reply
deletebooleanDelete the message
kickbooleanKick the user (group only)
banbooleanBan/mute the user (group only)
ban_durationnumberBan duration in seconds

Quick Action Examples

Auto Reply

{
  "reply": "Thanks for your message!"
}

Reply with Mention

{
  "reply": "Hello there!",
  "reply_at": true
}

Delete and Ban

{
  "delete": true,
  "ban": true,
  "ban_duration": 600
}

Event Types

Message Events

{
  "post_type": "message",
  "message_type": "private",
  "sub_type": "friend",
  "message_id": 12345,
  "user_id": 87654321,
  "message": "Hello!",
  "raw_message": "Hello!"
}

Notice Events

{
  "post_type": "notice",
  "notice_type": "group_increase",
  "sub_type": "approve",
  "group_id": 12345678,
  "user_id": 87654321,
  "operator_id": 87654321
}

Request Events

{
  "post_type": "request",
  "request_type": "friend",
  "user_id": 87654321,
  "comment": "Please add me",
  "flag": "unique_request_flag"
}

Multiple Webhooks

You can configure multiple webhook endpoints:
{
  "network": {
    "httpClients": [
      {
        "name": "main-webhook",
        "enable": true,
        "url": "http://localhost:8080/napcat",
        "token": "main_token"
      },
      {
        "name": "backup-webhook",
        "enable": true,
        "url": "http://backup-server:8081/napcat",
        "token": "backup_token"
      },
      {
        "name": "logging-webhook",
        "enable": true,
        "url": "http://logger:8082/events",
        "token": "log_token"
      }
    ]
  }
}

Error Handling

NapCat logs errors if webhook delivery fails:
[OneBot] [Http Client] 新消息事件HTTP上报返回快速操作失败 Error: connect ECONNREFUSED 127.0.0.1:8080

Webhook Server Best Practices

  1. Return responses quickly - NapCat may timeout on slow responses
  2. Handle errors gracefully - Log errors but don’t crash
  3. Verify signatures - Always verify HMAC signatures in production
  4. Process asynchronously - Handle heavy operations in background tasks
  5. Monitor uptime - NapCat doesn’t retry failed deliveries

Testing Your Webhook

Using ngrok for Local Testing

# Start ngrok
ngrok http 8080

# Use the ngrok URL in NapCat config
{
  "url": "https://abc123.ngrok.io"
}

Manual Testing

Send a test POST request:
curl -X POST http://localhost:8080 \
  -H "Content-Type: application/json" \
  -H "X-Self-ID: 123456789" \
  -d '{
    "post_type": "message",
    "message_type": "private",
    "user_id": 12345,
    "message": "test"
  }'

Implementation Details

The HTTP client adapter is implemented in packages/napcat-onebot/network/http-client.ts:
  • Uses HMAC-SHA1 for request signing
  • Sends X-Self-ID header with bot’s QQ number
  • Supports quick action responses
  • Asynchronous event delivery with error logging

Webhook vs WebSocket

FeatureHTTP WebhookWebSocket
DirectionOne-way (push only)Bidirectional
ConnectionRequest per eventPersistent connection
API CallsVia separate HTTP/WSThrough same connection
LatencyHigherLower
SetupSimplerMore complex
Use CaseSimple bots, loggingReal-time apps

Security Considerations

  1. Use HTTPS - Encrypt webhook traffic in production
  2. Verify signatures - Always check X-Signature header
  3. Restrict access - Use firewall rules to limit webhook endpoint access
  4. Rotate tokens - Change tokens periodically
  5. Log suspicious activity - Monitor for invalid signatures

Troubleshooting

Events Not Received

  • Check that the HTTP client is enabled: "enable": true
  • Verify the webhook URL is correct and accessible
  • Check server logs for connection errors
  • Test the endpoint with curl

Signature Verification Fails

  • Ensure token matches exactly on both sides
  • Verify you’re hashing the raw request body
  • Check character encoding (use UTF-8)
  • Compare generated signature with received one

Quick Actions Not Working

  • Return actions in response within reasonable timeout
  • Check response format matches expected structure
  • Look for errors in NapCat debug logs
  • Verify the event type supports the quick action

Next Steps

Build docs developers (and LLMs) love