{
  "openapi": "3.1.0",
  "info": {
    "title": "Generation C public API",
    "version": "1.0.0",
    "summary": "Read-only informatie over Generation C, het Data & AI-bureau voor het MKB in Rotterdam.",
    "description": "Openbare, read-only JSON-API met dezelfde gegevens als de website van Generation C: bedrijfs- en contactgegevens, diensten, case studies, artikelen en vacatures. Geen API-sleutel of account nodig. Content is Nederlandstalig. Elke resource bevat een `url` (HTML) en een `markdownUrl` (Markdown) voor de volledige tekst. Rate limit: 60 requests per 60 seconden per IP-adres, gecommuniceerd via de RateLimit- en RateLimit-Policy-headers (draft-ietf-httpapi-ratelimit-headers) en Retry-After bij een 429. Fouten volgen RFC 9457 (application/problem+json). Generation C is een dienstverlener: deze API voert geen werk uit, maar helpt agents te bepalen of en hoe ze Generation C inschakelen.",
    "contact": {
      "name": "Generation C",
      "email": "info@generation-c.nl",
      "url": "https://www.generation-c.nl/contact"
    },
    "termsOfService": "https://www.generation-c.nl/algemene-voorwaarden"
  },
  "externalDocs": {
    "description": "Documentatie voor developers en AI-agents",
    "url": "https://www.generation-c.nl/developers"
  },
  "servers": [
    {
      "url": "https://www.generation-c.nl",
      "description": "Productie"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "company",
      "description": "Bedrijfs- en contactgegevens"
    },
    {
      "name": "content",
      "description": "Diensten, case studies, artikelen en vacatures"
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "Overzicht van de API",
        "description": "Geeft de beschikbare endpoints en links naar de OpenAPI-specificatie en documentatie.",
        "tags": [
          "company"
        ],
        "responses": {
          "200": {
            "description": "Index van de API.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/company": {
      "get": {
        "operationId": "getCompany",
        "summary": "Bedrijfs- en contactgegevens",
        "description": "Naam, omschrijving, adres, e-mail, telefoon, KvK- en btw-nummer, verzorgingsgebied en de link om een kennismaking te plannen. Gebruik dit om een gebruiker te vertellen hoe die contact opneemt.",
        "tags": [
          "company"
        ],
        "responses": {
          "200": {
            "description": "Bedrijfsgegevens.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Company"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/services": {
      "get": {
        "operationId": "listServices",
        "summary": "Diensten van Generation C",
        "description": "De vier dienstlijnen (Strategie, Ontwikkeling, AI Audit, Workshops) met omschrijving. Gebruik dit om te bepalen welke dienst past bij de vraag van een gebruiker.",
        "tags": [
          "content"
        ],
        "responses": {
          "200": {
            "description": "Lijst met diensten.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Service"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/case-studies": {
      "get": {
        "operationId": "listCaseStudies",
        "summary": "Case studies met resultaten",
        "description": "Gepubliceerde klantcases met klant, categorie, samenvatting en meetbare resultaten, nieuwste eerst.",
        "tags": [
          "content"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximaal aantal resultaten (1 tot en met 100). Standaard 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lijst met case studies.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaseStudy"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/articles": {
      "get": {
        "operationId": "listArticles",
        "summary": "Artikelen uit de kennisbank",
        "description": "Gepubliceerde artikelen over data en AI voor het MKB, nieuwste eerst. Het veld `answer` bevat een kort, citeerbaar antwoord; de volledige tekst staat op `markdownUrl`.",
        "tags": [
          "content"
        ],
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Alleen artikelen in deze categorie.",
            "schema": {
              "type": "string",
              "enum": [
                "AI",
                "Technologie",
                "Strategie",
                "Design",
                "Development",
                "Nieuws"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximaal aantal resultaten (1 tot en met 100). Standaard 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lijst met artikelen.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Article"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/v1/vacancies": {
      "get": {
        "operationId": "listVacancies",
        "summary": "Vacatures",
        "description": "Gepubliceerde vacatures met locatie, dienstverband en beschikbaarheid. Solliciteren gaat via de vacaturepagina (`url`).",
        "tags": [
          "content"
        ],
        "parameters": [
          {
            "name": "availability",
            "in": "query",
            "required": false,
            "description": "Filter op beschikbaarheid. Zonder filter komen alle gepubliceerde vacatures terug.",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lijst met vacatures.",
            "headers": {
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Vacancy"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Links": {
        "type": "object",
        "required": [
          "url",
          "markdownUrl"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Pagina op de website (HTML)."
          },
          "markdownUrl": {
            "type": "string",
            "format": "uri",
            "description": "Dezelfde pagina als Markdown."
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "required": [
          "name",
          "version",
          "endpoints"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "operationId",
                "method",
                "url"
              ],
              "properties": {
                "operationId": {
                  "type": "string"
                },
                "method": {
                  "type": "string",
                  "enum": [
                    "GET"
                  ]
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Company": {
        "type": "object",
        "required": [
          "name",
          "legalName",
          "description",
          "url",
          "email",
          "address",
          "contactUrl"
        ],
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "Generation C"
            ]
          },
          "legalName": {
            "type": "string",
            "examples": [
              "Generation C B.V."
            ]
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": "object",
            "required": [
              "street",
              "postalCode",
              "city",
              "country"
            ],
            "properties": {
              "street": {
                "type": "string"
              },
              "postalCode": {
                "type": "string"
              },
              "city": {
                "type": "string"
              },
              "country": {
                "type": "string",
                "description": "ISO 3166-1 alpha-2"
              }
            }
          },
          "chamberOfCommerceNumber": {
            "type": "string",
            "description": "KvK-nummer"
          },
          "vatNumber": {
            "type": "string",
            "description": "Btw-identificatienummer"
          },
          "areaServed": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "contactUrl": {
            "type": "string",
            "format": "uri"
          },
          "bookingUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Online een kennismaking plannen."
          },
          "sameAs": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "Service": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Links"
          },
          {
            "type": "object",
            "required": [
              "title",
              "slug"
            ],
            "properties": {
              "title": {
                "type": "string",
                "examples": [
                  "AI Audit"
                ]
              },
              "slug": {
                "type": "string"
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "summary": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Eerste zin van de omschrijving."
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "includes": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Onderdelen van de dienst."
              }
            }
          }
        ]
      },
      "CaseStudy": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Links"
          },
          {
            "type": "object",
            "required": [
              "title",
              "slug",
              "results"
            ],
            "properties": {
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "client": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "year": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ongoing": {
                "type": "boolean"
              },
              "summary": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "results": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "value",
                    "label"
                  ],
                  "properties": {
                    "value": {
                      "type": "string",
                      "examples": [
                        "+60%"
                      ]
                    },
                    "label": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "Article": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Links"
          },
          {
            "type": "object",
            "required": [
              "title",
              "slug"
            ],
            "properties": {
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "category": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "AI",
                  "Technologie",
                  "Strategie",
                  "Design",
                  "Development",
                  "Nieuws",
                  null
                ]
              },
              "publishedDate": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "summary": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "answer": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Kort, citeerbaar kernantwoord."
              }
            }
          }
        ]
      },
      "Vacancy": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Links"
          },
          {
            "type": "object",
            "required": [
              "title",
              "slug"
            ],
            "properties": {
              "title": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "location": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "employmentType": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "fulltime",
                  "parttime",
                  "stage",
                  "in-overleg",
                  null
                ]
              },
              "salary": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "availability": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "open",
                  "closed",
                  null
                ]
              }
            }
          }
        ]
      },
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details.",
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          }
        }
      }
    },
    "headers": {
      "RateLimit": {
        "description": "Resterend quotum, bv. `\"default\";r=59;t=42` (r = resterende requests, t = seconden tot reset).",
        "schema": {
          "type": "string"
        }
      },
      "RateLimit-Policy": {
        "description": "Quotumbeleid, bv. `\"default\";q=60;w=60`.",
        "schema": {
          "type": "string"
        }
      },
      "Retry-After": {
        "description": "Seconden wachten voor een nieuwe poging.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Ongeldige queryparameter.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit overschreden.",
        "headers": {
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "ServerError": {
        "description": "De gegevens konden niet worden opgehaald.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    }
  }
}