Skip to main content

Authenticated Server Route

Call Convex from Nitro with the incoming user's identity and a safe HTTP contract.

Result

A same-origin API route requires the Better Auth session, calls a protected Convex query, and maps failures without exposing credentials.

server/api/account/export.get.ts
import { api } from '#convex/api'
import { serverConvex } from '#convex/server'
import { ConvexCallError } from 'better-convex-nuxt/errors'

export default defineEventHandler(async (event) => {
  try {
    const account = await serverConvex(event, { auth: 'required' }).query(
      api.accounts.exportData,
      {},
    )

    setHeader(event, 'content-type', 'application/json')
    setHeader(event, 'cache-control', 'private, no-store')
    return account
  } catch (error) {
    if (error instanceof ConvexCallError && error.kind === 'authentication') {
      throw createError({ status: 401, statusText: 'Authentication required' })
    }
    throw createError({ status: 502, statusText: 'Export unavailable' })
  }
})

Security boundary

  • serverConvex exchanges only the request's relevant Better Auth cookies.
  • auth: 'required' refuses anonymous fallback.
  • accounts.exportData rechecks identity and product access.
  • The response is private and not cached.
  • Public errors do not contain cookies, tokens, or upstream bodies.

Verify

  • No-cookie request returns 401.
  • Valid session returns only that user's export.
  • Revoked/invalid session does not fall back to anonymous.
  • A transport failure returns the safe 502 contract.