API Documentation

Complete REST API reference for the ShiftPro healthcare workforce management platform.

🚀 Postman Collection

Test all 80+ endpoints instantly. Includes Auth, Admin, Hospital & Professional APIs.

Download Collection
BASE URL
https://shiftnew.jain.software/shift-api/public/api/v1

🔐 Authentication

â„šī¸
Bearer Token Authentication

All protected endpoints require a Bearer token. Include it in the header:
Authorization: Bearer YOUR_TOKEN

POST /auth/register Register new user

Request Body

{ "name": "City Hospital", "email": "admin@cityhospital.com", "password": "Secret@123", "password_confirmation": "Secret@123", "phone": "+919876543210", "user_type": "hospital", // or "professional" // If hospital: "hospital_name": "City Hospital", "registration_number": "REG-2024-001", "address": "123 Medical Lane", "city": "Mumbai", "state": "Maharashtra", "pincode": "400001", // If professional: "first_name": "John", "last_name": "Doe", "profession_type": "doctor", "specialization": "Cardiology" }
POST /auth/login User login

Request Body

{ "email": "admin@shiftapp.com", "password": "Admin@123" }

Response

{ "success": true, "message": "Login successful", "data": { "user": { "id": 1, "name": "Super Admin", ... }, "profile": { "id": 1, ... }, "subscription": { "id": 1, "plan": {...} }, "token": "1|xxxxxxxxxxxxx", "token_type": "Bearer" } }
POST /auth/login-mobile Login with Mobile & Passcode/OTP

Authenticate using phone number and either a Passcode (MPIN) or Firebase ID Token (for first-time/OTP login).

Request Body

{ "phone": "+919876543210", "passcode": "123456", // Optional if firebase_token used "firebase_token": "eyJhbG...", // Optional if passcode used "fcm_token": "optional_device_token...", "device_type": "android" }

Response

{ "success": true, "message": "Login successful", "data": { "user": { ... }, "token": "..." } }
GET /auth/profile Get current user profile
POST /auth/logout Logout and invalidate token

📊 Dashboard

GET /admin/dashboard Dashboard statistics

Response

{ "success": true, "data": { "hospitals": { "total": 4, "active": 3, "pending": 1, "growth": 12 }, "professionals": { "total": 150, "active": 120, "growth": 8 }, "shifts": { "total": 342, "active": 28, "cancelled": 5 }, "revenue": { "total": 1250000, "this_month": 185000, "growth": 15 } } }
GET /admin/dashboard/recent-activities Recent activity feed
GET /admin/dashboard/pending-verifications Pending KYC verifications

đŸĨ Hospitals

GET /admin/hospitals List all hospitals

Query Parameters

Parameter Description
page integer
Page number for pagination. Default: 1
per_page integer
Records per page. Default: 15
search string
Search by name, email, or phone
status string
Filter by status: active, inactive, pending
kyc_status string
Filter by KYC status: verified, pending, rejected
city string
Filter by city name

Response

{ "data": [ { "id": 1, "name": "City Hospital", "email": "admin@cityhosp.com", "phone": "9876543210", "status": "active", "kyc_status": "verified", "city": "Mumbai" } ], "meta": { "current_page": 1, "last_page": 5, "total": 50 } }
GET /admin/hospitals/{id} Get hospital details
POST /admin/hospitals Create new hospital

Request Body

{ "name": "City General Hospital", "email": "admin@citygeneral.com", "password": "Secret@123", "phone": "+919876543210", "registration_number": "REG-001", "address": "Park Ave", "city": "Mumbai", "state": "Maharashtra", "pincode": "400001" }
PUT /admin/hospitals/{id} Update hospital
DELETE /admin/hospitals/{id} Delete hospital
POST /admin/hospitals/{id}/verify-kyc Verify hospital KYC

Request Body

{ "status": "verified", // or "rejected" "remarks": "Documents verified successfully" }
POST /admin/hospitals/{id}/toggle-status Toggle active/inactive status

đŸ‘¨â€âš•ī¸ Professionals

GET /admin/professionals List all professionals

Query Parameters

Parameter Description
page integer
Page number (Default: 1)
search string
Search by name, email, phone
status string
active, inactive, pending
profession_type string
e.g. nurse, doctor

Response

{ "data": [ { "id": 1, "first_name": "John", "last_name": "Doe", "profession_type": "nurse", "status": "active", "verification_status": "verified" } ], "meta": { "total": 100 } }
GET /admin/professionals/{id} Get professional details
POST /admin/professionals/{id}/verify-kyc Verify professional KYC

📋 Shifts

GET /admin/shifts List all shifts

Query Parameters

Parameter Description
page integer
Page number (Default: 1)
hospital_id integer
Filter by Hospital ID
status string
draft, published, completed, cancelled
date_from date
YYYY-MM-DD start range

Response

{ "data": [ { "id": 101, "title": "Night Shift (ICU)", "hospital_name": "City Hospital", "shift_date": "2024-12-31", "start_time": "20:00", "status": "published", "positions_filled": 2, "positions_total": 5 } ], "meta": { "total": 25 } }
GET /admin/shifts/{id} Get shift details

💰 Finance

GET /admin/finance Finance overview
GET /admin/finance/transactions List transactions

Query Parameters

Parameter Description
page integer
Page number
type string
credit, debit, refund
status string
completed, pending, failed
GET /admin/finance/withdrawals List withdrawal requests
POST /admin/finance/withdrawals/{id}/process Process withdrawal

Request Body

{ "action": "approve", // or "reject" "remarks": "Processed successfully" }
GET /admin/finance/subscription-plans Get subscription plans

âš™ī¸ Settings

GET /admin/settings Get all settings
POST /admin/settings Update settings
GET /admin/settings/activity-logs Get activity logs
GET /admin/settings/system-health System health check

📅 Roster Management (Admin)

GET /admin/roster List rosters

Query Parameters

Parameter Description
hospital_id integer
Filter by Hospital ID
start_date date
Filter by start date
POST /admin/roster/auto-assign Auto-assign shifts

Request Body

{ "roster_id": 123, "strategy": "availability", "allow_overtime": false }
POST /admin/roster/import Import roster from CSV

Request Body

Multipart/form-data: file (CSV/Excel)

đŸĨ Hospital Portal - Profile & KYC

GET /hospital/profile Get hospital profile with stats

Response

{ "success": true, "data": { "id": 1, "name": "City Hospital", "email": "admin@city.com", "phone": "+919876543210", "hospital_type": "multi_specialty", "facilities": ["ICU", "OT"], "kyc_status": "verified", "logo_url": "https://..." } }
PUT /hospital/profile Update hospital profile

Request Body (form-data)

Field Type Description
name string Hospital name
hospital_type string government|private|multi_specialty|clinic
facilities JSON array ["ICU", "OT", "Emergency"]
logo file Image: jpeg,png,jpg max 2MB
latitude decimal -90 to 90
longitude decimal -180 to 180
POST /hospital/kyc/upload Upload KYC documents

Request Body (form-data)

Field Type Description
registration_document file PDF/Image max 5MB
license_document file Hospital License
gst_number file GST Certificate
pan_number file PAN Card
GET /hospital/kyc/status Get KYC verification status

Response

{ "success": true, "data": { "status": "verified", "remarks": "All documents approved", "documents": { "registration_document": "https://...", "license_document": "https://..." } } }

📊 Hospital Portal - Dashboard

GET /hospital/dashboard Dashboard with stats, attendance, shifts

Response

{ "success": true, "data": { "hospital": { "id": 5, "name": "City Hospital", ... }, "kyc_status": "verified", "wallet_balance": 15000.00, "subscription": { "plan": "Premium", "expires_at": "2025-12-31" }, "attendance": { "today_checked_in": 5, "today_completed": 3 }, "shifts": { "total": 50, "published": 10, "completed": 35 }, "stats": { "total_shifts": 156, "completed_shifts": 142, "professionals_hired": 48 }, "financial_overview": { "total_spent_this_month": 245000.00, "avg_cost_per_shift": 1570.00, "service_charges_paid": 24500.00 }, "pending_applications": 8, "recent_shifts": [...] } }
GET /hospital/stats Facility Statistics & Financial Overview

Response

{ "success": true, "data": { "facility_statistics": { "total_shifts": 156, "active_shifts": 12, "completed_shifts": 142, "professionals_hired": 48, "avg_rating": 4.7 }, "financial_overview": { "total_spent_this_month": 245000.00, "avg_cost_per_shift": 1570.00, "service_charges_paid": 24500.00, "total_spent_all_time": 500000.00 } } }

📋 Hospital Portal - Shifts

POST /hospital/fetch-shifts List hospital shifts (Paginated)

Request Body Parameters

Parameter Type Required Description
page integer No Page number (default: 1)
per_page integer No Items per page (default: 15)
limit integer No Alias for per_page
status string No draft|published|in_progress|completed|cancelled
filter_status string No today_shift|upcoming
shift_date date No Filter by date (YYYY-MM-DD)
profession_type string No Filter by profession type
search string No Search title, description, shift_code
sort_by string No Sort field (default: shift_date)
sort_order string No asc|desc (default: asc)

Response

{ "success": true, "data": [...], "pagination": { "current_page": 1, "per_page": 15, "total": 50, "last_page": 4, "from": 1, "to": 15, "has_more_pages": true }, "links": { "first": "...", "last": "...", "prev": null, "next": "..." } }
POST /hospital/shifts Create new shift

Request Body

Field Type Required Description
title string Yes Shift title, max 255
shift_date date Yes YYYY-MM-DD, today or future
start_time string Yes HH:mm (24hr format)
end_time string Yes HH:mm (after start_time)
profession_type string Yes doctor|nurse|technician|staff|paramedic
department_id integer No Department ID
positions_required integer Yes Min: 1
pay_type string Yes hourly|fixed
pay_rate decimal Yes Amount per hour/shift
priority string No normal|urgent|critical
is_night_shift boolean No Default: false
is_emergency boolean No Default: false
subscription_id integer No Active Sub ID (Auto-detected if omitted)

Response

{ "success": true, "message": "Shift created successfully", "data": { "id": 101, "shift_code": "SFT-20251227-ABC1", "title": "Night Shift ICU", "status": "draft", ... } }
GET /hospital/shifts/{id} Get shift details
PUT /hospital/shifts/{id} Update shift with wallet transactions

Update shift details. Handles wallet transactions when facility pay changes:
â€ĸ If extra_amount_to_pay > 0: Deducts immediately from wallet
â€ĸ If amount_to_refund > 0: Creates pending refund (credited after 7 days)

Request Body

Field Type Required Description
title string No Shift title, max 255
facility_pay decimal No New facility payment amount
service_charge_amount decimal No Service charge amount
extra_amount_to_pay decimal No Extra amount to deduct from wallet (when new > old facility_pay)
amount_to_refund decimal No Amount to refund (when old > new facility_pay). Refund credited after 7 days.

Response (with Deduction)

{ "success": true, "message": "Shift updated successfully", "data": { ... }, "wallet_transaction": { "type": "deduction", "transaction_id": "TXN-XXXX...", "amount": 500.00, "new_balance": 4500.00 } }

Response (with Pending Refund)

{ "success": true, "message": "Shift updated successfully", "data": { ... }, "refund_details": { "type": "refund_pending", "refund_id": "REF-XXXX...", "original_amount": 1000.00, "service_charge_deducted": 100.00, "refund_amount": 900.00, "available_at": "2026-02-04T12:00:00Z", "remaining_days": 7, "message": "Refund of ₹900.00 will be credited after 7 days" } }

Error Response (Insufficient Balance)

{ "success": false, "message": "Insufficient wallet balance. Required: ₹500.00", "required_amount": 500.00, "current_balance": 200.00 } // Status: 402 Payment Required
GET /hospital/shifts/{id}/applications Get shift applications

Response

{ "success": true, "data": [ { "id": 201, "status": "pending", "professional": { "id": 55, "first_name": "John", "rating": 4.8, "is_favorite": true } } ] }
GET /hospital/applications/{id} Get application details

Response

{ "success": true, "data": { "id": 201, "cover_note": "I am available.", "status": "pending", "professional": { ... }, "shift": { ... } } }
POST /hospital/shifts/{id}/cancel Cancel shift (with refund logic)
GET /hospital/shifts-completed List completed shifts
POST /hospital/shifts/{shift}/applications/{app} Accept/Reject application

đŸĸ Hospital Portal - Departments

GET /hospital/departments List departments
POST /hospital/departments Create department

Request Body

Field Type Required Description
name string Yes e.g., "Cardiology"
description string No Dept description

Response

{ "success": true, "data": { "id": 12, "name": "Cardiology", "active": true } }
PUT /hospital/departments/{id} Update department
DELETE /hospital/departments/{id} Delete department

đŸĨ Hospital Portal - Vacancies

POST /hospital/fetchVacancies List all vacancies (paginated, with applications)

Query Parameters

Parameter Type Required Description
per_page integer No Items per page (default: 10)
page integer No Page number

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "hospital_id": 5, "role": "nurse", "employment_type": "full-time", "job_title": "Senior ICU Nurse", "job_description": "...", "state": "Maharashtra", "city": "Mumbai", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "experience": 3, "status": "active", "applications": [ { "id": 10, "status": "applied", "professional": { "id": 12, "first_name": "Jane", ... } } ] } ], "total": 5, ...pagination } }
POST /hospital/vacancies Create a vacancy

Request Body

Field Type Required Description
role string Yes Job role (e.g. nurse, doctor, technician)
employment_type string Yes Full-time, Part-time, Contract, etc.
job_title string Yes Title of the job
job_description string Yes Detailed description
state string Yes State
city string Yes City
minimum_salary double Yes Min salary
maximum_salary double Yes Max salary
experience integer Yes Years of experience required
requirements string Yes Job requirements
benefits string Yes Job benefits
subscription_id integer No Active Sub ID (Auto-detected if omitted)

Response

{ "success": true, "message": "Vacancy created successfully", "data": { ... Vacancy object ... } }
GET /hospital/vacancies/{id} Get a single vacancy

Response

{ "success": true, "data": { ... Vacancy object ... } }
PUT /hospital/vacancies/{id} Update a vacancy

Request Body

Field Type Required Description
role string No Job role
employment_type string No Full-time, Part-time, etc.
job_title string No Title of the job
job_description string No Detailed description
state string No State
city string No City
minimum_salary double No Min salary
maximum_salary double No Max salary
experience integer No Years of experience required
requirements string No Job requirements
benefits string No Job benefits
status string No active | closed

Response

{ "success": true, "message": "Vacancy updated successfully", "data": { ... Vacancy object ... } }
DELETE /hospital/vacancies/{id} Delete a vacancy

Response

{ "success": true, "message": "Vacancy deleted successfully" }
GET /hospital/vacancies/{id}/applications List applications for a vacancy

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 10, "vacancy_id": 1, "professional_id": 12, "status": "applied", "professional": { "id": 12, "first_name": "Jane", ... } } ], "total": 8, ...pagination } }
POST /hospital/vacancies/{vacancy}/applications/{application} Update application status

Request Body

Field Type Required Description
status string Yes shortlisted | accepted | rejected | hired

Response

{ "success": true, "message": "Application status updated to hired" }
POST /hospital/fetchVacancyApplications Fetch ALL applications across all vacancies
â„šī¸
No vacancy_id needed

Uses authenticated hospital's ID to fetch applications across ALL vacancies. Each application includes full vacancy and professional details.

Request Body (all optional filters)

Field Type Required Description
status string|array No Filter: applied, shortlisted, accepted, rejected, hired
vacancy_id integer No Optionally filter to a specific vacancy
search string No Search by professional name, email, or vacancy title/role
from_date date No Applied from (YYYY-MM-DD)
to_date date No Applied to (YYYY-MM-DD)
per_page integer No Items per page (default: 10)
page integer No Page number

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 10, "vacancy_id": 1, "professional_id": 12, "status": "applied", "created_at": "2026-02-20T10:00:00Z", "vacancy": { "id": 1, "role": "nurse", "employment_type": "full-time", "job_title": "Senior ICU Nurse", "state": "Maharashtra", "city": "Mumbai", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "experience": 3, "status": "active" }, "professional": { "id": 12, "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com", "phone": "+919876543210", "profile_photo": "url" } } ], "total": 25, ...pagination } }

đŸ’ŗ Hospital Portal - Subscription

GET /hospital/subscription Get current subscription
GET /hospital/subscription-plans Get available plans
POST /hospital/subscription/subscribe Subscribe to plan

Request Body

Field Type Required Description
plan_id integer Yes ID of the plan
duration_months integer Yes 1, 6, or 12

Response

{ "success": true, "message": "Subscription successful", "data": { "status": "active", "expires_at": "2025-12-31" } }
GET /hospital/subscription/check-shift-limit Check Shift Limit
GET /hospital/subscription/check-roster-limit Check Roster Limit
GET /hospital/subscription/check-vacancy-limit Check Vacancy Limit
GET /hospital/subscription/check-sos-limit Check SOS Limit

✅ Hospital Portal - Attendance

GET /hospital/attendances List attendance records (Paginated)

Query Parameters

Parameter Type Required Description
page integer No Page number (default: 1)
per_page integer No Items per page (default: 15)
limit integer No Alias for per_page
date date No Filter by specific date (YYYY-MM-DD)
date_from date No Filter from date
date_to date No Filter to date
status string No pending|checked_in|completed|no_show
GET /hospital/shift-attendance Get attendance for shifts
POST /hospital/attendance/mark Manual attendance marking

Request Body

Field Type Required Description
shift_id integer Yes Shift ID
professional_id integer Yes Professional ID
status string Yes checked_in|completed|no_show
remarks string No Attendance notes

Response

{ "success": true, "message": "Attendance marked successfully" }

📅 Shift Extensions

GET /hospital/shift-extensions List extensions
POST /hospital/shift-extensions Request extension

Request Body

{ "application_id": 123, "start_date": "2026-02-01", "end_date": "2026-02-03" }
POST /hospital/shift-extensions/{id}/action Approve/Reject Professional Request

Request Body

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

💰 Hospital Portal - Wallet

GET /hospital/wallet Get wallet balance and recent transactions

Response

{ "success": true, "data": { "wallet": Wallet, "recent_transactions": Transaction[] } }
GET /hospital/transactions Get transaction history with filtering

Query Parameters

Field Type Required Description
type string No credit | debit
category string No shift_payment, wallet_topup, refund, etc.
date_from date No YYYY-MM-DD
date_to date No YYYY-MM-DD
per_page integer No Default 20
POST /hospital/wallet/create-topup-order Create Razorpay order for wallet topup

Request Body

Field Type Required Description
amount decimal Yes Amount to add (Min 100)

Response

{ "success": true, "data": { "order_id": "order_Obs8...", "amount": 1000, "currency": "INR", "key_id": "rzp_test_..." } }
POST /hospital/wallet/verify-topup-payment Verify Razorpay payment and credit wallet
â„šī¸
Two-Step Payment Flow

Step 1 (Pending): Send only razorpay_order_id + amount → creates pending transaction.
Step 2 (Complete): Send all 4 params → finds existing pending record and completes it, or creates a new completed record.

Request Body

Field Type Required Description
razorpay_order_id string Yes From create-topup-order
razorpay_payment_id string No From Razorpay SDK (omit for pending flow)
razorpay_signature string No From Razorpay SDK (omit for pending flow)
amount decimal Yes Amount paid

Response (Pending)

{ "success": true, "message": "Transaction created with pending status.", "data": { "wallet": Wallet, "transaction": { "status": "pending", ... } } }

Response (Completed)

{ "success": true, "message": "Payment successful. Funds added to wallet.", "data": { "wallet": Wallet, "transaction": { "status": "completed", ... } } }
POST /hospital/wallet/withdraw Request withdrawal (Bank/UPI)

Request Body

Field Type Required Description
amount decimal Yes Min 100
payment_method string Yes bank_transfer | upi
bank_name string No* Bank name (* required for bank_transfer)
account_number string No* Account number (* required for bank_transfer)
ifsc_code string No* IFSC code (* required for bank_transfer)
account_holder_name string No Account holder name
upi_id string No* UPI ID (* required for upi)

Response

{ "success": true, "message": "Withdrawal request submitted successfully", "data": { "id": 1, "amount": 500.00, "status": "pending" } }
GET /hospital/wallet/withdrawals Get withdrawal request history

Query Parameters

Field Type Required Description
per_page integer No Items per page (default: 15)

Response

{ "success": true, "data": { "data": WithdrawalRequest[], ...pagination } }

💰 Wallet Refunds

Track pending and completed refunds from shift edits. Refunds are credited to wallet after a 7-day waiting period.

GET /hospital/wallet/refunds List pending and completed refunds

Query Parameters

Parameter Type Required Description
status string No pending|processing|completed|cancelled|failed
per_page integer No Items per page (default: 15)

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "refund_id": "REF-XXXXXXXXXXXX", "original_amount": 1000.00, "service_charge_deducted": 100.00, "refund_amount": 900.00, "status": "pending", "reason": "Shift edit refund", "requested_at": "2026-01-28T12:00:00Z", "available_at": "2026-02-04T12:00:00Z", "remaining_days": 7 } ] }, "summary": { "total_pending": 1, "total_pending_amount": 900.00, "total_completed": 5, "total_completed_amount": 4500.00 } }

Refund Status Lifecycle

Status Description
pending Refund created, waiting for 7-day period
processing Refund is being processed
completed Refund credited to wallet
cancelled Refund was cancelled
failed Refund processing failed

📅 Hospital Portal - Roster Management

POST /hospital/roster Create a new roster

Request Body

Field Type Required Description
roster_name string Yes Name of roster
start_date date Yes YYYY-MM-DD
end_date date Yes YYYY-MM-DD
roster_type string Yes daily|weekly|monthly|custom
department_id integer No Department ID
subscription_id integer No Active Sub ID (Auto-detected if omitted)
created_roster array No Array of roster entries

🚨 Hospital Portal - Emergency SOS

â„šī¸
Emergency SOS Flow

Hospitals can create urgent shift requests with extra pay incentives. Professionals who respond within the urgency deadline receive bonus pay on shift completion. The extra amount is deducted from the hospital wallet upfront.

GET /hospital/emergency-sos/tiers Get available urgency tiers (for dropdown)

Returns the admin-configured urgency tiers with their extra pay percentages. Use this to populate the tier selection dropdown when creating an Emergency SOS.

Response

{ "success": true, "data": [ { "key": "under_2_hours", "label": "Under 2 Hours", "minutes": 120, "extra_pay_percent": 30 }, { "key": "under_1_hour", "label": "Under 1 Hour", "minutes": 60, "extra_pay_percent": 50 }, { "key": "under_30_mins", "label": "Under 30 Minutes", "minutes": 30, "extra_pay_percent": 75 } ] }
POST /hospital/emergency-sos Create Emergency SOS for a Shift

Creates an emergency SOS tied to a specific shift. The system calculates extra pay based on the selected urgency tier percentage × professional_receive × remaining positions, then deducts the total from the hospital wallet. Professionals within range are notified.

Request Body

Field Type Required Description
shift_id integer Yes The shift that needs urgent staffing
urgency_tier string Yes under_2_hours | under_1_hour | under_30_mins (from tiers endpoint)
radius_km integer Yes KM range for professional notifications (1-500)
additional_message string No Optional message to professionals (max 1000 chars)
subscription_id integer No Active Sub ID (auto-detected if omitted)

Response (201)

{ "success": true, "message": "Emergency SOS created successfully", "data": { "sos": { "id": 1, "shift_id": 42, "urgency_tier": "under_1_hour", "extra_pay_percent": 50, "extra_pay_amount_per_professional": 500.00, "total_extra_amount": 1000.00, "urgency_deadline": "2026-02-28T14:00:00Z", "status": "sent", "recipients_count": 15 }, "wallet_transaction": { "transaction_id": "TXN-ABCDEF123456", "amount_deducted": 1000.00, "new_balance": 4000.00 }, "tier_config": { "key": "under_1_hour", "label": "Under 1 Hour", ... }, "urgency_deadline": "2026-02-28T14:00:00+05:30", "professionals_notified": 15 } }

Error Responses

Code Description
400 Shift already has active SOS / All positions filled
402 Insufficient wallet balance (returns required vs available)
403 Free SOS limit exhausted, subscription required
422 Invalid urgency tier
GET /hospital/emergency-sos List hospital's Emergency SOS requests

Query Parameters

Field Type Required Description
per_page integer No Default: 10

Response

{ "success": true, "data": { "data": [ { "id": 1, "shift_id": 42, "urgency_tier": "under_1_hour", "extra_pay_percent": 50, "total_extra_amount": 1000.00, "urgency_deadline": "2026-02-28T14:00:00Z", "status": "sent", "responses_count": 3, "shift": { "id": 42, "shift_code": "SH-XYZ", ... } } ], ...pagination } }
GET /hospital/emergency-sos/{id} Get SOS details with applications

Returns the SOS details along with all applications linked to this SOS, showing which professionals are eligible for extra pay.

Response

{ "success": true, "data": { "id": 1, "urgency_tier": "under_1_hour", "urgency_deadline": "2026-02-28T14:00:00Z", "extra_pay_percent": 50, "total_extra_amount": 1000.00, "status": "sent", "shift": { ... }, "applications": [ { "id": 10, "eligible_for_extra_pay": true, "extra_pay_amount": 250.00, "professional": { "first_name": "John", ... } } ] } }
POST /hospital/wallet/emergency-sos-refund Request refund for unfilled Emergency SOS

Hospital can request a refund for the extra amount paid for an Emergency SOS when no professional has applied. The request will be reviewed by admin.

Request Body

Field Type Required Description
transaction_id string Yes The wallet transaction_id from SOS creation (e.g. TXN-ABCDEF123456)
shift_id integer Yes Shift ID linked to the SOS
refund_amount decimal Yes Amount to refund (cannot exceed original transaction)
description string Yes Reason for refund request (max 1000 chars)

Response (201)

{ "success": true, "message": "Emergency SOS refund request submitted successfully. It will be reviewed by admin.", "data": { "id": 5, "refund_id": "REF-XXXXXXXXXXXX", "refund_amount": 1000.00, "status": "pending", "reason": "emergency_sos_refund" } }
💡
How Extra Pay Works

When professional applies: If the shift has an active Emergency SOS, the system checks if the application is within the urgency deadline. The eligible_for_extra_pay and extra_pay_amount (per day) fields are set on the application automatically.

On shift completion: After all attendance days are completed, the professional receives their regular shift payment plus the emergency extra pay (if eligible) as a separate emergency_sos_extra_pay wallet transaction.

Application response includes:

{ "emergency_info": { "is_emergency_shift": true, "eligible_for_extra_pay": true, "extra_pay_per_day": 250.00, "total_extra_pay": 500.00, "urgency_tier": "under_1_hour", "urgency_deadline": "2026-02-28T14:00:00+05:30", "applied_within_deadline": true } }

👤 Professional Portal - Profile & KYC

GET /professional/profile Get profile with stats
PUT /professional/profile Update profile

Key Fields (form-data)

Field Type Description
qualifications JSON array ["MBBS", "MD"]
certifications JSON array ["ACLS", "BLS"]
skills JSON array ["IV Therapy"]
available_days JSON array ["monday","friday"]
profile_photo file Image max 2MB
face_id_photo file Face verification photo
POST /professional/kyc/upload Upload KYC documents
GET /professional/kyc/status Get KYC verification status

📊 Professional Portal - Dashboard

GET /professional/dashboard Dashboard with stats, earnings, upcoming shifts

Response

{ "success": true, "data": { "professional": { "id": 1, "first_name": "John", ... }, "kyc_status": "verified", "wallet_balance": 25000.00, "rating": 4.8, "reliability_score": 95, "today_attendance": { "check_in_time": "08:00", ... } | null, "applications": { "pending": 3, "accepted": 5, "rejected": 2 }, "upcoming_shifts": [...], "stats": { "completed_shifts": 45, "cancelled_shifts": 2, "monthly_earnings": 35000, "total_earnings": 450000 } } }

🔍 Professional Portal - Find Shifts

GET /professional/shifts Find available shifts
GET /professional/shifts/{id} View shift details
POST /professional/shifts/{id}/apply Apply for shift

Response

{ "success": true, "message": "Application submitted successfully" }
GET /professional/shifts-upcoming My upcoming shifts
GET /professional/shifts-completed My completed shifts

📝 Professional Portal - Applications

GET /professional/my-applications List my applications
POST /professional/applications/{id}/withdraw Withdraw pending application

đŸ‘¨â€âš•ī¸ Professional Portal - Vacancies

POST /professional/fetchVacancies Search/List active vacancies

Request Body (all optional filters)

Field Type Required Description
search string No Search in job_title, role, or hospital name
role string|array No Filter by role
employment_type string|array No Filter by employment type
state string|array No Filter by state
city string|array No Filter by city
min_salary decimal No Minimum salary filter
max_salary decimal No Maximum salary filter
from_date date No Created from (YYYY-MM-DD)
to_date date No Created to (YYYY-MM-DD)
per_page integer No Items per page (default: 10)

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "job_title": "Senior ICU Nurse", "role": "nurse", "employment_type": "full-time", "state": "Maharashtra", "city": "Mumbai", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "status": "active", "hospital": { "id": 5, "name": "City Hospital", ... }, "hasApplied": true, "myApplication": { "id": 10, "status": "applied" } | null } ], ...pagination } }
GET /professional/vacancies/{id} View vacancy details

Response

{ "success": true, "data": { "id": 1, "job_title": "Senior ICU Nurse", "role": "nurse", "employment_type": "full-time", "job_description": "...", "requirements": "...", "benefits": "...", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "hospital": { "id": 5, "name": "City Hospital", ... } }, "application_status": "applied" | null }
POST /professional/vacancies/{id}/apply Apply for vacancy

Response

{ "success": true, "message": "Applied successfully" }
POST /professional/my-vacancy-applications List my vacancy applications

Request Body (optional filters)

Field Type Required Description
status string|array No Filter: applied, shortlisted, accepted, rejected, hired
per_page integer No Items per page (default: 10)
page integer No Page number

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 10, "vacancy_id": 1, "professional_id": 12, "status": "applied", "vacancy": { "id": 1, "job_title": "Senior ICU Nurse", "hospital": { "id": 5, "name": "City Hospital" } } } ], ...pagination } }

✅ Professional Portal - Check-in/out

POST /professional/shifts/{id}/check-in Check-in with geofence (500m)

Request Body

{ "latitude": 19.0760, "longitude": 72.8777, "photo": "BASE64_SELFIE" }
POST /professional/shifts/{id}/check-out Check-out with hours calculation
GET /professional/my-attendance My attendance history

💰 Professional Portal - Earnings

GET /professional/earnings Earnings summary with monthly breakdown

Response

{ "success": true, "data": { "total_earnings": 450000.00, "pending_earnings": 15000.00, "this_month": 35000.00, "last_month": 42000.00, "monthly_breakdown": [ { "month": "Dec 2024", "earnings": 35000 }, { "month": "Nov 2024", "earnings": 42000 }, ... ], "wallet_balance": 25000.00 } }
GET /professional/wallet Wallet balance
POST /professional/wallet/withdraw Request withdrawal

Request Body

Field Type Required Description
amount decimal Yes Amount to withdraw
payment_method string Yes bank_transfer|upi

Response

{ "success": true, "message": "Withdrawal request submitted", "data": { "request_id": 123, "amount": 5000, "status": "pending", "new_balance": 20000 } }
GET /professional/my-reviews Reviews received

📅 Shift Extensions

GET /professional/shift-extensions List extensions
POST /professional/shift-extensions Request extension

Request Body

{ "application_id": 123, "start_date": "2026-02-01", "end_date": "2026-02-03" }
POST /professional/shift-extensions/{id}/action Accept/Reject Hospital Request

Request Body

{ "action": "accept" // or "reject" }

â„šī¸ Content & Support

GET /content/terms Get Terms and Conditions
GET /content/privacy-policy Get Privacy Policy
GET /content/faqs Get FAQs
GET /content/contact-info Get Help & Support Info

🔔 Notifications

The system sends push notifications via Firebase Cloud Messaging (FCM). Ensure fcm_token is updated for the user.

Notification Categories & Logic

Type (Key) Trigger Recipient
new_shift Hospital publishes a shift Professionals (Verified, Role, City, Rated)
new_vacancy Hospital creates a vacancy Professionals (Verified, Role)
roster Roster created/published Assigned Staff
attendance Check-in/out & Reminders Hospital & Professional
sos Emergency SOS Professionals (City/Location)
extension Shift Extension Hospital & Professional
admin_action Verification / Status User
support_ticket Ticket updates Creator
application_message Chat / Staff Request Recipient
shift_application App Accept/Reject Applicant / Hospital
vacancy_application App Updates Applicant / Hospital
GET /common/notifications Get user notifications
GET /common/notifications/unread-count Get unread count
PATCH /common/notifications/{id}/read Mark as read
POST /common/notifications/mark-all-read Mark all as read

âš ī¸ Error Handling

All error responses follow this format:

{ "success": false, "message": "Error description", "errors": { "field_name": ["Validation error message"] } }
Status Code Description
200 Success
201 Created
400 Bad Request - Invalid parameters
401 Unauthorized - Invalid or missing token
403 Forbidden - Insufficient permissions
404 Not Found - Resource doesn't exist
422 Validation Error
500 Server Error

🔐 Face ID Management

â„šī¸
Face Recognition

Store and manage face IDs (embeddings) for biometric verification during check-in/check-out.

User Self-Management

GET /common/face-ids Get my face IDs

Response

{ "success": true, "data": { "id": 1, "user_id": 5, "face_ids": [ { "embedding": [...], "label": "front" }, { "embedding": [...], "label": "left" } ], "total_faces_stored": 2, "is_active": true } }
POST /common/face-ids Add face IDs

Request Body

Field Type Required Description
face_data array|object Yes Face embeddings - single object or array of objects
primary_face_image file No Primary face photo (max 5MB)

Example Request

{ "face_data": [ { "embedding": [0.1, 0.2, ...], "label": "front" }, { "embedding": [0.3, 0.4, ...], "label": "left" } ] }
PUT /common/face-ids Replace all face IDs
DELETE /common/face-ids/{index} Remove face ID by index
DELETE /common/face-ids/clear Clear all face IDs
POST /common/face-ids/toggle-status Toggle face ID active status

Admin Management

GET /admin/users/{userId}/face-ids Get user's face IDs (Admin)
POST /admin/users/{userId}/face-ids Add face IDs for user (Admin)
Field Type Required Description
face_data array|object Yes Face embeddings
primary_face_image file No Primary face photo (max 5MB)
notes string No Admin notes (max 500 chars)
POST /admin/users/{userId}/face-ids/toggle-status Toggle status (Admin)
DELETE /admin/users/{userId}/face-ids Delete user's face IDs (Admin)

Simplified Face ID API (Google ML)

📱
Simple Face ID Storage

For Google ML face recognition. Stores face_id as JSON array in longtext column.

GET /common/face Fetch user's face IDs

Response

{ "success": true, "data": { "user_id": 5, "face_id": ["face_embedding_1", "face_embedding_2"], "count": 2 } }
POST /common/face Store face IDs
Field Type Required Description
face_id array|string Yes Face ID(s) to store (JSON encoded)
append boolean No If true, append to existing. Default: replace all
DELETE /common/face Delete face IDs
Query Param Type Required Description
index integer No Delete specific index only. Otherwise deletes all.

Admin Endpoints

GET /admin/users/{userId}/face Fetch user's face IDs (Admin)
POST /admin/users/{userId}/face Store face IDs for user (Admin)
DELETE /admin/users/{userId}/face Delete user's face IDs (Admin)

đŸ’Ŧ Messaging

GET /common/conversations Get user conversations

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "conversation_id": "CONV-ABC123XYZ", "participant_one_type": "App\\Models\\Hospital", "participant_one_id": 1, "participant_two_type": "App\\Models\\Professional", "participant_two_id": 5, "shift_id": 10, "application_id": 100, "last_message_at": "2024-01-01T12:00:00.000000Z", "is_archived": false, "unread_count": 2, "shift_application": { ... } } ], "total": 1 } }
POST /common/conversations/get-or-create Get or Create Conversation

Request Body

{ "participant_type": "professional", "participant_id": 5, "shift_id": 10, "application_id": 100 }

Response

{ "success": true, "data": { "id": 1, "conversation_id": "CONV-...", "shift_application": { ... } } }
GET /common/conversations/{id}/messages Get messages

Response

{ "success": true, "data": { "data": [ { "id": 10, "content": "Hello", "sender_type": "App\\Models\\Hospital" } ] } }
POST /common/conversations/{id}/messages Send message

Request Body

{ "content": "Hello", "type": "text", "attachment": null }

📋 Common - Vacancies (By Hospital ID)

â„šī¸
Fetch Vacancies by Hospital

These endpoints allow any authenticated user to fetch vacancy data for a specific hospital. Useful for viewing a hospital's open vacancies.

POST /common/fetch-hospital-vacancies Fetch vacancies by hospital ID

Request Body

Field Type Required Description
hospital_id integer Yes Hospital User ID
status string|array No Filter: active, closed
search string No Search in job_title and role
role string|array No Filter by role (e.g. nurse, doctor)
employment_type string|array No Filter by employment type
state string|array No Filter by state
city string|array No Filter by city
min_salary decimal No Minimum salary filter
max_salary decimal No Maximum salary filter
from_date date No Created from (YYYY-MM-DD)
to_date date No Created to (YYYY-MM-DD)
per_page integer No Items per page (default: 10)
page integer No Page number

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 1, "hospital_id": 5, "role": "nurse", "employment_type": "full-time", "job_title": "Senior ICU Nurse", "job_description": "Looking for experienced...", "state": "Maharashtra", "city": "Mumbai", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "experience": 3, "requirements": "BSc Nursing, ACLS", "benefits": "Health insurance", "status": "active", "hospital": { "id": 5, "name": "City Hospital", "email": "admin@cityhospital.com", "profile_photo": "url" }, "total_applications": 8, "applications_by_status": { "applied": 5, "shortlisted": 2, "hired": 1 }, "applications": [ ... ] } ], "total": 12, ...pagination } }
GET /common/vacancies/{id} Get vacancy detail with applications

Response

{ "success": true, "data": { "id": 1, "hospital_id": 5, "role": "nurse", "employment_type": "full-time", "job_title": "Senior ICU Nurse", "job_description": "...", "state": "Maharashtra", "city": "Mumbai", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "experience": 3, "requirements": "...", "benefits": "...", "status": "active", "hospital": { "id": 5, "name": "City Hospital", "email": "admin@cityhospital.com", "profile_photo": "url" }, "total_applications": 8, "applications_by_status": { "applied": 5, "shortlisted": 2, "hired": 1 }, "applications": [ { "id": 10, "status": "applied", "professional": { "id": 12, "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com", "phone": "+919876543210", "profile_photo": "url" } } ] } }
POST /common/fetch-hospital-vacancy-applications Fetch all applications for a hospital's vacancies

Request Body

Field Type Required Description
hospital_id integer Yes Hospital User ID
status string|array No Filter: applied, shortlisted, accepted, rejected, hired
vacancy_id integer No Filter by specific vacancy ID
search string No Search by professional name or vacancy title/role
from_date date No Applied from (YYYY-MM-DD)
to_date date No Applied to (YYYY-MM-DD)
per_page integer No Items per page (default: 10)
page integer No Page number

Response

{ "success": true, "data": { "current_page": 1, "data": [ { "id": 10, "vacancy_id": 1, "professional_id": 12, "status": "applied", "created_at": "2026-02-20T10:00:00Z", "vacancy": { "id": 1, "hospital_id": 5, "role": "nurse", "employment_type": "full-time", "job_title": "Senior ICU Nurse", "state": "Maharashtra", "city": "Mumbai", "minimum_salary": 35000.00, "maximum_salary": 55000.00, "status": "active" }, "professional": { "id": 12, "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com", "phone": "+919876543210", "profile_photo": "url" } } ], "total": 25, ...pagination } }

🔗 Webhooks

Public webhook endpoints for third-party payment callbacks. These routes do not require authentication — signature verification is handled internally.

POST /webhooks/razorpay Handle Razorpay payment webhook
🔒
Public Endpoint — No Auth Required

Webhook signature is verified using X-Razorpay-Signature header and the RAZORPAY_WEBHOOK_SECRET env variable configured in Razorpay Dashboard.

Webhook URL for Razorpay Dashboard

https://shiftnew.jain.software/shift-api/public/api/v1/webhooks/razorpay

Supported Events

Event Description
payment.captured Processes confirmed payment — finds or creates transaction, credits wallet

Flow

Step Action
1 Verifies webhook signature from X-Razorpay-Signature header
2 Extracts order_id, payment_id, amount from payload
3 Finds existing transaction by order_id:
â€ĸ Pending → updates to completed, credits wallet
â€ĸ Already completed → returns success (idempotent)
â€ĸ Not found → creates new completed transaction using hospital_id from notes
4 Sends wallet recharge notification to user

Response

{ "success": true, "message": "Webhook processed successfully" }

đŸ“Ļ Data Models & Field Types

💡
Array Fields

The following fields are JSON arrays and should be sent/received as arrays:

Hospital Model - Array Fields

Field Type Example
facilities string[] ["ICU", "OT", "Emergency", "Pharmacy"]
departments string[] ["Cardiology", "Neurology"] (legacy)
images string[] ["path/to/img1.jpg", "path/to/img2.jpg"]

Professional Model - Array Fields

Field Type Example
qualifications string[] ["MBBS", "MD - Cardiology"]
certifications string[] ["ACLS", "BLS", "PALS"]
skills string[] ["IV Therapy", "Ventilator", "ECG"]
available_days string[] ["monday", "tuesday", "friday"]
additional_documents string[] ["path/cert1.pdf", "path/cert2.pdf"]

Enum Field Values

Field Model Valid Values
hospital_type Hospital government | private | multi_specialty | clinic
kyc_status Both pending | verified | rejected
status Both pending | active | suspended
profession_type Professional doctor | nurse | technician | staff | paramedic
experience_level Professional junior | mid | senior | expert
availability_status Professional available | busy | unavailable
gender Professional male | female | other
id_proof_type Professional aadhaar | pan | passport | driving_license | voter_id
shift.status Shift draft | published | in_progress | completed | cancelled
shift.pay_type Shift hourly | fixed
shift.priority Shift normal | urgent | critical
attendance.status Attendance pending | checked_in | completed | no_show

🤝 Referrals (Admin)

GET /admin/referrals/settings Get referral settings

Response

{ "success": true, "data": { "referral_bonus": 50, "referee_bonus": 25, "coin_exchange_rate": 1.0 } }
POST /admin/referrals/settings Update settings & exchange rate

Request Body

{ "referral_bonus": 50, "referee_bonus": 25, "coin_exchange_rate": 1.0 }

đŸĻ Virtual Accounts (Admin)

GET /admin/virtual-accounts List virtual accounts
POST /admin/virtual-accounts Create virtual account

Request Body

{ "accountable_type": "hospital", "accountable_id": 12, "name": "City Hospital Main", "has_mandate": true, "mandate_max_amount": 50000 }
POST /admin/virtual-accounts/{id}/activate-mandate Activate mandate

âš ī¸ Low Amount Alerts (Admin)

GET /admin/low-amount-alerts List alerts
POST /admin/low-amount-alerts/{id}/review Review alert

Request Body

{ "status": "reviewed", "notes": "Verified manually" }

ShiftPro API v1.0 â€ĸ Last updated: December 2025

← Back to Homepage