# Turnstile API Guide

## Overview

The Turnstile API provides a complete control plane for access validation, gate operation, live monitoring, scheduling, software lifecycle management, and field administration.

This is the API you would present to customers, partners, or integrators who need to:

- validate a badge, card, or token
- open or lock the gate
- monitor device and schedule state in real time
- manage configuration
- retrieve logs
- manage releases and updates
- work with VTAP field media

Base URL examples:

- `http://<device-host>:5000`
- `https://<customer-domain>/turnstile-api`

Swagger UI is available on the device at:

- `/swagger`

## Audience

This API is best positioned for:

- access-control platform integrators
- kiosk and facility software vendors
- device fleet management portals
- service technicians and deployment teams
- customer admin tools

## Authentication

The API supports header-based authentication for protected endpoints.

Header:

```http
X-API-Key: <your-api-key>
```

Protected endpoint families:

- `/api/admin/*`
- `/api/update`
- `/api/update/status`
- `/api/shellcommand`
- `/api/initialconfig`

If authentication fails, the API returns:

```json
{ "error": "X-API-Key required" }
```

Notes:

- Core operational endpoints such as access validation, gate control, schedule status, and live event streaming are not currently protected by `X-API-Key` in the implementation.
- For a commercial deployment, these endpoints should normally be placed behind a trusted network boundary, reverse proxy, VPN, or additional auth layer.

## Response Conventions

Most endpoints return JSON. Common exceptions:

- `/api/live/events` returns Server-Sent Events (`text/event-stream`)
- `/api/admin/logs` returns plain text

Typical status patterns:

- `200 OK` for successful reads and actions
- `202 Accepted` for long-running background operations
- `400 Bad Request` for invalid input or missing configuration
- `401 Unauthorized` for protected endpoints without a valid API key
- `404 Not Found` for missing files or resources
- `423 Locked` when a gate-open request is blocked by a lock state
- `500 Internal Server Error` for execution failures

## API Groups

- Public status and identity
- Access validation and entry flow
- Gate operations
- Live monitoring
- Scheduling
- Administration and configuration
- Logs and diagnostics
- Updates and release management
- VTAP media operations
- Advanced device commands

## Public Status And Identity

### `GET /api/health`

Returns device health and gate capability state.

Example response:

```json
{
  "status": "ok",
  "readerEnabled": true,
  "gate": {
    "mode": "turnstile",
    "useGpio": true,
    "useSerial": false,
    "gpioPin": 26,
    "invertGpio": false,
    "invertOpenSequence": false,
    "useDoorSensor": false,
    "doorSensorPin": 0,
    "isDoorOpen": false,
    "serialPort": null,
    "isHeldOpen": false,
    "isForcedLockActive": false,
    "isManualLockActive": false,
    "currentReason": null
  }
}
```

Best use:

- uptime probes
- device inventory dashboards
- service validation after install or upgrade

### `GET /api/info`

Returns solution and site identity details.

Example response:

```json
{
  "site": "Downtown Club",
  "name": "Main Entrance Turnstile",
  "version": "6.1.0",
  "testMode": false,
  "equipmentType": "Turnstile"
}
```

Best use:

- admin portals
- fleet lists
- support tooling

## Access Validation And Entry Flow

### `POST /api/access/validate`

Validates a token without opening the gate.

Request body:

```json
{
  "token": "E004015319BB0121"
}
```

### `GET /api/access/validate?token=<token>`

Query-based validation variant for lightweight integrations.

Example success response:

```json
{
  "isValid": true,
  "message": "Access granted",
  "firstName": "Jane",
  "lastName": "Doe",
  "responseTimeSeconds": 0.24,
  "rawResponse": "{\"isValid\":1,\"Prenom\":\"Jane\",\"Nom\":\"Doe\",\"Message\":\"Access granted\"}"
}
```

Example failure response:

```json
{
  "isValid": false,
  "message": "Timeout"
}
```

Best use:

- mobile or kiosk pre-checks
- partner access workflows
- troubleshooting the upstream validation service

### `POST /api/access/open`

Validates a token and, if valid, opens the gate.

Request body:

```json
{
  "token": "E004015319BB0121",
  "delay": 4
}
```

### `GET /api/access/open?token=<token>&delay=<seconds>`

Query-based entry flow variant.

Behavior:

- validates the token against the configured upstream service
- opens the gate only if access is granted
- records the result in the recent access feed

Best use:

- reader devices
- unattended entry points
- partner systems that want a single-call validate-and-open flow

### `GET /api/access/recent`

Returns a snapshot of recent access attempts.

Example response:

```json
[
  {
    "occurredAtUtc": "2026-05-19T13:45:12.124Z",
    "granted": true,
    "token": "E004015319BB0121",
    "displayName": "Jane Doe",
    "message": "Access granted"
  }
]
```

Best use:

- operator dashboards
- recent-entry audit widgets
- live support sessions

## Gate Operations

### `GET /api/gate`

Opens the gate directly.

Query parameters:

- `delay`: open duration in seconds
- `reason`: human-readable reason for the operation
- `exclusive`: when `true`, requests an exclusive open mode

Example:

```http
GET /api/gate?delay=5&reason=remote-support&exclusive=true
```

Example success response:

```json
{
  "opened": true,
  "delaySeconds": 5,
  "exclusive": true
}
```

Example locked response:

```json
{
  "opened": false,
  "message": "manual lock active"
}
```

Commercial positioning:

- remote unlock from concierge or reception software
- operator-assisted entry
- support and maintenance workflows

### `GET /api/gate/state`

Returns the current gate state.

Example response:

```json
{
  "isOpen": false,
  "isHeldOpen": false,
  "hasTimedOpen": false,
  "isForcedLockActive": false,
  "isManualLockActive": false,
  "isDoorOpen": false,
  "currentReason": null
}
```

### `POST /api/gate/cancel`

Cancels an active gate-open operation.

Example response:

```json
{
  "canceled": true
}
```

If no operation is active:

```json
{
  "canceled": false,
  "message": "no active operation"
}
```

### `POST /api/gate/lock`

Activates manual lock mode.

Example response:

```json
{
  "locked": true
}
```

### `POST /api/gate/unlock`

Releases manual lock mode.

Example response:

```json
{
  "unlocked": true,
  "changed": true
}
```

## Live Monitoring

### `GET /api/live/events`

Streams real-time device events using Server-Sent Events.

Content type:

```text
text/event-stream
```

Initial events include:

- `gate-state`
- `schedule-state`
- `recent-access`

The stream also sends keep-alive comments approximately every 15 seconds.

Example client:

```javascript
const events = new EventSource("/api/live/events");

events.addEventListener("gate-state", (e) => {
  console.log("gate", JSON.parse(e.data));
});

events.addEventListener("schedule-state", (e) => {
  console.log("schedule", JSON.parse(e.data));
});

events.addEventListener("recent-access", (e) => {
  console.log("recent", JSON.parse(e.data));
});
```

Best use:

- live control rooms
- admin dashboards
- embedded monitoring panels

## Scheduling

### `GET /api/schedule/status`

Returns the evaluated schedule state at the current time.

Example response:

```json
{
  "enabled": true,
  "timeZone": "America/Toronto",
  "activeNow": true,
  "activeSource": "weekly",
  "activeAction": "unlock",
  "activeDay": "Tuesday",
  "activeWindowStart": "06:00",
  "activeWindowEnd": "22:00",
  "activeLabel": "Business Hours",
  "evaluatedAtUtc": "2026-05-19T13:46:00.000Z",
  "localNow": "2026-05-19T09:46:00-04:00"
}
```

Best use:

- displaying lock/unlock schedule state
- validating time-window configuration
- site readiness checks

## Administration And Configuration

These endpoints require `X-API-Key`.

### `GET /api/admin/config`

Returns the current effective configuration snapshot for major sections.

Returned sections:

- `access`
- `gate`
- `schedule`
- `solution`

### `PUT /api/admin/config`

Applies a structured configuration update.

This endpoint is intended for admin panels and remote management platforms rather than direct file editing.

Top-level request sections:

- `access`
- `gate`
- `schedule`
- `reader`
- `logging`
- `admin`

Example request:

```json
{
  "gate": {
    "openSeconds": 4,
    "useGpio": true,
    "gpioPin": 26
  },
  "schedule": {
    "enabled": true,
    "timeZone": "America/Toronto"
  },
  "logging": {
    "level": "Information"
  }
}
```

Example response:

```json
{
  "status": "saved",
  "path": "/opt/turnstile-config/appsettings.local.json",
  "restartRequired": true
}
```

### `GET /api/admin/config/raw`

Returns raw API config JSON from the configured admin config path.

Example response:

```json
{
  "path": "/opt/turnstile-config/appsettings.local.json",
  "config": {
    "Api": {}
  }
}
```

### `PUT /api/admin/config/raw`

Overwrites raw API config JSON at the configured admin config path.

Use this for advanced support tooling or import/export workflows when structured config updates are not sufficient.

### `GET /api/admin/site/config/raw`

Returns the merged site configuration view based on shared plus local override data.

### `PUT /api/admin/site/config/raw`

Writes the local site override configuration file.

### `POST /api/admin/restart`

Restarts the API service.

Commercial use:

- apply config changes
- remote support actions
- post-maintenance recovery

### `POST /api/admin/restartallservices`

Restarts the API service and triggers restart of the related service stack.

Intended for:

- full device refresh
- fleet support operations
- coordinated update recovery

### `POST /api/admin/rebootos`

Reboots the operating system.

This is a high-trust support endpoint and should be tightly controlled in production.

## Logs And Diagnostics

These endpoints require `X-API-Key`.

### `GET /api/admin/logs`

Returns recent logs as plain text.

Query parameters:

- `lines`: number of lines to return, defaulting to 200 and capped at 2000
- `service`: target service name or service set
- `level`: optional log-level filter

Example:

```http
GET /api/admin/logs?service=api&lines=300&level=error
X-API-Key: <your-api-key>
```

Behavior:

- for a single service, returns its plain-text log tail
- for multiple services, returns a grouped plain-text bundle

### `POST /api/admin/logs/clear`

Clears configured log files across the service set.

Example response:

```json
{
  "status": "done",
  "cleared": [
    "/var/log/turnstile/turnstile-api.log"
  ],
  "errors": []
}
```

## Updates And Release Management

These endpoints require `X-API-Key`.

### `POST /api/update`

Starts a background software update process.

Example response:

```json
{
  "status": "started",
  "message": "update running in background"
}
```

Returns `202 Accepted`.

### `GET /api/update/status`

Returns the current update status.

This endpoint is designed for polling during upgrade workflows from an admin UI or fleet portal.

### `GET /api/admin/releases`

Lists installed releases and identifies the current active version.

Typical use:

- rollback planning
- device inventory
- support diagnostics

### `POST /api/admin/releases/switch`

Switches the active deployment to a specific installed version.

Request body:

```json
{
  "version": "6.1.0"
}
```

Commercial use:

- controlled rollback
- staged deployment validation
- field support recovery

## VTAP Media Operations

These endpoints require `X-API-Key`.

VTAP endpoints support working with mounted field media and configuration payloads.

### `POST /api/admin/vtap/upload`

Uploads one or more files to the VTAP path using multipart form data.

Use cases:

- field package staging
- device-side content transfer
- service technician workflows

### `POST /api/admin/vtap/apply`

Applies a VTAP payload using optional mount details.

Request body:

```json
{
  "mountDevice": "/dev/sdb1",
  "mountPath": "/tmp/vtap"
}
```

### `GET /api/admin/vtap/devices`

Returns detected VTAP-capable devices.

Example response:

```json
{
  "devices": [
    {
      "path": "/dev/sdb1",
      "label": "VTAP100"
    }
  ]
}
```

### `GET /api/admin/vtap/config`

Reads VTAP configuration from the mounted media.

Optional query parameters:

- `mountDevice`
- `mountPath`

### `PUT /api/admin/vtap/config`

Writes VTAP configuration to the mounted media.

Optional query parameters:

- `mountDevice`
- `mountPath`

Request body:

- raw configuration content

### `GET /api/admin/vtap/boot`

Reads `boot.txt` from the VTAP media.

Useful for:

- field diagnostics
- deployment validation
- media inspection

## Advanced Device Commands

These endpoints require `X-API-Key`.

### `POST /api/shellcommand`

Executes a supplied shell command on the device.

Request body:

```json
{
  "command": "systemctl status turnstile-api"
}
```

This is a powerful support endpoint and should be considered high risk in any production sale. In most customer-facing deployments, this endpoint should be:

- disabled
- restricted to a support-only environment
- protected behind a private network and strong operational controls

### `POST /api/initialconfig`

Runs the first-time setup script at:

- `/opt/turnstile-api/setup.sh`

This endpoint is intended for initial provisioning and deployment automation.

## Recommended Product Packaging

If this API were being sold as part of a commercial product, I would document it in three layers.

### 1. Executive Overview

Keep a short product page that explains:

- what the API does
- who it is for
- how it integrates with access-control ecosystems
- which deployment models are supported

### 2. Integrator Guide

This is the document you would hand to partners. It should include:

- authentication
- environment setup
- core workflows
- endpoint reference
- sample requests and responses
- event-stream consumption
- error handling

### 3. Operations Guide

This is for installers and support teams. It should cover:

- restart and reboot procedures
- release switching
- update workflow
- logs
- VTAP usage
- security hardening

## Recommended Sales-Ready Narrative

The strongest product message is not "here are all our endpoints." It is:

"The Turnstile API gives partners a reliable, device-local interface for validating credentials, controlling entry hardware, monitoring state in real time, and remotely administering deployed units at scale."

That framing makes the product easier to sell because it ties the API to business outcomes:

- faster integrations
- fewer field visits
- lower support cost
- real-time operational visibility
- safer remote administration

## Recommended Next Improvements

Before publishing this externally, I would recommend:

- adding versioning such as `/api/v1/...`
- separating public, operator, and support-only endpoints
- protecting all gate-control endpoints with auth
- adding rate limits and audit logging
- documenting exact schemas in OpenAPI with examples
- adding webhook or event-contract documentation for live streams
- clearly marking dangerous endpoints such as shell access and OS reboot

## Endpoint Summary

### Public And Operational

- `GET /api/health`
- `GET /api/info`
- `POST /api/access/validate`
- `GET /api/access/validate`
- `POST /api/access/open`
- `GET /api/access/open`
- `GET /api/access/recent`
- `GET /api/gate`
- `GET /api/gate/state`
- `POST /api/gate/cancel`
- `POST /api/gate/lock`
- `POST /api/gate/unlock`
- `GET /api/live/events`
- `GET /api/schedule/status`

### Protected Admin And Support

- `GET /api/admin/config`
- `PUT /api/admin/config`
- `GET /api/admin/logs`
- `POST /api/admin/logs/clear`
- `POST /api/update`
- `GET /api/update/status`
- `GET /api/admin/config/raw`
- `PUT /api/admin/config/raw`
- `GET /api/admin/site/config/raw`
- `PUT /api/admin/site/config/raw`
- `POST /api/admin/restart`
- `POST /api/admin/restartallservices`
- `POST /api/admin/rebootos`
- `GET /api/admin/releases`
- `POST /api/admin/releases/switch`
- `POST /api/shellcommand`
- `POST /api/initialconfig`
- `POST /api/admin/vtap/upload`
- `POST /api/admin/vtap/apply`
- `GET /api/admin/vtap/devices`
- `GET /api/admin/vtap/config`
- `PUT /api/admin/vtap/config`
- `GET /api/admin/vtap/boot`

