Skip to main content
POST
/
api
/
threads
curl -X POST 'http://localhost:5079/api/threads' \
  -H 'Authorization: Bearer YOUR_JWT_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"title": "New Conversation"}'
{
  "thread_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "user_id": "user-uuid-here",
  "title": "New Conversation",
  "visibility": "private",
  "created_at": "2024-01-15T10:30:00.000Z",
  "updated_at": "2024-01-15T10:30:00.000Z"
}

Authentication

Required: JWT Bearer token JWT Claims Extraction (Lines 72-91):
sub | ClaimTypes.NameIdentifier → User UUID (required)
email | ClaimTypes.Email → User email
full_name | name | ClaimTypes.Name → Display name

Request Body

title
string
Thread titleValidation: None (controller accepts null or any string, Line 94)Default: null allowed (service may generate default title)Max Length: Not enforced by API contract

Response

thread_id
string
UUID identifier for created thread
user_id
string
Owner UUID (matches authenticated user)
title
string
Thread title (as provided or service-generated)
visibility
string
Default visibility (implementation-defined, likely "private")
created_at
string
ISO8601 UTC timestamp
updated_at
string
ISO8601 UTC timestamp
curl -X POST 'http://localhost:5079/api/threads' \
  -H 'Authorization: Bearer YOUR_JWT_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"title": "New Conversation"}'
{
  "thread_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "user_id": "user-uuid-here",
  "title": "New Conversation",
  "visibility": "private",
  "created_at": "2024-01-15T10:30:00.000Z",
  "updated_at": "2024-01-15T10:30:00.000Z"
}

Side Effects

Database Mutations (Lines 92-94):
  1. users table UPSERT (Lines 83-92):
    await _userSyncService.EnsureUserExistsAsync(userId.Value, email, name);
    
    • Timing: Happens before thread creation
    • Purpose: Ensures users table row exists (FK constraint requirement)
    • Idempotent: UPSERT operation
    • Failure: Would bubble to 500 error
  2. threads table INSERT (Line 94):
    await _threadsService.CreateThreadAsync(request?.Title, userId);
    
    • INSERT new thread row
    • Sets user_id = userId from JWT
    • Sets visibility to default value (service-defined)
    • Generates thread_id UUID
    • Sets created_at and updated_at timestamps
No Cascade Effects: Thread created empty (no messages yet)

Permissions

Who Can Create:
  • Any authenticated user
Ownership:
  • Thread user_id set to authenticated user’s UUID
  • Cannot create threads for other users

Validation

Title Validation (Line 94):
  • null allowed
  • Empty string allowed
  • Whitespace-only allowed
  • No length constraints enforced by controller
User ID Validation (Lines 78-81):
  • MUST be valid GUID from JWT
  • MUST exist in JWT claims
  • Returns 401 if missing or invalid

Authorization

Creation Rights:
  • Authenticated user can create unlimited threads
  • No quota enforcement by controller
Initial Visibility:
  • Set by service (not specified in controller)
  • Assumed default: "private"

Edge Cases

  1. Null title: Allowed, service may generate default (Line 94)
  2. Empty title: Allowed
  3. Very long title: Not validated by controller (database column limit may apply)
  4. Duplicate title: Allowed (titles not unique)
  5. User doesn’t exist in database: Synced before creation (Lines 92)
  6. User sync fails: 500 error (blocks thread creation)

Error Conditions

CodeHTTPCauseController Line
N/A401JWT missing or invalidMiddleware
N/A401User ID claim missing/invalid78-81
THREAD_CREATE_ERROR500User sync failure98-106
THREAD_CREATE_ERROR500Thread creation failure98-106
THREAD_CREATE_ERROR500Database constraint violation98-106
Exception Handling (Lines 98-106):
catch (Exception ex) {
    return StatusCode(500, new { error = ex.Message, code = "THREAD_CREATE_ERROR" });
}
  • All exceptions return 500
  • Error message exposed to client

Behavioral Guarantees

Atomicity: Not enforced by controller code
  • User sync and thread creation not wrapped in transaction
  • User sync failure blocks thread creation
  • Thread creation failure leaves user synced (not rolled back)
Idempotency: NOT idempotent
  • Each call creates new thread (even with same title)
  • No deduplication logic

Database Schema Dependencies

Foreign Key: threads.user_idusers.id Constraint Enforcement: User must exist before thread creation (Line 92)