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.
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
serverConvexexchanges only the request's relevant Better Auth cookies.auth: 'required'refuses anonymous fallback.accounts.exportDatarechecks 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.