{
    "openapi": "3.1.0",
    "info": {
        "title": "FarmNeural Agent API",
        "version": "1.0.0",
        "description": "Per-tenant read + control API for FarmNeural. Authenticate with a Bearer token minted in the client portal. Every request is scoped to the token's tenant. READ-scope tokens may query telemetry; CONTROL-scope tokens may additionally run irrigation. Control calls accept an Idempotency-Key header."
    },
    "servers": [
        {
            "url": "https://www.farmneural.com/api/v1"
        }
    ],
    "security": [
        {
            "bearerToken": []
        }
    ],
    "tags": [
        {
            "name": "read",
            "description": "Telemetry (scope: read)."
        },
        {
            "name": "control",
            "description": "Irrigation control (scope: control)."
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerToken": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "fnk_*",
                "description": "A per-tenant API token (prefix fnk_) from the client portal."
            }
        },
        "parameters": {
            "IdempotencyKey": {
                "name": "Idempotency-Key",
                "in": "header",
                "required": false,
                "description": "Replay-safe key. A repeat with the same key returns the original result without re-acting (24h).",
                "schema": {
                    "type": "string",
                    "maxLength": 200
                }
            }
        },
        "responses": {
            "Unauthorized": {
                "description": "Missing or invalid token."
            },
            "Forbidden": {
                "description": "Token lacks the required scope."
            },
            "NotFound": {
                "description": "Resource not found in this tenant, or zone not controllable."
            },
            "Conflict": {
                "description": "Control is read-only (recommend) mode."
            }
        }
    },
    "paths": {
        "/me": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Identity of the presented token.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/sensors": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "List sensor nodes.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/sensors/{node}": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Get one sensor node.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                },
                "parameters": [
                    {
                        "name": "node",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Sensor node id within the tenant."
                    }
                ]
            }
        },
        "/sensors/{node}/readings": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Recent readings for a node.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                },
                "parameters": [
                    {
                        "name": "node",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Sensor node id within the tenant."
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Max rows to return."
                    }
                ]
            }
        },
        "/zones": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "List irrigation zones (stations).",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/zones/{station}": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Get one zone.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                },
                "parameters": [
                    {
                        "name": "station",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Station (zone) id within the tenant."
                    }
                ]
            }
        },
        "/zones/{station}/recommendation": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Today's watering recommendation for a zone.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                },
                "parameters": [
                    {
                        "name": "station",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Station (zone) id within the tenant."
                    }
                ]
            }
        },
        "/status": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Fleet summary.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/alerts": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Open sensor + flow alerts.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/weather": {
            "get": {
                "tags": [
                    "read"
                ],
                "summary": "Recent weather observations.",
                "responses": {
                    "200": {
                        "description": "OK"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                },
                "parameters": [
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Max rows to return."
                    }
                ]
            }
        },
        "/zones/{station}/run": {
            "post": {
                "tags": [
                    "control"
                ],
                "summary": "Run a zone now for N minutes.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    },
                    {
                        "name": "station",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Station (zone) id within the tenant."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "minutes"
                                ],
                                "properties": {
                                    "minutes": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 180
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Action performed."
                    },
                    "202": {
                        "description": "Action accepted/started."
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "422": {
                        "description": "Validation error."
                    }
                }
            }
        },
        "/zones/{station}/skip": {
            "post": {
                "tags": [
                    "control"
                ],
                "summary": "Skip the zone's next scheduled run.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    },
                    {
                        "name": "station",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Station (zone) id within the tenant."
                    }
                ],
                "requestBody": null,
                "responses": {
                    "200": {
                        "description": "Action performed."
                    },
                    "202": {
                        "description": "Action accepted/started."
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "422": {
                        "description": "Validation error."
                    }
                }
            }
        },
        "/controller/stop": {
            "post": {
                "tags": [
                    "control"
                ],
                "summary": "Stop all watering.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": null,
                "responses": {
                    "200": {
                        "description": "Action performed."
                    },
                    "202": {
                        "description": "Action accepted/started."
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "422": {
                        "description": "Validation error."
                    }
                }
            }
        },
        "/controller/rain-delay": {
            "post": {
                "tags": [
                    "control"
                ],
                "summary": "Set a rain delay for N hours.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "hours"
                                ],
                                "properties": {
                                    "hours": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 72
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Action performed."
                    },
                    "202": {
                        "description": "Action accepted/started."
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "422": {
                        "description": "Validation error."
                    }
                }
            }
        },
        "/controller/standby": {
            "post": {
                "tags": [
                    "control"
                ],
                "summary": "Enter or exit standby.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "on"
                                ],
                                "properties": {
                                    "on": {
                                        "type": "boolean"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Action performed."
                    },
                    "202": {
                        "description": "Action accepted/started."
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "$ref": "#/components/responses/Conflict"
                    },
                    "422": {
                        "description": "Validation error."
                    }
                }
            }
        }
    }
}