Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - raisga/p4n4-api · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

p4n4-api

Unified REST API gateway for the P4N4 platform — written in Python.

p4n4-api is the central HTTP API layer for the P4N4 IoT + GenAI + Edge AI platform. It exposes a single, versioned, authenticated REST surface over the otherwise fragmented set of internal services (InfluxDB, MQTT, Ollama, Letta, Edge Impulse Runner), making it easy to build dashboards, mobile apps, or external integrations without touching each service directly.

Part of the p4n4 platform — an EdgeAI + GenAI integration platform for IoT deployments.


Status

v0.1 implements a read-only project/stack surface built on p4n4-lib (manifest, layout, validation, and Compose status — both flat and multi-layer project layouts):

MethodPathDescription
GET/healthLiveness probe
GET/api/v1/projectManifest, layout (flat/multi), and per-stack directories
GET/api/v1/project/validateRun p4n4_lib.validate checks; returns {ok, passed, errors}
GET/api/v1/stacksCompose service status per stack
GET/api/v1/stacks/{stack}One stack's service status (404 if not enabled)
GET/swagger-ui, /openapi.jsonInteractive docs / OpenAPI spec

Everything else in this README (auth, device registry, telemetry, SSE, agents, MQTT, metrics) is the design target, not yet implemented. State-changing endpoints (stack up/down, secret rotation) are deliberately deferred until auth lands.


Table of Contents


Architecture

 External clients (dashboards, mobile apps, scripts)
│
▼ HTTP / REST (port 8000)
┌─────────────────────┐
│ p4n4-api │
│ (Python · FastAPI) │
│ │
│ ┌───────────────┐ │
│ │ Auth (JWT) │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Device Reg. │ │
│ │ (SQLite) │ │
│ └───────────────┘ │
└──────────┬──────────┘
│ p4n4-net (Docker bridge)
┌───────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ p4n4-iot │ │ p4n4-ai │ │ p4n4-edge │
│ ───────── │ │ ───────── │ │ ────────── │
│ MQTT │ │ Ollama │ │ EI Runner │
│ InfluxDB │ │ Letta │ └──────────────┘
└─────────────┘ └─────────────┘

Data flow:

  1. Clients authenticate and receive a JWT.
  2. Requests are routed to the relevant upstream service (InfluxDB, MQTT, Ollama, Letta, or the Edge runner).
  3. Telemetry ingested via the API is written to InfluxDB and published to MQTT, so Node-RED flows trigger normally.
  4. A live telemetry SSE stream is backed by a persistent MQTT subscription.

Features

  • Unified auth — API key → JWT (HS256). Three roles: device, operator, admin.
  • Device registry — CRUD for devices; API keys hashed with argon2id; stored in SQLite.
  • Telemetry ingest — batch JSON → InfluxDB line protocol + MQTT publish.
  • Telemetry query — Flux proxy against InfluxDB with simple query-param interface.
  • Live SSE streamGET /api/v1/telemetry/stream delivers real-time readings over Server-Sent Events.
  • Inference — proxy to the Edge Impulse runner (POST /api/v1/inference).
  • AI agents — Ollama one-shot generation and Letta stateful chat.
  • MQTT publishPOST /api/v1/mqtt/publish for arbitrary messages.
  • Stack healthGET /api/v1/stacks pings all platform services and reports status.
  • OpenAPI 3.1/openapi.json + Swagger UI at /swagger-ui.
  • Prometheus metrics/metrics endpoint with request counters, latency histograms, and upstream call stats.

Prerequisites

  • Docker v24+ (with Compose v2)
  • p4n4-iot running (provides p4n4-net, MQTT, and InfluxDB)

For local development only:


Getting Started

  1. Clone and install (with p4n4-lib)

    git clone https://github.com/raisga/p4n4-api.git
    cd p4n4-api
    uv venv
    uv pip install "p4n4-lib @ git+https://github.com/raisga/p4n4-lib.git" -e .# monorepo: uv pip install -e ../../core/lib -e .
  2. Point it at a p4n4 project (scaffolded by p4n4 init; flat or multi-layer)

    export P4N4_PROJECT_DIR=~/projects/my-p4n4-project
  3. Start the API

    uv run p4n4-api
    # or: uv run uvicorn p4n4_api.main:app --reload --port 8000
  4. Verify it is running

    curl http://localhost:8000/health
    # {"status":"ok"}
    curl http://localhost:8000/api/v1/project
    curl http://localhost:8000/api/v1/project/validate
    curl http://localhost:8000/api/v1/stacks
    # Open the interactive API docs
    open http://localhost:8000/swagger-ui

Configuration

All configuration is read from environment variables. Currently used:

VariableDescription
P4N4_PROJECT_DIRp4n4 project directory to serve (walks up to .p4n4.json; default: the server's cwd)
P4N4_API_HOSTBind address (default: 127.0.0.1)
P4N4_API_PORTHTTP listen port (default: 8000)

Planned (for the upstream-proxy features below): P4N4_API_JWT_SECRET, INFLUXDB_URL, INFLUXDB_TOKEN, MQTT_HOST, MQTT_USER/MQTT_PASSWORD, OLLAMA_URL, LETTA_URL, LETTA_SERVER_PASSWORD, EDGE_RUNNER_URL, P4N4_API_DATABASE_URL.


API Reference

Base path: /api/v1 Authentication: Authorization: Bearer <jwt> (except public endpoints)

Public endpoints

MethodPathDescription
GET/healthLiveness probe
GET/readyReadiness probe (checks DB + MQTT)
GET/metricsPrometheus metrics
GET/openapi.jsonOpenAPI 3.1 spec
GET/swagger-uiSwagger UI

Authentication

MethodPathDescription
POST/api/v1/auth/tokenExchange API key for JWT
POST/api/v1/auth/refreshRotate access token

Stack health (operator+)

MethodPathDescription
GET/api/v1/stacksHealth of all platform stacks
GET/api/v1/stacks/{stack}Health of one stack (iot, ai, edge)

Devices (admin for writes, operator for reads)

MethodPathDescription
GET/api/v1/devicesList devices (paginated)
POST/api/v1/devicesRegister a new device
GET/api/v1/devices/{id}Get device by ID
PATCH/api/v1/devices/{id}Update device metadata
DELETE/api/v1/devices/{id}Deregister device
GET/api/v1/devices/{id}/keyRotate API key

Telemetry

MethodPathAuthDescription
POST/api/v1/telemetrydeviceIngest readings (→ InfluxDB + MQTT)
GET/api/v1/telemetryoperatorQuery historical data
GET/api/v1/telemetry/streamoperatorSSE live stream

Inference (operator+)

MethodPathDescription
POST/api/v1/inferenceSubmit feature vector for Edge Impulse inference
GET/api/v1/inference/resultsQuery recent results from InfluxDB ai_events

AI agents (operator+)

MethodPathDescription
GET/api/v1/agentsList Letta agents
POST/api/v1/agents/{id}/chatChat with a Letta agent
POST/api/v1/agents/generateOne-shot Ollama generation

MQTT (operator+)

MethodPathDescription
POST/api/v1/mqtt/publishPublish a message to a topic

See the DESIGN.md for complete request/response schemas, error codes, and middleware documentation.


Project Structure

Current (v0.1):

p4n4-api/
├── pyproject.toml
├── p4n4_api/
│ ├── main.py # FastAPI app factory + `p4n4-api` entrypoint
│ ├── config.py # Settings from environment variables
│ ├── deps.py # Project resolution dependency (p4n4_lib.manifest)
│ └── routes/ # One APIRouter per API group
│ ├── health.py # GET /health
│ ├── project.py # GET /api/v1/project, /project/validate
│ └── stacks.py # GET /api/v1/stacks, /stacks/{stack}
└── tests/

Planned additions as the upstream-proxy features land: auth/ (JWT), clients/ (async HTTP/MQTT clients per upstream service), models/ (Pydantic schemas), db/ + alembic/ (device registry), Dockerfile + docker-compose.yml.


Development

# Install dependencies (see Getting Started for the p4n4-lib install)
uv pip install -e ".[dev]"# Run locally against a scaffolded project
P4N4_PROJECT_DIR=~/projects/my-p4n4-project uv run uvicorn p4n4_api.main:app --reload --port 8000
# Tests
uv run pytest
# Lint
uv run ruff check .# Format
uv run ruff format .

Tests use synthetic projects and a stubbed Compose client, so they run without Docker or live services. Fixtures live in tests/conftest.py.


Default Port

ServicePort
p4n4-api8000

This does not conflict with any other service in the P4N4 platform.


Network Requirements

In v0.1 the API runs on the host (not in a container): the stack-status endpoints shell out to docker compose ps inside each stack directory, so the host needs the Docker CLI and access to the Docker daemon.

The containerized deployment (attaching to p4n4-net as an external network, with docker compose up -d in this repo and p4n4 up --api in the CLI) is planned along with the upstream-proxy features.


Security

  • JWT — HS256 signed tokens with role claims (device, operator, admin). Access tokens expire in 1 hour; refresh tokens in 7 days.
  • API keys — stored as argon2id hashes; plaintext shown only once at device registration.
  • Secrets — never stored in the database; all upstream credentials are injected via environment variables.
  • Rate limiting — per-subject token-bucket (in-memory); no Redis dependency.
  • CORS — permissive in development, allowlist in production (set via P4N4_API_CORS_ORIGINS).
  • Port exposure — for production, remove the 8000 host-port binding and front with a reverse proxy (nginx, Caddy, Traefik).

Resources

  • p4n4 Platform — umbrella repo and architecture docs
  • DESIGN.md — full API design document (tech stack, schemas, milestones)
  • p4n4-lib — shared library (manifest, layout, validation, Compose wrappers) consumed by this package
  • p4n4-iot — IoT stack (MQTT, InfluxDB, Node-RED, Grafana)
  • p4n4-ai — GenAI stack (Ollama, Letta, n8n)
  • p4n4-edge — Edge AI stack (Edge Impulse runner)
  • FastAPI — Python web framework (OpenAPI 3.1 built-in)
  • pydantic-settings — settings management via environment variables

License

This project is licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages