{"openapi":"3.1.0","info":{"title":"PEBIProxy API","description":"\nPEBIProxy API giver adgang til organisationsdata fra SOFD (Systematic Organization and Function Database)\nfor Favrskov Kommune.\n\n## Funktionalitet\n\nAPI'et tilbyder:\n\n* **Ledelseshierarki**: Generer komplet organisatorisk hierarki med CEO som root\n* **Medarbejderlister**: Adgang til filtrerede medarbejderdata (PEBL)\n* **Manager lister**: Liste over medarbejdere med lederniveau\n* **SOFD Tools**: Brugernavn lookup og status validering\n\n## Authentication\n\nAlle endpoints kræver API key authentication. Kontakt systemadministrator for at få tildelt en API key.\n\nFor dokumentation om authentication, se `/docs` endpoint.\n\n## Kontakt\n\nFor spørgsmål eller support, kontakt IT-afdelingen.\n","contact":{"name":"Favrskov Kommune IT","url":"https://favrskov.dk/"},"license":{"name":"Internal Use Only"},"version":"0.12.1"},"paths":{"/v1/globeteam/managerlist":{"get":{"tags":["v1"],"summary":"Globeteam Managerlist","description":"Returnerer en liste over medarbejdere med lederniveau ≥ 1.\n\nDenne endpoint henter alle medarbejdere fra SOFD der har et lederniveau på 1 eller højere,\nog returnerer deres email adresse og organisatoriske sti.\n\n**Authentication:** Kræver gyldig API key.\n\n**Response Fields:**\n- `message`: Beskrivende besked\n- `data`: Array af manager objekter med:\n  - `person_mail`: Medarbejderens email adresse\n  - `orgunit_name_path`: Fuld organisatorisk sti\n- `user_info`: Information om API brugeren\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/globeteam/managerlist\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"globeteam_managerlist_v1_globeteam_managerlist_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/pebl/full_list":{"get":{"tags":["v1"],"summary":"Pebl Full List","description":"Returnerer en komplet liste over alle medarbejdere i det format PEBL kræver.\nKræver adgang til medarbejderdata.\n\nEksempel:\n```bash\ncurl -X GET \"http://localhost:8000/v1/pebl/full_list\"          -H \"Authorization: <your-api-key>\"\n```\n\n:return: Dictionary med alle medarbejdere og deres data","operationId":"pebl_full_list_v1_pebl_full_list_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/pebl/favrskov":{"get":{"tags":["v1"],"summary":"Pebl Favrskov List","description":"Returnerer medarbejderliste eksklusiv Favrskov Forsyning.\nKræver adgang til medarbejderdata.\n\nEksempel:\n```bash\ncurl -X GET \"http://localhost:8000/v1/pebl/favrskov\"          -H \"Authorization: <your-api-key>\"\n```\n\n:return: Dictionary med Favrskov medarbejdere (ekskl. Forsyning)","operationId":"pebl_favrskov_list_v1_pebl_favrskov_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/pebl/forsyning":{"get":{"tags":["v1"],"summary":"Pebl Forsyning List","description":"Returnerer medarbejderliste kun for Favrskov Forsyning.\nKræver adgang til medarbejderdata.\n\nEksempel:\n```bash\ncurl -X GET \"http://localhost:8000/v1/pebl/forsyning\"          -H \"Authorization: <your-api-key>\"\n```\n\n:return: Dictionary med Favrskov Forsyning medarbejdere","operationId":"pebl_forsyning_list_v1_pebl_forsyning_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/pebl/download":{"get":{"tags":["v1"],"summary":"Download Pebl Data","description":"Returnerer Excel fil med PEBL data baseret på valgt datasæt.\nKræver adgang til medarbejderdata.\n\nEksempel:\n```bash\n# Download alle medarbejdere:\ncurl -X GET \"http://localhost:8000/v1/pebl/download?dataset=full_list\"          -H \"Authorization: <your-api-key>\"          -o full_list.xlsx\n\n# Download kun Favrskov (ekskl. Forsyning):\ncurl -X GET \"http://localhost:8000/v1/pebl/download?dataset=favrskov\"          -H \"Authorization: <your-api-key>\"          -o favrskov.xlsx\n\n# Download kun Favrskov Forsyning:\ncurl -X GET \"http://localhost:8000/v1/pebl/download?dataset=forsyning\"          -H \"Authorization: <your-api-key>\"          -o forsyning.xlsx\n```\n\n:param dataset: Type af datasæt (\"full_list\", \"favrskov\", \"forsyning\")\n:param user_info: Brugerinfo fra autentificering\n:return: Excel fil som StreamingResponse","operationId":"download_pebl_data_v1_pebl_download_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"dataset","in":"query","required":true,"schema":{"type":"string","description":"Dataset type: full_list, favrskov, or forsyning","title":"Dataset"},"description":"Dataset type: full_list, favrskov, or forsyning"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request - Invalid dataset parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ledelseshierarki/config/schema":{"get":{"tags":["v1"],"summary":"Get Config Schema","description":"Returnerer JSON Schema for ledelseshierarki konfiguration.\n\nDette endpoint giver mulighed for at opdage kravene til config strukturen programmatisk.\n\n**Authentication:** Kræver gyldig API key.\n\n**Response:** JSON Schema for LeadershipHierarchyConfig\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/ledelseshierarki/config/schema\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"get_config_schema_v1_ledelseshierarki_config_schema_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Config Schema V1 Ledelseshierarki Config Schema Get"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/ledelseshierarki/config/default":{"get":{"tags":["v1"],"summary":"Get Default Config","description":"Returnerer default konfiguration for ledelseshierarki.\n\nDette endpoint giver adgang til at se den aktuelle default config,\nsom kan bruges som skabelon for custom konfigurationer.\n\n**Authentication:** Kræver gyldig API key.\n\n**Response:** Default konfiguration som JSON\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/ledelseshierarki/config/default\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"get_default_config_v1_ledelseshierarki_config_default_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Default Config V1 Ledelseshierarki Config Default Get"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/ledelseshierarki/generate":{"post":{"tags":["v1"],"summary":"Generate Ledelseshierarki","description":"Genererer et komplet ledelseshierarki baseret på SOFD data.\n\nGenererer organisatorisk hierarki med CEO som root node. Request body kan\nindeholde optional config - hvis ingen config angives, bruges default konfiguration.\n\n**Authentication:** Kræver gyldig API key.\n\n**Request Body:**\n- `config` (optional): Custom konfiguration (se `/config/schema` for struktur)\n\n**Response:** Hierarki træ med CEO som root node og nested children\n\n**Response Fields:**\n- `orgunit_uuid`: UUID for organisationsenheden\n- `department`: Navn på organisationsenheden\n- `person_uuid`: UUID for lederen\n- `name`: Lederens fulde navn\n- `jobtitle`: Jobtitel\n- `manager_initialer`: Lederens initialer\n- `phone`: Telefonnummer (maskeret baseret på config)\n- `depth_counter`: Dybde i hierarkiet (1 = CEO, 2 = direkte rapportering, osv.)\n- `children`: Array af underordnede ledere (rekursiv struktur)\n\n**Eksempler:**\n```bash\n# Med default config:\ncurl -X POST \"http://localhost:8000/v1/ledelseshierarki/generate\"          -H \"Authorization: <your-api-key>\"          -H \"Content-Type: application/json\"          -d '{}'\n\n# Med custom config:\ncurl -X POST \"http://localhost:8000/v1/ledelseshierarki/generate\"          -H \"Authorization: <your-api-key>\"          -H \"Content-Type: application/json\"          -d '{\"config\": {\"top_orgunit\": \"...\", \"exclude_orgunits\": [...]}}'\n```","operationId":"generate_ledelseshierarki_v1_ledelseshierarki_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HierarchyRequest","default":{}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Generate Ledelseshierarki V1 Ledelseshierarki Generate Post"}}}},"400":{"description":"Bad Request - Invalid configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/admin/generate-keys":{"post":{"tags":["v1","admin"],"summary":"Generate Keys","description":"Genererer 5 nye API keys til brug i systemet.\n\nDette endpoint genererer nye API keys som kan tildeles til brugere.\nKun tilgængeligt for administrators med administrative rettigheder.\n\n**Authentication:** Kræver gyldig API key med administrative rettigheder.\n\n**Response Fields:**\n- `message`: Bekræftelsesbesked\n- `keys`: Array af 5 genererede API keys\n- `count`: Antal keys genereret\n\n**Note:** Efter generering skal keys tildeles brugere af systemadministrator.\n\n**Eksempel:**\n```bash\ncurl -X POST \"http://localhost:8000/v1/admin/generate-keys\"          -H \"Authorization: <your-api-key>\"          -H \"Content-Type: application/json\"\n```","operationId":"generate_keys_v1_admin_generate_keys_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateKeysResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Administrative privileges required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/admin/reload-permissions":{"post":{"tags":["v1","admin"],"summary":"Reload Permissions","description":"Force reload af permissions configuration.\n\nDette endpoint tvinger systemet til at reload permissions config og bypass cache.\nNyttigt når permissions er blevet opdateret og skal anvendes med det samme.\n\n**Authentication:** Kræver gyldig API key med administrative rettigheder.\n\n**Response Fields:**\n- `message`: Status besked\n- `version`: Config version\n- `last_updated`: Sidste opdaterings tidspunkt\n- `groups_count`: Antal grupper i config\n- `endpoints_count`: Antal endpoints i config\n\n**Eksempel:**\n```bash\ncurl -X POST \"http://localhost:8000/v1/admin/reload-permissions\"          -H \"Authorization: <your-api-key>\"          -H \"Content-Type: application/json\"\n```","operationId":"reload_permissions_v1_admin_reload_permissions_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Reload Permissions V1 Admin Reload Permissions Post"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Administrative privileges required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/sofdtools/usernames":{"get":{"tags":["v1","sofdtools"],"summary":"Get All Usernames","description":"Returnerer en liste med alle kendte brugernavne fra SOFD.\n\nDenne endpoint henter alle aktive brugernavne registreret i SOFD systemet.\n\n**Authentication:** Kræver gyldig API key.\n\n**Response Fields:**\n- `message`: Beskrivende besked\n- `data`: Array af brugernavn objekter med:\n  - `person_initialer`: Brugerens initialer/brugernavn\n  - `person_navn`: Brugerens fulde navn\n  - `person_mail`: Brugerens email adresse\n- `user_info`: Information om API brugeren\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/sofdtools/usernames\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"get_all_usernames_v1_sofdtools_usernames_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/sofdtools/usernames/{initialer}":{"get":{"tags":["v1","sofdtools"],"summary":"Get Specific Username","description":"Returnerer information om et specifikt brugernavn fra SOFD.\n\nDenne endpoint henter detaljer om en specifik bruger baseret på initialer/brugernavn.\n\n**Authentication:** Kræver gyldig API key.\n\n**Path Parameters:**\n- `initialer`: Brugerens initialer/brugernavn (case-sensitive)\n\n**Response Fields:**\n- `message`: Beskrivende besked\n- `data`: Array af brugernavn objekter (tom array hvis ikke fundet)\n- `user_info`: Information om API brugeren\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/sofdtools/usernames/abc123\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"get_specific_username_v1_sofdtools_usernames__initialer__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"initialer","in":"path","required":true,"schema":{"type":"string","title":"Initialer"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sofdtools/users/{initialer}/status":{"get":{"tags":["v1","sofdtools"],"summary":"Get User Status","description":"Tjekker om en bruger er aktiv og returnerer UUID hvis aktiv.\n\nDenne endpoint verificerer om en bruger er aktiv i SOFD systemet og returnerer\nbrugerens UUID hvis aktiv.\n\n**Authentication:** Kræver gyldig API key.\n\n**Path Parameters:**\n- `initialer`: Brugerens initialer/brugernavn\n\n**Response Fields:**\n- `status`: Brugerens status (`active` eller `inactive`)\n- `uuid`: Brugerens UUID fra SOFD (kun hvis aktiv, ellers `null`)\n- `message`: Beskrivende besked\n- `user_info`: Information om API brugeren\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/sofdtools/users/abc123/status\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"get_user_status_v1_sofdtools_users__initialer__status_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"initialer","in":"path","required":true,"schema":{"type":"string","title":"Initialer"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get User Status V1 Sofdtools Users  Initialer  Status Get"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sofdtools/users/{initialer}/uuid":{"get":{"tags":["v1","sofdtools"],"summary":"Get Inactive User Uuid","description":"Henter UUID for en inaktiv bruger.\n\nDenne endpoint henter UUID for en inaktiv bruger fra SOFD systemet.\n\n**Note:** Nogle inaktive brugere har ikke en UUID i systemet.\n\n**Authentication:** Kræver gyldig API key.\n\n**Path Parameters:**\n- `initialer`: Brugerens initialer/brugernavn\n\n**Response Fields:**\n- `uuid`: Brugerens UUID fra SOFD (kun hvis fundet)\n- `message`: Beskrivende besked\n- `user_info`: Information om API brugeren\n\n**Status Codes:**\n- `200 OK`: UUID fundet for inaktiv bruger\n- `404 Not Found`: UUID ikke fundet for bruger\n\n**Eksempel:**\n```bash\ncurl -X GET \"http://localhost:8000/v1/sofdtools/users/abc123/uuid\"          -H \"Authorization: <your-api-key>\"\n```","operationId":"get_inactive_user_uuid_v1_sofdtools_users__initialer__uuid_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"initialer","in":"path","required":true,"schema":{"type":"string","title":"Initialer"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Inactive User Uuid V1 Sofdtools Users  Initialer  Uuid Get"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - UUID not found for user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tjoh/virk-pnumre":{"get":{"tags":["v1","tjoh"],"summary":"Get Virk Pnumre","description":"Hent CVR data for organisationens P-numre som JSON.\n\nData hentes direkte fra Virk API via cvrapi pakken.\nKolonnenavne mappes til legacy format for backward compatibility.\n\nEksempel:\n```bash\n# Hent alle data sorteret efter enheds_navn:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre\" \\\n     -H \"Authorization: <your-api-key>\"\n\n# Sortér efter branchekode:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre?sort_by=branchekode&sort_order=desc\" \\\n     -H \"Authorization: <your-api-key>\"\n\n# Filtrer på branchekode:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre?branchekode=6201,6202\" \\\n     -H \"Authorization: <your-api-key>\"\n```\n\n:return: Dictionary med CVR data","operationId":"get_virk_pnumre_v1_tjoh_virk_pnumre_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonne at sortere efter (default: enheds_navn). Skal være en gyldig kolonne i datasættet.","title":"Sort By"},"description":"Kolonne at sortere efter (default: enheds_navn). Skal være en gyldig kolonne i datasættet."},{"name":"sort_order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","description":"Sorteringsretning: 'asc' (stigende) eller 'desc' (faldende)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning: 'asc' (stigende) eller 'desc' (faldende)"},{"name":"branchekode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer på branchekode. Komma-separeret for flere værdier (fx '6201,6202')","title":"Branchekode"},"description":"Filtrer på branchekode. Komma-separeret for flere værdier (fx '6201,6202')"},{"name":"pnummer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer på P-nummer. Komma-separeret for flere værdier","title":"Pnummer"},"description":"Filtrer på P-nummer. Komma-separeret for flere værdier"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardAPIResponse"}}}},"400":{"description":"Bad Request - Invalid sort column","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tjoh/virk-pnumre/download":{"get":{"tags":["v1","tjoh"],"summary":"Download Virk Pnumre","description":"Download CVR data for organisationens P-numre som Excel eller CSV fil.\n\nData hentes direkte fra Virk API via cvrapi pakken.\nKolonnenavne mappes til legacy format for backward compatibility.\n\nEksempel:\n```bash\n# Download som Excel:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre/download?format=excel\" \\\n     -H \"Authorization: <your-api-key>\" \\\n     -o virk_pnumre.xlsx\n\n# Download som CSV:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre/download?format=csv\" \\\n     -H \"Authorization: <your-api-key>\" \\\n     -o virk_pnumre.csv\n\n# Download med sortering og filtrering:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre/download?format=excel&sort_by=branchekode&branchekode=6201\" \\\n     -H \"Authorization: <your-api-key>\" \\\n     -o virk_pnumre_filtered.xlsx\n\n# Download med specifikke kolonner i bestemt rækkefølge:\ncurl -X GET \"http://localhost:8000/v1/tjoh/virk-pnumre/download?format=excel&columns=enheds_navn,pnummer,adr_kommune\" \\\n     -H \"Authorization: <your-api-key>\" \\\n     -o virk_pnumre_kolonner.xlsx\n```\n\n:return: Excel eller CSV fil som StreamingResponse","operationId":"download_virk_pnumre_v1_tjoh_virk_pnumre_download_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"enum":["excel","csv"],"type":"string","description":"Output format: 'excel' for .xlsx eller 'csv' for .csv","default":"excel","title":"Format"},"description":"Output format: 'excel' for .xlsx eller 'csv' for .csv"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonne at sortere efter (default: enheds_navn)","title":"Sort By"},"description":"Kolonne at sortere efter (default: enheds_navn)"},{"name":"sort_order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","description":"Sorteringsretning: 'asc' (stigende) eller 'desc' (faldende)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning: 'asc' (stigende) eller 'desc' (faldende)"},{"name":"branchekode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer på branchekode. Komma-separeret for flere værdier","title":"Branchekode"},"description":"Filtrer på branchekode. Komma-separeret for flere værdier"},{"name":"pnummer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer på P-nummer. Komma-separeret for flere værdier","title":"Pnummer"},"description":"Filtrer på P-nummer. Komma-separeret for flere værdier"},{"name":"columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Komma-separeret liste af kolonner at inkludere i output. Kolonner returneres i angivet rækkefølge. Eksempel: 'pnummer,enheds_navn,adr_kommune'. Hvis ikke angivet, inkluderes alle kolonner.","title":"Columns"},"description":"Komma-separeret liste af kolonner at inkludere i output. Kolonner returneres i angivet rækkefølge. Eksempel: 'pnummer,enheds_navn,adr_kommune'. Hvis ikke angivet, inkluderes alle kolonner."}],"responses":{"200":{"description":"CVR data som Excel eller CSV fil","content":{"application/json":{"schema":{}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{},"text/csv":{}}},"400":{"description":"Bad Request - Invalid sort column","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/data/persons":{"get":{"tags":["v2","v2-data"],"summary":"Dynamisk persons data","description":"Henter persons data med fleksibel kolonnevalg, filtrering, pagination og sortering.\n\n**Column Selection:**\n- `include`: Comma-separated liste af kolonner der skal inkluderes (f.eks. \"person_uuid,person_initialer,orgunit_name\")\n- `exclude`: Comma-separated liste af kolonner der skal ekskluderes (f.eks. \"person_cpr,person_landline\")\n- Hvis ingen er sat, returneres alle kolonner\n\n**Filtering:**\n- `orgunit_uuid`: Filtrer til specifik organisationsenhed\n- `orgunit_uuid_include_children`: Inkluder underliggende orgunits (default: true)\n- `ledelsesniveau`: Komma-separeret liste af ledelsesniveauer (f.eks. \"1,2\" for niveau 1 og 2)\n- `exclude_empty_columns`: Comma-separated kolonner hvor tomme værdier skal fjernes (null/None/NaN/''/whitespace)\n- `exclude_empty_logic`: AND (alle kolonner skal være udfyldt) eller OR (mindst én skal være udfyldt)\n\n**Pagination:**\n- `limit`: Maksimalt antal rækker (1-10000, None = alle)\n- `offset`: Antal rækker der skal springes over (0-baseret)\n\n**Sorting:**\n- `sort_by`: Kolonnenavn der skal sorteres efter\n- `sort_order`: Sorteringsretning (asc/desc)\n\n**Tilgængelige Kolonner:**\nPerson data indeholder 31 kolonner fra SofdPull PersonRecord:\n- Person identifikation: person_uuid, person_firstname, person_surname, person_chosenname, person_medarbejdernummer\n- Kontaktinfo: person_initialer, person_mail, person_skoleinitialer, person_schoolmail, person_landline, person_mobile\n- Ansættelse: person_startdate, person_stopdate, person_titel, person_ansaettelsesforhold, person_affiliationtype, person_normtid, person_arbejdstid, person_ledelsesniveau\n- Optionelle: person_cpr, person_arbejdstidsbroek\n- System: opus_employee_number, opus_username, kspcics_username\n- Organisatorisk: orgunit_uuid, orgunit_name, orgunit_parent_uuid, orgunit_master, orgunit_uuid_path, orgunit_name_path, orgunit_division_uuid, orgunit_division_name\n- Manager: manager_uuid, manager_inherited, manager_initialer\n\n**Eksempler:**\n```bash\n# Kun UUID og initialer\nGET /v2/data/persons?include=person_uuid,person_initialer\n\n# Alle i specifik orgunit (inkl. underliggende), ekskluder personlige oplysninger\nGET /v2/data/persons?orgunit_uuid=550e8400-e29b-41d4-a716-446655440000&orgunit_uuid_include_children=true&exclude=person_cpr,person_landline,person_mobile\n\n# Kun i specifik orgunit (uden underliggende)\nGET /v2/data/persons?orgunit_uuid=550e8400-e29b-41d4-a716-446655440000&orgunit_uuid_include_children=false\n\n# Ledere niveau 1 og 2, sorteret efter navn, første 100\nGET /v2/data/persons?ledelsesniveau=1,2&sort_by=person_surname&sort_order=asc&limit=100&offset=0\n```\n\n**Access Control:**\nKræver adgang til organisationsdata.","operationId":"get_persons_data_v2_data_persons_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal inkluderes","examples":["person_uuid,person_initialer,orgunit_name"],"title":"Include"},"description":"Comma-separated kolonner der skal inkluderes"},{"name":"exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal ekskluderes","examples":["person_cpr,person_landline"],"title":"Exclude"},"description":"Comma-separated kolonner der skal ekskluderes"},{"name":"orgunit_uuid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer til specifik orgunit UUID","title":"Orgunit Uuid"},"description":"Filtrer til specifik orgunit UUID"},{"name":"orgunit_uuid_include_children","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Inkluder underliggende organisationsenheder (default: true)","default":true,"title":"Orgunit Uuid Include Children"},"description":"Inkluder underliggende organisationsenheder (default: true)"},{"name":"ledelsesniveau","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Komma-separeret liste af ledelsesniveauer (f.eks. '1,2,3')","title":"Ledelsesniveau"},"description":"Komma-separeret liste af ledelsesniveauer (f.eks. '1,2,3')"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maksimalt antal rækker (1-10000)","title":"Limit"},"description":"Maksimalt antal rækker (1-10000)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Antal rækker der skal springes over","default":0,"title":"Offset"},"description":"Antal rækker der skal springes over"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonnenavn der skal sorteres efter","title":"Sort By"},"description":"Kolonnenavn der skal sorteres efter"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sorteringsretning (asc/desc)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning (asc/desc)"},{"name":"exclude_empty_columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner hvor tomme værdier skal fjernes (null/None/NaN/''/whitespace)","examples":["person_mail,person_mobile"],"title":"Exclude Empty Columns"},"description":"Comma-separated kolonner hvor tomme værdier skal fjernes (null/None/NaN/''/whitespace)"},{"name":"exclude_empty_logic","in":"query","required":false,"schema":{"type":"string","pattern":"^(AND|OR)$","description":"Logik for empty value filtering. AND=alle kolonner skal være udfyldt, OR=mindst én kolonne skal være udfyldt","default":"AND","title":"Exclude Empty Logic"},"description":"Logik for empty value filtering. AND=alle kolonner skal være udfyldt, OR=mindst én kolonne skal være udfyldt"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/data/persons/csv":{"get":{"tags":["v2","v2-data"],"summary":"Dynamisk persons data som CSV","description":"Henter persons data som CSV fil med fleksibel kolonnevalg, filtrering, pagination og sortering.\n\nSamme query parameters som JSON endpoint (`/v2/data/persons`).\n\n**CSV Format:**\n- UTF-8 encoding med BOM (for Excel compatibility)\n- Comma delimiter\n- Headers included i første række\n- Timestamp i filnavn: `persons_YYYYMMDD_HHMMSS.csv`\n\n**Eksempel:**\n```bash\n# Download som CSV\ncurl -X GET \"http://localhost:8000/v2/data/persons/csv?include=person_uuid,person_initialer,orgunit_name\" \\\n  -H \"Authorization: <your-api-key>\" \\\n  -o persons_export.csv\n```\n\n**Access Control:**\nKræver adgang til organisationsdata.","operationId":"get_persons_data_csv_v2_data_persons_csv_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal inkluderes","examples":["person_uuid,person_initialer,orgunit_name"],"title":"Include"},"description":"Comma-separated kolonner der skal inkluderes"},{"name":"exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal ekskluderes","examples":["person_cpr,person_landline"],"title":"Exclude"},"description":"Comma-separated kolonner der skal ekskluderes"},{"name":"orgunit_uuid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer til specifik orgunit UUID","title":"Orgunit Uuid"},"description":"Filtrer til specifik orgunit UUID"},{"name":"orgunit_uuid_include_children","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Inkluder underliggende organisationsenheder (default: true)","default":true,"title":"Orgunit Uuid Include Children"},"description":"Inkluder underliggende organisationsenheder (default: true)"},{"name":"ledelsesniveau","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Komma-separeret liste af ledelsesniveauer (f.eks. '1,2,3')","title":"Ledelsesniveau"},"description":"Komma-separeret liste af ledelsesniveauer (f.eks. '1,2,3')"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maksimalt antal rækker (1-10000)","title":"Limit"},"description":"Maksimalt antal rækker (1-10000)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Antal rækker der skal springes over","default":0,"title":"Offset"},"description":"Antal rækker der skal springes over"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonnenavn der skal sorteres efter","title":"Sort By"},"description":"Kolonnenavn der skal sorteres efter"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sorteringsretning (asc/desc)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning (asc/desc)"},{"name":"exclude_empty_columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner hvor tomme værdier skal fjernes","examples":["person_mail,person_mobile"],"title":"Exclude Empty Columns"},"description":"Comma-separated kolonner hvor tomme værdier skal fjernes"},{"name":"exclude_empty_logic","in":"query","required":false,"schema":{"type":"string","pattern":"^(AND|OR)$","description":"Logik for empty value filtering","default":"AND","title":"Exclude Empty Logic"},"description":"Logik for empty value filtering"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/data/persons/excel":{"get":{"tags":["v2","v2-data"],"summary":"Dynamisk persons data som Excel","description":"Henter persons data som Excel fil med fleksibel kolonnevalg, filtrering, pagination og sortering.\n\nSamme query parameters som JSON endpoint (`/v2/data/persons`).\n\n**Excel Format:**\n- XLSX format (OpenXML)\n- Pæn formatering med freeze header og table styling\n- Timestamp i filnavn: `persons_YYYYMMDD_HHMMSS.xlsx`\n- Korrekt håndtering af datetime kolonner (person_startdate, person_stopdate)\n\n**Eksempel:**\n```bash\n# Download som Excel\ncurl -X GET \"http://localhost:8000/v2/data/persons/excel?include=person_uuid,person_initialer,person_startdate,person_stopdate\" \\\n  -H \"Authorization: <your-api-key>\" \\\n  -o persons_export.xlsx\n```\n\n**Access Control:**\nKræver adgang til organisationsdata.","operationId":"get_persons_data_excel_v2_data_persons_excel_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal inkluderes","examples":["person_uuid,person_initialer,orgunit_name"],"title":"Include"},"description":"Comma-separated kolonner der skal inkluderes"},{"name":"exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal ekskluderes","examples":["person_cpr,person_landline"],"title":"Exclude"},"description":"Comma-separated kolonner der skal ekskluderes"},{"name":"orgunit_uuid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer til specifik orgunit UUID","title":"Orgunit Uuid"},"description":"Filtrer til specifik orgunit UUID"},{"name":"orgunit_uuid_include_children","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Inkluder underliggende organisationsenheder (default: true)","default":true,"title":"Orgunit Uuid Include Children"},"description":"Inkluder underliggende organisationsenheder (default: true)"},{"name":"ledelsesniveau","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Komma-separeret liste af ledelsesniveauer (f.eks. '1,2,3')","title":"Ledelsesniveau"},"description":"Komma-separeret liste af ledelsesniveauer (f.eks. '1,2,3')"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maksimalt antal rækker (1-10000)","title":"Limit"},"description":"Maksimalt antal rækker (1-10000)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Antal rækker der skal springes over","default":0,"title":"Offset"},"description":"Antal rækker der skal springes over"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonnenavn der skal sorteres efter","title":"Sort By"},"description":"Kolonnenavn der skal sorteres efter"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sorteringsretning (asc/desc)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning (asc/desc)"},{"name":"exclude_empty_columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner hvor tomme værdier skal fjernes","examples":["person_mail,person_mobile"],"title":"Exclude Empty Columns"},"description":"Comma-separated kolonner hvor tomme værdier skal fjernes"},{"name":"exclude_empty_logic","in":"query","required":false,"schema":{"type":"string","pattern":"^(AND|OR)$","description":"Logik for empty value filtering","default":"AND","title":"Exclude Empty Logic"},"description":"Logik for empty value filtering"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/data/orgunits":{"get":{"tags":["v2","v2-data"],"summary":"Dynamisk orgunits data","description":"Henter orgunits data med fleksibel kolonnevalg, filtrering, pagination og sortering.\n\n**Column Selection:**\n- `include`: Comma-separated liste af kolonner der skal inkluderes (f.eks. \"orgunit_uuid,orgunit_name,orgunit_parent_uuid\")\n- `exclude`: Comma-separated liste af kolonner der skal ekskluderes (f.eks. \"orgunit_p_nummer,virk_branchekode\")\n- Hvis ingen er sat, returneres alle kolonner\n\n**Filtering:**\n- `orgunit_uuid`: Filtrer til specifik organisationsenhed\n- `orgunit_uuid_include_children`: Inkluder underliggende orgunits (default: true)\n\n**Pagination:**\n- `limit`: Maksimalt antal rækker (1-10000, None = alle)\n- `offset`: Antal rækker der skal springes over (0-baseret)\n\n**Sorting:**\n- `sort_by`: Kolonnenavn der skal sorteres efter\n- `sort_order`: Sorteringsretning (asc/desc)\n\n**Tilgængelige Kolonner:**\nOrgunit data indeholder 25 kolonner fra SofdPull OrgunitRecord:\n- Identifikation: orgunit_uuid, orgunit_name, orgunit_type, orgunit_master, orgunit_los_id, fkorg_excluded\n- Hierarki: orgunit_parent_uuid, orgunit_uuid_path, orgunit_name_path, orgunit_division_uuid, orgunit_division_name\n- Manager: manager_firstname, manager_surname, manager_uuid, manager_inherited\n- Økonomi: orgunit_debitornummer, orgunit_debitornummer_nedarvet, orgunit_ean, orgunit_ean_inherited, orgunit_p_nummer, virk_branchekode, virk_branchetekst\n- Adresse: orgunit_street, orgunit_postalcode, orgunit_city\n\n**Eksempler:**\n```bash\n# Alle orgunits med kun UUID og navn\nGET /v2/data/orgunits?include=orgunit_uuid,orgunit_name,orgunit_type\n\n# Specifik orgunit og alle underliggende\nGET /v2/data/orgunits?orgunit_uuid=550e8400-e29b-41d4-a716-446655440000&orgunit_uuid_include_children=true\n\n# Kun specifik orgunit (uden underliggende)\nGET /v2/data/orgunits?orgunit_uuid=550e8400-e29b-41d4-a716-446655440000&orgunit_uuid_include_children=false\n```\n\n**Access Control:**\nKræver adgang til organisationsdata.","operationId":"get_orgunits_data_v2_data_orgunits_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal inkluderes","examples":["orgunit_uuid,orgunit_name,orgunit_parent_uuid"],"title":"Include"},"description":"Comma-separated kolonner der skal inkluderes"},{"name":"exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal ekskluderes","examples":["orgunit_p_nummer,virk_branchekode"],"title":"Exclude"},"description":"Comma-separated kolonner der skal ekskluderes"},{"name":"orgunit_uuid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer til specifik orgunit UUID","title":"Orgunit Uuid"},"description":"Filtrer til specifik orgunit UUID"},{"name":"orgunit_uuid_include_children","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Inkluder underliggende organisationsenheder (default: true)","default":true,"title":"Orgunit Uuid Include Children"},"description":"Inkluder underliggende organisationsenheder (default: true)"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maksimalt antal rækker (1-10000)","title":"Limit"},"description":"Maksimalt antal rækker (1-10000)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Antal rækker der skal springes over","default":0,"title":"Offset"},"description":"Antal rækker der skal springes over"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonnenavn der skal sorteres efter","title":"Sort By"},"description":"Kolonnenavn der skal sorteres efter"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sorteringsretning (asc/desc)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning (asc/desc)"},{"name":"exclude_empty_columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner hvor tomme værdier skal fjernes","examples":["manager_uuid,orgunit_ean"],"title":"Exclude Empty Columns"},"description":"Comma-separated kolonner hvor tomme værdier skal fjernes"},{"name":"exclude_empty_logic","in":"query","required":false,"schema":{"type":"string","pattern":"^(AND|OR)$","description":"Logik for empty value filtering","default":"AND","title":"Exclude Empty Logic"},"description":"Logik for empty value filtering"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DynamicDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/data/orgunits/csv":{"get":{"tags":["v2","v2-data"],"summary":"Dynamisk orgunits data som CSV","description":"Henter orgunits data som CSV fil med fleksibel kolonnevalg, filtrering, pagination og sortering.\n\nSamme query parameters som JSON endpoint (`/v2/data/orgunits`).\n\n**CSV Format:**\n- UTF-8 encoding med BOM (for Excel compatibility)\n- Comma delimiter\n- Headers included i første række\n- Timestamp i filnavn: `orgunits_YYYYMMDD_HHMMSS.csv`\n\n**Eksempel:**\n```bash\n# Download som CSV\ncurl -X GET \"http://localhost:8000/v2/data/orgunits/csv?include=orgunit_uuid,orgunit_name,orgunit_type\" \\\n  -H \"Authorization: <your-api-key>\" \\\n  -o orgunits_export.csv\n```\n\n**Access Control:**\nKræver adgang til organisationsdata.","operationId":"get_orgunits_data_csv_v2_data_orgunits_csv_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal inkluderes","examples":["orgunit_uuid,orgunit_name,orgunit_parent_uuid"],"title":"Include"},"description":"Comma-separated kolonner der skal inkluderes"},{"name":"exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal ekskluderes","examples":["orgunit_p_nummer,virk_branchekode"],"title":"Exclude"},"description":"Comma-separated kolonner der skal ekskluderes"},{"name":"orgunit_uuid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer til specifik orgunit UUID","title":"Orgunit Uuid"},"description":"Filtrer til specifik orgunit UUID"},{"name":"orgunit_uuid_include_children","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Inkluder underliggende organisationsenheder (default: true)","default":true,"title":"Orgunit Uuid Include Children"},"description":"Inkluder underliggende organisationsenheder (default: true)"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maksimalt antal rækker (1-10000)","title":"Limit"},"description":"Maksimalt antal rækker (1-10000)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Antal rækker der skal springes over","default":0,"title":"Offset"},"description":"Antal rækker der skal springes over"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonnenavn der skal sorteres efter","title":"Sort By"},"description":"Kolonnenavn der skal sorteres efter"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sorteringsretning (asc/desc)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning (asc/desc)"},{"name":"exclude_empty_columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner hvor tomme værdier skal fjernes","examples":["manager_uuid,orgunit_ean"],"title":"Exclude Empty Columns"},"description":"Comma-separated kolonner hvor tomme værdier skal fjernes"},{"name":"exclude_empty_logic","in":"query","required":false,"schema":{"type":"string","pattern":"^(AND|OR)$","description":"Logik for empty value filtering","default":"AND","title":"Exclude Empty Logic"},"description":"Logik for empty value filtering"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/data/orgunits/excel":{"get":{"tags":["v2","v2-data"],"summary":"Dynamisk orgunits data som Excel","description":"Henter orgunits data som Excel fil med fleksibel kolonnevalg, filtrering, pagination og sortering.\n\nSamme query parameters som JSON endpoint (`/v2/data/orgunits`).\n\n**Excel Format:**\n- XLSX format (OpenXML)\n- Pæn formatering med freeze header og table styling\n- Timestamp i filnavn: `orgunits_YYYYMMDD_HHMMSS.xlsx`\n- Korrekt håndtering af datetime kolonner\n\n**Eksempel:**\n```bash\n# Download som Excel\ncurl -X GET \"http://localhost:8000/v2/data/orgunits/excel?include=orgunit_uuid,orgunit_name,orgunit_type\" \\\n  -H \"Authorization: <your-api-key>\" \\\n  -o orgunits_export.xlsx\n```\n\n**Access Control:**\nKræver adgang til organisationsdata.","operationId":"get_orgunits_data_excel_v2_data_orgunits_excel_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal inkluderes","examples":["orgunit_uuid,orgunit_name,orgunit_parent_uuid"],"title":"Include"},"description":"Comma-separated kolonner der skal inkluderes"},{"name":"exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner der skal ekskluderes","examples":["orgunit_p_nummer,virk_branchekode"],"title":"Exclude"},"description":"Comma-separated kolonner der skal ekskluderes"},{"name":"orgunit_uuid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filtrer til specifik orgunit UUID","title":"Orgunit Uuid"},"description":"Filtrer til specifik orgunit UUID"},{"name":"orgunit_uuid_include_children","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Inkluder underliggende organisationsenheder (default: true)","default":true,"title":"Orgunit Uuid Include Children"},"description":"Inkluder underliggende organisationsenheder (default: true)"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Maksimalt antal rækker (1-10000)","title":"Limit"},"description":"Maksimalt antal rækker (1-10000)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Antal rækker der skal springes over","default":0,"title":"Offset"},"description":"Antal rækker der skal springes over"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Kolonnenavn der skal sorteres efter","title":"Sort By"},"description":"Kolonnenavn der skal sorteres efter"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sorteringsretning (asc/desc)","default":"asc","title":"Sort Order"},"description":"Sorteringsretning (asc/desc)"},{"name":"exclude_empty_columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated kolonner hvor tomme værdier skal fjernes","examples":["manager_uuid,orgunit_ean"],"title":"Exclude Empty Columns"},"description":"Comma-separated kolonner hvor tomme værdier skal fjernes"},{"name":"exclude_empty_logic","in":"query","required":false,"schema":{"type":"string","pattern":"^(AND|OR)$","description":"Logik for empty value filtering","default":"AND","title":"Exclude Empty Logic"},"description":"Logik for empty value filtering"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tools/query-builder":{"get":{"tags":["tools","Tools"],"summary":"Web Query Builder","description":"Web-baseret query builder til V2 Dynamic Data API.\n\n**Access Control:**\nPublic endpoint - authentication sker via API key validation i UI.\n\n**Features:**\n- Interaktiv UI til query building\n- Kolonnevalg (include/exclude/all modes)\n- Filtrering (type-specifik)\n- Pagination og sortering\n- JSON pretty print visning\n- Curl kommando generering\n\n**URL:** `/tools/query-builder`","operationId":"get_query_builder_tools_query_builder_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}},"security":[{"APIKeyHeader":[]}]}},"/tools/query-builder/validate-key":{"post":{"tags":["tools","Tools"],"summary":"Validate API Key","description":"Validerer en API key og returnerer brugerinfo.\n\n**Request Body:**\n```json\n{\n  \"api_key\": \"<your-api-key>\"\n}\n```\n\n**Response:**\n```json\n{\n  \"valid\": true,\n  \"user_info\": {\n    \"user_initials\": \"abc\",\n    \"groups\": [\"internal\", \"pebl\"]\n  }\n}\n```","operationId":"validate_api_key_endpoint_tools_query_builder_validate_key_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/tools/query-builder/columns/{data_type}":{"get":{"tags":["tools","Tools"],"summary":"Get Available Columns","description":"Henter liste af tilgængelige kolonner for en data type.\n\n**Path Parameters:**\n- `data_type`: persons eller orgunits\n\n**Response:**\n```json\n{\n  \"data_type\": \"persons\",\n  \"columns\": [\"person_uuid\", \"person_initialer\", ...],\n  \"count\": 31,\n  \"restricted_columns\": {\n    \"person_cpr\": [\"root\", \"cpr_allow\"]\n  },\n  \"user_groups\": [\"internal\", \"pebl\"]\n}\n```","operationId":"get_columns_tools_query_builder_columns__data_type__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"data_type","in":"path","required":true,"schema":{"type":"string","title":"Data Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/session/login":{"post":{"tags":["session","Session"],"summary":"Login og opret session","description":"Validerer API key og opretter en HTTP-only cookie session.\n\n**Request Body:**\n```json\n{\n  \"api_key\": \"FAV-KEY-XXXX-XXXX-XXXX-XXXX\"\n}\n```\n\n**Success Response:**\n```json\n{\n  \"success\": true,\n  \"user_info\": {\n    \"user_initials\": \"abc\",\n    \"groups\": [\"internal\", \"pebl\"]\n  }\n}\n```\n\n**Error Response:**\n```json\n{\n  \"success\": false,\n  \"error\": \"Invalid API key\"\n}\n```\n\n**Cookie:**\nVed success saettes en HTTP-only cookie med session ID.","operationId":"login_session_login_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/session/logout":{"post":{"tags":["session","Session"],"summary":"Logout og slet session","description":"Sletter session og rydder cookie.\n\n**Response:**\n```json\n{\n  \"success\": true\n}\n```\n\n**Cookie:**\nSession cookie ryddes uanset om session eksisterer.","operationId":"logout_session_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"APIKeyHeader":[]}]}},"/session/status":{"get":{"tags":["session","Session"],"summary":"Check session status","description":"Checker om session er valid og returnerer user info.\n\n**Authenticated Response:**\n```json\n{\n  \"authenticated\": true,\n  \"user_info\": {\n    \"user_initials\": \"abc\",\n    \"groups\": [\"internal\", \"pebl\"]\n  }\n}\n```\n\n**Not Authenticated Response:**\n```json\n{\n  \"authenticated\": false\n}\n```","operationId":"status_session_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Status Session Status Get"}}}}},"security":[{"APIKeyHeader":[]}]}},"/health":{"get":{"tags":["Health"],"summary":"Health Check","description":"Kontrollerer sundheden af systemet og returnerer status.\nDenne funktion bruges som en endpoint til at verificere,\nat applikationen kører korrekt.\n\n:return: Et dict som indeholder status for applikationens sundhed\n:rtype: dict","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"DynamicDataResponse":{"properties":{"data":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Data","description":"Data rækker som dictionary list"},"count":{"type":"integer","title":"Count","description":"Antal rækker returneret i data"},"pagination":{"anyOf":[{"$ref":"#/components/schemas/PaginationInfo"},{"type":"null"}],"description":"Pagination metadata (None hvis pagination ikke anvendt)"},"query":{"$ref":"#/components/schemas/QueryMetadata","description":"Metadata om den udførte query"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"Tidsstempel for response generering"}},"type":"object","required":["data","count","pagination","query","timestamp"],"title":"DynamicDataResponse","description":"Standardiseret response format for dynamiske data endpoints.\n\nIndeholder:\n- data: De faktiske data rækker\n- count: Metadata om antal rækker\n- pagination: Pagination info (hvis anvendt)\n- query: Information om den udførte query\n- timestamp: Tidsstempel for responsen","examples":[{"count":1,"data":[{"orgunit_name":"IT-afdelingen","person_initialer":"jdoe","person_uuid":"550e8400-e29b-41d4-a716-446655440000"}],"pagination":{"has_more":true,"limit":100,"offset":0,"returned":1,"total":150},"query":{"filters_applied":{"active_only":true},"include_columns":["person_uuid","person_initialer","orgunit_name"],"sort_by":"person_initialer","sort_order":"asc"},"timestamp":"2025-10-17T12:00:00Z"}]},"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Fejlbesked"}},"type":"object","required":["detail"],"title":"ErrorResponse","description":"Standard error response format.","example":{"detail":"Authentication failed"}},"GenerateKeysResponse":{"properties":{"message":{"type":"string","title":"Message"},"keys":{"items":{"type":"string"},"type":"array","title":"Keys"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["message","keys","count"],"title":"GenerateKeysResponse","description":"Response model for generate-keys endpoint."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HierarchyRequest":{"properties":{"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"}},"type":"object","title":"HierarchyRequest","description":"Request model til at generere ledelseshierarki.\nConfig er optional - hvis ikke angivet bruges default config."},"PaginationInfo":{"properties":{"total":{"type":"integer","title":"Total","description":"Totalt antal rækker EFTER filtrering men FØR pagination","examples":[1500]},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit","description":"Anvendt limit (None hvis alle rækker returneres)","examples":[100,null]},"offset":{"type":"integer","title":"Offset","description":"Anvendt offset","examples":[0,100]},"returned":{"type":"integer","title":"Returned","description":"Antal rækker returneret i denne response","examples":[100]},"has_more":{"type":"boolean","title":"Has More","description":"Om der er flere rækker tilgængelige efter denne batch","examples":[true,false]}},"type":"object","required":["total","limit","offset","returned","has_more"],"title":"PaginationInfo","description":"Pagination metadata inkluderet i response."},"QueryMetadata":{"properties":{"include_columns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Include Columns","description":"Anvendte include kolonner (None hvis alle)"},"exclude_columns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Exclude Columns","description":"Anvendte exclude kolonner (None hvis ingen)"},"filters_applied":{"additionalProperties":true,"type":"object","title":"Filters Applied","description":"Anvendte filtre"},"sort_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By","description":"Anvendt sorteringskolonne"},"sort_order":{"type":"string","title":"Sort Order","description":"Anvendt sorteringsretning"}},"type":"object","required":["include_columns","exclude_columns","filters_applied","sort_by","sort_order"],"title":"QueryMetadata","description":"Metadata om den udførte query."},"StandardAPIResponse":{"properties":{"message":{"type":"string","title":"Message","description":"Beskrivende besked om operationen"},"data":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Data","description":"Data array med resultater"},"count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Count","description":"Antal elementer i data array"},"user_info":{"$ref":"#/components/schemas/UserInfo","description":"Information om den autentificerede bruger"}},"type":"object","required":["message","data","user_info"],"title":"StandardAPIResponse","description":"Standard response format for de fleste V1 endpoints.","example":{"count":1,"data":[{"person_initialer":"abc","person_uuid":"550e8400-e29b-41d4-a716-446655440000"}],"message":"Data retrieved successfully","user_info":{"groups":["root"],"user_initials":"test"}}},"UserInfo":{"properties":{"user_initials":{"type":"string","title":"User Initials","description":"Brugerens initialer"},"groups":{"items":{"type":"string"},"type":"array","title":"Groups","description":"Brugerens grupper"}},"type":"object","required":["user_initials","groups"],"title":"UserInfo","description":"Bruger information inkluderet i API responses."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"Authorization","description":"API key authentication. Kontakt systemadministrator for at få tildelt en API key.\n\nBrug API key direkte i Authorization header.\n\n**Bemærk:** API keys er personlige og skal behandles fortroligt."}}}}