# Time Coordinate API

Coordinate-to-local-time API for business systems that need the current or historical local time at any latitude/longitude on Earth.

This service is becoming a broader calculated context API suite:

- Time by coordinate.
- Geospatial calculations.
- Date calculations.

## Accuracy Model

This API does not estimate time from longitude. It resolves the coordinate to an IANA timezone identifier using geographic timezone boundary lookup, then calculates local time with IANA timezone rules from the server runtime.

This matters because real time is political as well as geographic: daylight saving rules, island territories, border towns, and historical rule changes cannot be handled by simple UTC offset math.

## Endpoints

### `GET /v1/time`

Query parameters:

- `lat`: latitude, `-90` to `90`.
- `lon`: longitude, `-180` to `180`.
- `at`: optional ISO-8601 timestamp, epoch seconds, or epoch milliseconds. Defaults to now.

Example:

```bash
curl 'http://127.0.0.1:4110/v1/time?lat=48.137154&lon=11.576124'
```

### `POST /v1/time/batch`

Body:

```json
{
  "at": "2026-07-12T12:00:00Z",
  "points": [
    { "lat": 48.137154, "lon": 11.576124 },
    { "lat": -33.8688, "lon": 151.2093 }
  ]
}
```

Maximum batch size: 100 points.

### `GET /health`

Basic service health response.

## Geospatial Endpoints

### `GET /v1/geo/distance`

Calculates distance and initial bearing between two coordinates.

```bash
curl 'http://127.0.0.1:4110/v1/geo/distance?from_lat=48.137154&from_lon=11.576124&to_lat=52.52&to_lon=13.405'
```

Returns kilometers, miles, meters, nautical miles, bearing degrees, and compass direction.

### `GET /v1/geo/midpoint`

Calculates the great-circle midpoint between two coordinates.

```bash
curl 'http://127.0.0.1:4110/v1/geo/midpoint?from_lat=48.137154&from_lon=11.576124&to_lat=52.52&to_lon=13.405'
```

### `GET /v1/geo/bounding-box`

Returns a spherical-approximation bounding box around a coordinate and radius.

```bash
curl 'http://127.0.0.1:4110/v1/geo/bounding-box?lat=48.137154&lon=11.576124&radius_km=50'
```

## Date Endpoints

### `GET /v1/date/difference`

Calculates calendar day difference.

```bash
curl 'http://127.0.0.1:4110/v1/date/difference?start=2026-07-12&end=2026-08-01'
```

### `GET /v1/date/add`

Adds years, months, weeks, and days to a date.

```bash
curl 'http://127.0.0.1:4110/v1/date/add?start=2026-07-12&months=1&days=5'
```

### `POST /v1/date/business-days`

Counts business days between two dates, excluding Saturdays, Sundays, and optional holiday dates.

```json
{
  "start": "2026-07-12",
  "end": "2026-07-31",
  "holidays": ["2026-07-20"]
}
```

## API Key Middleware

Set `TIME_API_KEYS` to a comma-separated list of accepted keys. Clients may send either:

- `Authorization: Bearer <key>`
- `X-API-Key: <key>`

The local private service can still run without keys while `TIME_API_KEYS` is empty and `REQUIRE_API_KEY=false`. Set `REQUIRE_API_KEY=true` before any public launch, and configure keys before enabling that mode.

Keys can optionally be scoped as `customer_id:key-value` so rate limits and usage logs can identify the customer without logging the secret.

## Rate Limiting

Set `RATE_LIMIT_PER_MINUTE` to control basic in-process rate limiting. The default is `120` requests per minute per customer. Set `TIME_API_CUSTOMER_RATE_LIMITS` to a JSON object such as `{"customer_a":240}` for customer-specific limits. Set the default to `0` only behind a stronger gateway-level limiter.

## Deterministic Cache

Set `TIME_API_CACHE=memory` for the default in-process cache, `TIME_API_CACHE=off` to disable it, or `TIME_API_CACHE=redis` only after Redis is deliberately provisioned and `REDIS_URL` is configured.

The API does not cache current-time responses where `at` is omitted. It can cache deterministic inputs such as explicit timestamp coordinate conversions, date calculations, business-day calculations, distance, midpoint, and bounding-box results.

## Logging

The Fastify HTTP layer emits structured request logs with route, status, latency, customer id, API key fingerprint, and cache status. It avoids logging request bodies, query inputs, or raw API keys.

## Commercial Notes

This API is suitable for scheduling, compliance timestamps, logistics, CRM records, remote workforce tools, event planning, travel, billing cutoffs, and time-sensitive customer notifications.

Geospatial endpoints are suitable for territory checks, routing estimates, field-service assignment, delivery radius filters, branch proximity tools, and customer segmentation. They are not a replacement for surveyed legal boundaries or turn-by-turn routing engines.

Date endpoints are suitable for billing windows, SLA calculations, business-day estimates, subscription periods, due dates, and payroll-like date workflows. Jurisdiction-specific holidays should be supplied by the client or a future jurisdiction-holiday module.

Public commercial deployment should add:

- API keys per customer.
- Rate limits per customer.
- Usage logging without storing unnecessary personal data.
- SLA wording tied to IANA timezone database freshness.
- Versioned response schema.
- Monitoring and external uptime checks.

## Local Deployment

Current local service:

```text
http://127.0.0.1:4110
```

Keep it localhost-only until nginx/TLS/API-key/rate-limit policy is approved.

Suggested public shape:

```text
Internet -> nginx TLS vhost -> 127.0.0.1:4110
```
