`nb.version` causes 403 with a valid token
pynetbox version
v7.5.0
NetBox version
v4.4.7
Python version
3.11
Steps to Reproduce
On NetBox server:
sudo tail -f /var/log/nginx/access.log | grep /api/
Then:
import pynetbox
nb = pynetbox.api(NETBOX_URL, NETBOX_TOKEN)
nb.version
Expected Behavior
Request handled with status 200, and no errors in Django logs.
Observed Behavior
Request handled with status 403:
xxx.xxx.xxx.xxx - - [03/Dec/2025:15:39:34 +0200] "GET /api/ HTTP/1.1" 403 58 "-" "python-requests/2.32.5"
There is also error in Django logs (when logging has been enabled):
2025-12-03 15:39:34,257 django.request WARNING: Forbidden: /api/
The reason seems to be that Request.get_version() does not set the token in the request header:
https://github.com/netbox-community/pynetbox/blob/a2853726b5495e22cd16fcfec04efef2c7f5b2f2/pynetbox/core/query.py#L262-L264
If accepted, I can send PR for this.
Request.get_openapi() doesn't supply the token either, but apparently NetBox allows the /api/schema/ call without token, while /api/ call (used by Request.get_version()) requires the auth token.
See also #641 where the intent of using token when getting version was presented.
@markkuleinio The nb.version call is working fine for me, there is no 403 error shown. I'm not sure from your bug report if you are passing a valid token and you you are getting this error. I am passing a valid token when I setup pynetbox and the subsequent nb.version call is working fine and returns the correct version number.
Here I get 403 in all these three cases:
>>> nb = pynetbox.api("http://netbox-test.lein.io/")
>>> nb.version
'4.4'
>>> nb = pynetbox.api("http://netbox-test.lein.io/", token="invalidtoken")
>>> nb.version
'4.4'
>>> # This is a correct token:
>>> nb = pynetbox.api("http://netbox-test.lein.io/", token="3db66aecdeb0e6613cb17e4cbdb1939b34dca416")
>>> nb.version
'4.4'
>>>
Corresponding logs:
$ sudo tail -f /var/log/nginx/access.log | grep /api/
x.x.x.x - - [08/Dec/2025:18:45:42 +0200] "GET /api/ HTTP/1.1" 403 58 "-" "python-requests/2.32.3"
x.x.x.x - - [08/Dec/2025:18:45:58 +0200] "GET /api/ HTTP/1.1" 403 58 "-" "python-requests/2.32.3"
x.x.x.x - - [08/Dec/2025:18:46:06 +0200] "GET /api/ HTTP/1.1" 403 58 "-" "python-requests/2.32.3"
$ sudo grep LOGIN_REQUIRED /opt/netbox/netbox/netbox/configuration.py
LOGIN_REQUIRED = True
(If I set LOGIN_REQUIRED = False, then I get all 200's.)
If I add the token in the Request.get_version() call (as drafted in https://github.com/markkuleinio/pynetbox/commit/f865ccd90087bcbdad7275d5502fb34a52b2abce), then I get these with the same commands above:
x.x.x.x - - [08/Dec/2025:18:57:01 +0200] "GET /api/ HTTP/1.1" 403 58 "-" "python-requests/2.32.5"
x.x.x.x - - [08/Dec/2025:18:57:07 +0200] "GET /api/ HTTP/1.1" 403 26 "-" "python-requests/2.32.5"
x.x.x.x - - [08/Dec/2025:18:57:11 +0200] "GET /api/ HTTP/1.1" 200 609 "-" "python-requests/2.32.5"
= the last one with the correct token gets a 200, as expected.
Thanks for following up, @markkuleinio. I can reproduce what you're seeing. When using a valid token to instantiate a pynetbox.api object, the token is not actually being passed to the API call that is made via <api obj>.version. The feature continues to work, however, since the version is read from the API response headers, which is present even on 403 responses.
I'm assigning to you. Thanks for volunteering.