Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Ishaq74/concordia/llms.txt

Use this file to discover all available pages before exploring further.

Profile API

The Profile API allows authenticated users to view and update their profile information. Profiles are automatically created on first access.

Authentication

All endpoints require:
  • Valid user session
  • Session cookie or Bearer token
Authorization: Bearer <session-token>

Get user profile

Retrieve the authenticated user’s profile. If no profile exists, one is created automatically. Endpoint: GET /api/profile
curl -X GET https://your-domain.com/api/profile \
  -H "Authorization: Bearer <session-token>"
Response:
id
string
Profile UUID
userId
string
User ID (references auth user table)
fullName
string
User’s full name
bio
text
User biography/description
avatarUrl
string
Profile picture URL
location
string
User location (city, region)
website
string
User website URL
preferredLanguage
string
Preferred language code: "fr", "en", "ar", or "es"
createdAt
timestamp
Profile creation timestamp
updatedAt
timestamp
Last update timestamp
Example response:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "userId": "auth-user-id",
  "fullName": "Marie Dubois",
  "bio": "Community organizer and urban gardener",
  "avatarUrl": "https://example.com/avatars/marie.jpg",
  "location": "Lyon, France",
  "website": "https://marie-gardens.fr",
  "preferredLanguage": "fr",
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-03-20T14:22:00Z"
}

Update user profile

Update the authenticated user’s profile. Only specified fields are updated. Endpoint: PATCH /api/profile
curl -X PATCH https://your-domain.com/api/profile \
  -H "Authorization: Bearer <session-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "fullName": "Marie Dubois",
    "bio": "Community organizer and urban gardener",
    "location": "Lyon, France",
    "preferredLanguage": "fr"
  }'
Request Body: All fields are optional. Only provided fields will be updated.
fullName
string
User’s full name
bio
text
Biography or description
avatarUrl
string
Profile picture URL
location
string
Location (city, region, country)
website
string
Personal website URL
preferredLanguage
string
Language preference: "fr", "en", "ar", or "es"
Security: Only the authenticated user can update their own profile. The userId field cannot be changed and is enforced by the API.
Response: Returns the updated profile object with the same structure as GET.
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "userId": "auth-user-id",
  "fullName": "Marie Dubois",
  "bio": "Community organizer and urban gardener",
  "location": "Lyon, France",
  "preferredLanguage": "fr",
  "updatedAt": "2024-03-20T15:45:00Z"
}

Auto-creation behavior

When a user first accesses their profile via GET /api/profile:
  1. Profile exists: Returns existing profile
  2. No profile: Automatically creates one with:
    • fullName populated from auth user’s name
    • preferredLanguage set to "fr" (default)
    • Other fields set to null
This ensures every authenticated user has a profile without requiring explicit creation.

Validation rules

The API validates update requests:
  • Allowed fields only: Only the 6 editable fields can be updated
  • No userId changes: The userId field is immutable
  • Type checking: Fields must match expected types
  • SQL injection prevention: All inputs are parameterized
Attempting to update disallowed fields will silently ignore them.

Response codes

200
success
Profile retrieved or updated successfully
400
error
Invalid request body (malformed JSON)
401
error
Unauthorized - valid session required
500
error
Database error or internal server error

Error responses

{
  "error": "AUTH_UNAUTHORIZED"
}
{
  "error": "invalid_json"
}

Implementation reference

Source: /src/pages/api/profile/index.ts The profile endpoint:
  • Uses Better Auth session validation
  • Queries the profile table with Drizzle ORM
  • Auto-creates profiles on first GET request
  • Validates updates against a whitelist of allowed fields
  • Sets security headers (X-Content-Type-Options: nosniff)

Database schema

The profile table structure:
profile {
  id: uuid (primary key)
  userId: text (foreign keyuser.id, unique)
  fullName: text
  bio: text
  avatarUrl: text
  location: text
  website: text
  preferredLanguage: text (default: 'fr')
  createdAt: timestamp (default: now())
  updatedAt: timestamp (default: now())
}
The preferredLanguage field integrates with the i18n system. When set, the application UI will display in the user’s preferred language across all routes.

See also

Build docs developers (and LLMs) love