> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ontime.hosai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Biometric terminals

> How F500-class terminals reach OnTime through the connector, and the no-data-loss contract that makes it reliable.

Biometric attendance terminals — fingerprint and face clocks on a factory wall — are the most reliable way to capture attendance for people who do not carry a work phone. They also cannot talk to a cloud service directly, which is why OnTime ships a small bridge.

## The topology

```mermaid theme={null}
flowchart LR
  T1[Terminal<br/>F500 class] -->|raw TCP · XML| C
  T2[Terminal] -->|raw TCP · XML| C
  C[OnTime connector<br/>on your network] -->|HTTPS| B[OnTime backend]
  B --> D[Day records]
```

<CardGroup cols={2}>
  <Card title="Terminals speak raw TCP" icon="cable">
    An F500-class device opens a persistent TCP connection to a configured IP and port and streams null-terminated XML. It has no HTTPS, no certificates and no notion of a REST API.
  </Card>

  <Card title="The connector translates" icon="arrow-left-right">
    A small stateless service you run on the same network. It terminates those TCP sessions and forwards each message to OnTime over HTTPS.
  </Card>
</CardGroup>

## Why the connector exists

Three reasons, in order of importance:

1. **Terminals cannot speak HTTPS.** There is no way to point one at a cloud endpoint.
2. **They need a listener on the local network.** The device connects outward to an IP and port you configure on it — so something has to be listening there.
3. **It keeps no state.** The connector holds nothing, has no queue and no database. Restarting it mid-session loses nothing, which is what lets it be deployed like any other service.

## The no-data-loss contract

<Warning>
  **The device's own flash memory is the retry queue, and the connector acks a punch only after OnTime has accepted it.**

  This single rule is the whole reliability model. If OnTime is unreachable, the connector does not acknowledge the punch; the device sees no acknowledgement, keeps the record, and re-sends it. Nothing is lost to an outage, a deploy or a network blip.
</Warning>

The device re-sends any unacknowledged record roughly every 60 seconds and holds the rest of its queue behind it. Combined with OnTime's deduplication, that produces **at-least-once delivery with exactly-once storage** — a punch cannot be missed, and cannot be counted twice.

## Two things that are not obvious

<AccordionGroup>
  <Accordion title="An unmapped punch parks — it never drops" icon="inbox">
    A terminal identifies people by its own numeric user ID. Until that ID is linked to an OnTime employee, the punch is held rather than discarded. Creating the mapping replays everything parked.

    So "punches aren't appearing" is almost never lost data. See [Map terminal users](/terminals/map-terminal-users).
  </Accordion>

  <Accordion title="One connector serves every organization" icon="building">
    The connector authenticates with a platform-level secret rather than an organization API key. Which organization a punch belongs to is resolved on the OnTime side, from the device's serial number.

    Practically: you configure the connector once, and registering a device is what assigns it to your organization.
  </Accordion>
</AccordionGroup>

## Setting up

<Steps>
  <Step title="Install the connector">
    On a machine that can reach both your terminals and the internet. See [Install the connector](/terminals/install-the-connector).
  </Step>

  <Step title="Point the terminals at it">
    Set each device's LogServer IP and port to the connector's host.
  </Step>

  <Step title="Register the devices">
    They appear by serial once they first connect. See [Register a terminal](/terminals/register-a-terminal).
  </Step>

  <Step title="Map terminal users to employees">
    Otherwise every punch parks. See [Map terminal users](/terminals/map-terminal-users).
  </Step>

  <Step title="Verify without hardware">
    A fake-device script replays a realistic session. See [Test with a fake device](/terminals/test-with-fake-device).
  </Step>
</Steps>

## Where the connector runs

<Note>
  The connector is a Docker image that runs anywhere with a raw TCP port reachable from your terminals.

  **It cannot run on Render**, which OnTime otherwise deploys to — Render web services accept only public HTTP(S), and this needs a raw TCP listener. Run it on your own network, or on a host that supports raw TCP.
</Note>
