{
  "openapi": "3.1.0",
  "info": {
    "title": "Infrastructure Functions API",
    "version": "1.0.0",
    "description": "Serverless JavaScript functions with versioning, rollback, per-function environment variables, per-function outbound network access, invocation logs, metrics and cron schedules. Every function runs inside a bubblewrap sandbox. The owner of every resource is derived from the credential, never from the body or the URL. Errors use the envelope `{ \"error\": { \"code\", \"message\", \"details\"? } }` with a stable `code`; collections use `{ items, page: { limit, offset, total, hasMore } }`. Authenticate data routes with an `fk_` key in `x-api-key` (or as `Authorization: Bearer fk_…`), or with an Infrastructure Auth session JWT. Same login, authorization per product. The MCP server at `/mcp` is a separate transport and is not described here.",
    "contact": {
      "name": "Infrastructure",
      "url": "https://myinfrastructure.click/contact"
    },
    "license": {
      "name": "MIT",
      "identifier": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://functions.manager.myinfrastructure.click"
    }
  ],
  "externalDocs": {
    "description": "Agent-oriented implementation guide",
    "url": "https://myinfrastructure.click/products/functions/llms.txt"
  },
  "tags": [
    {
      "name": "Functions",
      "description": "Publish, inspect and remove functions."
    },
    {
      "name": "Versions",
      "description": "Version history and rollback."
    },
    {
      "name": "Configuration",
      "description": "Environment variables and outbound network access."
    },
    {
      "name": "Observability",
      "description": "Invocation logs and metrics."
    },
    {
      "name": "Execution",
      "description": "Invoking a function over HTTP."
    },
    {
      "name": "Schedules",
      "description": "Cron schedules that invoke functions."
    },
    {
      "name": "Account",
      "description": "Identity, API key, plan and account deletion."
    },
    {
      "name": "Service",
      "description": "Public health and documentation."
    }
  ],
  "paths": {
    "/": {
      "get": {
        "operationId": "getWelcomePage",
        "tags": [
          "Service"
        ],
        "summary": "Documentation page",
        "description": "Human-readable HTML page with the minimal API documentation and the active limits.",
        "responses": {
          "200": {
            "description": "HTML page.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/status": {
      "get": {
        "operationId": "getStatus",
        "tags": [
          "Service"
        ],
        "summary": "Service health",
        "description": "Public health check. Reports the sandbox level and which isolation limits are actually enforced. Never reports commercial volume.",
        "responses": {
          "200": {
            "description": "Service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceStatus"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/functions": {
      "get": {
        "operationId": "listFunctions",
        "tags": [
          "Functions"
        ],
        "summary": "List functions",
        "description": "Lists every function of the account, newest first. The list is not paginated: `page.total` and `page.hasMore` are `null`.",
        "responses": {
          "200": {
            "description": "The functions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "page"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FunctionSummary"
                      }
                    },
                    "page": {
                      "$ref": "#/components/schemas/Page"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "post": {
        "operationId": "publishFunction",
        "tags": [
          "Functions"
        ],
        "summary": "Publish a function",
        "description": "Creates the function, or publishes a new version of an existing one and makes it active. The endpoint (`/fn/{name}`) never changes. The plan limit is checked only when a NEW function is created; publishing a new version never hits it.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishFunctionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A new version of an existing function was published (`created: false`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublishFunctionResult"
                }
              }
            }
          },
          "201": {
            "description": "The function was created (`created: true`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublishFunctionResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "get": {
        "operationId": "getFunction",
        "tags": [
          "Functions"
        ],
        "summary": "Get a function",
        "description": "Returns the function with the code of its active version.",
        "responses": {
          "200": {
            "description": "The function.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FunctionDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteFunction",
        "tags": [
          "Functions"
        ],
        "summary": "Delete a function",
        "description": "Deletes the function together with its versions, environment variables, schedules and invocation history.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/versions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "get": {
        "operationId": "listFunctionVersions",
        "tags": [
          "Versions"
        ],
        "summary": "List versions",
        "description": "Version history, newest first, flagging the active one. Not paginated: `page.total` and `page.hasMore` are `null`.",
        "responses": {
          "200": {
            "description": "The versions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "page"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/VersionSummary"
                      }
                    },
                    "page": {
                      "$ref": "#/components/schemas/Page"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/versions/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        },
        {
          "name": "id",
          "in": "path",
          "required": true,
          "description": "Version id (as returned in `versionId`).",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "getFunctionVersion",
        "tags": [
          "Versions"
        ],
        "summary": "Get a version",
        "description": "Returns the code of a specific version.",
        "responses": {
          "200": {
            "description": "The version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Version"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/rollback": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "post": {
        "operationId": "rollbackFunction",
        "tags": [
          "Versions"
        ],
        "summary": "Roll back to a version",
        "description": "Makes an earlier version active. No code is re-sent; only the active pointer moves.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollbackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The version is now active.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "activeVersionId"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "activeVersionId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/network": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "get": {
        "operationId": "getFunctionNetwork",
        "tags": [
          "Configuration"
        ],
        "summary": "Get outbound network access",
        "description": "Whether the function may reach the internet, plus what the manager actually enforces.",
        "responses": {
          "200": {
            "description": "Network state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "allowNetwork",
                    "enforced"
                  ],
                  "properties": {
                    "allowNetwork": {
                      "type": "boolean"
                    },
                    "enforced": {
                      "$ref": "#/components/schemas/EnforcedLimits"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "put": {
        "operationId": "setFunctionNetwork",
        "tags": [
          "Configuration"
        ],
        "summary": "Turn outbound network access on or off",
        "description": "Idempotent. Network is off by default. When enabled on a manager without isolated egress, the value is saved but `effective` is `false` and `warning` explains that invocations will fail with `network_unavailable`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enabled"
                ],
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "allowNetwork",
                    "effective"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "allowNetwork": {
                      "type": "boolean"
                    },
                    "effective": {
                      "type": "boolean",
                      "description": "Whether the saved setting actually works on this manager."
                    },
                    "warning": {
                      "type": "string",
                      "description": "Present only when network is enabled but egress is unavailable."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/env": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "get": {
        "operationId": "listFunctionEnv",
        "tags": [
          "Configuration"
        ],
        "summary": "List environment variables",
        "description": "Variables the function receives in `ctx.env`, ordered by name. Secret values are never returned. Not paginated: `page.total` and `page.hasMore` are `null`.",
        "responses": {
          "200": {
            "description": "The variables.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "page"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EnvVar"
                      }
                    },
                    "page": {
                      "$ref": "#/components/schemas/Page"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "put": {
        "operationId": "setFunctionEnv",
        "tags": [
          "Configuration"
        ],
        "summary": "Set an environment variable",
        "description": "Creates or replaces one variable. Field names are in Portuguese on the wire: `chave` (name), `valor` (value), `secreto` (secret).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetEnvRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/env/{key}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        },
        {
          "name": "key",
          "in": "path",
          "required": true,
          "description": "Variable name.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "operationId": "deleteFunctionEnv",
        "tags": [
          "Configuration"
        ],
        "summary": "Delete an environment variable",
        "description": "Removes one variable from the function.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/logs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "get": {
        "operationId": "listFunctionInvocations",
        "tags": [
          "Observability"
        ],
        "summary": "List invocations",
        "description": "Invocation log of the function (HTTP and cron), newest first, with captured console output. Paginated; `page.limit` is the applied limit.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of invocations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "page"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invocation"
                      }
                    },
                    "page": {
                      "$ref": "#/components/schemas/Page"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/functions/{name}/metrics": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FunctionName"
        }
      ],
      "get": {
        "operationId": "getFunctionMetrics",
        "tags": [
          "Observability"
        ],
        "summary": "Get metrics",
        "description": "Aggregated invocation metrics over a window, with an hourly series (empty hours filled with zeros) and the publishes in the window.",
        "parameters": [
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "description": "Window size in hours, clamped to 1–168.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 168,
              "default": 24
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The metrics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FunctionMetrics"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/fn/{name}": {
      "get": {
        "operationId": "invokeFunctionGet",
        "tags": [
          "Execution"
        ],
        "summary": "Invoke a function (GET)",
        "description": "Runs the active version of the named function, owned by the account behind the credential, inside the sandbox. The function receives the method, the query string (`ctx.query`), the parsed body (`ctx.body`: parsed JSON when `content-type` is `application/json`, raw text otherwise) and its environment variables (`ctx.env`). Forwarded request headers: `content-type`, `accept`, `accept-language`, `user-agent`, `date`, any `x-*` header and known webhook signature headers (`stripe-signature`, `paypal-transmission-sig`, `webhook-signature`, `webhook-id`, `webhook-timestamp`); credentials (`x-api-key`, `authorization`, `cookie`) and infrastructure headers are never forwarded. The response status, headers and body are whatever the function returns (a plain object becomes JSON with status 200); `set-cookie`, `access-control-*` and hop-by-hop headers set by the function are stripped. The same route also answers HEAD. Body limit: 1 MB by default.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FunctionName"
          }
        ],
        "responses": {
          "200": {
            "description": "Response produced by the function. Status (200–599), headers and body are defined by the function code.",
            "content": {
              "*/*": {
                "schema": {}
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The function has no published version (`error: \"no_active_version\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "500": {
            "description": "The function threw or failed to load (`runtime_error`, `load_error`, `no_default_export`, `network_unavailable`, `spawn_error`, `bad_harness_output`). Carries the message and, for runtime errors, the stack.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "503": {
            "description": "Too many concurrent invocations on the manager. Retry after the number of seconds in `retry-after`.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (always 1)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "The function exceeded its timeout (`error: \"timeout\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "507": {
            "description": "The function response exceeded the output limit (`error: \"output_too_large\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "post": {
        "operationId": "invokeFunctionPost",
        "tags": [
          "Execution"
        ],
        "summary": "Invoke a function (POST)",
        "description": "Runs the active version of the named function, owned by the account behind the credential, inside the sandbox. The function receives the method, the query string (`ctx.query`), the parsed body (`ctx.body`: parsed JSON when `content-type` is `application/json`, raw text otherwise) and its environment variables (`ctx.env`). Forwarded request headers: `content-type`, `accept`, `accept-language`, `user-agent`, `date`, any `x-*` header and known webhook signature headers (`stripe-signature`, `paypal-transmission-sig`, `webhook-signature`, `webhook-id`, `webhook-timestamp`); credentials (`x-api-key`, `authorization`, `cookie`) and infrastructure headers are never forwarded. The response status, headers and body are whatever the function returns (a plain object becomes JSON with status 200); `set-cookie`, `access-control-*` and hop-by-hop headers set by the function are stripped. The same route also answers HEAD. Body limit: 1 MB by default.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FunctionName"
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Any payload. JSON is parsed when `content-type` is `application/json`; any other content type reaches the function as a string.",
          "content": {
            "application/json": {
              "schema": {}
            },
            "*/*": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response produced by the function. Status (200–599), headers and body are defined by the function code.",
            "content": {
              "*/*": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The function has no published version (`error: \"no_active_version\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "500": {
            "description": "The function threw or failed to load (`runtime_error`, `load_error`, `no_default_export`, `network_unavailable`, `spawn_error`, `bad_harness_output`). Carries the message and, for runtime errors, the stack.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "503": {
            "description": "Too many concurrent invocations on the manager. Retry after the number of seconds in `retry-after`.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (always 1)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "The function exceeded its timeout (`error: \"timeout\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "507": {
            "description": "The function response exceeded the output limit (`error: \"output_too_large\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "put": {
        "operationId": "invokeFunctionPut",
        "tags": [
          "Execution"
        ],
        "summary": "Invoke a function (PUT)",
        "description": "Runs the active version of the named function, owned by the account behind the credential, inside the sandbox. The function receives the method, the query string (`ctx.query`), the parsed body (`ctx.body`: parsed JSON when `content-type` is `application/json`, raw text otherwise) and its environment variables (`ctx.env`). Forwarded request headers: `content-type`, `accept`, `accept-language`, `user-agent`, `date`, any `x-*` header and known webhook signature headers (`stripe-signature`, `paypal-transmission-sig`, `webhook-signature`, `webhook-id`, `webhook-timestamp`); credentials (`x-api-key`, `authorization`, `cookie`) and infrastructure headers are never forwarded. The response status, headers and body are whatever the function returns (a plain object becomes JSON with status 200); `set-cookie`, `access-control-*` and hop-by-hop headers set by the function are stripped. The same route also answers HEAD. Body limit: 1 MB by default.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FunctionName"
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Any payload. JSON is parsed when `content-type` is `application/json`; any other content type reaches the function as a string.",
          "content": {
            "application/json": {
              "schema": {}
            },
            "*/*": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response produced by the function. Status (200–599), headers and body are defined by the function code.",
            "content": {
              "*/*": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The function has no published version (`error: \"no_active_version\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "500": {
            "description": "The function threw or failed to load (`runtime_error`, `load_error`, `no_default_export`, `network_unavailable`, `spawn_error`, `bad_harness_output`). Carries the message and, for runtime errors, the stack.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "503": {
            "description": "Too many concurrent invocations on the manager. Retry after the number of seconds in `retry-after`.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (always 1)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "The function exceeded its timeout (`error: \"timeout\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "507": {
            "description": "The function response exceeded the output limit (`error: \"output_too_large\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "patch": {
        "operationId": "invokeFunctionPatch",
        "tags": [
          "Execution"
        ],
        "summary": "Invoke a function (PATCH)",
        "description": "Runs the active version of the named function, owned by the account behind the credential, inside the sandbox. The function receives the method, the query string (`ctx.query`), the parsed body (`ctx.body`: parsed JSON when `content-type` is `application/json`, raw text otherwise) and its environment variables (`ctx.env`). Forwarded request headers: `content-type`, `accept`, `accept-language`, `user-agent`, `date`, any `x-*` header and known webhook signature headers (`stripe-signature`, `paypal-transmission-sig`, `webhook-signature`, `webhook-id`, `webhook-timestamp`); credentials (`x-api-key`, `authorization`, `cookie`) and infrastructure headers are never forwarded. The response status, headers and body are whatever the function returns (a plain object becomes JSON with status 200); `set-cookie`, `access-control-*` and hop-by-hop headers set by the function are stripped. The same route also answers HEAD. Body limit: 1 MB by default.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FunctionName"
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Any payload. JSON is parsed when `content-type` is `application/json`; any other content type reaches the function as a string.",
          "content": {
            "application/json": {
              "schema": {}
            },
            "*/*": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Response produced by the function. Status (200–599), headers and body are defined by the function code.",
            "content": {
              "*/*": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The function has no published version (`error: \"no_active_version\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "500": {
            "description": "The function threw or failed to load (`runtime_error`, `load_error`, `no_default_export`, `network_unavailable`, `spawn_error`, `bad_harness_output`). Carries the message and, for runtime errors, the stack.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "503": {
            "description": "Too many concurrent invocations on the manager. Retry after the number of seconds in `retry-after`.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (always 1)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "The function exceeded its timeout (`error: \"timeout\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "507": {
            "description": "The function response exceeded the output limit (`error: \"output_too_large\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "delete": {
        "operationId": "invokeFunctionDelete",
        "tags": [
          "Execution"
        ],
        "summary": "Invoke a function (DELETE)",
        "description": "Runs the active version of the named function, owned by the account behind the credential, inside the sandbox. The function receives the method, the query string (`ctx.query`), the parsed body (`ctx.body`: parsed JSON when `content-type` is `application/json`, raw text otherwise) and its environment variables (`ctx.env`). Forwarded request headers: `content-type`, `accept`, `accept-language`, `user-agent`, `date`, any `x-*` header and known webhook signature headers (`stripe-signature`, `paypal-transmission-sig`, `webhook-signature`, `webhook-id`, `webhook-timestamp`); credentials (`x-api-key`, `authorization`, `cookie`) and infrastructure headers are never forwarded. The response status, headers and body are whatever the function returns (a plain object becomes JSON with status 200); `set-cookie`, `access-control-*` and hop-by-hop headers set by the function are stripped. The same route also answers HEAD. Body limit: 1 MB by default.",
        "parameters": [
          {
            "$ref": "#/components/parameters/FunctionName"
          }
        ],
        "responses": {
          "200": {
            "description": "Response produced by the function. Status (200–599), headers and body are defined by the function code.",
            "content": {
              "*/*": {
                "schema": {}
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The function has no published version (`error: \"no_active_version\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "500": {
            "description": "The function threw or failed to load (`runtime_error`, `load_error`, `no_default_export`, `network_unavailable`, `spawn_error`, `bad_harness_output`). Carries the message and, for runtime errors, the stack.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "503": {
            "description": "Too many concurrent invocations on the manager. Retry after the number of seconds in `retry-after`.",
            "headers": {
              "retry-after": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (always 1)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "The function exceeded its timeout (`error: \"timeout\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          },
          "507": {
            "description": "The function response exceeded the output limit (`error: \"output_too_large\"`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvocationError"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/schedules": {
      "get": {
        "operationId": "listSchedules",
        "tags": [
          "Schedules"
        ],
        "summary": "List schedules",
        "description": "Every schedule of the account, newest first, with the last cron run and the next run. Not paginated: `page.total` and `page.hasMore` are `null`.",
        "responses": {
          "200": {
            "description": "The schedules.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items",
                    "page"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Schedule"
                      }
                    },
                    "page": {
                      "$ref": "#/components/schemas/Page"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "post": {
        "operationId": "createSchedule",
        "tags": [
          "Schedules"
        ],
        "summary": "Create a schedule",
        "description": "Schedules a function on a cron expression. The schedule fires once per tick (not once per worker).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateScheduleRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "id",
                    "function",
                    "cron"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "id": {
                      "type": "string"
                    },
                    "function": {
                      "type": "string",
                      "description": "Function name."
                    },
                    "cron": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/schedules/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ScheduleId"
        }
      ],
      "patch": {
        "operationId": "updateSchedule",
        "tags": [
          "Schedules"
        ],
        "summary": "Update a schedule",
        "description": "Changes the cron expression and/or the params, keeping the id. At least one field is required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateScheduleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated schedule.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ScheduleRow"
                    }
                  ],
                  "type": "object",
                  "properties": {
                    "next_run": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "Next run (ISO 8601). Note: snake_case here, `nextRun` in the list."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteSchedule",
        "tags": [
          "Schedules"
        ],
        "summary": "Delete a schedule",
        "description": "Removes the schedule and disarms its timer.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/schedules/{id}/run": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ScheduleId"
        }
      ],
      "post": {
        "operationId": "runSchedule",
        "tags": [
          "Schedules"
        ],
        "summary": "Run a schedule now",
        "description": "Invokes the scheduled function immediately with the schedule params. Recorded in the log with source `cron`. A failed function run still answers 200 with `ok: false`.",
        "responses": {
          "200": {
            "description": "The run result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleRunResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/plan": {
      "get": {
        "operationId": "getPlan",
        "tags": [
          "Account"
        ],
        "summary": "Get plan notice",
        "description": "The account plan and a billing notice, for display. Never fails: `state: \"unknown\"` when billing cannot be reached. It never decides access.",
        "responses": {
          "200": {
            "description": "The plan notice.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanNotice"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        },
        "security": [
          {
            "apiKey": []
          },
          {
            "apiKeyBearer": []
          },
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Account"
        ],
        "summary": "Get identity and API key",
        "description": "Exchanges an Infrastructure Auth JWT for the account identity. On the first visit the account `fk_` key is created and returned in cleartext in `apiKey`; afterwards `apiKey` is `null` and only `keyPrefix` identifies it. Use `POST /me/key` to obtain a new one.",
        "responses": {
          "200": {
            "description": "The identity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "security": [
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteAccount",
        "tags": [
          "Account"
        ],
        "summary": "Delete the account data",
        "description": "Removes the account API keys from Functions. Refused with `HAS_RESOURCES` while any function exists. The account itself lives in Infrastructure Auth. Requires the Auth JWT; an `fk_` key is refused.",
        "responses": {
          "200": {
            "description": "Account data removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "message",
                    "deleted"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "message": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "object",
                      "required": [
                        "apiKeys"
                      ],
                      "properties": {
                        "apiKeys": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/JwtRequired"
          },
          "409": {
            "description": "Functions still exist (`HAS_RESOURCES`); `details` carries `functions`, `schedules` and `apiKeys` counts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/me/key": {
      "post": {
        "operationId": "rotateApiKey",
        "tags": [
          "Account"
        ],
        "summary": "Generate a new API key",
        "description": "Creates a new `fk_` key and revokes every previous key of the account. The cleartext value is returned only here. Requires the Auth JWT; an `fk_` key is refused.",
        "responses": {
          "201": {
            "description": "The new key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "apiKey",
                    "keyPrefix"
                  ],
                  "properties": {
                    "apiKey": {
                      "type": "string",
                      "pattern": "^fk_[0-9a-f]{64}$"
                    },
                    "keyPrefix": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/JwtRequired"
          }
        },
        "security": [
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    },
    "/me/deletion-preview": {
      "get": {
        "operationId": "getDeletionPreview",
        "tags": [
          "Account"
        ],
        "summary": "Preview account deletion",
        "description": "What the account holds in Functions, so the caller can decide before `DELETE /me`. Requires the Auth JWT; an `fk_` key is refused.",
        "responses": {
          "200": {
            "description": "The inventory.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountInventory"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/JwtRequired"
          }
        },
        "security": [
          {
            "sessionToken": []
          },
          {
            "oauth2": []
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Account API key, prefix `fk_`. Accepted on every data route; refused on `/me*`."
      },
      "apiKeyBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "fk_ API key",
        "description": "The same `fk_` key sent as `Authorization: Bearer fk_…`. Accepted on every data route; refused on `/me*`."
      },
      "sessionToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Infrastructure Auth JWT (RS256, `iss: riligar-auth`), e.g. a dashboard session or a device-flow token from https://auth.worker.myinfrastructure.click. Required on `/me*`; also accepted on data routes."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code with PKCE (S256), issued by Infrastructure Auth. Use it to act on behalf of a person; scopes are listed in the authorization server metadata.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://auth.worker.myinfrastructure.click/oauth/authorize",
            "tokenUrl": "https://auth.worker.myinfrastructure.click/oauth/token",
            "refreshUrl": "https://auth.worker.myinfrastructure.click/oauth/token",
            "scopes": {
              "auth:read": "Read functions, versions, logs, metrics and schedules.",
              "auth:write": "Publish, configure, roll back and schedule functions."
            }
          }
        }
      }
    },
    "parameters": {
      "FunctionName": {
        "name": "name",
        "in": "path",
        "required": true,
        "description": "Function name.",
        "schema": {
          "type": "string",
          "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"
        }
      },
      "ScheduleId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Schedule id.",
        "schema": {
          "type": "string"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size; values above 200 are clamped and the applied value is reported.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "required": false,
        "description": "Rows to skip.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request (`VALIDATION_ERROR`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing credential, or invalid/expired token (`UNAUTHORIZED`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The API key does not match any account (`FORBIDDEN`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "JwtRequired": {
        "description": "An `fk_` key (or no Bearer token) was sent where the Infrastructure Auth JWT is required (`FORBIDDEN`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found (`NOT_FOUND`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflict (`CONFLICT`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PlanLimit": {
        "description": "Plan limit reached on function creation: `PLAN_LIMIT` (upgrade) or `SUBSCRIPTION_REQUIRED` (subscribe). `details` carries `resource`, `current`, `limit`, `plan`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Payload above the limit (`PAYLOAD_TOO_LARGE`): code above 512 KB, env value above 8 KB, or invocation body above 1 MB.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "UNAUTHORIZED",
                  "FORBIDDEN",
                  "NOT_FOUND",
                  "VALIDATION_ERROR",
                  "CONFLICT",
                  "PLAN_LIMIT",
                  "SUBSCRIPTION_REQUIRED",
                  "HAS_RESOURCES",
                  "RATE_LIMITED",
                  "NAME_TAKEN",
                  "EXPIRED",
                  "PAYLOAD_TOO_LARGE",
                  "INTERNAL_ERROR",
                  "SERVICE_UNAVAILABLE"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable (Portuguese); may change."
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              },
              "retriable": {
                "type": "boolean",
                "description": "Present (true) when retrying may succeed."
              }
            }
          }
        }
      },
      "InvocationError": {
        "type": "object",
        "description": "Sandbox failure of a function invocation. Not the standard error envelope: `error` is a string.",
        "required": [
          "error",
          "durationMs"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "no_active_version",
              "timeout",
              "output_too_large",
              "runtime_error",
              "load_error",
              "no_default_export",
              "network_unavailable",
              "spawn_error",
              "bad_harness_output"
            ]
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "stack": {
            "type": "string"
          },
          "durationMs": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "limit",
          "offset",
          "total",
          "hasMore"
        ],
        "properties": {
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`null` when the route does not count (unpaginated lists)."
          },
          "hasMore": {
            "type": [
              "boolean",
              "null"
            ]
          }
        }
      },
      "Ok": {
        "type": "object",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "const": true
          }
        }
      },
      "ServiceStatus": {
        "type": "object",
        "required": [
          "service",
          "status",
          "uptime_s",
          "sandbox",
          "enforced",
          "auth",
          "scheduler"
        ],
        "properties": {
          "service": {
            "const": "riligar-functions"
          },
          "status": {
            "const": "ok"
          },
          "uptime_s": {
            "type": "integer"
          },
          "sandbox": {
            "type": "string",
            "enum": [
              "bwrap",
              "process"
            ]
          },
          "enforced": {
            "$ref": "#/components/schemas/EnforcedLimits"
          },
          "auth": {
            "type": "string",
            "enum": [
              "riligar-auth",
              "dev-user"
            ]
          },
          "scheduler": {
            "type": "string",
            "enum": [
              "primary",
              "worker"
            ]
          },
          "gateDecisionsLastHour": {
            "type": "integer"
          },
          "gateBlindLastHour": {
            "type": "integer"
          }
        }
      },
      "EnforcedLimits": {
        "type": "object",
        "properties": {
          "sandbox": {
            "type": "string",
            "enum": [
              "bwrap",
              "process"
            ]
          },
          "timeout": {
            "type": "boolean"
          },
          "outputSize": {
            "type": "boolean"
          },
          "memory": {
            "type": "boolean"
          },
          "network": {
            "type": "boolean",
            "description": "The network policy is enforced by the jail."
          },
          "egress": {
            "type": "boolean",
            "description": "The manager can deliver isolated internet access to functions that enable it."
          },
          "filesystem": {
            "type": "boolean"
          },
          "processes": {
            "type": "boolean"
          }
        }
      },
      "PublishFunctionRequest": {
        "type": "object",
        "required": [
          "name",
          "code"
        ],
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
            "description": "Lowercase letters, digits and hyphens, 1–63 chars. Reserved: functions, schedules, me, admin, status, health, mcp."
          },
          "code": {
            "type": "string",
            "description": "ES module source with a default export `(req, ctx) => Response | object`. Max 512 KB."
          }
        }
      },
      "PublishFunctionResult": {
        "type": "object",
        "required": [
          "ok",
          "name",
          "versionId",
          "created",
          "endpoint"
        ],
        "properties": {
          "ok": {
            "const": true
          },
          "name": {
            "type": "string"
          },
          "versionId": {
            "type": "string"
          },
          "created": {
            "type": "boolean"
          },
          "endpoint": {
            "type": "string",
            "examples": [
              "/fn/hello"
            ]
          }
        }
      },
      "FunctionSummary": {
        "type": "object",
        "required": [
          "id",
          "name",
          "activeVersionId",
          "allowNetwork",
          "createdAt",
          "updatedAt",
          "versions"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "activeVersionId": {
            "type": [
              "string",
              "null"
            ]
          },
          "allowNetwork": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "description": "Raw 0/1 in the list (boolean in the detail)."
          },
          "createdAt": {
            "type": "integer",
            "description": "Epoch milliseconds."
          },
          "updatedAt": {
            "type": "integer",
            "description": "Epoch milliseconds."
          },
          "versions": {
            "type": "integer",
            "description": "Number of versions."
          }
        }
      },
      "FunctionDetail": {
        "type": "object",
        "required": [
          "id",
          "name",
          "activeVersionId",
          "allowNetwork",
          "code",
          "endpoint"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "activeVersionId": {
            "type": [
              "string",
              "null"
            ]
          },
          "allowNetwork": {
            "type": "boolean"
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Code of the active version."
          },
          "endpoint": {
            "type": "string",
            "examples": [
              "/fn/hello"
            ]
          }
        }
      },
      "VersionSummary": {
        "type": "object",
        "required": [
          "id",
          "createdAt",
          "active"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "createdAt": {
            "type": "integer",
            "description": "Epoch milliseconds."
          },
          "active": {
            "type": "boolean"
          }
        }
      },
      "Version": {
        "type": "object",
        "required": [
          "id",
          "code",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "created_at": {
            "type": "integer",
            "description": "Epoch milliseconds (snake_case on this route)."
          }
        }
      },
      "RollbackRequest": {
        "type": "object",
        "required": [
          "versionId"
        ],
        "properties": {
          "versionId": {
            "type": "string"
          }
        }
      },
      "EnvVar": {
        "type": "object",
        "required": [
          "chave",
          "valor",
          "secreto",
          "preview",
          "updated_at"
        ],
        "properties": {
          "chave": {
            "type": "string",
            "description": "Variable name."
          },
          "valor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value; `null` for secrets."
          },
          "secreto": {
            "type": "boolean",
            "description": "Whether the variable is secret."
          },
          "preview": {
            "type": [
              "string",
              "null"
            ],
            "description": "Masked placeholder for secrets; `null` otherwise."
          },
          "updated_at": {
            "type": "integer",
            "description": "Epoch milliseconds."
          }
        }
      },
      "SetEnvRequest": {
        "type": "object",
        "required": [
          "chave",
          "valor"
        ],
        "properties": {
          "chave": {
            "type": "string",
            "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$",
            "description": "Variable name."
          },
          "valor": {
            "type": "string",
            "maxLength": 8192,
            "description": "Value (max 8 KB)."
          },
          "secreto": {
            "type": "boolean",
            "default": false,
            "description": "Secret values are never returned again."
          }
        }
      },
      "LogLine": {
        "type": "object",
        "properties": {
          "nivel": {
            "type": "string",
            "enum": [
              "log",
              "info",
              "warn",
              "error",
              "debug"
            ],
            "description": "Console level."
          },
          "texto": {
            "type": "string",
            "description": "Text."
          },
          "t": {
            "type": "integer",
            "description": "Epoch milliseconds."
          }
        }
      },
      "Invocation": {
        "type": "object",
        "required": [
          "id",
          "source",
          "status",
          "ok",
          "durationMs",
          "error",
          "logs",
          "versionId",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "http",
              "cron"
            ]
          },
          "status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status returned by the function; `null` on failure."
          },
          "ok": {
            "type": "integer",
            "enum": [
              0,
              1
            ]
          },
          "durationMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "logs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LogLine"
            }
          },
          "versionId": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "integer",
            "description": "Epoch milliseconds."
          }
        }
      },
      "FunctionMetrics": {
        "type": "object",
        "required": [
          "windowHours",
          "total",
          "errors",
          "average",
          "peak",
          "p50",
          "p95",
          "series",
          "publishes"
        ],
        "properties": {
          "windowHours": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "errors": {
            "type": "integer"
          },
          "average": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Mean duration (ms)."
          },
          "peak": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Max duration (ms)."
          },
          "p50": {
            "type": [
              "integer",
              "null"
            ]
          },
          "p95": {
            "type": [
              "integer",
              "null"
            ]
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "hour",
                "invocations",
                "errors"
              ],
              "properties": {
                "hour": {
                  "type": "integer",
                  "description": "Bucket start, epoch ms."
                },
                "invocations": {
                  "type": "integer"
                },
                "errors": {
                  "type": "integer"
                }
              }
            }
          },
          "publishes": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "created_at"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "created_at": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "ScheduleParams": {
        "type": "object",
        "description": "What the scheduled invocation receives. With `body` the run is a POST, otherwise a GET.",
        "properties": {
          "query": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "body": {}
        }
      },
      "CreateScheduleRequest": {
        "type": "object",
        "required": [
          "name",
          "cron"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the function to schedule."
          },
          "cron": {
            "type": "string",
            "examples": [
              "*/5 * * * *"
            ]
          },
          "params": {
            "$ref": "#/components/schemas/ScheduleParams"
          }
        }
      },
      "UpdateScheduleRequest": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "cron": {
            "type": "string"
          },
          "params": {
            "$ref": "#/components/schemas/ScheduleParams"
          }
        }
      },
      "ScheduleRow": {
        "type": "object",
        "required": [
          "id",
          "cron",
          "params",
          "createdAt",
          "functionName",
          "functionId"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "cron": {
            "type": "string"
          },
          "params": {
            "type": [
              "string",
              "null"
            ],
            "description": "JSON-encoded ScheduleParams."
          },
          "createdAt": {
            "type": "integer",
            "description": "Epoch milliseconds."
          },
          "functionName": {
            "type": "string"
          },
          "functionId": {
            "type": "string"
          },
          "lastOk": {
            "type": [
              "integer",
              "null"
            ],
            "enum": [
              0,
              1,
              null
            ]
          },
          "lastStatus": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lastError": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastDurationMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lastRun": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Last cron run, epoch ms."
          }
        }
      },
      "Schedule": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ScheduleRow"
          }
        ],
        "type": "object",
        "properties": {
          "nextRun": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ScheduleRunResult": {
        "type": "object",
        "required": [
          "ok",
          "status",
          "durationMs",
          "error",
          "message",
          "logs"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "durationMs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "logs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LogLine"
            }
          }
        }
      },
      "PlanNotice": {
        "type": "object",
        "required": [
          "state",
          "plan",
          "limit",
          "message"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "unknown",
              "active",
              "free",
              "none"
            ]
          },
          "plan": {
            "type": [
              "string",
              "null"
            ]
          },
          "limit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Me": {
        "type": "object",
        "required": [
          "user",
          "apiKey",
          "keyPrefix",
          "mode"
        ],
        "properties": {
          "user": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "apiKey": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cleartext `fk_` key, only on the visit that creates it."
          },
          "keyPrefix": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "auth",
              "dev-user"
            ]
          }
        }
      },
      "AccountInventory": {
        "type": "object",
        "required": [
          "functions",
          "schedules",
          "apiKeys"
        ],
        "properties": {
          "functions": {
            "type": "integer"
          },
          "schedules": {
            "type": "integer"
          },
          "apiKeys": {
            "type": "integer"
          }
        }
      }
    }
  }
}
