{
  "openapi": "3.1.0",
  "info": {
    "title": "Curbo API",
    "version": "1.0.0",
    "description": "De API van Curbo. Documentatie: https://docs.curbo.nl"
  },
  "servers": [
    {
      "url": "https://curbo.nl/api/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "sleutel": {
        "type": "http",
        "scheme": "bearer",
        "description": "Een API-sleutel uit Beheer → API."
      }
    }
  },
  "paths": {
    "/organisatie": {
      "get": {
        "operationId": "organisatie",
        "summary": "Organisatie",
        "description": "De organisatie van deze sleutel, met teams en vestigingen.\n\nScope: `organisatie:lezen`.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "0d9c8b7a-0000-4000-8000-000000000000",
                  "naam": "Bakkerij De Vier Seizoenen",
                  "teams": [
                    {
                      "id": "a1b2c3d4-0000-4000-8000-000000000001",
                      "naam": "Bakkerij"
                    }
                  ],
                  "vestigingen": [
                    {
                      "id": "a1b2c3d4-0000-4000-8000-000000000002",
                      "naam": "Centrum"
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    },
    "/medewerkers": {
      "get": {
        "operationId": "medewerkers",
        "summary": "Medewerkers",
        "description": "Alle medewerkers, op achternaam. Zonder BSN, IBAN, salaris of gezondheidsgegevens.\n\nScope: `medewerkers:lezen`.",
        "parameters": [
          {
            "name": "actief",
            "in": "query",
            "required": false,
            "description": "Alleen in dienst (true) of ook uit dienst (false). Standaard true.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "limiet",
            "in": "query",
            "required": false,
            "description": "Aantal per pagina, 1 tot 200 (standaard 100).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "na",
            "in": "query",
            "required": false,
            "description": "De waarde van `volgende` uit het vorige antwoord, voor de volgende pagina.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                      "voornaam": "Sanne",
                      "achternaam": "de Boer",
                      "email": "sanne@bakkerij.nl",
                      "functie": "Bakker",
                      "team": {
                        "id": "a1b2c3d4-0000-4000-8000-000000000001",
                        "naam": "Bakkerij"
                      },
                      "vestiging": {
                        "id": "a1b2c3d4-0000-4000-8000-000000000002",
                        "naam": "Centrum"
                      },
                      "in_dienst_sinds": "2024-03-01",
                      "actief": true
                    }
                  ],
                  "volgende": null
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      },
      "post": {
        "operationId": "medewerker-maken",
        "summary": "Medewerker aanmaken",
        "description": "Maakt een medewerker aan zonder inlogaccount. Uitnodigen doe je in het portaal. Curbo Koppel.\n\nScope: `medewerkers:schrijven`.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "voornaam",
                  "achternaam",
                  "email"
                ],
                "properties": {
                  "voornaam": {
                    "type": "string",
                    "description": "Voornaam."
                  },
                  "achternaam": {
                    "type": "string",
                    "description": "Achternaam."
                  },
                  "email": {
                    "type": "string",
                    "description": "Werkmail; uniek binnen de organisatie."
                  },
                  "functie": {
                    "type": "string",
                    "description": "Functie."
                  },
                  "team_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Team."
                  },
                  "vestiging_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Vestiging."
                  },
                  "in_dienst_sinds": {
                    "type": "string",
                    "format": "date",
                    "description": "Datum in dienst."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                  "voornaam": "Sanne",
                  "achternaam": "de Boer",
                  "email": "sanne@bakkerij.nl",
                  "functie": "Bakker",
                  "team": {
                    "id": "a1b2c3d4-0000-4000-8000-000000000001",
                    "naam": "Bakkerij"
                  },
                  "vestiging": {
                    "id": "a1b2c3d4-0000-4000-8000-000000000002",
                    "naam": "Centrum"
                  },
                  "in_dienst_sinds": "2024-03-01",
                  "actief": true
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    },
    "/medewerkers/{id}": {
      "get": {
        "operationId": "medewerker",
        "summary": "Eén medewerker",
        "description": "Een medewerker op id.\n\nScope: `medewerkers:lezen`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                  "voornaam": "Sanne",
                  "achternaam": "de Boer",
                  "email": "sanne@bakkerij.nl",
                  "functie": "Bakker",
                  "team": {
                    "id": "a1b2c3d4-0000-4000-8000-000000000001",
                    "naam": "Bakkerij"
                  },
                  "vestiging": {
                    "id": "a1b2c3d4-0000-4000-8000-000000000002",
                    "naam": "Centrum"
                  },
                  "in_dienst_sinds": "2024-03-01",
                  "actief": true
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      },
      "patch": {
        "operationId": "medewerker-wijzigen",
        "summary": "Medewerker wijzigen",
        "description": "Wijzigt alleen de velden die je meestuurt. Curbo Koppel.\n\nScope: `medewerkers:schrijven`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "voornaam": {
                    "type": "string",
                    "description": "Voornaam."
                  },
                  "achternaam": {
                    "type": "string",
                    "description": "Achternaam."
                  },
                  "functie": {
                    "type": "string",
                    "description": "Functie."
                  },
                  "team_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Team (leeg = geen team)."
                  },
                  "vestiging_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Vestiging (leeg = geen vestiging)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                  "voornaam": "Sanne",
                  "achternaam": "de Boer",
                  "email": "sanne@bakkerij.nl",
                  "functie": "Bakker",
                  "team": {
                    "id": "a1b2c3d4-0000-4000-8000-000000000001",
                    "naam": "Bakkerij"
                  },
                  "vestiging": {
                    "id": "a1b2c3d4-0000-4000-8000-000000000002",
                    "naam": "Centrum"
                  },
                  "in_dienst_sinds": "2024-03-01",
                  "actief": true
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    },
    "/diensten": {
      "get": {
        "operationId": "diensten",
        "summary": "Diensten",
        "description": "Diensten in een periode, ook open diensten (medewerker_id is dan null). Geschrapte diensten niet.\n\nScope: `rooster:lezen`.",
        "parameters": [
          {
            "name": "van",
            "in": "query",
            "required": true,
            "description": "Eerste dag (JJJJ-MM-DD).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "tot",
            "in": "query",
            "required": true,
            "description": "Laatste dag; hooguit 93 dagen na van.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "medewerker_id",
            "in": "query",
            "required": false,
            "description": "Alleen van deze medewerker.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limiet",
            "in": "query",
            "required": false,
            "description": "Aantal per pagina, 1 tot 200 (standaard 100).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "na",
            "in": "query",
            "required": false,
            "description": "De waarde van `volgende` uit het vorige antwoord, voor de volgende pagina.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "5e6f7a8b-0000-4000-8000-000000000003",
                      "datum": "2026-11-16",
                      "begin": "06:00",
                      "einde": "14:00",
                      "pauze_minuten": 30,
                      "functie": "Bakker",
                      "medewerker_id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                      "team_id": "a1b2c3d4-0000-4000-8000-000000000001",
                      "vestiging_id": "a1b2c3d4-0000-4000-8000-000000000002",
                      "gepubliceerd": true
                    }
                  ],
                  "volgende": null
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      },
      "post": {
        "operationId": "dienst-maken",
        "summary": "Dienst aanmaken",
        "description": "Plant een dienst. Zonder medewerker_id wordt het een open dienst. Curbo Koppel.\n\nScope: `rooster:schrijven`.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "datum",
                  "begin",
                  "einde"
                ],
                "properties": {
                  "datum": {
                    "type": "string",
                    "format": "date",
                    "description": "Datum."
                  },
                  "begin": {
                    "type": "string",
                    "description": "Begintijd (UU:MM)."
                  },
                  "einde": {
                    "type": "string",
                    "description": "Eindtijd (UU:MM)."
                  },
                  "pauze_minuten": {
                    "type": "integer",
                    "description": "Pauze in minuten (standaard 0)."
                  },
                  "functie": {
                    "type": "string",
                    "description": "Functie op de dienst."
                  },
                  "medewerker_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Wie hem draait."
                  },
                  "team_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Team."
                  },
                  "vestiging_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Vestiging."
                  },
                  "publiceren": {
                    "type": "boolean",
                    "description": "Meteen zichtbaar voor de medewerker (standaard false)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "5e6f7a8b-0000-4000-8000-000000000003",
                  "datum": "2026-11-16",
                  "begin": "06:00",
                  "einde": "14:00",
                  "pauze_minuten": 30,
                  "functie": "Bakker",
                  "medewerker_id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                  "team_id": "a1b2c3d4-0000-4000-8000-000000000001",
                  "vestiging_id": "a1b2c3d4-0000-4000-8000-000000000002",
                  "gepubliceerd": true
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    },
    "/diensten/{id}": {
      "patch": {
        "operationId": "dienst-wijzigen",
        "summary": "Dienst wijzigen",
        "description": "Wijzigt alleen de velden die je meestuurt. Curbo Koppel.\n\nScope: `rooster:schrijven`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "datum": {
                    "type": "string",
                    "format": "date",
                    "description": "Datum."
                  },
                  "begin": {
                    "type": "string",
                    "description": "Begintijd."
                  },
                  "einde": {
                    "type": "string",
                    "description": "Eindtijd."
                  },
                  "pauze_minuten": {
                    "type": "integer",
                    "description": "Pauze."
                  },
                  "functie": {
                    "type": "string",
                    "description": "Functie."
                  },
                  "medewerker_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Wie hem draait (null = open dienst)."
                  },
                  "publiceren": {
                    "type": "boolean",
                    "description": "Zichtbaar maken."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "5e6f7a8b-0000-4000-8000-000000000003",
                  "datum": "2026-11-16",
                  "begin": "06:00",
                  "einde": "14:00",
                  "pauze_minuten": 30,
                  "functie": "Bakker",
                  "medewerker_id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                  "team_id": "a1b2c3d4-0000-4000-8000-000000000001",
                  "vestiging_id": "a1b2c3d4-0000-4000-8000-000000000002",
                  "gepubliceerd": true
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      },
      "delete": {
        "operationId": "dienst-schrappen",
        "summary": "Dienst schrappen",
        "description": "Schrapt de dienst; de medewerker ziet hem niet meer. Curbo Koppel.\n\nScope: `rooster:schrijven`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "id": "5e6f7a8b-0000-4000-8000-000000000003",
                  "geschrapt": true
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    },
    "/uren": {
      "get": {
        "operationId": "uren",
        "summary": "Uren",
        "description": "Gewerkte uren in een periode, met status ingediend of akkoord.\n\nScope: `uren:lezen`.",
        "parameters": [
          {
            "name": "van",
            "in": "query",
            "required": true,
            "description": "Eerste dag (JJJJ-MM-DD).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "tot",
            "in": "query",
            "required": true,
            "description": "Laatste dag; hooguit 93 dagen na van.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "medewerker_id",
            "in": "query",
            "required": false,
            "description": "Alleen van deze medewerker.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limiet",
            "in": "query",
            "required": false,
            "description": "Aantal per pagina, 1 tot 200 (standaard 100).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "na",
            "in": "query",
            "required": false,
            "description": "De waarde van `volgende` uit het vorige antwoord, voor de volgende pagina.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "9a8b7c6d-0000-4000-8000-000000000004",
                      "medewerker_id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                      "datum": "2026-11-16",
                      "begin": "06:02",
                      "einde": "14:05",
                      "pauze_minuten": 30,
                      "status": "akkoord",
                      "dienst_id": "5e6f7a8b-0000-4000-8000-000000000003"
                    }
                  ],
                  "volgende": null
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    },
    "/verlof": {
      "get": {
        "operationId": "verlof",
        "summary": "Verlof",
        "description": "Goedgekeurd verlof dat in de periode valt. Ziekte en de reden van afwezigheid gaan niet via de API.\n\nScope: `verlof:lezen`.",
        "parameters": [
          {
            "name": "van",
            "in": "query",
            "required": true,
            "description": "Eerste dag (JJJJ-MM-DD).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "tot",
            "in": "query",
            "required": true,
            "description": "Laatste dag; hooguit 93 dagen na van.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limiet",
            "in": "query",
            "required": false,
            "description": "Aantal per pagina, 1 tot 200 (standaard 100).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "na",
            "in": "query",
            "required": false,
            "description": "De waarde van `volgende` uit het vorige antwoord, voor de volgende pagina.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Gelukt",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "1f2e3d4c-0000-4000-8000-000000000005",
                      "medewerker_id": "7c0f6d3e-1b2a-4c5d-9e8f-001122334455",
                      "soort": "wettelijk",
                      "van": "2026-12-24",
                      "tot": "2026-12-31",
                      "dagen": 5
                    }
                  ],
                  "volgende": null
                }
              }
            }
          }
        },
        "security": [
          {
            "sleutel": []
          }
        ]
      }
    }
  }
}