API Reference

Complete API documentation for the Lakra system. All API calls are made through the Supabase JavaScript client.

Overview

Lakra uses Supabase client libraries for all backend operations. The API is organized into modules:

  • Authentication API - User authentication

  • Sentences API - Sentence management

  • Annotations API - Annotation operations

  • Evaluations API - Evaluation operations

  • Quality Assessments API - AI quality assessments

  • Admin API - Administrative functions

Authentication

Located in src/services/supabase-api.ts

authAPI

login(credentials)

Sign in a user with email or username.

Parameters:

{
  identifier: string;  // email or username
  password: string;
  isUsername?: boolean; // true if identifier is username
}

Returns:

{
  user: User;
  session: Session;
  error: null | Error;
}

Example:

const { user, error } = await authAPI.login({
  identifier: 'user@example.com',
  password: 'password123'
});

register(userData)

Register a new user.

Parameters:

{
  email: string;
  password: string;
  username?: string;
  fullName?: string;
  role: 'annotator' | 'evaluator';
}

logout()

Sign out the current user.

getCurrentUser()

Get the currently authenticated user with profile data.

Returns:

{
  id: string;
  email: string;
  username?: string;
  role: string;
  // ... other user fields
}

updatePassword(newPassword)

Update user password.

Sentences

sentencesAPI

getSentences(filters)

Fetch sentences with optional filtering.

Parameters:

{
  languagePair?: {source: string, target: string};
  domain?: string;
  activeOnly?: boolean;
  limit?: number;
  offset?: number;
}

Returns: Array of sentence objects

Example:

const sentences = await sentencesAPI.getSentences({
  languagePair: {source: 'en', target: 'fil'},
  activeOnly: true,
  limit: 20
});

getSentenceById(id)

Fetch a specific sentence by ID.

getNextSentence(userId)

Get the next unannotated sentence for a user.

Returns: Sentence object or null

createSentence(sentenceData)

Create a new sentence (admin only).

Parameters:

{
  sourceText: string;
  machineTranslation: string;
  sourceLanguage: string;
  targetLanguage: string;
  domain?: string;
  context?: string;
  backTranslation?: string;
  isActive?: boolean;
}

updateSentence(id, updates)

Update an existing sentence (admin only).

deleteSentence(id)

Delete a sentence (admin only).

importSentencesFromCSV(csvData)

Bulk import sentences from CSV data (admin only).

Parameters:

{
  csvData: Array<{
    source_text: string;
    machine_translation: string;
    source_language: string;
    target_language: string;
    domain?: string;
  }>;
}

Returns:

{
  successful: number;
  failed: number;
  errors: Array<{row: number, error: string}>;
}

Annotations

annotationsAPI

createAnnotation(annotationData)

Create a new annotation.

Parameters:

{
  sentenceId: string;
  fluencyScore: number;      // 1-5
  adequacyScore: number;     // 1-5
  overallQualityScore: number; // 1-5
  comments?: string;
  suggestedCorrection?: string;
  voiceRecordingUrl?: string;
  timeSpentSeconds?: number;
  textHighlights?: Array<{
    startPosition: number;
    endPosition: number;
    highlightedText: string;
    errorType: 'MI_ST' | 'MI_SE' | 'MA_ST' | 'MA_SE';
    errorDescription?: string;
    suggestedFix?: string;
  }>;
}

Returns: Created annotation object

Example:

const annotation = await annotationsAPI.createAnnotation({
  sentenceId: 'uuid-here',
  fluencyScore: 4,
  adequacyScore: 4,
  overallQualityScore: 4,
  comments: 'Good translation overall',
  textHighlights: [
    {
      startPosition: 0,
      endPosition: 5,
      highlightedText: 'Hello',
      errorType: 'MI_ST',
      errorDescription: 'Missing punctuation'
    }
  ]
});

getMyAnnotations(userId, options)

Get all annotations by a specific user.

Parameters:

{
  limit?: number;
  offset?: number;
  status?: 'draft' | 'completed' | 'under_review';
}

getAnnotationById(id)

Fetch a specific annotation with all related data.

Returns:

{
  id: string;
  sentence: Sentence;
  fluencyScore: number;
  // ... all annotation fields
  textHighlights: TextHighlight[];
  evaluations: Evaluation[];
}

updateAnnotation(id, updates)

Update an existing annotation (before evaluation).

deleteAnnotation(id)

Delete an annotation (before evaluation).

getAnnotationsBysentence(sentenceId)

Get all annotations for a specific sentence.

Evaluations

evaluationsAPI

createEvaluation(evaluationData)

Create a new evaluation of an annotation.

Parameters:

{
  annotationId: string;
  accuracyScore: number;      // 1-5
  completenessScore: number;  // 1-5
  overallQualityScore: number; // 1-5
  feedback: string;
  strengths?: string;
  improvementsNeeded?: string;
  missedErrors?: string[];
  incorrectClassifications?: string[];
  timeSpentSeconds?: number;
}

getMyEvaluations(evaluatorId, options)

Get all evaluations by a specific evaluator.

getPendingEvaluations(evaluatorId, options)

Get annotations awaiting evaluation.

Returns: Array of annotations without evaluations from this evaluator

getEvaluationById(id)

Fetch a specific evaluation.

getEvaluationsForAnnotation(annotationId)

Get all evaluations for a specific annotation.

Quality Assessments

qualityAssessmentsAPI

createQualityAssessment(assessmentData)

Create an AI quality assessment for a sentence.

Parameters:

{
  sentenceId: string;
  evaluatedBy?: string;
  // AI scores populated by backend AI service
}

getQualityAssessment(sentenceId)

Get quality assessment for a sentence.

validateQualityAssessment(id, validation)

Validate/modify an AI quality assessment.

Parameters:

{
  humanFluencyScore: number;
  humanAdequacyScore: number;
  humanOverallScore: number;
  humanFeedback: string;
  validationStatus: 'confirmed' | 'rejected' | 'modified';
}

Admin Functions

adminAPI

getStats()

Get system-wide statistics.

Returns:

{
  totalUsers: number;
  usersByRole: {admin: number, annotator: number, evaluator: number};
  totalSentences: number;
  totalAnnotations: number;
  totalEvaluations: number;
  averageQualityScores: {
    fluency: number;
    adequacy: number;
    overall: number;
  };
  recentActivity: Array<Activity>;
}

getAllUsers(options)

Get all users (admin only).

Parameters:

{
  role?: string;
  isActive?: boolean;
  limit?: number;
  offset?: number;
}

createUser(userData)

Create a new user (admin only).

Parameters:

{
  email: string;
  username?: string;
  password: string;
  role: 'admin' | 'annotator' | 'evaluator';
  fullName?: string;
}

updateUser(userId, updates)

Update user profile (admin only).

deleteUser(userId)

Delete a user (admin only).

getAnnotationMetrics(options)

Get detailed annotation metrics.

Parameters:

{
  startDate?: Date;
  endDate?: Date;
  annotatorId?: string;
  languagePair?: {source: string, target: string};
}

Returns:

{
  totalAnnotations: number;
  averageTimePerAnnotation: number;
  errorDistribution: {
    MI_ST: number;
    MI_SE: number;
    MA_ST: number;
    MA_SE: number;
  };
  qualityTrends: Array<{date: string, avgScore: number}>;
}

Storage (Voice Recordings)

storageAPI

uploadVoiceRecording(file, annotationId)

Upload voice recording to Supabase Storage.

Parameters:

{
  file: File; // Audio file (WebM, MP3, etc.)
  annotationId: string;
}

Returns:

{
  url: string; // Public or signed URL
  path: string; // Storage path
}

Example:

const { url } = await storageAPI.uploadVoiceRecording(
  audioBlob,
  annotationId
);

getVoiceRecordingUrl(path)

Get a signed URL for a voice recording.

Returns: Temporary signed URL (expires in 1 hour)

deleteVoiceRecording(path)

Delete a voice recording from storage.

Error Handling

All API functions return errors in a consistent format:

{
  data: null,
  error: {
    message: string;
    code?: string;
    details?: any;
  }
}

Common Error Codes:

  • PGRST116 - No rows found

  • 23505 - Unique violation

  • 42501 - Insufficient privilege (RLS policy)

  • 08006 - Connection failure

Example Error Handling:

const { data, error } = await annotationsAPI.createAnnotation(annotationData);

if (error) {
  if (error.code === '23505') {
    console.error('Duplicate annotation');
  } else {
    console.error('Error:', error.message);
  }
  return;
}

// Use data
console.log('Annotation created:', data);

Real-Time Subscriptions

Subscribe to database changes (optional feature):

// Subscribe to new annotations
const subscription = supabase
  .channel('annotations')
  .on(
    'postgres_changes',
    {
      event: 'INSERT',
      schema: 'public',
      table: 'annotations'
    },
    (payload) => {
      console.log('New annotation:', payload.new);
    }
  )
  .subscribe();

// Unsubscribe
subscription.unsubscribe();

Rate Limiting

Supabase applies rate limiting:

  • Anonymous requests: 100/hour

  • Authenticated requests: 500/hour

For production, configure appropriate limits in Supabase dashboard.

Best Practices

  1. Always handle errors - Check for error objects on every API call

  2. Use TypeScript - Type safety prevents many runtime errors

  3. Implement loading states - Show loading indicators during API calls

  4. Optimize queries - Use selective field fetching, pagination

  5. Cache when appropriate - Store frequently accessed data client-side

  6. Debounce user input - Prevent excessive API calls during typing

  7. Handle offline scenarios - Graceful degradation when network fails

See Also