-
Notifications
You must be signed in to change notification settings - Fork 33
Closed
clerk/openapi-specs
#42Description
Version: clerk-backend-api 1.7.0
Possible related issue: #67
Summary: Passing in expires_in_seconds
(as int or float) into clerk_client.create_session_token
results in 400
Application: Testing backend auth
ERROR - Failed to create session token using SDK: API error occurred: Status 400
{"errors":[{"message":"Request body invalid","long_message":"The request body is invalid. Please consult the API documentation for more information."
,"code":"request_body_invalid"}],"clerk_trace_id":"2efb09d4de0199f552e1616b597cf0eb"}
Here is code basis to reproduce, which includes a working manual request method and the non-working sdk method:
"""Utility for creating Clerk session tokens"""
import logging
from typing import Optional
import httpx
from clerk_backend_api import Clerk
logger = logging.getLogger(__name__)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)
def _create_session_token_sdk(clerk_client: Clerk, session_id: str) -> Optional[str]:
"""Create a session token using the Clerk SDK (currently not working)"""
try:
token_response = clerk_client.sessions.create_session_token(
session_id=session_id,
expires_in_seconds=3600,
)
return token_response.jwt if token_response else None
except Exception as e:
logger.error(f"Failed to create session token using SDK: {str(e)}")
return None
def _create_session_token_manual(clerk_client: Clerk, session_id: str) -> Optional[str]:
"""Create a session token using direct HTTP request"""
try:
url = f"https://api.clerk.com/v1/sessions/{session_id}/tokens"
headers = {
"Authorization": f"Bearer {clerk_client.sdk_configuration.security.bearer_auth}",
"Content-Type": "application/json",
}
payload = {"expires_in_seconds": 3600}
response = httpx.post(url, json=payload, headers=headers)
if response.status_code == 200:
return response.json()["jwt"]
else:
logger.error(f"Failed to create session token: {response.status_code}")
logger.error(f"Response: {response.text}")
return None
except Exception as e:
logger.error(f"Failed to create session token manually: {str(e)}")
return None
def create_session_token(clerk_client: Clerk, clerk_user_id: str) -> Optional[str]:
"""Create a session token for a Clerk user"""
try:
# First create a session for the user
logger.info(f"Creating session for user {clerk_user_id}")
session = clerk_client.sessions.create_session(
request={
"user_id": clerk_user_id,
}
)
if not session:
logger.error(f"Failed to create session for user {clerk_user_id}")
return None
logger.info(f"Created session {session.id}, creating token...")
# Using manual approach for now as SDK method is not working
jwt = _create_session_token_manual(clerk_client, session.id)
# jwt = _create_session_token_sdk(clerk_client, session.id)
logger.info(f"Created session token for session {session.id}")
return jwt
except Exception as e:
logger.error(f"Failed to create session: {str(e)}")
return None
Metadata
Metadata
Assignees
Labels
No labels
Activity
owentran commentedon Feb 1, 2025
I see the same issue with clerk-backend-api==1.7.2. I have to comment out expires_in_seconds to avoid the 400 invalid body error.
hsteidel commentedon Feb 25, 2025
I think I found the problem.
The issue is that the body model is typed to a
float
but the Service Side API wants anint
Using the debugger and overriding the value to an
int
BEFORE the SDK builds and serialized the request works.Using the API page and trying out the same call confirms my suspicion that it wants an
int
https://clerk.com/docs/reference/backend-api/tag/Sessions#operation/CreateSessionTokenFromTemplate
alexmavr commentedon Jul 17, 2025
+1 on this issue