Hi,
I try to use the v2 api with python 3.7. I use the script below to create a post but I always get the error ‘Invalid token’. Tried many things but with no success. What’s wrong with my code?
Kind regards,
Jacques Bopp
import json
import requests
import jwt # https://pyjwt.readthedocs.io
import datetime
key = 'my:admin_key' # Admin API keys can be obtained by creating a new Custom Integration
id, secret = key.split(':') *# Split the API key by the : into an id and a secret*
secret = bytes.fromhex(secret) # Decode the hexadecimal secret into the original binary byte array
now = int(datetime.datetime.now().timestamp())
payload = {'iat': now,'exp': now+(5*60),'aud': '/v2/admin/'} # Timestamps are seconds sine the unix epoch: 'iat': 'now', 'exp': Max 5 minutes after 'now'
token = jwt.encode({'payload': payload}, secret, algorithm='HS256', headers={'alg': 'HS256', 'kid': id, 'typ': 'JWT'})
url = 'https://mydomain.com/ghost/api/v2/admin/posts/'
body = {'posts': [{'title': 'Hello World'}]}
headers = {'Authorization': 'Ghost {}'.format(token)}
r = requests.post(url, data=json.dumps(body), headers=headers)
# r.content = b'{"errors":[{"message":"Invalid token","context":null,"type":"BadRequestError","details":null,"property":null,"help":null,"code":"INVALID_JWT","id":"b77efe10-d3e7-11e9-b529-c11e6c33226b"}]}'
Was very close to working, have fixed the issues and included below:
payload should be given to jwt.encode directly, not as an object
token is a python3 byte string, so the authorization header was was being sent as Ghost b'long-token-here'. Calling token.decode() fixes this.
Once the token was fixed it became clear requests wasn’t sending the data as json. One solution was to add a “content-type: application/json” header, but more elegant is to remove the json lib and use requests built-in ability to serialize json.
import requests
import jwt # https://pyjwt.readthedocs.io
import datetime
key = 'my:admin_key' # Admin API keys can be obtained by creating a new Custom Integration
id, secret = key.split(':') # Split the API key by the : into an id and a secret*
secret = bytes.fromhex(secret) # Decode the hexadecimal secret into the original binary byte array
now = int(datetime.datetime.now().timestamp())
payload = {'iat': now,'exp': now+(5*60),'aud': '/v2/admin/'} # Timestamps are seconds sine the unix epoch: 'iat': 'now', 'exp': Max 5 minutes after 'now'
token = jwt.encode(payload, secret, algorithm='HS256', headers={'alg': 'HS256', 'kid': id, 'typ': 'JWT'})
url = 'http://localhost:2368/ghost/api/v2/admin/posts/'
body = {'posts': [{'title': 'Hello World'}]}
headers = {'Authorization': 'Ghost {}'.format(token.decode())}
r = requests.post(url, json=body, headers=headers)
print(r)
I’d like to get this example added to our API docs
Sounds like something is wrong with the code syntax rather than the key. Have you checked that the correct quote symbols are being used around the string?