Session Handler Control Center

Realtime API synchronization and platform monitoring dashboard

System Online
A
Dynamic Integration Guide

API Documentation

Use this guide to connect external Laravel platforms to the Session Handler using dynamic platform registration, manifest fetching, record pulling, webhook receiving, realtime dashboard monitoring, Laravel Scheduler, and queue-based background processing.

Receiver Online
GET Fetch platform status, manifest, modules, fields, old records, and dashboard realtime data.
POST Receive new records, manually queue Pull All Existing Records, and test platform connections.
PATCH Receive updated record data from connected platforms without creating duplicate records.

Session Handler Receiver Endpoint

This endpoint is used by external platforms for realtime sending. Use POST for newly created records and PATCH for updated records.

Receiver URL
https://session-handler.bmwaresd.com/api/webhook/receive
New Record POST
Update Record PATCH
Platform Detection X-API-KEY

Required Headers for Webhook Sending

External platforms must include these headers when pushing data to the Session Handler.

Accept: application/json
Content-Type: application/json
X-API-KEY: SESSION_HANDLER_GENERATED_API_KEY
ngrok-skip-browser-warning: true
Reminder: The API key identifies the platform automatically. The request body no longer needs platform_name.

Latest System Updates

These are the current important updates applied to the Session Handler dashboard and API workflow.

1

Dashboard browser AJAX now only refreshes display/status data through GET /dashboard/realtime.

2

Browser JavaScript must not automatically POST Pull All Existing Records every few seconds.

3

Pull All Existing Records now runs only when the user manually clicks the button or when Laravel Scheduler starts it server-side.

4

Heavy pulling is handled using Laravel queue jobs so the dashboard does not reload or freeze.

5

Reverb can be disabled safely. When disabled, AJAX polling fallback will update the dashboard every 10 seconds.

6

For deployment, queue workers and scheduler/cron must be configured so background jobs actually finish.

Dashboard Realtime Polling Endpoint

This endpoint is used by the dashboard frontend to quietly refresh stats, platform status, synced records, logs, latest sync, and pull progress.

GET https://session-handler.bmwaresd.com/dashboard/realtime
Headers:
Accept: application/json
X-Requested-With: XMLHttpRequest
Important: This endpoint must only be called by browser polling every 10 seconds. It must not perform heavy pulling.

Manual Pull All Existing Records

This endpoint is triggered only when the user manually clicks the Pull All Existing Records button. It queues a background job instead of running the whole pull directly in browser JavaScript.

POST https://session-handler.bmwaresd.com/dashboard/pull-all-existing-records
Required Blade form:
<form method="POST"
      action="https://session-handler.bmwaresd.com/dashboard/pull-all-existing-records"
      data-ajax-form="pull-all-records">
    
    <button type="button">
        Pull All Existing Records
    </button>
</form>
Important: This endpoint may return 409 Conflict if another pull is already running. This is normal protection against duplicate heavy pull jobs.

Required AJAX Setup for Dashboard Actions

All AJAX POST requests from the dashboard must include the CSRF token, same-origin credentials, and JSON response handling.

const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');

const response = await fetch('/dashboard/pull-all-existing-records', {
    method: 'POST',
    headers: {
        Accept: 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRF-TOKEN': csrfToken,
    },
    credentials: 'same-origin',
    body: new FormData(form),
});

const data = await response.json();
Required: The main layout must include <meta name="csrf-token" content="WyUrNxJIRxV12YgISSPJqZ6ZGGDTkJxHg0Jrj1jb">.

Browser Polling Rule

The browser must only poll dashboard display data. It must not start heavy pull operations automatically.

Correct browser behavior:
GET /dashboard/realtime every 10 seconds

Wrong browser behavior:
POST /dashboard/pull-all-existing-records every 10 seconds
POST /dashboard/auto-sync every few seconds
location.reload() after AJAX
Rule: Realtime polling updates the UI only. Pulling records is a server-side job.

Auto Sync Status Endpoint

This endpoint should be status-only. It must not execute heavy pull logic from the browser.

POST https://session-handler.bmwaresd.com/dashboard/auto-sync
Expected behavior:
{
    "success": true,
    "status": "idle",
    "message": "Browser auto-sync is disabled. Automatic pulling is handled by Laravel Scheduler and queue jobs."
}
Safety Update: Even if old cached JavaScript calls this endpoint, it should not run Pull All Existing Records.

Laravel Scheduler and Queue Setup

Automatic pulling must be handled server-side using Laravel Scheduler and queue jobs.

// routes/console.php

use Illuminate\Support\Facades\Schedule;

Schedule::command('session-handler:auto-pull-existing-records')
    ->everyMinute()
    ->withoutOverlapping();
Important: withoutOverlapping() prevents the scheduler from starting another automatic pull while one is already running.

Local Herd Testing Setup

Use this setup when testing in Laravel Herd using http://session-handler.test.

APP_URL=http://session-handler.test
ASSET_URL=

SESSION_DRIVER=file
SESSION_DOMAIN=null
SESSION_SECURE_COOKIE=false
SESSION_SAME_SITE=lax

QUEUE_CONNECTION=sync

BROADCAST_CONNECTION=log
VITE_ENABLE_REVERB=false
Local Note: If only Herd is open and no queue worker is running, use QUEUE_CONNECTION=sync for local testing.

Production / Online Deployment Setup

Use this setup when deploying online with queue worker and scheduler support.

APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
ASSET_URL=

SESSION_DRIVER=file
SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=lax

QUEUE_CONNECTION=database
CACHE_STORE=file

BROADCAST_CONNECTION=log
VITE_ENABLE_REVERB=false
Production Note: If QUEUE_CONNECTION=database is used, a queue worker must run on the server.

Required Deployment Commands

Run these after uploading changes, editing CSS/JS, changing environment values, or deploying to a server.

composer install --optimize-autoloader --no-dev
npm run build

php artisan migrate --force
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache

Queue Worker Command

Required when QUEUE_CONNECTION=database. Without this, Pull All jobs will stay queued forever.

php artisan queue:work --tries=1 --timeout=900
Important: If this command is not running, the dashboard may show background pull as running forever.

Scheduler Command

Required for automatic server-side Pull All Existing Records.

php artisan schedule:work
Alternative: On production servers, use cron: * * * * * php artisan schedule:run.

Dynamic Registration Flow

This is the correct process for registering another platform using the plus button.

1

Send the external platform integration kit or required API instructions to your teammate.

2

They add the ping, manifest, records, and optional search endpoints to their Laravel platform.

3

In Session Handler, click the plus button and input their Platform Base API URL and Source Platform API Key.

4

Click Test Connection or Fetch Platform Data to verify the platform and load manifest data.

5

Select the modules/data you want to receive, then register the platform.

6

Copy the generated Session Handler API key and give it back to the external platform for webhook sending.

7

Use Pull All Existing Records manually or allow Laravel Scheduler to pull records server-side.

External Platform Ping Endpoint

This endpoint is used by the Session Handler to test if an external platform is active and reachable.

GET {SOURCE_BASE_API_URL}/api/session-handler/ping
Headers:
Accept: application/json
X-PLATFORM-API-KEY: SOURCE_PLATFORM_API_KEY
ngrok-skip-browser-warning: true
Expected response:
{
    "success": true,
    "message": "Platform is online.",
    "platform_name": "PWD-CS Platform"
}

External Platform Manifest Endpoint

This endpoint must exist on the external platform. The Session Handler uses it to fetch platform name, title, modules/tabs, record types, and fields.

GET {SOURCE_BASE_API_URL}/api/session-handler/manifest
Headers:
Accept: application/json
X-PLATFORM-API-KEY: SOURCE_PLATFORM_API_KEY
ngrok-skip-browser-warning: true

External Platform Records Endpoint

This endpoint is used by the Session Handler to pull old/existing records from a selected module.

GET {SOURCE_BASE_API_URL}/api/session-handler/records/{record_type}
Example:
GET https://pwd-platform.ngrok-free.dev/api/session-handler/records/pwd_record

External Platform Search Endpoint

This optional endpoint allows the Session Handler to search external platform data by keyword or person context.

GET {SOURCE_BASE_API_URL}/api/session-handler/search?query=juan
Headers:
Accept: application/json
X-PLATFORM-API-KEY: SOURCE_PLATFORM_API_KEY
ngrok-skip-browser-warning: true

Sample Manifest Response

This is what the external platform should return from its manifest endpoint. These fields become the dynamic table headers in Session Handler.

{
    "success": true,
    "platform_name": "PWD-CS Platform",
    "platform_title": "PWD-CS Management System",
    "platform_description": "Platform for managing PWD and Senior Citizen records.",
    "modules": [
        {
            "module_name": "PWD Records",
            "record_type": "pwd_record",
            "description": "PWD registration records",
            "fields": [
                {
                    "key": "pwd_number",
                    "label": "PWD Number",
                    "type": "string",
                    "required": true
                },
                {
                    "key": "first_name",
                    "label": "First Name",
                    "type": "string",
                    "required": true
                },
                {
                    "key": "middle_name",
                    "label": "Middle Name",
                    "type": "string",
                    "required": false
                },
                {
                    "key": "last_name",
                    "label": "Last Name",
                    "type": "string",
                    "required": true
                },
                {
                    "key": "suffix",
                    "label": "Suffix",
                    "type": "string",
                    "required": false
                },
                {
                    "key": "barangay",
                    "label": "Barangay",
                    "type": "string",
                    "required": false
                },
                {
                    "key": "address",
                    "label": "Address",
                    "type": "string",
                    "required": false
                },
                {
                    "key": "contact_number",
                    "label": "Contact Number",
                    "type": "string",
                    "required": false
                }
            ]
        },
        {
            "module_name": "Senior Citizens",
            "record_type": "senior_citizen_record",
            "description": "Senior citizen registration records",
            "fields": [
                {
                    "key": "senior_number",
                    "label": "Senior Citizen Number",
                    "type": "string",
                    "required": true
                },
                {
                    "key": "first_name",
                    "label": "First Name",
                    "type": "string",
                    "required": true
                },
                {
                    "key": "last_name",
                    "label": "Last Name",
                    "type": "string",
                    "required": true
                }
            ]
        }
    ]
}

Sample Old Records Response

This is what the external platform should return when Session Handler pulls existing records.

{
    "success": true,
    "platform_name": "PWD-CS Platform",
    "module_name": "PWD Records",
    "record_type": "pwd_record",
    "total": 1,
    "records": [
        {
            "reference_number": "PWD-001",
            "full_name": "Juan Santos Dela Cruz",
            "data": {
                "pwd_number": "PWD-001",
                "first_name": "Juan",
                "middle_name": "Santos",
                "last_name": "Dela Cruz",
                "suffix": null,
                "barangay": "San Juan",
                "address": "Purok 1, San Juan",
                "contact_number": "09123456789"
            }
        }
    ]
}

POST New Record

External platforms use POST after creating or registering a new record.

{
    "module_name": "PWD Records",
    "record_type": "pwd_record",
    "reference_number": "PWD-001",
    "full_name": "Juan Santos Dela Cruz",
    "data": {
        "pwd_number": "PWD-001",
        "first_name": "Juan",
        "middle_name": "Santos",
        "last_name": "Dela Cruz",
        "suffix": null,
        "barangay": "San Juan",
        "address": "Purok 1, San Juan",
        "contact_number": "09123456789"
    }
}

PATCH Updated Record

External platforms use PATCH after updating an existing record.

{
    "module_name": "PWD Records",
    "record_type": "pwd_record",
    "reference_number": "PWD-001",
    "full_name": "Juan Santos Dela Cruz",
    "data": {
        "barangay": "San Pedro",
        "contact_number": "09991234567"
    }
}

Sample Laravel Sender Service Usage

Use this in the external Laravel platform after creating or updating a record.

use App\Services\SessionHandlerWebhookService;

// After create/store
SessionHandlerWebhookService::sendCreated(
    moduleName: 'PWD Records',
    recordType: 'pwd_record',
    data: $pwd->toArray(),
    fullName: trim($pwd->first_name . ' ' . $pwd->middle_name . ' ' . $pwd->last_name),
    referenceNumber: $pwd->pwd_number
);

// After update
SessionHandlerWebhookService::sendUpdated(
    moduleName: 'PWD Records',
    recordType: 'pwd_record',
    data: $pwd->fresh()->toArray(),
    fullName: trim($pwd->first_name . ' ' . $pwd->middle_name . ' ' . $pwd->last_name),
    referenceNumber: $pwd->pwd_number
);

Webhook Success Response

Returned when the Session Handler successfully receives data.

{
    "success": true,
    "message": "New record received from PWD-CS Platform.",
    "method": "POST",
    "platform_name": "PWD-CS Platform",
    "module_name": "PWD Records",
    "record_id": 1
}

Webhook Error Response

Returned when the API key is invalid, the platform is inactive, or the module is not registered.

{
    "success": false,
    "message": "API key is missing, invalid, or platform is inactive."
}

Common Troubleshooting

Use these checks if the dashboard, API connection, or Pull All process behaves abnormally.

419

CSRF token mismatch. Make sure the layout has the CSRF meta tag, AJAX sends X-CSRF-TOKEN, and local HTTP uses SESSION_SECURE_COOKIE=false.

409

Pull All is already running. Clear stuck cache or wait for the existing job to finish. If using database queue, make sure php artisan queue:work is running.

JS

If the UI looks different without npm run dev, run npm run build, clear Laravel cache, and make sure ASSET_URL= is blank for local Herd.

10s

If /dashboard/realtime appears every second, check for duplicate polling, old cached JavaScript, or Reverb events triggering unthrottled refreshes.

Queue

If background pull never ends, the queue worker is probably not running or a cache lock is stuck.

Registered Platforms and API Keys

Give the generated Session Handler API key to the correct external platform. This key is used for POST and PATCH realtime sending.

Barangay Information System Cloud Active
Platform Name

BISCloud

Connection Type

dynamic_api

Source Base URL

https://remote-synopses-stream.ngrok-free.dev

Manifest Fetched

Jun 10, 2026 04:34 PM

Latest Sync

Jun 08, 2026 09:49 AM

Modules

12 registered

lqhA3Jy0BdI7Si98b9isujpNevOI9FOXK8zRVuHj

Registered Modules and Fields

Resident Records resident
Resident ID resident_id Reference Number reference_number Full Name full_name Household No. household_no Barangay barangay_description Purok/Street purok_street Gender gender Age age Contact No. contact_no Resident Type resident_type Vital Status vital_status Created At created_at Updated At updated_at
Blotter Records blotter
Blotter ID blotter_id Reference Number reference_number Case Title case_title Complainant complainant Respondent respondent Date of Filing date_of_filing Status status Barangay barangay_description Created At created_at Updated At updated_at
Health Assessments health_assessment
Assessment ID assessment_id Reference Number reference_number Full Name full_name Assessment Date assessment_date Gender gender Age age Contact Number contact_number Temperature temperature BP Systolic bp_systolic BP Diastolic bp_diastolic Assessed By assessed_by Barangay barangay_description
Daily Health Maintenance daily_health
Daily Health ID daily_health_id Reference Number reference_number Patient Name patient_name Gender gender Age age Contact No. contact_no Date of Visit date_of_visit Medicine medicine Barangay barangay_description
Certificate Issuances certificate_issuance
Certificate Issuance ID certificate_issuance_id Reference Number reference_number Resident Name resident_name Resident Identifier resident_identifier Template Title template_title Signed By signed_by E-Signed esigned Created At created_at
Barangay Physical Info barangay_physical_info
Barangay Info ID barangay_info_id Reference Number reference_number Barangay barangay_description Municipality municipality_description Province province_description Region region_description Total Land Area total_land_area Barangay Category barangay_category Land Classification land_classification
Official Records official
Official ID official_id Reference Number reference_number Name name Position position Type type Gender gender Age age Barangay barangay_description
Fiscal Records fiscal_record
Fiscal Record ID fiscal_record_id Reference Number reference_number Category category Total total Barangay barangay_description
Awards award
Award ID award_id Reference Number reference_number Award Level award_level Title title Date Awarded date_awarded Barangay barangay_description
Socio Facilities socio_facility
Facility ID facility_id Reference Number reference_number Facility facility Status status Remarks remarks Barangay barangay_description
Socio Properties socio_property
Property ID property_id Reference Number reference_number Property property Quantity quantity Remarks remarks Barangay barangay_description
Socio Water socio_water
Water ID water_id Reference Number reference_number Type Level type_level Households households Barangay barangay_description
BITAL Electronic Medical Records Active
Platform Name

BITAL EMR

Connection Type

dynamic_api

Source Base URL

https://press-dance-lasso.ngrok-free.dev

Manifest Fetched

Jun 04, 2026 04:43 PM

Latest Sync

Jun 08, 2026 01:43 PM

Modules

7 registered

Gwi7rnGKQdkw5VLnHuNWT8qmk5qFgkzKlbOm877T

Registered Modules and Fields

Patient Records patient
Patient ID patient_id Reference Number reference_number Full Name full_name Birthdate birthdate Age age Gender gender Mobile mobile Telephone telephone Address address Civil Status civil_status Transaction Type type_of_transaction Card Number card_number
Appointment Records appointment
Appointment ID appointment_id Reference Number reference_number Patient Name patient_name Clinic clinic Appointment For appointment_for Appointment Date appointment_date Status status
Visiting Records visiting_record
Visit ID visit_id Reference Number reference_number Patient Name patient_name Visit Date visit_date Assessment assessment Plan plan Remarks remarks
Laboratory Records laboratory_record
Laboratory Record ID laboratory_record_id Reference Number reference_number Patient Name patient_name Entry Date entry_date Result result
Prescription Records prescription
Prescription ID prescription_id Reference Number reference_number Patient Name patient_name Date Prescribed date_prescribed Medication medication Remarks remarks
Billing Records billing
Billing ID billing_id Reference Number reference_number Patient Name patient_name Billing Number billing_number Transaction Date date_of_transaction Clinic clinic Diagnosis diagnosis Attending Physician attending_physician
Clinical Abstracts clinical_abstract
Clinical Abstract ID clinical_abstract_id Reference Number reference_number Patient Name patient_name Date of Admission date_of_admission Date of Discharge date_of_discharge Chief Complaint chief_complaint Final Diagnosis final_diagnosis
Patient Booking System Active
Platform Name

Patient Booking

Connection Type

dynamic_api

Source Base URL

https://carpenter-unwritten-wildcat.ngrok-free.dev

Manifest Fetched

Jun 04, 2026 07:48 AM

Latest Sync

Jun 08, 2026 04:38 AM

Modules

3 registered

jUIuQwfDxF2CCWkeluShhDxs5xKJgbmZw1449FrF

Registered Modules and Fields

Appointment Requests appointment_request
Request ID appointment_request_id Reference Number reference_number Patient Name patient_name Doctor Name doctor_name Clinic clinic Date date Start Time start End Time end Status status Synced to EMR is_synced_to_emr
Doctor Records doctor
Doctor ID doctor_id Reference Number reference_number Doctor Name name Specialty specialty Code code
Doctor Schedules doctor_schedule
Schedule ID schedule_id Reference Number reference_number Doctor Name doctor_name Clinic clinic Day day Start Time start End Time end
PWD-CS Management System Active
Platform Name

PWD-CS Platform

Connection Type

dynamic_api

Source Base URL

https://wrecking-nicotine-ninja.ngrok-free.dev

Manifest Fetched

Jun 04, 2026 06:14 AM

Latest Sync

Jun 04, 2026 06:32 AM

Modules

2 registered

RWsAytIvK0WvkzcpbKdE7ZLHBW6MeuNPESND7fLJ

Registered Modules and Fields

PWD Records pwd_record
PWD Number pwd_number First Name first_name Middle Name middle_name Last Name last_name Suffix suffix Barangay barangay_description Purok / Street purok_street Gender gender Birthdate date_of_birth Age age Contact Number contact_no PWD Status person_with_disabilities Registered Voter registered_voter Precinct No precinct_no Civil Status civil_status Occupation occupation Vital Status vital_status
Senior Citizens senior_citizen_record
Senior Citizen Number sc_number First Name first_name Middle Name middle_name Last Name last_name Suffix suffix Barangay barangay_description Purok / Street purok_street Gender gender Birthdate date_of_birth Age age Contact Number contact_no Registered Voter registered_voter Precinct No precinct_no Civil Status civil_status Occupation occupation Vital Status vital_status
Dispatch Management System Active
Platform Name

Dispatch App

Connection Type

dynamic_api

Source Base URL

https://remote-synopses-stream.ngrok-free.dev

Manifest Fetched

Jun 04, 2026 05:28 AM

Latest Sync

Jun 10, 2026 05:12 PM

Modules

6 registered

k7ebpWnxN5ivDMFupp76hnYiaa75LTeBB94FCocM

Registered Modules and Fields

Emergency Reports emergency
Emergency ID emergency_id Reference Number reference_number Incident incident Reported By reported_by Reporter Phone reporter_phone Latitude latitude Longitude longitude Status status Created At created_at Updated At updated_at
Incident Records incident
Incident ID incident_id Reference Number reference_number Emergency ID emergency_id Incident Type incident_type Address address Status status Assigned At assigned_at Resolved At resolved_at Created At created_at Updated At updated_at
Responder Records responder
Responder ID responder_id Reference Number reference_number Responder Code responder_code Responder Name responder_name Service Name service_name Latitude latitude Longitude longitude Status status Created At created_at Updated At updated_at
Branch Records branch
Branch ID branch_id Reference Number reference_number Branch Name name Service Name service_name Address address Contact Number contact_number Latitude latitude Longitude longitude Status status
Service Records service
Service ID service_id Reference Number reference_number Service Name name Description description Created At created_at Updated At updated_at
Dispatch Records dispatch
Dispatch ID dispatch_id Reference Number reference_number Incident Type incident_type Location location Description description Reported At reported_at Status status Created At created_at Updated At updated_at