Convex + Python
I'm creating an application with a python (FastAPI) backend and wanted to access data from my convex db with python. I've seen a bunch of conflicting approaches on how to do this online so was looking for some advice/best practices.
26 Replies
The convex PyPI package is the best way to do this: https://pypi.org/project/convex/. There are some upgrades coming very soon to it, but the API will be very nearly compatible so it'll be an optional upgrade with instructions about how to change your code in the case that something needs to be changed.
@yashvisal what are you seeing online, do you have other questions about this? Except for some rare use cases this should be what just about everyone using Python with Convex is using.
Ah it's working now, not quite sure what went wrong the first time
I'm having a little trouble with the auth token though, where exactly can I find that?
What kind of auth token do you need, or what are you trying to do? .set_token() is for JWTs, usually obtained in web browsers to identify a specific user. If your FastAPI server is receiving requests from browsers then how to get this token depends in how you authenticate your users.
You may not need an auth token, in which case you could add an argument to your functions fir a secret ket shared with the FastAPI server
I'm not entirely sure, I was just trying to tets out accessing data from my db in a python notebook like in the picture attached

but when that didn't work the error said it was a problem with auth so I tried messing around with the auth token which didn't really get me anywhere either
I'm just trying to play around with it to better understand how I can implement it into my fastapi python code
Ah cool, what's does the implementation of
getSearch
look like in documents
?export const getSearch = query({
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
throw new Error("Not authenticated");
}
const userId = identity.subject;
const documents = await ctx.db
.query("documents")
.withIndex("by_user", (q) => q.eq("userId", userId))
.filter((q) => q.eq(q.field("isArchived"), false))
.order("desc")
.collect();
return documents; } }); --- it was one of my simpler queries so I was trying to use that to get a hang of how to better work with convex in python
return documents; } }); --- it was one of my simpler queries so I was trying to use that to get a hang of how to better work with convex in python
@yashvisal the
ctx.auth
makes more sense for end users, not scripts; you need to have a JWT token (usually obtained through a web browser)
Since you're writing a server, you probably want to get this token from browsers? You could send it in in the network requests bound for your FastAPI server.
Or you can use your build-in authentication and not use ctx.auth.getUserIdentity()
at all; implementing identity using whatever method you already use instead of the JWT-based cx.auth
I'm sorry I don't quite understand, I'm using convex for auth and was just doing that for error handling which has been working fine in my fully typescript program
and the aim is to deal with multiple end users so isn't this the best way to do that?
@yashvisal sorry I keep back slowly to these! How are you doing authentication in your web app?
"Using Convex for auth" sounds like you're using Clerk or Auth0 or similar from the browser?
The two options I think of here are:
1. Write separate endpoints for
a. public Convex queries, mutations etc. that can be called from the browser (and use
ctx.auth
) and
b. queries+mutations that require an extra argument for a secret only the server knows. Then these don't require per-user auth.
It's nice that from your Python server you can do things that wouldn't be safe from the browser because no user should have permissions to do them, e.g. ban a user. These functions are only callable from your Python backend so don't use ctx.auth.
Or
2. Use the same functions everywhere. Send in the JWT in network requests from the browser to your FastAPI server so that that JWT can be used with the Python client.
I'm not sure I'm following what you're trying to do totally, it sounds like option 2?Yes sorry I meant to say clerk not convex, my bad 😅
For more information, I started with the tutorial for the notion clone that was posted on this server and am trying to extend that with some additional AI capability that I’ve written in python
But for those to function as well as possible they’d need to access information from my convex db
So if I did step 2 and did it with the JWT then there’d be no auth issues and I’d be able to access all data/functions from my typescript side in python with my FastAPI application?
Sorry this is my first full stack application so I’m still trying to figure out the intricacies of it all
@yashvisal If you do option 2 when you call any of the functions you call from your frontend from Python they should work the same way
This might be a stupid question but how do exactly can I go about doing that second option?
If you're using clerk, these might already be in your request cookies. I'd start with looking at the cookies in the HTTP requests being made to your FastAPI server.
If they aren't there, then you need to get the JWT in the browser. That will involve changing the auth code a bit. Clerk has docs on this, generally it's
getToken({ template: "convex" })
, something like that. Which Clerk library are you using?so if it’s already there then I wouldn’t have to change anything?
I’m using clerk-react
I don't think clerk-reacts adds it since there's nothing server-side going on
@yashvisal Could you say more about what you're doing, why you want user-authed functions from a Python server?
I just want to make sure I'm not pointing you the wrong way for your big picture goals
sending in JWTs is totally reasonable, that's how Clerk's e.g. Next.js integration works
So essentially, the foundation of my application is a notion clone for which I’m using convex but I want to use the data from that to use as context for my LLM pipelines that I’m creating in my FastAPI application with langchain
Maybe another question is what kind sof things do you do on your Python server
cool!
Primarily just using langchain for the most part
so you have endpoints like "I'm this user, go fetch whatever context is relevant for me and do langchain-y stuff"
yes exactly
and you could gather that context from the client side and send it in in the request, but why send data to the browser that the user doens't really need, just request it from the server
ok makes sense to me, unfortunately we don't have off-the-shelf demos for grabbing JWTs. Clerk docs should have more, you want to call that
getToken
function right before making the network request and send it along.
Make sure to create new Python http clients for each request, since auth is a stateful thing
client.set_auth("token-from-authetication-flow")
after running that line every query, mutation, and action made by this client instance will send in that authSo basically I need to figure out how to get the JWTs from Clerk and then use that token to set auth after initializing the ConvexClient and then I should be able to access queries from my db?
That's right.
Something like
Okay perfect! This has been really useful, I really appreciate it
I’ll try this out and let you know if I come across any difficulties