The Registration Endpoint
Exit

The Registration Endpoint

Add a POST /register endpoint that creates user accounts

💻

Writing code and entering commands is only available on desktop. Open this page on a larger screen to complete this chapter.

The first endpoint that uses your auth module

Right now, auth.py has a User model and a hash_password function, but nothing in main.py uses them. The registration endpoint connects the two.

POST /register accepts an email and password as JSON, checks if the email is already taken, hashes the password, stores the user in the database, and returns the user's identifier and email. It never returns the password hash.

Why UserCreate is separate from User

You need a new model called UserCreate for the request body. You cannot reuse the User model because User is a database table with fields the client should never set directly — id (auto-generated) and password_hash (computed from the plain password). UserCreate has only two fields: email and password. This keeps the API surface clean and prevents clients from injecting values into fields they should not control.

Instructions

Add a registration endpoint to main.py.

  1. Add from auth import User, hash_password to the imports at the top of the file — this brings in the User model and the bcrypt hashing function you built in Lesson 1.
  2. Define a class called UserCreate that extends BaseModel with two fields: email: str and password: str. Place it below ErrorResponse. This is the shape of the JSON body that clients send when registering.
  3. Define the register endpoint with @app.post("/register", status_code=201) and def register(user_data: UserCreate, session: SessionDep): — the status_code=201 tells clients that a new resource (the user account) was created.
  4. Before creating the account, check if the email is already taken: existing = session.exec(select(User).where(User.email == user_data.email)).first() — this queries the database for any user with the same email.
  5. If existing is not None, someone already registered with that email — raise HTTPException(status_code=400, detail="Email already registered").
  6. Create the user object: user = User(email=user_data.email, password_hash=hash_password(user_data.password)) — notice you hash the password here, never storing the original.
  7. Save the user to the database with three calls: session.add(user) stages it, session.commit() writes it, and session.refresh(user) reloads the row so user.id is populated with the auto-generated value.
  8. Return {"id": user.id, "email": user.email} — only the identifier and email. Never include password_hash in API responses.