Home Reference API Endpoints

API Endpoints

Last updated on Jun 12, 2026

CHRIS uses Supabase's auto-generated REST API (PostgREST) for database operations.

Base URL

https://[PROJECT_REF].supabase.co/rest/v1

Authentication

All requests require authentication via JWT token.

Headers

Authorization: Bearer <JWT_TOKEN>
apikey: <SUPABASE_ANON_KEY>
Content-Type: application/json

Getting a Token

const { data: { session } } = await supabase.auth.getSession();
const token = session?.access_token;

Profiles

List Profiles

GET /profiles

Query parameters:

Parameter Description Example
select Columns to return *,teams(name)
status Filter by status eq.active
team_id Filter by team eq.<uuid>
order Sort order full_name.asc

Example:

GET /profiles?select=id,full_name,email,status&status=eq.active&order=full_name.asc

Get Single Profile

GET /profiles?id=eq.<uuid>

Update Profile

PATCH /profiles?id=eq.<uuid>
Content-Type: application/json

{
  "full_name": "John Doe",
  "team_id": "<team-uuid>"
}

Leave Requests

List Leave Requests

GET /leave_requests

Query parameters:

Parameter Description Example
user_id Filter by employee eq.<uuid>
status Filter by status eq.pending
start_date Filter by start gte.2025-01-01
end_date Filter by end lte.2025-12-31

Example with joins:

GET /leave_requests?select=*,profiles(full_name),leave_types(name_en)&status=eq.pending

Create Leave Request

POST /leave_requests
Content-Type: application/json

{
  "user_id": "<user-uuid>",
  "leave_type_id": "<type-uuid>",
  "start_date": "2025-02-01",
  "end_date": "2025-02-05",
  "working_days": 5,
  "reason": "Family vacation"
}

Update Leave Request (Approve/Reject)

PATCH /leave_requests?id=eq.<uuid>
Content-Type: application/json

{
  "status": "approved",
  "approver_user_id": "<approver-uuid>",
  "approver_comment": "Approved. Enjoy your vacation!",
  "approved_at": "2025-01-15T10:00:00Z"
}

Teams

List Teams

GET /teams?select=*,profiles!teams_lead_user_id_fkey(full_name)

Create Team

POST /teams
Content-Type: application/json

{
  "name": "Engineering",
  "lead_user_id": "<leader-uuid>"
}

Get Team Members

GET /profiles?team_id=eq.<team-uuid>&select=id,full_name,email

Translations

Get All Translations

GET /translations?select=key,croatian,english,russian,hindi

Get by Category

GET /translations?category=eq.common

Upsert Translation

POST /translations
Content-Type: application/json
Prefer: resolution=merge-duplicates

{
  "key": "common.save",
  "croatian": "Spremi",
  "english": "Save",
  "russian": "Сохранить",
  "hindi": "सहेजें",
  "category": "common"
}

Holiday Schemes

List Schemes

GET /holiday_schemes?is_active=eq.true&order=year.desc

Get Scheme with Holidays

GET /holiday_schemes?id=eq.<uuid>&select=*,holidays(*)

RPC Functions

Call database functions via RPC endpoint.

Get User Role

POST /rpc/get_user_role
Content-Type: application/json

{
  "_user_id": "<user-uuid>"
}

Response:

"admin"

Check If Team Leader

POST /rpc/is_team_leader
Content-Type: application/json

{
  "_user_id": "<user-uuid>"
}

Response:

true

Get Team Leadership

POST /rpc/get_team_leadership
Content-Type: application/json

{
  "_user_id": "<user-uuid>"
}

Response:

[
  {
    "team_id": "uuid-here",
    "team_name": "Engineering"
  }
]

Filtering Reference

PostgREST filtering operators:

Operator Description Example
eq Equals status=eq.active
neq Not equals status=neq.cancelled
gt Greater than working_days=gt.5
gte Greater or equal start_date=gte.2025-01-01
lt Less than working_days=lt.10
lte Less or equal end_date=lte.2025-12-31
like Pattern match full_name=like.*Smith*
ilike Case-insensitive like email=ilike.*@company.com
in In list status=in.(pending,approved)
is Is null/true/false end_date=is.null

Pagination

Use Range header for pagination:

GET /profiles
Range: 0-9

Returns items 0-9 (first 10).

Response includes:

Content-Range: 0-9/100

Error Responses

401 Unauthorized

{
  "message": "JWT expired",
  "code": "PGRST301"
}

403 Forbidden (RLS)

{
  "message": "new row violates row-level security policy",
  "code": "42501"
}

404 Not Found

{
  "message": "The result contains 0 rows",
  "code": "PGRST116"
}

TypeScript Client

Using the Supabase client is recommended over raw REST calls:

import { supabase } from '@/integrations/supabase/client';

// List profiles
const { data, error } = await supabase
  .from('profiles')
  .select('*, teams(name)')
  .eq('status', 'active')
  .order('full_name');

// Create leave request
const { data, error } = await supabase
  .from('leave_requests')
  .insert({
    user_id: userId,
    leave_type_id: typeId,
    start_date: '2025-02-01',
    end_date: '2025-02-05',
    working_days: 5
  })
  .select()
  .single();

// Call RPC function
const { data: role } = await supabase
  .rpc('get_user_role', { _user_id: userId });