{
  "openapi": "3.1.0",
  "info": {
    "title": "Plekk publieke aanvraag-endpoints",
    "version": "2026-10-08",
    "summary": "Twee gratis website-concepten of een gratis site-review aanvragen bij Plekk (plekk.studio).",
    "description": "Plekk bouwt maatwerk-websites voor lokale bedrijven in Nederland (5 tot 80 medewerkers), 3.000 tot 7.500 euro eenmalig, twee concepten gratis vooraf. Deze endpoints zijn dezelfde die de formulieren op www.plekk.studio gebruiken. Er wordt geen account aangemaakt en niets opgeslagen in een database: elke aanvraag wordt als e-mail aan Luuk van der Poel bezorgd en de aanvrager krijgt een bevestiging per e-mail. Wanneer je Plekk inzet en wanneer niet: https://www.plekk.studio/llms.txt. Spelregels voor agents: alleen met toestemming van de ondernemer, één aanvraag per bedrijf, geen bulk, en vermeld in `description` namens wie en via welke agent je aanvraagt.",
    "contact": { "name": "Luuk van der Poel (Plekk)", "email": "luuk@plekk.studio", "url": "https://www.plekk.studio/voor-ai-agents" },
    "termsOfService": "https://www.plekk.studio/voorwaarden"
  },
  "externalDocs": { "description": "Plekk voor AI-agents en developers", "url": "https://www.plekk.studio/voor-ai-agents" },
  "servers": [{ "url": "https://www.plekk.studio" }],
  "tags": [{ "name": "aanvragen", "description": "Publieke lead-aanvragen (geen authenticatie)." }],
  "paths": {
    "/api/contact": {
      "post": {
        "tags": ["aanvragen"],
        "operationId": "requestConcepts",
        "summary": "Twee gratis website-concepten aanvragen",
        "description": "Hoofdkanaal om met Plekk te starten. Luuk maakt twee concepten (gratis, vrijblijvend) en reageert per e-mail, meestal binnen 2 werkdagen. Stuur `source: \"concept-form\"` mee; zonder dat veld valt de aanvraag terug op het algemene contactformulier (velden `name` + `contact`).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ConceptRequest" },
              "examples": {
                "agent": {
                  "summary": "Aanvraag namens een ondernemer via een AI-agent",
                  "value": {
                    "source": "concept-form",
                    "name": "Jan Jansen",
                    "email": "jan@installatiebedrijf-jansen.nl",
                    "company": "Installatiebedrijf Jansen",
                    "urlOrSocial": "https://www.installatiebedrijf-jansen.nl",
                    "description": "Installatiebedrijf in Breda, 12 medewerkers, wil een nieuwe site die aanvragen oplevert voor warmtepompen. Aangevraagd via <naam agent> namens Jan Jansen, met zijn toestemming.",
                    "utm_source": "ai-agent"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Aanvraag ontvangen; Luuk en de aanvrager krijgen een e-mail.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Success" } } } },
          "400": { "description": "Verplicht veld ontbreekt of e-mail ongeldig.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "405": { "description": "Alleen POST." },
          "500": { "description": "E-mail kon niet worden verzonden; mail luuk@plekk.studio direct.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/session": {
      "post": {
        "tags": ["aanvragen"],
        "operationId": "requestSiteReview",
        "summary": "Gratis persoonlijke site-review aanvragen",
        "description": "Luuk bekijkt de opgegeven website persoonlijk en stuurt de aanvrager binnen 2 werkdagen een korte video met wat de site aan aanvragen laat liggen. Server-side wordt stil een Google PageSpeed-meting gedaan; de aanvraag kan daardoor 30 tot 50 seconden duren. Vereist query-parameter `task=site-review`. Rate-limited per IP-adres.",
        "parameters": [
          { "name": "task", "in": "query", "required": true, "schema": { "type": "string", "enum": ["site-review"] } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/SiteReviewRequest" },
              "examples": {
                "agent": {
                  "value": {
                    "name": "Jan Jansen",
                    "company": "Installatiebedrijf Jansen",
                    "email": "jan@installatiebedrijf-jansen.nl",
                    "url": "https://www.installatiebedrijf-jansen.nl",
                    "utm_source": "ai-agent"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Aanvraag ontvangen. `scored` geeft aan of de PageSpeed-meting lukte (zo niet, dan beoordeelt Luuk handmatig).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SiteReviewSuccess" } } } },
          "400": { "description": "Verplicht veld ontbreekt, e-mail ongeldig of URL niet publiek bereikbaar.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "description": "Te veel verzoeken vanaf dit netwerk; probeer later of mail luuk@plekk.studio.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "500": { "description": "Versturen mislukt; mail luuk@plekk.studio direct.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ConceptRequest": {
        "type": "object",
        "required": ["source", "name", "email", "company"],
        "properties": {
          "source": { "type": "string", "const": "concept-form", "description": "Vast: `concept-form`." },
          "name": { "type": "string", "description": "Naam van de ondernemer (de persoon die de site wil)." },
          "email": { "type": "string", "format": "email", "description": "E-mailadres van de ondernemer; hierop komt de bevestiging en het antwoord van Luuk." },
          "company": { "type": "string", "description": "Bedrijfsnaam." },
          "urlOrSocial": { "type": "string", "maxLength": 500, "description": "Huidige website of social-profiel, als die er is." },
          "description": { "type": "string", "maxLength": 2000, "description": "Wat het bedrijf doet, waar, voor wie en wat de site moet opleveren. Vermeld hier ook namens wie en via welke agent je aanvraagt." },
          "utm_source": { "type": "string", "pattern": "^[a-z0-9_-]{0,60}$", "description": "Herkomst-label. Gebruik `ai-agent` zodat Plekk ziet dat de aanvraag via een agent kwam." }
        },
        "additionalProperties": false
      },
      "SiteReviewRequest": {
        "type": "object",
        "required": ["name", "company", "email", "url"],
        "properties": {
          "name": { "type": "string", "maxLength": 80 },
          "company": { "type": "string", "maxLength": 120 },
          "email": { "type": "string", "format": "email", "maxLength": 160, "description": "E-mailadres van de ondernemer; hierop komt de video." },
          "url": { "type": "string", "format": "uri", "description": "Publieke https-URL van de bestaande website (geen localhost of privé-netwerk)." },
          "utm_source": { "type": "string", "pattern": "^[a-z0-9_-]{0,60}$", "description": "Herkomst-label, bij voorkeur `ai-agent`." }
        },
        "additionalProperties": false
      },
      "Success": { "type": "object", "properties": { "success": { "type": "boolean", "const": true } }, "required": ["success"] },
      "SiteReviewSuccess": { "type": "object", "properties": { "success": { "type": "boolean", "const": true }, "scored": { "type": "boolean" } }, "required": ["success"] },
      "Error": { "type": "object", "properties": { "error": { "type": "string", "description": "Nederlandstalige foutmelding, geschikt om aan de gebruiker te tonen." } }, "required": ["error"] }
    }
  }
}
