{
  "openapi": "3.1.0",
  "info": {
    "title": "Xylem AB site API",
    "version": "1.0.0",
    "summary": "Read-only company, services and contact data for Xylem AB, a wood technology consultancy in Sweden.",
    "description": "Xylem AB (Xylem Aktiebolag, org.nr 556271-5648) is an independent wood technology consultancy in Sweden. Independent wood technology consultancy in Sweden; not affiliated with Xylem Inc. (water technology). This API exposes the same facts the website shows, as JSON, for software agents and integrations. It is public, read-only, unauthenticated and rate-limited only by the hosting platform. Errors follow RFC 9457 (application/problem+json) with a `hint` field describing how to recover. Human-readable context: https://www.xylem.se/llms.txt. Any page on the site can be fetched as markdown with `Accept: text/markdown` or at its .md twin (for example /about.md); that content channel is not part of this API.",
    "contact": {
      "name": "Thomas Thörnqvist",
      "email": "thomas@xylem.se",
      "url": "https://www.xylem.se/contact"
    },
    "license": {
      "name": "Site content, all rights reserved; API data may be quoted with attribution",
      "url": "https://www.xylem.se/privacy"
    }
  },
  "externalDocs": {
    "description": "llms.txt: site summary and when to use Xylem AB",
    "url": "https://www.xylem.se/llms.txt"
  },
  "servers": [
    {
      "url": "https://www.xylem.se",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "discovery",
      "description": "Entry points that list what else exists."
    },
    {
      "name": "company",
      "description": "Who Xylem AB is."
    },
    {
      "name": "services",
      "description": "What Xylem AB does."
    },
    {
      "name": "contact",
      "description": "How to get in touch."
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "xylem_get_api_index",
        "tags": [
          "discovery"
        ],
        "summary": "List the API's resources",
        "description": "Returns the API name, version and absolute links to every resource plus the OpenAPI document, llms.txt, agents.md and sitemap. Call this first if you only know the host and want to discover what exists; the answer never changes per request, so one call per session is enough. Do not use it to look up company facts; follow the links it returns (xylem_get_company, xylem_list_services, xylem_get_contact) instead. Read-only; no authentication.",
        "responses": {
          "200": {
            "description": "Index of resources.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          },
          "405": {
            "description": "Only GET, HEAD and OPTIONS are supported.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Any other error, as RFC 9457 problem details.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/company": {
      "get": {
        "operationId": "xylem_get_company",
        "tags": [
          "company"
        ],
        "summary": "Get the company profile",
        "description": "Legal name, Swedish organisation number, founding year, registered location (locality level), languages, founder and the ids of the services offered. Use this to identify or verify Xylem AB, or to answer 'who is Xylem AB' questions. Pass include=services to embed the full service objects instead of making a second call. Do not use it for Xylem Inc. (water technology, pumps): that is an unrelated company, and this API describes only the Swedish wood-technology consultancy Xylem AB. Read-only, static data; no authentication.",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Comma-separated related resources to embed. Currently only `services`.",
            "schema": {
              "type": "string",
              "enum": [
                "services"
              ]
            },
            "example": "services"
          }
        ],
        "responses": {
          "200": {
            "description": "The company profile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          },
          "400": {
            "description": "Malformed query parameter; see components.responses.BadRequest for an example.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Only GET, HEAD and OPTIONS are supported.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Any other error, as RFC 9457 problem details.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/services": {
      "get": {
        "operationId": "xylem_list_services",
        "tags": [
          "services"
        ],
        "summary": "List consulting services",
        "description": "All consulting services Xylem AB offers, each with a stable id usable with xylem_get_service. The list is small (currently three), so the defaults return everything; limit and offset exist for clients that page uniformly across APIs. Use this to answer 'what does Xylem AB do' or to pick a service id, then call xylem_get_service for one item. The data is static, so cache the result rather than calling repeatedly. Read-only; no authentication.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return (1-50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 50
            },
            "example": 10
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of items to skip before the first returned item.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "example": 0
          }
        ],
        "responses": {
          "200": {
            "description": "The service list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceList"
                }
              }
            }
          },
          "400": {
            "description": "Malformed query parameter; see components.responses.BadRequest for an example.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Only GET, HEAD and OPTIONS are supported.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Any other error, as RFC 9457 problem details.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/services/{id}": {
      "get": {
        "operationId": "xylem_get_service",
        "tags": [
          "services"
        ],
        "summary": "Get one service by id",
        "description": "Returns one consulting service by id: its name, a one-sentence description and the URL where the website describes it. Use it after xylem_list_services when you need a single service's details; ids are stable slugs. Unknown ids return a 404 problem whose detail lists the known ids, so you can self-correct without another list call. Read-only; no authentication.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Service id (slug).",
            "schema": {
              "type": "string",
              "enum": [
                "manufacturing-optimization",
                "product-innovation",
                "sustainability-consulting"
              ]
            },
            "example": "manufacturing-optimization"
          }
        ],
        "responses": {
          "200": {
            "description": "The service.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Service"
                }
              }
            }
          },
          "404": {
            "description": "Unknown id; detail lists the known ids.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "405": {
            "description": "Only GET, HEAD and OPTIONS are supported.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Any other error, as RFC 9457 problem details.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact": {
      "get": {
        "operationId": "xylem_get_contact",
        "tags": [
          "contact"
        ],
        "summary": "Get contact details",
        "description": "Returns how to reach Xylem AB: the email address (the only channel; there is no phone number or contact form), location, organisation number, working languages, and a checklist of what an enquiry should contain. Use it when a user wants to contact, hire or ask Xylem AB something, then draft the email yourself; there is no endpoint that sends messages. Do not use it to contact Xylem Inc. (water technology), an unrelated company. Read-only; no authentication.",
        "responses": {
          "200": {
            "description": "Contact details.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "405": {
            "description": "Only GET, HEAD and OPTIONS are supported.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Any other error, as RFC 9457 problem details.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "responses": {
      "BadRequest": {
        "description": "A query parameter is malformed; detail names the parameter and the accepted values.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "about:blank",
              "title": "Bad Request",
              "status": 400,
              "detail": "Query parameter \"limit\" must be an integer between 1 and 50; got \"500\".",
              "instance": "/api/v1/services?limit=500",
              "hint": "Omit \"limit\" to use the default, or see the parameter schema in the OpenAPI document."
            }
          }
        }
      },
      "Problem": {
        "description": "Any other error, as RFC 9457 problem details.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "about:blank",
              "title": "Internal Server Error",
              "status": 500,
              "detail": "Unexpected error."
            }
          }
        }
      },
      "NotFound": {
        "description": "The resource does not exist.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "about:blank",
              "title": "Not Found",
              "status": 404,
              "detail": "No service with id \"x\". Known ids: manufacturing-optimization, product-innovation, sustainability-consulting.",
              "instance": "/api/v1/services/x",
              "hint": "List the available operations in the OpenAPI document at /openapi.json or start from /api/v1."
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Only GET, HEAD and OPTIONS are supported; the API is read-only.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "about:blank",
              "title": "Method Not Allowed",
              "status": 405,
              "detail": "POST is not supported on /api/v1/company.",
              "instance": "/api/v1/company",
              "hint": "Use GET, HEAD, OPTIONS. This API is read-only."
            }
          }
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 Problem Details, plus `hint` and `links` extension members.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Problem type URI; about:blank when the title is the HTTP reason phrase."
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation specific to this occurrence."
          },
          "instance": {
            "type": "string",
            "description": "Path that produced the problem."
          },
          "hint": {
            "type": "string",
            "description": "One actionable sentence on how to recover."
          },
          "links": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            },
            "description": "URIs worth trying next (openapi, llms, sitemap, api)."
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "required": [
          "name",
          "version",
          "description",
          "openapi",
          "links"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "links": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "Address": {
        "type": "object",
        "description": "Registered location at locality level; no street address is published.",
        "required": [
          "locality",
          "region",
          "country",
          "countryCode"
        ],
        "properties": {
          "locality": {
            "type": "string",
            "example": "Jät"
          },
          "region": {
            "type": "string",
            "example": "Kronoberg County"
          },
          "country": {
            "type": "string",
            "example": "Sweden"
          },
          "countryCode": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "example": "SE"
          }
        }
      },
      "Person": {
        "type": "object",
        "required": [
          "name",
          "jobTitle"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "jobTitle": {
            "type": "string"
          }
        }
      },
      "Company": {
        "type": "object",
        "required": [
          "id",
          "name",
          "legalName",
          "organisationNumber",
          "url",
          "email",
          "address",
          "languages",
          "founder",
          "serviceIds"
        ],
        "properties": {
          "id": {
            "type": "string",
            "const": "xylem-ab"
          },
          "name": {
            "type": "string"
          },
          "legalName": {
            "type": "string"
          },
          "organisationNumber": {
            "type": "string",
            "pattern": "^\\d{6}-\\d{4}$",
            "description": "Swedish organisationsnummer."
          },
          "foundingYear": {
            "type": "integer"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "description": {
            "type": "string"
          },
          "disambiguation": {
            "type": "string"
          },
          "industry": {
            "type": "string"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "BCP 47 language tag"
            }
          },
          "founder": {
            "$ref": "#/components/schemas/Person"
          },
          "serviceIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Service"
            },
            "description": "Present only when include=services."
          },
          "lastModified": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "Service": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "url",
          "provider"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Where the service is described on the website."
          },
          "provider": {
            "type": "string",
            "format": "uri",
            "description": "Link to the company resource."
          }
        }
      },
      "ServiceList": {
        "type": "object",
        "required": [
          "items",
          "total",
          "limit",
          "offset",
          "next"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Service"
            }
          },
          "total": {
            "type": "integer",
            "description": "Total number of services regardless of paging."
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "URL of the next page, or null on the last page."
          }
        }
      },
      "Contact": {
        "type": "object",
        "required": [
          "email",
          "mailto",
          "preferredChannel",
          "location",
          "organisationNumber",
          "languages",
          "whatToInclude",
          "page"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "mailto": {
            "type": "string",
            "format": "uri"
          },
          "preferredChannel": {
            "type": "string",
            "const": "email"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "No phone number is published."
          },
          "location": {
            "type": "string"
          },
          "organisationNumber": {
            "type": "string"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "whatToInclude": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "page": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    }
  }
}