{
  "openapi": "3.1.0",
  "info": {
    "title": "Noda public content API",
    "version": "1.0.0",
    "description": "A read-only JSON API of what is public on noda.energy: Noda's use cases (each with the first message it sends and a link that opens Noda with it), the three guides, the FAQ and the pages. No key is needed. Noda's app (app.noda.energy) has no public API yet; write to hello@noda.energy for partner access.",
    "termsOfService": "https://trust.noda.energy/terms",
    "contact": {
      "name": "Noda (TIMPIA S.R.L.)",
      "email": "hello@noda.energy",
      "url": "https://noda.energy/contact"
    }
  },
  "servers": [
    {
      "url": "https://noda.energy",
      "description": "noda.energy"
    }
  ],
  "externalDocs": {
    "description": "Noda API and developer docs",
    "url": "https://noda.energy/docs"
  },
  "tags": [
    {
      "name": "content",
      "description": "Read-only content of noda.energy. GET or HEAD, no key, CORS open."
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "List the API's endpoints and files",
        "description": "The entry point: the API's version, its endpoints and the machine-readable files of the site.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "List the API's endpoints and files.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/v1/use-cases": {
      "get": {
        "operationId": "listUseCases",
        "summary": "List Noda's use cases",
        "description": "Every ready-to-send job Noda's app offers, with when to use it, what to provide, the steps, the outcome, the first message it opens with and a link that opens Noda with that message.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "List Noda's use cases.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UseCaseList"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/v1/use-cases/{useCaseId}": {
      "get": {
        "operationId": "getUseCase",
        "summary": "Get one use case",
        "description": "One use case by its id, for example `screen` (screen a possible site) or `grid` (compare grid connection options).",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "Get one use case.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UseCase"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        },
        "parameters": [
          {
            "name": "useCaseId",
            "in": "path",
            "required": true,
            "description": "The id. One of: data, protected, screen, compare, risks, evidence, grid, permits, yield, battery, application, offer.",
            "schema": {
              "type": "string",
              "enum": [
                "data",
                "protected",
                "screen",
                "compare",
                "risks",
                "evidence",
                "grid",
                "permits",
                "yield",
                "battery",
                "application",
                "offer"
              ]
            },
            "example": "data"
          }
        ]
      }
    },
    "/api/v1/guides": {
      "get": {
        "operationId": "listGuides",
        "summary": "List the three guides",
        "description": "The three guides on noda.energy (find a site, risk screening, continue development), each with its use cases and FAQ.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "List the three guides.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GuideList"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/v1/guides/{guideId}": {
      "get": {
        "operationId": "getGuide",
        "summary": "Get one guide",
        "description": "One guide by its id: `site-finding`, `screening` or `development`.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "Get one guide.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Guide"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        },
        "parameters": [
          {
            "name": "guideId",
            "in": "path",
            "required": true,
            "description": "The id. One of: site-finding, screening, development.",
            "schema": {
              "type": "string",
              "enum": [
                "site-finding",
                "screening",
                "development"
              ]
            },
            "example": "site-finding"
          }
        ]
      }
    },
    "/api/v1/faq": {
      "get": {
        "operationId": "listFaq",
        "summary": "List the frequently asked questions",
        "description": "Every question and answer on noda.energy, with the page it is on.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "List the frequently asked questions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FaqList"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "listPages",
        "summary": "List the site's pages",
        "description": "Every page of noda.energy with its title, description and the URL of its Markdown version.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "List the site's pages.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageList"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Link": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The id."
          },
          "name": {
            "type": "string",
            "description": "The name."
          },
          "title": {
            "type": "string",
            "description": "The title."
          },
          "url": {
            "type": "string",
            "description": "The page.",
            "format": "uri"
          },
          "apiUrl": {
            "type": "string",
            "description": "This item in the API.",
            "format": "uri"
          }
        }
      },
      "UseCase": {
        "type": "object",
        "description": "One ready-to-send job in Noda's app.",
        "required": [
          "id",
          "title",
          "summary",
          "guide",
          "firstMessage",
          "askUrl",
          "url",
          "apiUrl"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The use case's id, for example `screen`."
          },
          "title": {
            "type": "string",
            "description": "The title, for example \"Screen a possible site\"."
          },
          "shortDescription": {
            "type": "string",
            "description": "One short line."
          },
          "summary": {
            "type": "string",
            "description": "What the job does."
          },
          "guide": {
            "$ref": "#/components/schemas/Link",
            "description": "The guide this use case belongs to."
          },
          "phase": {
            "type": "string",
            "description": "The project phase: Find, Assess or Develop."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Topics, for example Grid or Land."
          },
          "whenToUse": {
            "type": "string",
            "description": "When the job fits."
          },
          "whatToProvide": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What to give Noda."
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What happens, in order."
          },
          "outcome": {
            "type": "string",
            "description": "What you get."
          },
          "firstMessage": {
            "type": "string",
            "description": "The whole first message the job sends, with its default values."
          },
          "askUrl": {
            "type": "string",
            "description": "Opens Noda with the first message. A signed-in user gets a new project with it; a visitor signs up first.",
            "format": "uri"
          },
          "url": {
            "type": "string",
            "description": "The use case on noda.energy.",
            "format": "uri"
          },
          "apiUrl": {
            "type": "string",
            "description": "This use case in the API.",
            "format": "uri"
          }
        }
      },
      "UseCaseList": {
        "type": "object",
        "required": [
          "count",
          "useCases"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many use cases."
          },
          "useCases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UseCase"
            }
          }
        }
      },
      "FaqEntry": {
        "type": "object",
        "required": [
          "question",
          "answer"
        ],
        "properties": {
          "question": {
            "type": "string",
            "description": "The question."
          },
          "answer": {
            "type": "string",
            "description": "The answer."
          },
          "page": {
            "type": "string",
            "description": "The page the question is on.",
            "format": "uri"
          },
          "topic": {
            "type": "string",
            "description": "Noda, or the guide's name."
          }
        }
      },
      "FaqList": {
        "type": "object",
        "required": [
          "count",
          "faq"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many questions."
          },
          "faq": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FaqEntry"
            }
          }
        }
      },
      "Guide": {
        "type": "object",
        "description": "One of the three guides on noda.energy.",
        "required": [
          "id",
          "name",
          "url",
          "useCases",
          "faq"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The guide's id.",
            "enum": [
              "site-finding",
              "screening",
              "development"
            ]
          },
          "name": {
            "type": "string",
            "description": "The name, for example \"Find a site\"."
          },
          "tagline": {
            "type": "string",
            "description": "One line."
          },
          "title": {
            "type": "string",
            "description": "The page title."
          },
          "description": {
            "type": "string",
            "description": "The page description."
          },
          "url": {
            "type": "string",
            "description": "The guide.",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "description": "The guide in Markdown.",
            "format": "uri"
          },
          "apiUrl": {
            "type": "string",
            "description": "This guide in the API.",
            "format": "uri"
          },
          "useCases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Link"
            }
          },
          "faq": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "question",
                "answer"
              ],
              "properties": {
                "question": {
                  "type": "string",
                  "description": "The question."
                },
                "answer": {
                  "type": "string",
                  "description": "The answer."
                }
              }
            },
            "description": "The guide's FAQ."
          }
        }
      },
      "GuideList": {
        "type": "object",
        "required": [
          "count",
          "guides"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many guides."
          },
          "guides": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Guide"
            }
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "path",
          "url",
          "markdownUrl",
          "title"
        ],
        "properties": {
          "path": {
            "type": "string",
            "description": "The path on the page's host, for example /screening. url has the host: noda.energy, or trust.noda.energy for the legal documents."
          },
          "url": {
            "type": "string",
            "description": "The page.",
            "format": "uri"
          },
          "markdownUrl": {
            "type": "string",
            "description": "The page in Markdown.",
            "format": "uri"
          },
          "title": {
            "type": "string",
            "description": "The title."
          },
          "description": {
            "type": "string",
            "description": "The description."
          }
        }
      },
      "PageList": {
        "type": "object",
        "required": [
          "count",
          "pages"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "How many pages."
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "required": [
          "name",
          "version",
          "endpoints"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The API's name."
          },
          "version": {
            "type": "string",
            "description": "The API's version."
          },
          "description": {
            "type": "string",
            "description": "What the API holds."
          },
          "documentation": {
            "type": "string",
            "description": "The documentation.",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "description": "This description.",
            "format": "uri"
          },
          "endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "method",
                "path",
                "operationId"
              ],
              "properties": {
                "method": {
                  "type": "string",
                  "description": "The HTTP method."
                },
                "path": {
                  "type": "string",
                  "description": "The path."
                },
                "url": {
                  "type": "string",
                  "description": "The full URL.",
                  "format": "uri"
                },
                "operationId": {
                  "type": "string",
                  "description": "The operation's id in /openapi.json."
                },
                "summary": {
                  "type": "string",
                  "description": "What it returns."
                }
              }
            }
          },
          "files": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            },
            "description": "The site's machine-readable files."
          },
          "openNodaWithAPrompt": {
            "type": "string",
            "description": "The app link pattern that opens Noda with a prompt."
          },
          "contact": {
            "type": "string",
            "description": "Email."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "status",
              "code",
              "message",
              "hint",
              "docs"
            ],
            "properties": {
              "status": {
                "type": "integer",
                "description": "The HTTP status."
              },
              "code": {
                "type": "string",
                "description": "A stable code: not_found, method_not_allowed or server_error.",
                "enum": [
                  "not_found",
                  "method_not_allowed",
                  "server_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "What went wrong."
              },
              "hint": {
                "type": "string",
                "description": "What to do next."
              },
              "docs": {
                "type": "string",
                "description": "The documentation.",
                "format": "uri"
              }
            }
          }
        }
      }
    },
    "responses": {
      "NotFound": {
        "description": "No endpoint, use case or guide at this address.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "The API is read-only: GET and HEAD only.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
