API Live

Shift Leader API

Integrate your time clock, payroll, or scheduling system with Shift Leader.

Base URL: https://shiftleader-api.eternalremedy35.workers.dev

Auth: All endpoints require a Bearer token. Get one via POST /auth/login

Format: JSON request/response. Set Content-Type: application/json

Rate Limits: 200 shifts/day, 5 reports/day, 2 locations/day per user

Contact: [email protected] · (843) 617-9450

Authentication

POST /auth/login

Get a JWT token (valid 30 days).

// Request
{ "email": "[email protected]", "password": "secret" }

// Response
{ "token": "eyJ...", "user": { "id": "...", "name": "...", "role": "manager" } }

Include the token in all subsequent requests:

Authorization: Bearer eyJ...

POST /auth/signup

Create a new account.

{ "email": "[email protected]", "password": "min6chars", "name": "Full Name", "role": "employee" }

User Profile

GET /me

Get current user profile, locations, and department memberships.

PUT /me

Update profile: name, phone, timezone, notification_email, notification_sms

Locations

POST /locations

Create a new location. Auto-upgrades user to manager.

{ "name": "KJ's Market #659", "address": "123 Main St", "timezone": "America/New_York", "category": "Grocery" }

POST /join

Join a location by invite code.

{ "invite_code": "ABC123", "role": "employee", "department_id": "optional" }

GET /locations/{id}/members

List all team members with roles, titles, avatar, shifts covered.

Departments

GET /locations/{id}/departments

List departments at a location.

POST /locations/{id}/departments

Create a department. Manager-only.

{ "name": "Emergency Room" }

POST /locations/{id}/departments/{deptId}/members

Add a user to a department.

{ "user_id": "abc123", "is_primary": true }

Shifts

POST /shifts

Create a shift. Manager-only. Supports direct assignment and department scoping.

{
  "location_id": "loc_abc",
  "department_id": "dept_xyz",     // optional — scopes to department
  "title": "Morning Cashier",
  "shift_date": "2026-04-14",
  "start_time": "08:00",
  "end_time": "16:00",
  "slots_needed": 1,
  "urgency": "normal",             // low | normal | high | critical
  "assign_to": "user_id_here"      // optional — direct assignment
}

GET /shifts?location_id=X&status=open&department_id=mine

List shifts. Filters: location_id, status, date, department_id (mine = user's departments + location-wide).

GET /shifts/{id}

Get shift details with claims. Managers see all claims; employees see only theirs.

PUT /shifts/{id}

Update a shift. Manager-only.

{ "title": "Updated Title", "start_time": "09:00", "end_time": "17:00" }

DELETE /shifts/{id}

Cancel a shift. Notifies assigned employees.

Claims

POST /shifts/{id}/claim

Claim an open shift.

PUT /shifts/{shiftId}/claims/{claimId}

Approve or deny a claim. Manager-only.

{ "status": "approved" }  // or "denied"

Budget Tracking

GET /locations/{id}/budget?week_of=2026-04-12

Get budget vs scheduled vs actual hours for a week, broken down by department and by day.

// Response
{
  "location_budget": 180,
  "total_scheduled": 175.5,
  "total_actual": 82.0,
  "total_status": "good",        // good | warning | over
  "departments": [...],
  "daily": [
    { "date": "2026-04-12", "day": "Sun", "scheduled": 42, "actual": 40.5 },
    ...
  ]
}

PUT /locations/{id}/budget

Set budget hours. Store Manager only for location-wide; dept managers for their own dept.

{
  "location_budget": 800,
  "departments": [
    { "department_id": "dept_meat", "budget_hours": 180 },
    { "department_id": "dept_deli", "budget_hours": 120 }
  ]
}

Import

POST /import-schedule

AI-powered schedule parsing. Send text or a base64 image — returns structured shifts for preview.

{
  "location_id": "loc_abc",
  "text": "Mon 8am-4pm Patricia\nTue 9am-5pm Van",
  "image_base64": "data:image/png;base64,..."    // or text, not both required
}

// Response: preview to confirm before creating
{
  "shifts": [
    { "employee_name": "Patricia", "shift_date": "2026-04-13", "start_time": "08:00", "end_time": "16:00", "matched": true },
    ...
  ]
}

POST /locations/{id}/import-hours

Import actual hours from a CSV export. Manager-only.

{
  "csv_text": "Name, Date, Hours\nPatricia, 4/12/2026, 8.5\nVan, 4/12/2026, 9.0"
}

Notifications

GET /notifications

List notifications. Optional: ?unread_only=1

PUT /notifications/read-all

Mark all notifications as read.

Trust & Safety

POST /report

Report a user or shift. 3+ reports = auto-suspension.

{ "reported_user_id": "abc", "location_id": "loc_xyz", "reason": "Posting fake shifts" }

POST /locations/{id}/approve-manager/{userId}

Approve or deny a pending manager. Existing manager only.

{ "action": "approve" }  // or "deny"

Integration Examples

Connect your system

// 1. Authenticate once
const res = await fetch('https://shiftleader-api.eternalremedy35.workers.dev/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: '[email protected]', password: 'secret' })
});
const { token } = await res.json();

// 2. Push actual hours from your time clock system
await fetch('https://shiftleader-api.eternalremedy35.workers.dev/locations/YOUR_LOC_ID/import-hours', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
  body: JSON.stringify({ csv_text: 'Patricia,4/12/2026,8.5\nVan,4/12/2026,9.0' })
});

// 3. Pull the current schedule
const shifts = await fetch('https://shiftleader-api.eternalremedy35.workers.dev/shifts?location_id=YOUR_LOC_ID', {
  headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());