Questions about Webhooks and Moonraker

Hi,

I’m trying to create a Klippy extra to interface with Moonraker’s websockets through a webhook. I’ve been able to create a webhook accessible through the below URL:

http://klippy.local:7125/printer/test/webhook

and receive a reply:

{"result":{"status":{"key":"value"}}}

However, when I try to access this through the Moonraker websocket API with the following request (from Python using single-quotes, but properly JSON serialized before sending):

{
    'jsonrpc': '2.0',
    'method': 'printer.test.webhook',
    'id': 0,
}

it errors with:

{'jsonrpc': '2.0', 'error': {'code': -32601, 'message': 'Method not found'}, 'id': 0}

Also, when I try to read the config section:

{
    'jsonrpc': '2.0',
    'method': 'printer.objects.query',
    'params': {
        'objects': {
            'test_config': None,
        }
    },
    'id': 1,
}

it returns an empty dictionary.

{'jsonrpc': '2.0', 'result': {'eventtime': 285900.34715596, 'status': {'test_config': {}}}, 'id': 1}

Below is the minimal extras file test_config.py.

class TestConfig:
    def __init__(self, config):
        self.printer = config.get_printer()

        self.webhooks = self.printer.lookup_object('webhooks')
        self.webhooks.register_endpoint('test/webhook', self.webhook_handler)
    
    def webhook_handler(self, request):
        request.send({
            'status': self.get_status(0)
        })

    def get_status(self, eventtime):
        return {
            'key': 'value',
        }


def load_config(config):
    return TestConfig(config)

Any help would be appreciated!

I think you expected Moonraker to do some autoproxy for the Klipper API.
It seems to me that it is not the case: moonraker/moonraker/components/klippy_apis.py at master · Arksine/moonraker · GitHub

So, I suspect that to call any unspecified klipper api method, you need to establish a bridge WebSocket: Introduction - Moonraker

Mmm, according to: Printer Administration - Moonraker
It seems that you need to query a configfile object, instead of test_config.

Hope that helps.

Moonraker does auto generate HTTP and JRPC APIs for all webhooks registered by Klipper. Judging by the fact that the query doesn’t respond with key: value as returned by the get_status() method I suspect that the test_config.py module is not correctly loading.

1 Like

Thank you both for the quick replies!

I think the main issue I’m seeing is a discrepancy between the data available in the HTTP API and the JSON RPC API.

For the HTTP endpoint printer/objects/query?test_config, I get the following (expected) response:

{
  "result": {
    "eventtime": 57711.269499045,
    "status": {
      "test_config": {
        "key": "value"
      }
    }
  }
}

However when I use the JSON RPC to access the same endpoint over webhooks in Moonraker with:

{
    'jsonrpc': '2.0',
    'method': 'printer.objects.query',
    'params': {
        'objects': {
            'test_config': None,
        }
    },
    'id': 1,
}

it just returns the empty dictionary and not key: value

{'jsonrpc': '2.0', 'result': {'eventtime': 285900.34715596, 'status': {'test_config': {}}}, 'id': 1}

I can try that, but I’d rather figure out this discrepancy first.

I think the best way to determine what is happening is to enable verbose logging for Moonraker, reproduce, and upload the log. It will provide details about each request so I can see what his happening.

This is getting strange. I’ve enabled verbose logging by putting a -v before the -d parameter in moonraker.env, but now I can see what’s happening.

When I initiate an HTTP request, it shows up in the log:

025-09-06 14:46:23,194 [application.py:_log_debug()] - HTTP Request::GET /printer/objects/query::{'objects': {'test_config': None}}
2025-09-06 14:46:23,383 [application.py:_log_debug()] - HTTP Response::GET /printer/objects/query::{'result': {'eventtime': 85938.153687425, 'status': {'test_config': {'key': 'value'}}}}

But when I initiate a websocket request at the /websocket path, nothing gets logged, but I do get a reply with the empty dictionary:

{'jsonrpc': '2.0', 'result': {'eventtime': 371506.826833712, 'status': {'test_config': {}}}, 'id': 0}

When I initiate a request at /klippysocket with method set to objects.query, I get a reply with the empty dictionary:

{'id': 0, 'result': {'eventtime': 371624.138378272, 'status': {'test_config': {}}}}

Finally, if I connect to Klippy over the unix socket (my application needs Wi-Fi connection, but this is for testing). I send the below JSON:

{"method":"objects/query","id":0,"params":{"objects":{"test_config": null}}}

and I get the expected reply:

{"id":0,"result":{"eventtime":86485.806003913,"status":{"test_config":{"key":"value"}}}}

To summarize:

  • Klippy’s UNIX socket and Moonraker’s HTTP API agree with the correct data
  • Moonraker’s websocket (both normal and bridge) agree with each other (empty data) but not with the HTTP API or Klippy’s UNIX socket.

Attached is the moonraker.log with verbose logging and the HTTP, Websocket, and bridge websocket requests attempted.

moonraker.log (8.7 KB)

1 Like

Looking at the log it appears that you have multiple instances of Moonraker running. My guess is that your client websocket is connecting to the wrong instance of Moonraker.

2 Likes

Thank you!! I looked in my testing code and I was connecting to port 7125, and not 7126 for my test Klipper. Now I’m getting the expected replies.

1 Like

Could you share the output, I’m just curious?

Sure. The expected reply I’m getting for my test setup is:

{
    "jsonrpc":"2.0",
    "result":{
        "eventtime":187975.581085587,
        "status":{
            "test_config":{
                "key":"value"
            }
        }
    },
    "id":0
}
1 Like