[{"data":1,"prerenderedAt":5668},["ShallowReactive",2],{"blog-list-en":3},[4,442,796,1040,2197,2648,4658,4682,4707,4900],{"id":5,"title":6,"body":7,"date":432,"description":433,"draft":434,"extension":435,"meta":436,"navigation":437,"path":438,"seo":439,"stem":440,"__hash__":441},"blogEn\u002Fblog\u002Fopensource-helpdesk-ki-apis-automation-datenschutz.md","Open Source Helpdesk and AI: Between Product Capabilities, APIs, and a Neutral Automation Layer",{"type":8,"value":9,"toc":418},"minimark",[10,27,32,39,61,72,76,81,100,120,124,135,144,163,172,192,201,205,231,247,251,278,292,315,325,329,332,362,365,369,397,400],[11,12,13,14,18,19,22,23,26],"p",{},"Open-source ticket and helpdesk systems remain the foundation for service processes in many organizations. At the same time, AI assistance (summaries, routing, classification, reply suggestions) is taking center stage—often combined with the desire for ",[15,16,17],"strong",{},"traceability",", ",[15,20,21],{},"on-prem or local inference",", and ",[15,24,25],{},"independence from individual cloud providers",". This article outlines the emerging variations and what teams should look out for regarding architecture and governance.",[28,29,31],"h2",{"id":30},"ai-in-the-helpdesk-native-feature-api-integration-or-dedicated-automation-layer","AI in the Helpdesk: Native Feature, API Integration, or Dedicated Automation Layer?",[11,33,34,35,38],{},"In proprietary suites, AI features are frequently bundled with licenses and data processing. With open systems, a ",[15,36,37],{},"spectrum"," emerges:",[40,41,42,49,55],"ul",{},[43,44,45,48],"li",{},[15,46,47],{},"Product-integrated"," functions (e.g., summaries, categorization), potentially with configurable model endpoints.",[43,50,51,54],{},[15,52,53],{},"API- and webhook-connected"," automation (orchestration tools, custom services), where the ticketing system remains the source of truth.",[43,56,57,60],{},[15,58,59],{},"Separate automation layer"," that unifies multiple ticket backends—ideal for integrators, MSPs, or mixed system landscapes.",[11,62,63,64,67,68,71],{},"The following sections primarily refer to ",[15,65,66],{},"Zammad"," (which has well-documented public AI and API classifications) as well as an ",[15,69,70],{},"open-source project for cross-ticket pipelines",". Many API and data privacy principles apply analogously to Znuny- and OTOBO-oriented environments, even though specific configurations vary per instance.",[28,73,75],{"id":74},"zammad-7-and-ai-what-is-officially-planned-and-what-communities-are-building-today","Zammad 7 and AI: What Is Officially Planned and What Communities Are Building Today",[77,78,80],"h3",{"id":79},"roadmap-and-native-ai","Roadmap and Native AI",[11,82,83,84,87,88,91,92,95,96,99],{},"In a 2025 blog post, Zammad explicitly describes that ",[15,85,86],{},"native AI features will be introduced with Zammad 7.0","—with goals such as summaries, automatic categorization, and sentiment and escalation indicators. At the same time, it emphasizes that ",[15,89,90],{},"local models (e.g., via Ollama)"," are taken into account to avoid necessarily sending sensitive data to third-party providers. The article also points to a ",[15,93,94],{},"separate AI strategy"," on the company blog and demonstrates in parallel how ",[15,97,98],{},"REST APIs, webhooks, triggers, and schedulers"," can already be combined with tools like n8n today for AI-supported routing or prioritization.",[40,101,102,112],{},[43,103,104,111],{},[105,106,110],"a",{"href":107,"rel":108},"https:\u002F\u002Fzammad.com\u002Fen\u002Fblog\u002Fautomate-support-workflows-with-zammad-n8n-and-ai",[109],"nofollow","From API to AI: Streamline Support Operations with Zammad, n8n and Ollama"," (Zammad Blog, state of presentation: see site)",[43,113,114,119],{},[105,115,118],{"href":116,"rel":117},"https:\u002F\u002Fzammad.com\u002Fen\u002Fblog\u002Fai-strategy-for-zammad-helpdesk",[109],"AI in Service of Support Agents"," (Strategy article, linked from the post above)",[77,121,123],{"id":122},"community-expectation-management-and-practice","Community: Expectation Management and Practice",[11,125,126,127,130,131,134],{},"In mid-2024, the Zammad core team pointed the Zammad community to the status of ",[15,128,129],{},"\"not much yet\""," regarding product-level GenAI features and referred to the discussion on GPT integration—a useful reminder that ",[15,132,133],{},"older forum posts"," do not always reflect the current product state as new releases roll out.",[40,136,137],{},[43,138,139],{},[105,140,143],{"href":141,"rel":142},"https:\u002F\u002Fcommunity.zammad.org\u002Ft\u002Fgenai-capabilities-in-zammad\u002F14987",[109],"GenAI capabilities in zammad",[11,145,146,147,150,151,154,155,158,159,162],{},"Users have long discussed ",[15,148,149],{},"GPT integration, anonymization, and costs"," (token-based pricing, effort for indexing large data sets). Among other things, a core team member highlights ",[15,152,153],{},"GDPR risks"," and the need for strong anonymization when ticket contents are used for external models. In practice, the approach via ",[15,156,157],{},"notes in the ticket"," is mentioned so that agents can ",[15,160,161],{},"review and partially adopt"," suggestions instead of replying automatically.",[40,164,165],{},[43,166,167],{},[105,168,171],{"href":169,"rel":170},"https:\u002F\u002Fcommunity.zammad.org\u002Ft\u002Fintegrate-with-gpt\u002F12738",[109],"Integrate with GPT",[11,173,174,175,178,179,183,184,187,188,191],{},"Freely accessible answers contain ",[15,176,177],{},"concrete tech stacks"," (e.g., Python, ",[180,181,182],"code",{},"zammad_py",", vector\u002Fretrieval components, ",[15,185,186],{},"Microsoft Presidio"," for identifying and anonymizing sensitive text). While this is not official Zammad documentation, it is a robust description of a ",[15,189,190],{},"pattern"," that organizations often need to customize—for example, regarding the retention of embeddings.",[40,193,194],{},[43,195,196],{},[105,197,200],{"href":198,"rel":199},"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fpresidio",[109],"Presidio (Microsoft)",[77,202,204],{"id":203},"local-llms-ollama-in-the-ticketing-system-which-model-which-risks","Local LLMs (Ollama) in the Ticketing System: Which Model, Which Risks?",[11,206,207,208,211,212,215,216,219,220,223,224,18,227,230],{},"Following the product overview on the Zammad blog, ",[15,209,210],{},"support for local models"," is explicitly mentioned. In operational practice, an active forum thread exemplifies that ",[15,213,214],{},"\"works locally with Ollama\""," does not automatically mean every model works out of the box: For summaries and structured response formats, ",[15,217,218],{},"JSON or schema requirements"," can fail if the model or runtime environment does not deliver compliant outputs. In this context, a core team member points to an ",[15,221,222],{},"issue in the Ollama repositories"," concerning structured outputs with certain models—a reminder to test such risks during ",[15,225,226],{},"model family selection",[15,228,229],{},"regression testing, and monitoring",".",[40,232,233,240],{},[43,234,235],{},[105,236,239],{"href":237,"rel":238},"https:\u002F\u002Fcommunity.zammad.org\u002Ft\u002Fwhich-model-from-ollama-works-best-for-ai-features\u002F19730",[109],"Which model from Ollama works best for AI features?",[43,241,242],{},[105,243,246],{"href":244,"rel":245},"https:\u002F\u002Fgithub.com\u002Follama\u002Follama\u002Fissues\u002F11691",[109],"Structured output with OpenAI SDK and gpt-oss:20b not working (Ollama)",[28,248,250],{"id":249},"open-ticket-ai-a-neutral-automation-layer-for-zammad-otobo-and-znuny","Open Ticket AI: A Neutral Automation Layer for Zammad, OTOBO, and Znuny",[11,252,253,254,257,258,261,262,265,266,269,270,273,274,277],{},"Independent of any single vendor, the ",[15,255,256],{},"Open Ticket AI"," project (LGPL-2.1, code and docs public) describes a ",[15,259,260],{},"plugin-based, on-premise-capable automation engine"," with a unified ticket model and configurable pipelines (including classification, ticket updates, and enrichment). According to the repository README and introductory article, integrations include the ",[15,263,264],{},"OTOBO\u002FZnuny\u002FOTRS family"," as well as ",[15,267,268],{},"Zammad (with a beta notice)",". Extensions can be distributed via ",[15,271,272],{},"PyPI packages"," with the ",[180,275,276],{},"otai-"," name prefix.",[11,279,280,281,284,285,288,289,230],{},"This is not a replacement for a helpdesk backend, but rather an ",[15,282,283],{},"integration and orchestration framework","—comparable to the ETL\u002Fworkflow approach outlined in the Zammad blog, but with a stronger focus on ",[15,286,287],{},"reusable pipes"," and ",[15,290,291],{},"multiple systems in parallel",[40,293,294,301,308],{},[43,295,296],{},[105,297,300],{"href":298,"rel":299},"https:\u002F\u002Fgithub.com\u002FSoftoft-Orga\u002Fopen-ticket-ai",[109],"open-ticket-ai on GitHub",[43,302,303],{},[105,304,307],{"href":305,"rel":306},"https:\u002F\u002Fopenticketai.com\u002F",[109],"Documentation (openticketai.com)",[43,309,310],{},[105,311,314],{"href":312,"rel":313},"https:\u002F\u002Fmedium.com\u002F@softoft\u002Fopen-ticket-ai-the-open-source-automation-engine-for-every-ticket-system-7a54b13ea32f",[109],"Introductory article (Medium, author: Tobias Bück)",[11,316,317,320,321,324],{},[15,318,319],{},"Classification Note:"," As with any open-source project, maturity, stable releases, and production experiences vary. Before making a broad production decision, running a ",[15,322,323],{},"pilot with load and DPIA-relevant scenarios"," is recommended.",[28,326,328],{"id":327},"gdpr-in-the-ai-helpdesk-purpose-limitation-pseudonymization-and-data-processing-agreements","GDPR in the AI Helpdesk: Purpose Limitation, Pseudonymization, and Data Processing Agreements",[11,330,331],{},"Using AI over ticketing systems brings several aspects together:",[40,333,334,340,346,352],{},[43,335,336,339],{},[15,337,338],{},"Purpose limitation and legal basis",": What tasks is automation allowed to perform (drafting only, internal routing only vs. external communication)?",[43,341,342,345],{},[15,343,344],{},"Data minimization and pseudonymization",": Before transmitting to cloud endpoints or even before local long-term storage of embeddings.",[43,347,348,351],{},[15,349,350],{},"Data processing agreements (DPAs) and subcontractors",": When external provider APIs are used, review contracts and deletion concepts; for local inference, still keep logging and support access in mind.",[43,353,354,357,358,361],{},[15,355,356],{},"Transparency and human control",": Employment law and qualitative aspects (liability, quality assurance) often speak in favor of a ",[15,359,360],{},"human-in-the-loop"," approach, as outlined in community examples for Zammad.",[11,363,364],{},"This does not replace legal advice; implementation depends on your industry, works council\u002Femployee representation, and specific data processing activities.",[28,366,368],{"id":367},"implications-for-an-open-helpdesk-plugin-directory","Implications for an Open Helpdesk Plugin Directory",[11,370,371,372,375,376,18,380,18,384,388,389,392,393,230],{},"An ",[15,373,374],{},"open directory"," for extensions and compatible packages (see ",[105,377,379],{"href":378},"\u002Fznuny-plugins","Znuny plugins",[105,381,383],{"href":382},"\u002Fzammad-plugins","Zammad plugins",[105,385,387],{"href":386},"\u002Fotobo-plugins","OTOBO plugins",") helps make such integration paths ",[15,390,391],{},"visible and comparable","—regardless of whether AI is integrated into the core product, via n8n & co., or through a dedicated engine. You can find further insights in the ",[105,394,396],{"href":395},"\u002Fblog","blog overview",[398,399],"hr",{},[11,401,402,405,406,409,410,413,414,417],{},[15,403,404],{},"Transparency regarding uncertainties:"," You should cross-check the exact feature list and stability of ",[15,407,408],{},"Zammad 7.x AI features"," against the ",[15,411,412],{},"release notes and admin documentation of your installed version",". Community threads often reflect point-in-time experiences rather than the full product scope. The same applies to ",[15,415,416],{},"model and Ollama versions"," in ongoing operations—here, reproducibility and regression testing are crucial.",{"title":419,"searchDepth":420,"depth":420,"links":421},"",2,[422,423,429,430,431],{"id":30,"depth":420,"text":31},{"id":74,"depth":420,"text":75,"children":424},[425,427,428],{"id":79,"depth":426,"text":80},3,{"id":122,"depth":426,"text":123},{"id":203,"depth":426,"text":204},{"id":249,"depth":420,"text":250},{"id":327,"depth":420,"text":328},{"id":367,"depth":420,"text":368},"2026-05-03","Classification of how teams use AI with Zammad, Znuny\u002FOTOBO ecosystems, and others: native features, API-driven workflows, open-source automation engines, and typical privacy questions from a DACH perspective.",false,"md",{},true,"\u002Fblog\u002Fopensource-helpdesk-ki-apis-automation-datenschutz",{"title":6,"description":433},"blog\u002Fopensource-helpdesk-ki-apis-automation-datenschutz","23yxhptffCZIjwXpyCxIhUK6T91k6xvMN9Sfo29aOFo",{"id":443,"title":444,"body":445,"date":788,"description":789,"draft":437,"extension":435,"meta":790,"navigation":437,"path":792,"seo":793,"stem":794,"__hash__":795},"blogEn\u002Fblog\u002Fotai-desk-ki-first-helpdesk.md","OTAI Desk: AI-First Helpdesk — Open Source, On-Premise, No Cloud Lock-In",{"type":8,"value":446,"toc":777},[447,451,475,478,482,552,569,573,576,580,587,591,598,607,622,626,645,652,656,690,694,713,723,725,729,766,768],[448,449,444],"h1",{"id":450},"otai-desk-ai-first-helpdesk-open-source-on-premise-no-cloud-lock-in",[11,452,453,454,457,458,463,464,467,468,471,472,230],{},"Traditional helpdesks were built for human agents. ",[15,455,456],{},"AI was added later"," — often as a cloud add-on with unclear data processing. ",[105,459,462],{"href":460,"rel":461},"https:\u002F\u002Fdesk.openticketai.com",[109],"OTAI Desk"," reverses this approach: It is an ",[15,465,466],{},"AI-first helpdesk"," from the ground up, running on the open-source ",[105,469,256],{"href":298,"rel":470},[109]," platform (LGPL) and deployed ",[15,473,474],{},"completely on your own infrastructure",[11,476,477],{},"For IT leaders in German-speaking Europe and beyond who want to deploy AI in the service desk without sending ticket content to US clouds, this is a highly relevant new approach.",[28,479,481],{"id":480},"what-sets-otai-desk-apart","What Sets OTAI Desk Apart",[483,484,485,498],"table",{},[486,487,488],"thead",{},[489,490,491,495],"tr",{},[492,493,494],"th",{},"Feature",[492,496,497],{},"Significance for IT Teams",[499,500,501,512,522,532,542],"tbody",{},[489,502,503,509],{},[504,505,506],"td",{},[15,507,508],{},"AI-First Architecture",[504,510,511],{},"Local LLMs and RAG are at the core — not an optional plugin",[489,513,514,519],{},[504,515,516],{},[15,517,518],{},"100% On-Premise",[504,520,521],{},"No ongoing cloud dependency; inference stays within your own network",[489,523,524,529],{},[504,525,526],{},[15,527,528],{},"L1 Deflection",[504,530,531],{},"Up to 30–40% of standard requests are answered automatically",[489,533,534,539],{},[504,535,536],{},[15,537,538],{},"Audit Trails",[504,540,541],{},"Every AI decision, prompt, and action is logged",[489,543,544,549],{},[504,545,546],{},[15,547,548],{},"Keep Existing Systems",[504,550,551],{},"Optionally deployable as an intelligent front layer before Zammad, Znuny, Jira, etc.",[11,553,554,555,560,561,564,565,568],{},"According to ",[105,556,559],{"href":557,"rel":558},"https:\u002F\u002Fdesk.openticketai.com\u002F",[109],"desk.openticketai.com",", OTAI Desk promises, among other things, ",[15,562,563],{},"initial response times under 30 seconds"," through AI and a ",[15,566,567],{},"reduction in routing effort by around 60%"," — metrics that naturally vary depending on the specific pilot project.",[28,570,572],{"id":571},"two-deployment-models-one-product","Two Deployment Models — One Product",[11,574,575],{},"OTAI Desk can be deployed in two distinct ways:",[77,577,579],{"id":578},"_1-standalone-ai-helpdesk","1. Standalone AI Helpdesk",[11,581,582,583,586],{},"As an ",[15,584,585],{},"independent ticketing system",", OTAI Desk receives requests via chat, email, or Microsoft Teams. Local LLMs classify requests, search the internal knowledge base (RAG), and resolve routine cases — such as password resets or FAQ inquiries — directly.",[77,588,590],{"id":589},"_2-intelligent-front-layer-no-rip-and-replace","2. Intelligent Front Layer (No Rip-and-Replace)",[11,592,593,594,597],{},"Organizations already operating Zammad, Znuny, OTOBO, Jira Service Management, or Matrix42 can ",[15,595,596],{},"place OTAI Desk in front"," of them: The AI intercepts L1 requests; anything it cannot resolve is handed over to the backend as a structured ticket with full context. Processes and workflows in the existing system remain untouched.",[11,599,600,601,606],{},"The four-step workflow — ",[105,602,605],{"href":603,"rel":604},"https:\u002F\u002Fdesk.openticketai.com\u002Fhow-it-works\u002F",[109],"as described on the product page",":",[608,609,610,613,616,619],"ol",{},[43,611,612],{},"Employee submits a request (chat, email, Teams)",[43,614,615],{},"AI classifies, searches the knowledge base, and resolves or executes actions",[43,617,618],{},"Unresolved cases are sent to the backend as tickets (bidirectional sync)",[43,620,621],{},"Audit & Reporting: deflection rates, SLAs, and savings metrics in the dashboard",[28,623,625],{"id":624},"open-source-as-a-foundation-not-a-marketing-label","Open Source as a Foundation — Not a Marketing Label",[11,627,628,629,632,633,637,638,641,642,230],{},"OTAI Desk is built on the ",[15,630,631],{},"Open Ticket AI Runtime"," — the same open-source project listed in the ",[105,634,636],{"href":635},"\u002Fpackages\u002Fopen-ticket-ai-runtime","Open ITSM Hub"," as an automation engine for Znuny, OTOBO, and Zammad. The runtime is available under ",[15,639,640],{},"LGPL-2.1"," and runs via Docker on standard CPU hardware, ",[15,643,644],{},"without requiring a GPU",[11,646,647,648,651],{},"This sets OTAI Desk apart from generic SaaS AI helpdesks: the model and inference remain under your control. According to Open Ticket AI, training uses only ",[15,649,650],{},"configuration metadata"," — no ticket bodies or customer data in the cloud.",[28,653,655],{"id":654},"who-benefits-most-from-evaluating-it","Who Benefits Most from Evaluating It?",[40,657,658,664,674,683],{},[43,659,660,663],{},[15,661,662],{},"Regulated industries"," (healthcare, finance, government) with strict data protection requirements",[43,665,666,669,670,673],{},[15,667,668],{},"Mid-sized companies"," seeking AI benefits while taking ",[15,671,672],{},"works councils and compliance"," seriously",[43,675,676,679,680],{},[15,677,678],{},"Existing customers"," of Zammad, Znuny, or OTOBO looking to offload L1 support ",[15,681,682],{},"without changing systems",[43,684,685,686,689],{},"Teams operating ",[15,687,688],{},"air-gapped"," or fully isolated environments",[28,691,693],{"id":692},"classification-in-the-open-itsm-hub","Classification in the Open ITSM Hub",[11,695,696,697,701,702,18,705,22,709,230],{},"OTAI Desk is now listed in our ",[105,698,700],{"href":699},"\u002Fsystems\u002Fotai-desk","ticketing system directory"," alongside established platforms such as ",[105,703,66],{"href":704},"\u002Fsystems\u002Fzammad",[105,706,708],{"href":707},"\u002Fsystems\u002Fznuny","Znuny",[105,710,712],{"href":711},"\u002Fsystems\u002Fotobo","OTOBO",[11,714,715,716,719,720,230],{},"It fills a specific gap: a ",[15,717,718],{},"modern, AI-native helpdesk"," that does not stem from the Perl\u002FRuby tradition of classic OTRS forks, but rather from the Python\u002FOpen Ticket AI ecosystem — while still ",[15,721,722],{},"coexisting with existing systems",[398,724],{},[28,726,728],{"id":727},"further-reading","Further Reading",[40,730,731,737,743,749,756,761],{},[43,732,733],{},[105,734,736],{"href":460,"rel":735},[109],"OTAI Desk — Product Page",[43,738,739],{},[105,740,742],{"href":603,"rel":741},[109],"How OTAI Desk Works (Architecture)",[43,744,745],{},[105,746,748],{"href":298,"rel":747},[109],"Open Ticket AI Runtime on GitHub",[43,750,751],{},[105,752,755],{"href":753,"rel":754},"https:\u002F\u002Fopenticketai.com\u002Fen\u002Fdocs\u002F",[109],"Open Ticket AI Documentation",[43,757,758],{},[105,759,760],{"href":635},"Open Ticket AI Runtime in the Package Directory",[43,762,763],{},[105,764,765],{"href":438},"AI in Open Source Helpdesks: APIs, Automation Layers, and Data Protection",[398,767],{},[11,769,770],{},[771,772,773,774,230],"em",{},"This article is a neutral classification within the Open ITSM Hub. For binding product and pricing information, please visit ",[105,775,559],{"href":460,"rel":776},[109],{"title":419,"searchDepth":420,"depth":420,"links":778},[779,780,784,785,786,787],{"id":480,"depth":420,"text":481},{"id":571,"depth":420,"text":572,"children":781},[782,783],{"id":578,"depth":426,"text":579},{"id":589,"depth":426,"text":590},{"id":624,"depth":420,"text":625},{"id":654,"depth":420,"text":655},{"id":692,"depth":420,"text":693},{"id":727,"depth":420,"text":728},"2026-06-27","OTAI Desk is a modern, AI-powered ticketing system built on open source: local LLMs, RAG deflection, GDPR-compliant — and optionally acting as a front layer before Zammad, Znuny, or Jira.",{"language":791},"en","\u002Fblog\u002Fotai-desk-ki-first-helpdesk",{"title":444,"description":789},"blog\u002Fotai-desk-ki-first-helpdesk","9d6Nl9UdbwueClNTeM6YH5Aoq7w9hkmjm92LFYx-x5I",{"id":797,"title":798,"body":799,"date":1033,"description":1034,"draft":434,"extension":435,"meta":1035,"navigation":437,"path":1036,"seo":1037,"stem":1038,"__hash__":1039},"blogEn\u002Fblog\u002Fotobo-11-1-ki-kurzuberblick.md","OTOBO 11.1 & AI: Brief Overview for IT Teams",{"type":8,"value":800,"toc":1027},[801,804,818,822,891,895,913,916,920,946,970,972,976,987,1012],[448,802,798],{"id":803},"otobo-111-ai-brief-overview-for-it-teams",[11,805,806,809,810,813,814,817],{},[15,807,808],{},"OTOBO 11.1"," (in beta since June 2026) bundles many previous add-on packages into the core and lays the foundation for ",[15,811,812],{},"native AI features"," under the name ",[15,815,816],{},"Roboto",". For admins evaluating OTOBO or planning an upgrade, the main changes are: fewer extra packages, stronger Elasticsearch integration, and a clear AI path with a focus on data sovereignty.",[28,819,821],{"id":820},"key-new-features-at-a-glance","Key New Features at a Glance",[483,823,824,837],{},[486,825,826],{},[489,827,828,831,834],{},[492,829,830],{},"Area",[492,832,833],{},"What's New",[492,835,836],{},"Relevance for Admins",[499,838,839,852,865,878],{},[489,840,841,846,849],{},[504,842,843],{},[15,844,845],{},"Ticket Handling",[504,847,848],{},"Extended Elasticsearch syntax, similar tickets widget, edit\u002Fresolve\u002Fpin articles in core",[504,850,851],{},"Less manual searching, faster escalation",[489,853,854,859,862],{},[504,855,856],{},[15,857,858],{},"Process Management",[504,860,861],{},"Namespaces, global vs. local, extended transition logic",[504,863,864],{},"Complex workflows are easier to maintain",[489,866,867,872,875],{},[504,868,869],{},[15,870,871],{},"Integration",[504,873,874],{},"OAuth token management, OpenID Connect SSO, multipart\u002Fform-data for web services",[504,876,877],{},"JIRA\u002FOpenProject integration without workarounds",[489,879,880,885,888],{},[504,881,882],{},[15,883,884],{},"AI (Roboto)",[504,886,887],{},"Suggested responses from local vector database, AI dashboard, Ollama, or hosted German server",[504,889,890],{},"On-premise AI without US cloud dependency",[28,892,894],{"id":893},"ai-roboto-instead-of-saas-add-on","AI: Roboto Instead of SaaS Add-on",[11,896,897,898,900,901,904,905,908,909,912],{},"Rother OSS positions ",[15,899,816],{}," as a native OTOBO add-on: tickets, FAQs, and documentation are indexed in a ",[15,902,903],{},"ChromaDB vector database",". Agents receive drafted responses directly inside the ticket — optionally via ",[15,906,907],{},"Ollama on-premise"," or a ",[15,910,911],{},"GDPR-compliant server in Germany"," (beta).",[11,914,915],{},"This is what sets OTOBO apart from purely cloud-based AI helpdesks: your infrastructure remains under your control.",[28,917,919],{"id":918},"upgrade-notes-brief","Upgrade Notes (Brief)",[40,921,922,929,935],{},[43,923,924,925,928],{},"The ",[15,926,927],{},"MailAccountOAuth2"," mechanism has been moved into the core — check this during the upgrade.",[43,930,931,932,230],{},"Docker installations partially switch from Redis to the ",[15,933,934],{},"file system cache",[43,936,937,938,941,942,945],{},"OTOBO and ",[15,939,940],{},"OTOBO Docker"," have ",[15,943,944],{},"independent release cycles"," starting from version 11.1.",[11,947,948,949,954,955,954,960,954,965],{},"Details and breaking changes: ",[105,950,953],{"href":951,"rel":952},"https:\u002F\u002Fgithub.com\u002FRotherOSS\u002Fotobo",[109],"RotherOSS\u002Fotobo on GitHub"," · ",[105,956,959],{"href":957,"rel":958},"https:\u002F\u002Fgithub.com\u002FRotherOSS\u002Fotobo\u002Fblob\u002Frel-11_1\u002FCHANGES.md",[109],"Changelog rel-11_1",[105,961,964],{"href":962,"rel":963},"https:\u002F\u002Fgithub.com\u002FRotherOSS\u002Fotobo\u002Fmilestone\u002F44",[109],"Milestone 11.1",[105,966,969],{"href":967,"rel":968},"https:\u002F\u002Fotobo-docs.softoft.de\u002Fde\u002Fother\u002Fotobo-version-11\u002F",[109],"OTOBO 11 Guide (softoft Community Docs)",[398,971],{},[28,973,975],{"id":974},"deep-dive-not-here-but-on-softoftde","Deep Dive — Not Here, But on softoft.de",[11,977,978,979,982,983,986],{},"You can find the ",[15,980,981],{},"detailed article"," on OTOBO 11.1, the AI roadmap, and practical upgrade insights on ",[15,984,985],{},"softoft.de"," — check out the deep dive there:",[40,988,989,998,1005],{},[43,990,991],{},[15,992,993],{},[105,994,997],{"href":995,"rel":996},"https:\u002F\u002Fsoftoft.de\u002Fblog\u002Fotobo-11-1\u002F",[109],"OTOBO 11.1 & AI — Detailed Article on softoft.de",[43,999,1000],{},[105,1001,1004],{"href":1002,"rel":1003},"https:\u002F\u002Fotobo-docs.softoft.de\u002Fde\u002Fother\u002Ftechnology\u002Fotobo-ki\u002F",[109],"OTOBO AI & Automation (Community Guide)",[43,1006,1007],{},[105,1008,1011],{"href":1009,"rel":1010},"https:\u002F\u002Fotobo-docs.softoft.de\u002Fde\u002Fother\u002Fotobo-assistant\u002F",[109],"OTOBO AI Assistant — Custom GPT for OTOBO & Znuny",[11,1013,1014,1017,1018,1023,1024],{},[15,1015,1016],{},"Advanced AI automation"," (classification, queue routing, custom models): ",[105,1019,1022],{"href":1020,"rel":1021},"https:\u002F\u002Fwww.openticketai.com\u002F",[109],"OpenTicketAI"," · matching packages in the ",[105,1025,1026],{"href":386},"OTOBO Directory",{"title":419,"searchDepth":420,"depth":420,"links":1028},[1029,1030,1031,1032],{"id":820,"depth":420,"text":821},{"id":893,"depth":420,"text":894},{"id":918,"depth":420,"text":919},{"id":974,"depth":420,"text":975},"2026-07-05","Neutral overview of OTOBO 11.1 — ticket handling, process management, and native AI (Roboto). Detailed analysis on softoft.de.",{"language":791},"\u002Fblog\u002Fotobo-11-1-ki-kurzuberblick",{"title":798,"description":1034},"blog\u002Fotobo-11-1-ki-kurzuberblick","Bd1FdYvurADnxv9nofFeXeYbaK8pu11HyBZ97Ps-TQs",{"id":1041,"title":1042,"body":1043,"date":2190,"description":2191,"draft":434,"extension":435,"meta":2192,"navigation":437,"path":2193,"seo":2194,"stem":2195,"__hash__":2196},"blogEn\u002Fblog\u002Fotobo-docker-sicherheit-performance-compose.md","OTOBO Docker: More Secure and Performant with Hardened Docker Compose",{"type":8,"value":1044,"toc":2160},[1045,1048,1061,1068,1070,1074,1180,1192,1194,1198,1206,1217,1265,1271,1275,1286,1295,1300,1395,1402,1404,1408,1412,1454,1461,1464,1467,1493,1497,1500,1544,1548,1567,1569,1573,1577,1606,1610,1625,1629,1649,1653,1660,1662,1666,1764,1770,1772,1776,1782,1805,1819,1824,1830,1838,1897,1901,1911,1913,1917,2033,2043,2045,2049,2056,2100,2102,2106,2113,2127,2134,2136,2138,2156],[448,1046,1042],{"id":1047},"otobo-docker-more-secure-and-performant-with-hardened-docker-compose",[11,1049,1050,1051,1056,1057,1060],{},"The official ",[105,1052,1055],{"href":1053,"rel":1054},"https:\u002F\u002Fgithub.com\u002FRotherOSS\u002Fotobo-docker",[109],"RotherOSS\u002Fotobo-docker"," stack gets OTOBO up and running quickly — web, MariaDB, Elasticsearch, Redis, and optionally Nginx in just minutes. For ",[15,1058,1059],{},"production environments",", \"it runs\" is often not enough: volume permissions, missing network isolation, root containers, and unpinned images are typical vulnerabilities that admins usually only discover under load or during a security audit.",[11,1062,1063,1064,1067],{},"This article summarizes how to ",[15,1065,1066],{},"secure and tune"," OTOBO Docker without bypassing the official image release cycle.",[398,1069],{},[28,1071,1073],{"id":1072},"initial-situation-what-the-standard-stack-does-well-and-where-it-falls-short","Initial Situation: What the Standard Stack Does Well — and Where It Falls Short",[483,1075,1076,1090],{},[486,1077,1078],{},[489,1079,1080,1084,1087],{},[492,1081,1083],{"align":1082},"left","Aspect",[492,1085,1086],{"align":1082},"Official Stack",[492,1088,1089],{"align":1082},"Typical Production Gap",[499,1091,1092,1113,1126,1139,1152,1165],{},[489,1093,1094,1099,1106],{},[504,1095,1096],{"align":1082},[15,1097,1098],{},"Installation",[504,1100,1101,1102,1105],{"align":1082},"Proven Compose snippets, ",[180,1103,1104],{},".env"," samples",[504,1107,1108,1109,1112],{"align":1082},"Multiple override files in ",[180,1110,1111],{},"COMPOSE_FILE"," — hard to keep track of",[489,1114,1115,1120,1123],{},[504,1116,1117],{"align":1082},[15,1118,1119],{},"TLS",[504,1121,1122],{"align":1082},"Integrated nginx override",[504,1124,1125],{"align":1082},"Security headers, rate limits, and asset caching often minimal",[489,1127,1128,1133,1136],{},[504,1129,1130],{"align":1082},[15,1131,1132],{},"Network",[504,1134,1135],{"align":1082},"A single shared Docker network",[504,1137,1138],{"align":1082},"DB, Redis, and Elasticsearch theoretically reachable from the proxy",[489,1140,1141,1146,1149],{},[504,1142,1143],{"align":1082},[15,1144,1145],{},"Container Hardening",[504,1147,1148],{"align":1082},"Functionally designed",[504,1150,1151],{"align":1082},"Root UIDs, open volume modes (777), broad capabilities",[489,1153,1154,1159,1162],{},[504,1155,1156],{"align":1082},[15,1157,1158],{},"Performance",[504,1160,1161],{"align":1082},"Defaults",[504,1163,1164],{"align":1082},"MariaDB\u002FRedis\u002FES not tuned for ticket workloads",[489,1166,1167,1172,1177],{},[504,1168,1169],{"align":1082},[15,1170,1171],{},"Operations",[504,1173,1174],{"align":1082},[180,1175,1176],{},"scripts\u002Fupdate.sh",[504,1178,1179],{"align":1082},"No least-privilege model for technical admins",[11,1181,1182,1183,1187,1188,1191],{},"Starting with OTOBO 11.1, ",[105,1184,1186],{"href":1053,"rel":1185},[109],"OTOBO Core and OTOBO Docker have independent release cycles"," — a good time to intentionally own the ",[15,1189,1190],{},"infrastructure layer"," rather than just pulling images.",[398,1193],{},[28,1195,1197],{"id":1196},"two-sensible-approaches","Two Sensible Approaches",[77,1199,1201,1202,1205],{"id":1200},"_1-hardening-overlay-for-existing-otobo-docker-installations","1. Hardening Overlay (for Existing ",[180,1203,1204],{},"otobo-docker"," Installations)",[11,1207,1208,1209,1212,1213,1216],{},"If you are already using the official stack, you can retrofit a ",[15,1210,1211],{},"Compose override"," plus a ",[15,1214,1215],{},"host script"," without losing the upstream workflow:",[40,1218,1219,1225,1235,1248],{},[43,1220,1221,1224],{},[15,1222,1223],{},"Non-root UIDs"," for web, daemon, db, redis, and Elasticsearch",[43,1226,1227,1230,1231,1234],{},[15,1228,1229],{},"Config bind mount"," to ",[180,1232,1233],{},"\u002Fopt\u002Fotobo-config\u002F"," (read-only in the container)",[43,1236,1237,1240,1241,18,1244,1247],{},[15,1238,1239],{},"Volume permissions"," changed from 777 to service-specific owners (e.g., ",[180,1242,1243],{},"1000:1000",[180,1245,1246],{},"999:999",")",[43,1249,1250,1253,1254,1257,1258,18,1261,1264],{},[15,1251,1252],{},"Least-privilege sudo"," for the ",[180,1255,1256],{},"otobo-admin"," group (only ",[180,1259,1260],{},"docker ps\u002Flogs",[180,1262,1263],{},"sudoedit"," on config, no root shell)",[11,1266,1267,1268,1270],{},"The overlay is appended to ",[180,1269,1111],{}," and applied idempotently via script — including a backup of the Docker volumes before restarting.",[77,1272,1274],{"id":1273},"_2-project-owned-compose-stack-greenfield-controlled-upgrades","2. Project-Owned Compose Stack (Greenfield \u002F Controlled Upgrades)",[11,1276,1277,1278,1281,1282,1285],{},"For new deployments, a ",[15,1279,1280],{},"dedicated, streamlined Compose stack"," under ",[180,1283,1284],{},"docker\u002F"," is worth setting up:",[1287,1288,1293],"pre",{"className":1289,"code":1291,"language":1292},[1290],"language-text","docker-compose.yml          # Base topology (db, redis, elastic, web, daemon)\ndocker-compose.dev.yml      # HTTP on :8080, DB localhost only\ndocker-compose.prod.yml     # Nginx TLS proxy, no direct host ports\nconfig\u002Fmariadb\u002Fotobo.cnf    # InnoDB tuning (utf8mb4, buffer pool)\nconfig\u002Fredis\u002Fredis.conf     # maxmemory + LRU eviction\nconfig\u002Fnginx\u002F               # TLS, security headers, static cache, rate limits\n","text",[180,1294,1291],{"__ignoreMap":419},[11,1296,1297],{},[15,1298,1299],{},"Design Principles:",[483,1301,1302,1312],{},[486,1303,1304],{},[489,1305,1306,1309],{},[492,1307,1308],{"align":1082},"Principle",[492,1310,1311],{"align":1082},"Implementation",[499,1313,1314,1328,1342,1357,1376,1387],{},[489,1315,1316,1319],{},[504,1317,1318],{"align":1082},"Reproducibility",[504,1320,1321,1322,1324,1325],{"align":1082},"Image tags pinned in ",[180,1323,1104],{},"; upgrade = tag bump + ",[180,1326,1327],{},"scripts\u002Fupgrade.sh",[489,1329,1330,1333],{},[504,1331,1332],{"align":1082},"Defense in Depth",[504,1334,1335,18,1338,1341],{"align":1082},[180,1336,1337],{},"cap_drop: ALL",[180,1339,1340],{},"no-new-privileges",", non-root where possible",[489,1343,1344,1347],{},[504,1345,1346],{"align":1082},"Network Segmentation",[504,1348,1349,1352,1353,1356],{"align":1082},[180,1350,1351],{},"frontend"," (nginx ↔ web) and ",[180,1354,1355],{},"backend"," (datastores) — DB\u002FRedis\u002FES never exposed to the proxy",[489,1358,1359,1361],{},[504,1360,1158],{"align":1082},[504,1362,1363,1364,1367,1368,1371,1372,1375],{"align":1082},"MariaDB ",[180,1365,1366],{},"innodb_buffer_pool_size",", Redis ",[180,1369,1370],{},"maxmemory",", ES ",[180,1373,1374],{},"ES_JAVA_OPTS"," configured",[489,1377,1378,1381],{},[504,1379,1380],{"align":1082},"Observability",[504,1382,1383,1384],{"align":1082},"Health checks with ",[180,1385,1386],{},"depends_on: condition: service_healthy",[489,1388,1389,1392],{},[504,1390,1391],{"align":1082},"Resource Governance",[504,1393,1394],{"align":1082},"CPU\u002Fmemory limits per service",[11,1396,1397,1398,1401],{},"In production, ",[15,1399,1400],{},"only nginx"," terminates TLS; the OTOBO web container stays internal on port 5000.",[398,1403],{},[28,1405,1407],{"id":1406},"security-in-detail","Security in Detail",[77,1409,1411],{"id":1410},"network-frontend-vs-backend","Network: Frontend vs. Backend",[1287,1413,1417],{"className":1414,"code":1415,"language":1416,"meta":419,"style":419},"language-yaml shiki shiki-themes one-dark-pro","networks:\n  frontend: # nginx ↔ web\n  backend: # web\u002Fdaemon ↔ db\u002Fredis\u002Felastic\n","yaml",[180,1418,1419,1432,1444],{"__ignoreMap":419},[1420,1421,1424,1428],"span",{"class":1422,"line":1423},"line",1,[1420,1425,1427],{"class":1426},"sVyAn","networks",[1420,1429,1431],{"class":1430},"sn6KH",":\n",[1420,1433,1434,1437,1440],{"class":1422,"line":420},[1420,1435,1436],{"class":1426},"  frontend",[1420,1438,1439],{"class":1430},": ",[1420,1441,1443],{"class":1442},"sV9Aq","# nginx ↔ web\n",[1420,1445,1446,1449,1451],{"class":1422,"line":426},[1420,1447,1448],{"class":1426},"  backend",[1420,1450,1439],{"class":1430},[1420,1452,1453],{"class":1442},"# web\u002Fdaemon ↔ db\u002Fredis\u002Felastic\n",[11,1455,1456,1457,1460],{},"The database and cache are ",[15,1458,1459],{},"not"," on the same network as the reverse proxy. Even if the nginx container is compromised, direct access to MariaDB remains blocked.",[77,1462,1145],{"id":1463},"container-hardening",[11,1465,1466],{},"Every service starts with:",[40,1468,1469,1478,1483],{},[43,1470,1471,1474,1475],{},[180,1472,1473],{},"cap_drop: [ALL]"," plus minimally required ",[180,1476,1477],{},"cap_add",[43,1479,1480],{},[180,1481,1482],{},"security_opt: [no-new-privileges:true]",[43,1484,1485,1486,18,1489,1492],{},"Dedicated Linux users (",[180,1487,1488],{},"mysql:mysql",[180,1490,1491],{},"redis:redis",", UID mapping for OTOBO)",[77,1494,1496],{"id":1495},"nginx-as-the-single-entry-point","Nginx as the Single Entry Point",[11,1498,1499],{},"The production override sets up:",[40,1501,1502,1508,1514,1528,1534],{},[43,1503,1504,1507],{},[15,1505,1506],{},"HTTP → HTTPS"," redirect",[43,1509,1510,1513],{},[15,1511,1512],{},"TLS 1.2\u002F1.3"," (Mozilla Intermediate Profile)",[43,1515,1516,18,1519,18,1522,18,1525],{},[15,1517,1518],{},"HSTS",[180,1520,1521],{},"X-Frame-Options",[180,1523,1524],{},"X-Content-Type-Options",[180,1526,1527],{},"Referrer-Policy",[43,1529,1530,1533],{},[15,1531,1532],{},"Rate limiting"," and connection limits on dynamic requests",[43,1535,1536,1539,1540,1543],{},[15,1537,1538],{},"Proxy cache"," for ",[180,1541,1542],{},"\u002Fotobo-web\u002F"," assets (skins, JS, CSS) — offloads Perl\u002FPSGI",[77,1545,1547],{"id":1546},"config-outside-the-container","Config Outside the Container",[11,1549,1550,288,1553,1556,1557,1559,1560,1562,1563,1566],{},[180,1551,1552],{},"Config.pm",[180,1554,1555],{},"Kernel\u002FConfig\u002FFiles\u002F"," reside on the host under ",[180,1558,1233],{}," and are mounted read-only. Changes are made via ",[180,1561,1263],{}," — not via ",[180,1564,1565],{},"docker exec"," as root inside the running container.",[398,1568],{},[28,1570,1572],{"id":1571},"performance-in-detail","Performance in Detail",[77,1574,1576],{"id":1575},"mariadb","MariaDB",[40,1578,1579,1584,1590,1596],{},[43,1580,1581,1583],{},[180,1582,1366],{}," ≈ 70–80% of the DB container limit",[43,1585,1586,1589],{},[180,1587,1588],{},"innodb_log_file_size"," 512M (fewer checkpoint churns than the 256M minimum)",[43,1591,1592,1595],{},[180,1593,1594],{},"max_allowed_packet"," 128M for large ticket attachments",[43,1597,1598,1601,1602,1605],{},[180,1599,1600],{},"utf8mb4"," + ",[180,1603,1604],{},"dynamic"," row format (mandatory for OTOBO)",[77,1607,1609],{"id":1608},"redis","Redis",[40,1611,1612,1622],{},[43,1613,1614,1615,1618,1619],{},"Pure cache: ",[180,1616,1617],{},"maxmemory 512mb"," with ",[180,1620,1621],{},"allkeys-lru",[43,1623,1624],{},"No host port — internal backend network only",[77,1626,1628],{"id":1627},"elasticsearch","Elasticsearch",[40,1630,1631,1640,1643],{},[43,1632,1633,1636,1637],{},[180,1634,1635],{},"bootstrap.memory_lock: true"," + matching ",[180,1638,1639],{},"ulimits",[43,1641,1642],{},"JVM heap ≤ 50% of the container memory limit",[43,1644,1645,1646],{},"Host kernel: ",[180,1647,1648],{},"vm.max_map_count=262144",[77,1650,1652],{"id":1651},"nginx-static-cache","Nginx Static Cache",[11,1654,1655,1656,1659],{},"Static assets are cached at the proxy for seven days (",[180,1657,1658],{},"X-Cache-Status"," header for debugging). Dynamic ticket requests remain uncached but rate-limited.",[398,1661],{},[28,1663,1665],{"id":1664},"resource-budget-reference-values","Resource Budget (Reference Values)",[483,1667,1668,1684],{},[486,1669,1670],{},[489,1671,1672,1675,1678,1681],{},[492,1673,1674],{"align":1082},"Service",[492,1676,1677],{"align":1082},"CPU",[492,1679,1680],{"align":1082},"RAM",[492,1682,1683],{"align":1082},"Note",[499,1685,1686,1699,1710,1725,1739,1751],{},[489,1687,1688,1690,1693,1696],{},[504,1689,1576],{"align":1082},[504,1691,1692],{"align":1082},"2",[504,1694,1695],{"align":1082},"2 GB",[504,1697,1698],{"align":1082},"Keep buffer pool in sync",[489,1700,1701,1703,1705,1707],{},[504,1702,1628],{"align":1082},[504,1704,1692],{"align":1082},[504,1706,1695],{"align":1082},[504,1708,1709],{"align":1082},"Heap ≤ 1 GB",[489,1711,1712,1715,1717,1719],{},[504,1713,1714],{"align":1082},"Web (PSGI)",[504,1716,1692],{"align":1082},[504,1718,1695],{"align":1082},[504,1720,1721,1724],{"align":1082},[180,1722,1723],{},"OTOBO_WEB_OPTION=deployment"," in prod",[489,1726,1727,1730,1733,1736],{},[504,1728,1729],{"align":1082},"Daemon",[504,1731,1732],{"align":1082},"1",[504,1734,1735],{"align":1082},"1 GB",[504,1737,1738],{"align":1082},"GenericAgent, escalations",[489,1740,1741,1743,1745,1748],{},[504,1742,1609],{"align":1082},[504,1744,1732],{"align":1082},[504,1746,1747],{"align":1082},"768 MB",[504,1749,1750],{"align":1082},"maxmemory \u003C limit",[489,1752,1753,1756,1758,1761],{},[504,1754,1755],{"align":1082},"Nginx",[504,1757,1732],{"align":1082},[504,1759,1760],{"align":1082},"256 MB",[504,1762,1763],{"align":1082},"prod only",[11,1765,1766,1769],{},[15,1767,1768],{},"Minimum Host:"," 8 GB RAM, 2 vCPUs, 50 GB SSD. For productive teams, 16 GB is recommended.",[398,1771],{},[28,1773,1775],{"id":1774},"github-repo-yes-and-where","GitHub Repo: Yes — and Where?",[11,1777,1778,1781],{},[15,1779,1780],{},"Yes, a public repo makes sense"," — for three reasons:",[608,1783,1784,1790,1796],{},[43,1785,1786,1789],{},[15,1787,1788],{},"Reusability:"," Other OTOBO admins are looking for these exact patterns (hardening, nginx, tuning).",[43,1791,1792,1795],{},[15,1793,1794],{},"Transparency:"," Security-relevant infrastructure belongs in versioned, reviewable files — not just in client projects.",[43,1797,1798,1801,1802,1804],{},[15,1799,1800],{},"SEO & Community:"," Linking from the ",[105,1803,636],{"href":711}," and OTOBO documentation strengthens the ecosystem.",[11,1806,1807,1810,1811,1814,1815,1818],{},[15,1808,1809],{},"Suggested Repo Name:"," ",[180,1812,1813],{},"otobo-docker-production"," — as a ",[15,1816,1817],{},"community infrastructure",", not as a fork of RotherOSS.",[11,1820,1821],{},[15,1822,1823],{},"Structure:",[1287,1825,1828],{"className":1826,"code":1827,"language":1292,"meta":419},[1290],"otobo-docker-production\u002F\n├── overlay\u002F                 # For users of the official RotherOSS stack\n│   ├── otobo-override-hardening.yml\n│   ├── harden-docker.sh\n│   └── otobo-admin.sudoers\n├── compose\u002F                 # Complete project-owned stack\n│   ├── docker-compose.yml\n│   ├── docker-compose.dev.yml\n│   ├── docker-compose.prod.yml\n│   ├── config\u002F\n│   └── scripts\u002F\n└── README.md                # Decision guide: Overlay vs. Compose\n",[180,1829,1827],{"__ignoreMap":419},[77,1831,1833,1834,1837],{"id":1832},"what-does-not-belong-in-the-repo","What ",[15,1835,1836],{},"Does Not"," Belong in the Repo",[483,1839,1840,1850],{},[486,1841,1842],{},[489,1843,1844,1847],{},[492,1845,1846],{"align":1082},"Do Not Fork Upstream",[492,1848,1849],{"align":1082},"Instead",[499,1851,1852,1861,1872,1886],{},[489,1853,1854,1858],{},[504,1855,1856],{"align":1082},[180,1857,1055],{},[504,1859,1860],{"align":1082},"Reference override files, link upstream in README",[489,1862,1863,1869],{},[504,1864,1865,1868],{"align":1082},[180,1866,1867],{},"RotherOSS\u002Fotobo"," images",[504,1870,1871],{"align":1082},"Pin tags, pull images",[489,1873,1874,1880],{},[504,1875,1876,1877,1879],{"align":1082},"Client-specific ",[180,1878,1104],{}," secrets",[504,1881,1882,1885],{"align":1082},[180,1883,1884],{},".env.example"," with placeholders",[489,1887,1888,1891],{},[504,1889,1890],{"align":1082},"TLS private keys",[504,1892,1893,1896],{"align":1082},[180,1894,1895],{},".gitignore"," + cert generation script",[77,1898,1900],{"id":1899},"upstream-contributions","Upstream Contributions",[11,1902,1903,1904,1230,1907,1910],{},"Generic improvements (e.g., default volume permissions, documented non-root UIDs) can be submitted as ",[15,1905,1906],{},"issues or PRs",[105,1908,1055],{"href":1053,"rel":1909},[109]," — the overlay approach remains independent of merge speeds.",[398,1912],{},[28,1914,1916],{"id":1915},"quick-start-compose-stack","Quick Start (Compose Stack)",[1287,1918,1922],{"className":1919,"code":1920,"language":1921,"meta":419,"style":419},"language-bash shiki shiki-themes one-dark-pro","cd otobo-docker-production\u002Fcompose\ncp .env.example .env\n# Set OTOBO_DB_ROOT_PASSWORD\n\n# Development (HTTP)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d\n\n# Production (TLS)\n.\u002Fscripts\u002Fgen-selfsigned-cert.sh helpdesk.example.com   # or a real certificate\ndocker compose -f docker-compose.yml -f docker-compose.prod.yml up -d\n","bash",[180,1923,1924,1934,1946,1951,1957,1963,1990,1995,2001,2013],{"__ignoreMap":419},[1420,1925,1926,1930],{"class":1422,"line":1423},[1420,1927,1929],{"class":1928},"sjrmR","cd",[1420,1931,1933],{"class":1932},"subq3"," otobo-docker-production\u002Fcompose\n",[1420,1935,1936,1940,1943],{"class":1422,"line":420},[1420,1937,1939],{"class":1938},"sVbv2","cp",[1420,1941,1942],{"class":1932}," .env.example",[1420,1944,1945],{"class":1932}," .env\n",[1420,1947,1948],{"class":1422,"line":426},[1420,1949,1950],{"class":1442},"# Set OTOBO_DB_ROOT_PASSWORD\n",[1420,1952,1954],{"class":1422,"line":1953},4,[1420,1955,1956],{"emptyLinePlaceholder":437},"\n",[1420,1958,1960],{"class":1422,"line":1959},5,[1420,1961,1962],{"class":1442},"# Development (HTTP)\n",[1420,1964,1966,1969,1972,1976,1979,1981,1984,1987],{"class":1422,"line":1965},6,[1420,1967,1968],{"class":1938},"docker",[1420,1970,1971],{"class":1932}," compose",[1420,1973,1975],{"class":1974},"sVC51"," -f",[1420,1977,1978],{"class":1932}," docker-compose.yml",[1420,1980,1975],{"class":1974},[1420,1982,1983],{"class":1932}," docker-compose.dev.yml",[1420,1985,1986],{"class":1932}," up",[1420,1988,1989],{"class":1974}," -d\n",[1420,1991,1993],{"class":1422,"line":1992},7,[1420,1994,1956],{"emptyLinePlaceholder":437},[1420,1996,1998],{"class":1422,"line":1997},8,[1420,1999,2000],{"class":1442},"# Production (TLS)\n",[1420,2002,2004,2007,2010],{"class":1422,"line":2003},9,[1420,2005,2006],{"class":1938},".\u002Fscripts\u002Fgen-selfsigned-cert.sh",[1420,2008,2009],{"class":1932}," helpdesk.example.com",[1420,2011,2012],{"class":1442},"   # or a real certificate\n",[1420,2014,2016,2018,2020,2022,2024,2026,2029,2031],{"class":1422,"line":2015},10,[1420,2017,1968],{"class":1938},[1420,2019,1971],{"class":1932},[1420,2021,1975],{"class":1974},[1420,2023,1978],{"class":1932},[1420,2025,1975],{"class":1974},[1420,2027,2028],{"class":1932}," docker-compose.prod.yml",[1420,2030,1986],{"class":1932},[1420,2032,1989],{"class":1974},[11,2034,2035,2036,2039,2040,230],{},"Web installer: ",[180,2037,2038],{},"https:\u002F\u002F\u003Cfqdn>\u002Fotobo\u002Finstaller.pl"," — DB host = ",[180,2041,2042],{},"db",[398,2044],{},[28,2046,2048],{"id":2047},"quick-start-hardening-overlay","Quick Start (Hardening Overlay)",[11,2050,2051,2052,2055],{},"For existing ",[180,2053,2054],{},"\u002Fopt\u002Fotobo-docker"," installations:",[1287,2057,2059],{"className":1919,"code":2058,"language":1921,"meta":419,"style":419},"# After cloning the overlay\u002F folder\nbash harden-docker.sh              # Volume fix, override, sudoers, restart\nbash harden-docker.sh --dry-run    # Preview only\nbash harden-docker.sh --add-admin max.mustermann\n",[180,2060,2061,2066,2076,2088],{"__ignoreMap":419},[1420,2062,2063],{"class":1422,"line":1423},[1420,2064,2065],{"class":1442},"# After cloning the overlay\u002F folder\n",[1420,2067,2068,2070,2073],{"class":1422,"line":420},[1420,2069,1921],{"class":1938},[1420,2071,2072],{"class":1932}," harden-docker.sh",[1420,2074,2075],{"class":1442},"              # Volume fix, override, sudoers, restart\n",[1420,2077,2078,2080,2082,2085],{"class":1422,"line":426},[1420,2079,1921],{"class":1938},[1420,2081,2072],{"class":1932},[1420,2083,2084],{"class":1974}," --dry-run",[1420,2086,2087],{"class":1442},"    # Preview only\n",[1420,2089,2090,2092,2094,2097],{"class":1422,"line":1953},[1420,2091,1921],{"class":1938},[1420,2093,2072],{"class":1932},[1420,2095,2096],{"class":1974}," --add-admin",[1420,2098,2099],{"class":1932}," max.mustermann\n",[398,2101],{},[28,2103,2105],{"id":2104},"conclusion","Conclusion",[11,2107,2108,2109,2112],{},"The official OTOBO Docker stack is the right entry point. For ",[15,2110,2111],{},"production",", building an intentional layer on top pays off:",[40,2114,2115,2121],{},[43,2116,2117,2120],{},[15,2118,2119],{},"Overlay"," — fast, upstream-compatible, for existing installations",[43,2122,2123,2126],{},[15,2124,2125],{},"Dedicated Compose stack"," — maximum control, clear dev\u002Fprod separation, reproducible upgrades",[11,2128,2129,2130,2133],{},"Both are valuable open source contributions — and belong in a dedicated repo, not in ",[180,2131,2132],{},"open-itsm-hub"," (directory\u002Fcontent) and not as a fork of RotherOSS.",[398,2135],{},[28,2137,728],{"id":727},[40,2139,2140,2145,2151],{},[43,2141,2142],{},[105,2143,2144],{"href":711},"OTOBO in the Open ITSM Hub",[43,2146,2147],{},[105,2148,2150],{"href":1053,"rel":2149},[109],"Official otobo-docker Stack",[43,2152,2153],{},[105,2154,2155],{"href":1036},"OTOBO 11.1 Quick Overview",[2157,2158,2159],"style",{},"html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}",{"title":419,"searchDepth":420,"depth":420,"links":2161},[2162,2163,2168,2174,2180,2181,2186,2187,2188,2189],{"id":1072,"depth":420,"text":1073},{"id":1196,"depth":420,"text":1197,"children":2164},[2165,2167],{"id":1200,"depth":426,"text":2166},"1. Hardening Overlay (for Existing otobo-docker Installations)",{"id":1273,"depth":426,"text":1274},{"id":1406,"depth":420,"text":1407,"children":2169},[2170,2171,2172,2173],{"id":1410,"depth":426,"text":1411},{"id":1463,"depth":426,"text":1145},{"id":1495,"depth":426,"text":1496},{"id":1546,"depth":426,"text":1547},{"id":1571,"depth":420,"text":1572,"children":2175},[2176,2177,2178,2179],{"id":1575,"depth":426,"text":1576},{"id":1608,"depth":426,"text":1609},{"id":1627,"depth":426,"text":1628},{"id":1651,"depth":426,"text":1652},{"id":1664,"depth":420,"text":1665},{"id":1774,"depth":420,"text":1775,"children":2182},[2183,2185],{"id":1832,"depth":426,"text":2184},"What Does Not Belong in the Repo",{"id":1899,"depth":426,"text":1900},{"id":1915,"depth":420,"text":1916},{"id":2047,"depth":420,"text":2048},{"id":2104,"depth":420,"text":2105},{"id":727,"depth":420,"text":728},"2026-07-11","A practical guide to hardened OTOBO Docker Compose — network segmentation, non-root containers, nginx TLS proxy, resource limits, and a hardening overlay for the official RotherOSS stack.",{"language":791},"\u002Fblog\u002Fotobo-docker-sicherheit-performance-compose",{"title":1042,"description":2191},"blog\u002Fotobo-docker-sicherheit-performance-compose","ChOtO-DeWZG60UTpB-iCwj1bfYSR7ndNRyBINL_WlMI",{"id":2198,"title":2199,"body":2200,"date":2641,"description":2642,"draft":434,"extension":435,"meta":2643,"navigation":437,"path":2644,"seo":2645,"stem":2646,"__hash__":2647},"blogEn\u002Fblog\u002Fotrs-fork-plugin-oekosystem-opm-kompatibilitaet.md","Plugins Between Znuny, OTOBO & KIX: How Portable Is the .opm Ecosystem?",{"type":8,"value":2201,"toc":2627},[2202,2218,2227,2239,2241,2245,2253,2287,2290,2292,2296,2303,2361,2368,2370,2374,2378,2402,2406,2409,2413,2420,2424,2430,2439,2441,2445,2457,2459,2463,2470,2473,2501,2503,2507,2513,2518,2541,2546,2555,2560,2602,2604,2606,2612,2620,2622],[11,2203,2204,2205,18,2207,22,2209,2213,2214,2217],{},"The OTRS Community Edition lives on in three active forks—",[105,2206,708],{"href":707},[105,2208,712],{"href":711},[105,2210,2212],{"href":2211},"\u002Fsystems\u002Fkix","KIX",". Which one is right for your team depends on the feature set, AI strategy, and migration path. Other sources examine these questions in great detail (links at the end of this article). From the perspective of a ",[15,2215,2216],{},"vendor-neutral plugin directory",", however, a very different and often underestimated question arises:",[11,2219,2220],{},[15,2221,2222,2223,2226],{},"How portable is the shared ",[180,2224,2225],{},".opm"," ecosystem really—and can I simply take a package found for OTRS or Znuny and install it in OTOBO or KIX?",[11,2228,2229,2230,2234,2235,230],{},"Let's take a closer look. For the preliminary system selection, check out the separate, data-driven comparison ",[105,2231,2233],{"href":2232},"\u002Fcompare\u002Fotrs-forks-und-zammad","OTRS Forks and Zammad 2026"," as well as all ",[105,2236,2238],{"href":2237},"\u002Fcompare","direct system comparisons",[398,2240],{},[28,2242,2244],{"id":2243},"a-shared-root-a-shared-package-format","A Shared Root, a Shared Package Format",[11,2246,2247,2248,2252],{},"All three forks descend from the ",[105,2249,2251],{"href":2250},"\u002Fsystems\u002Fotrs-ce","OTRS Community Edition"," and therefore share the same basic building blocks for extensions:",[40,2254,2255,2263,2275,2281],{},[43,2256,2257,2262],{},[15,2258,2259,2261],{},[180,2260,2225],{}," as a package format","—an XML-based container format that bundles code, database changes, and configuration.",[43,2264,2265,2271,2272,230],{},[15,2266,2267,2270],{},[180,2268,2269],{},"SOPM"," as a manifest","—the source file of a package declares, among other things, its name, version, and—crucially—the ",[15,2273,2274],{},"compatible framework version",[43,2276,2277,2280],{},[15,2278,2279],{},"The Generic Interface","—the REST\u002FSOAP web service layer used to connect integrations.",[43,2282,2283,2286],{},[15,2284,2285],{},"Dynamic Fields, ACLs, process management","—conceptually familiar across all forks.",[11,2288,2289],{},"On paper, this looks like perfect interchangeability. In practice, however, portability is a spectrum—and that is precisely what makes a well-maintained directory valuable.",[398,2291],{},[28,2293,2295],{"id":2294},"package-sources-across-the-three-forks","Package Sources Across the Three Forks",[11,2297,2298,2299,606],{},"Each fork maintains its own distribution channel. We aggregate these sources in our ",[105,2300,2302],{"href":2301},"\u002Ftools\u002Fpackage-sources","package sources overview",[483,2304,2305,2318],{},[486,2306,2307],{},[489,2308,2309,2312,2315],{},[492,2310,2311],{"align":1082},"Fork",[492,2313,2314],{"align":1082},"Official Package Source",[492,2316,2317],{"align":1082},"Format",[499,2319,2320,2333,2346],{},[489,2321,2322,2324,2329],{},[504,2323,708],{"align":1082},[504,2325,2326],{"align":1082},[180,2327,2328],{},"addons.znuny.com",[504,2330,2331],{"align":1082},[180,2332,2225],{},[489,2334,2335,2337,2342],{},[504,2336,712],{"align":1082},[504,2338,2339],{"align":1082},[180,2340,2341],{},"ftp.otobo.org\u002Fpub\u002Fotobo\u002Fpackages\u002F",[504,2343,2344],{"align":1082},[180,2345,2225],{},[489,2347,2348,2351,2357],{},[504,2349,2350],{"align":1082},"KIX (Classic)",[504,2352,2353,2356],{"align":1082},[180,2354,2355],{},"kixdesk.com"," \u002F Repos",[504,2358,2359],{"align":1082},[180,2360,2225],{},[11,2362,2363,2364,2367],{},"Because the same file extension is used, it easily gives the impression that a single package runs everywhere. In reality, compatibility is tied to the respective ",[15,2365,2366],{},"framework version"," and internal API assumptions.",[398,2369],{},[28,2371,2373],{"id":2372},"portability-in-practice-four-pitfalls","Portability in Practice: Four Pitfalls",[77,2375,2377],{"id":2376},"_1-the-declared-framework-version","1. The Declared Framework Version",[11,2379,2380,2381,2383,2384,2387,2388,18,2391,18,2394,2397,2398,2401],{},"In the ",[180,2382,2269],{},"\u002F",[180,2385,2386],{},"OPM"," file, a package specifies which framework versions it is compatible with (e.g., ",[180,2389,2390],{},"6.x",[180,2392,2393],{},"10.x",[180,2395,2396],{},"11.x","). A package that only declares ",[180,2399,2400],{},"\u003CFramework>6.0.x\u003C\u002FFramework>"," cannot be easily installed on a modern OTOBO 11—the package manager will block it or issue a warning. Znuny packages close to the OTRS 6 baseline are therefore not automatically runnable in OTOBO 11.",[77,2403,2405],{"id":2404},"_2-diverging-internal-apis","2. Diverging Internal APIs",[11,2407,2408],{},"Even if the format is identical, OTOBO and KIX have modernized parts of their core. Calls to internal Perl modules, modified method signatures, or new caching layers (e.g., OTOBO relies on Redis\u002FElasticsearch) can cause a syntactically installable package to throw runtime errors.",[77,2410,2412],{"id":2411},"_3-template-and-frontend-differences","3. Template and Frontend Differences",[11,2414,2415,2416,2419],{},"Skins and frontend extensions are particularly sensitive. An agent skin built for the classic OTRS\u002FZnuny interface rarely fits OTOBO 1:1—and certainly not the reimagined frontend of ",[15,2417,2418],{},"KIX 18",", which is architecturally the furthest removed from the original.",[77,2421,2423],{"id":2422},"_4-dependencies-between-packages","4. Dependencies Between Packages",[11,2425,2426,2427,2429],{},"Many extensions require other ",[180,2428,2225],{}," packages or Perl modules. If a declared dependency is missing in the target system or only exists in an incompatible version, the installation fails, regardless of the fork.",[2431,2432,2433],"blockquote",{},[11,2434,2435,2438],{},[15,2436,2437],{},"Rule of thumb:"," The closer a package stays to pure business logic (Dynamic Fields, ACLs, Generic Interface mappings), the more portable it is. The deeper it digs into the frontend or internal core APIs, the more likely it needs a fork-specific variant.",[398,2440],{},[28,2442,2444],{"id":2443},"special-case-kix-18-same-heritage-different-world","Special Case KIX 18: Same Heritage, Different World",[11,2446,2447,2448,2450,2451,2453,2454,2456],{},"KIX maintains a classic Perl line and the newer ",[15,2449,2418],{}," in parallel. KIX 18 is a largely rewritten development featuring a REST API-centric architecture and its own frontend. For plugin portability, this means that classic ",[180,2452,2225],{}," add-ons from the OTRS world are the hardest to adopt directly here. In return, the API-first architecture opens up alternative integration paths—such as through external services rather than embedded ",[180,2455,2225],{}," modules.",[398,2458],{},[28,2460,2462],{"id":2461},"how-an-open-directory-helps","How an Open Directory Helps",[11,2464,2465,2466,2469],{},"This is precisely where the Open ITSM Hub comes in: Instead of merely listing packages, we capture ",[15,2467,2468],{},"compatibility metadata","—showing which package is intended for which system and versions. This allows you to see at a glance whether an extension fits your installation before testing it in a staging environment.",[11,2471,2472],{},"Browse by system:",[40,2474,2475,2480,2485,2490],{},[43,2476,2477],{},[105,2478,2479],{"href":378},"Znuny Plugins",[43,2481,2482],{},[105,2483,2484],{"href":386},"OTOBO Plugins",[43,2486,2487],{},[105,2488,2489],{"href":382},"Zammad Plugins",[43,2491,2492,2493,288,2497],{},"Complete overview of all ",[105,2494,2496],{"href":2495},"\u002Fitsm-plugins","ITSM Plugins",[105,2498,2500],{"href":2499},"\u002Fpackages","Packages",[398,2502],{},[28,2504,2506],{"id":2505},"digging-deeper-comparison-migration-ai","Digging Deeper: Comparison, Migration & AI",[11,2508,2509,2510,2512],{},"This article deliberately does ",[15,2511,1459],{}," answer the question \"Which fork is the best?\"—there are already excellent, detailed sources for that. If you are interested in selection, migration, or the AI perspective, continue reading at:",[11,2514,2515],{},[15,2516,2517],{},"Fork Selection & Feature\u002FAI Comparison:",[40,2519,2520,2527,2534],{},[43,2521,2522],{},[105,2523,2526],{"href":2524,"rel":2525},"https:\u002F\u002Fsoftoft.de\u002Fblog\u002Fotobo-znuny-zammad-ai-comparison",[109],"OTOBO vs. Znuny vs. Zammad – The AI Comparison (softoft.de)",[43,2528,2529],{},[105,2530,2533],{"href":2531,"rel":2532},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fdocs\u002Fblog\u002Fopen-source-ai-ticket-system-best-options-2026",[109],"Open-Source AI Ticket System: Best Options 2026 (openticketai.com)",[43,2535,2536],{},[105,2537,2540],{"href":2538,"rel":2539},"https:\u002F\u002Fsoftoft.de\u002Fblog\u002Fotobo-version-11",[109],"What OTOBO 11 Brings (softoft.de)",[11,2542,2543],{},[15,2544,2545],{},"Migration from OTRS:",[40,2547,2548],{},[43,2549,2550],{},[105,2551,2554],{"href":2552,"rel":2553},"https:\u002F\u002Fsoftoft.de\u002Fblog\u002Fotrs-migration-path-2026",[109],"OTRS Migration Path 2026 (softoft.de)",[11,2556,2557],{},[15,2558,2559],{},"AI Automation on These Systems:",[40,2561,2562,2578,2591],{},[43,2563,2564,2565,18,2569,22,2573,2577],{},"Solution pages for ",[105,2566,712],{"href":2567,"rel":2568},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fsolutions\u002Fotobo",[109],[105,2570,708],{"href":2571,"rel":2572},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fsolutions\u002Fznuny",[109],[105,2574,2212],{"href":2575,"rel":2576},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fsolutions\u002Fkixdesk",[109]," at Open Ticket AI",[43,2579,2580,2581,288,2586],{},"Practical guides: ",[105,2582,2585],{"href":2583,"rel":2584},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fdocs\u002Fblog\u002Fautomation-in-znuny-ticket-system",[109],"Automation in Znuny",[105,2587,2590],{"href":2588,"rel":2589},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fdocs\u002Fblog\u002Fotobo-ticket-automation-guide",[109],"OTOBO Ticket Automation",[43,2592,2593,2594,288,2598],{},"Python SDKs for ",[105,2595,712],{"href":2596,"rel":2597},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fdocs\u002Fotobo-python-sdk",[109],[105,2599,708],{"href":2600,"rel":2601},"https:\u002F\u002Fopenticketai.com\u002Fde\u002Fdocs\u002Fznuny-python-sdk",[109],[398,2603],{},[28,2605,2105],{"id":2104},[11,2607,2608,2609,2611],{},"The shared ",[180,2610,2225],{}," heritage of the OTRS forks is a blessing for the community, but it is no guarantee of blind interchangeability. The portability of an extension depends on the declared framework version, internal APIs, frontend interventions, and dependencies. Anyone using third-party packages should always verify declared compatibility and test in a staging environment.",[11,2613,2614,2615,2617,2618,230],{},"Which fork—Znuny, OTOBO, or KIX—is ultimately the right one is answered by the comparison and migration articles linked above. Our task is to make the surrounding ecosystem ",[15,2616,391],{},". You can find further classifications in the ",[105,2619,396],{"href":395},[398,2621],{},[11,2623,2624],{},[771,2625,2626],{},"This article is a neutral Open ITSM Hub summary on the plugin ecosystem. For binding compatibility and version specifications, please consult the official documentation of the respective project.",{"title":419,"searchDepth":420,"depth":420,"links":2628},[2629,2630,2631,2637,2638,2639,2640],{"id":2243,"depth":420,"text":2244},{"id":2294,"depth":420,"text":2295},{"id":2372,"depth":420,"text":2373,"children":2632},[2633,2634,2635,2636],{"id":2376,"depth":426,"text":2377},{"id":2404,"depth":426,"text":2405},{"id":2411,"depth":426,"text":2412},{"id":2422,"depth":426,"text":2423},{"id":2443,"depth":420,"text":2444},{"id":2461,"depth":420,"text":2462},{"id":2505,"depth":420,"text":2506},{"id":2104,"depth":420,"text":2105},"2026-06-21","From a directory perspective: how compatible are .opm packages and skins across the OTRS forks Znuny, OTOBO, and KIX, and what admins should look out for when installing third-party extensions.",{"language":791},"\u002Fblog\u002Fotrs-fork-plugin-oekosystem-opm-kompatibilitaet",{"title":2199,"description":2642},"blog\u002Fotrs-fork-plugin-oekosystem-opm-kompatibilitaet","YgDk7cpAhEa8CJT47X6GTyC69Iq2vo-GxVgXYvicnJU",{"id":2649,"title":2650,"body":2651,"date":4651,"description":4652,"draft":434,"extension":435,"meta":4653,"navigation":437,"path":4654,"seo":4655,"stem":4656,"__hash__":4657},"blogEn\u002Fblog\u002Fpython-automation-ticketsysteme-rest-api.md","Ticketing System Automation with Python: REST APIs, Libraries, and Practical Patterns",{"type":8,"value":2652,"toc":4630},[2653,2656,2666,2668,2672,2732,2734,2738,2742,2747,3034,3040,3046,3051,3054,3302,3307,3323,3325,3329,3336,3340,3639,3643,3646,3663,3667,3683,3685,3689,3693,3879,3883,4050,4054,4160,4162,4166,4169,4421,4423,4427,4430,4493,4495,4499,4581,4583,4587,4593,4613,4620,4622,4627],[448,2654,2650],{"id":2655},"ticketing-system-automation-with-python-rest-apis-libraries-and-practical-patterns",[11,2657,2658,2659,18,2661,22,2663,2665],{},"Python is the lingua franca of system automation, and open-source ticketing systems like ",[15,2660,66],{},[15,2662,712],{},[15,2664,708],{}," (an OTRS fork) offer a wide range of integration options. This article breaks down available Python clients, official APIs, and proven patterns for recurring automation tasks.",[398,2667],{},[28,2669,2671],{"id":2670},"the-three-paths-to-python-integration","The Three Paths to Python Integration",[483,2673,2674,2687],{},[486,2675,2676],{},[489,2677,2678,2681,2684],{},[492,2679,2680],{},"Approach",[492,2682,2683],{},"When to Use",[492,2685,2686],{},"Complexity",[499,2688,2689,2702,2718],{},[489,2690,2691,2696,2699],{},[504,2692,2693],{},[15,2694,2695],{},"Official Python Client Library",[504,2697,2698],{},"Quick start, documented endpoints",[504,2700,2701],{},"Low",[489,2703,2704,2712,2715],{},[504,2705,2706],{},[15,2707,2708,2709],{},"Direct REST API with ",[180,2710,2711],{},"requests",[504,2713,2714],{},"Full control, custom endpoints, debugging",[504,2716,2717],{},"Medium",[489,2719,2720,2726,2729],{},[504,2721,2722,2725],{},[15,2723,2724],{},"Wrapper\u002FETL Frameworks"," (e.g., open-ticket-ai)",[504,2727,2728],{},"Multi-system automation, pipelines, RAG",[504,2730,2731],{},"High",[398,2733],{},[28,2735,2737],{"id":2736},"zammad-zammad-py-and-the-rest-api","Zammad: Zammad-Py and the REST API",[77,2739,2741],{"id":2740},"zammad-py-community-client","Zammad-Py (Community Client)",[11,2743,924,2744,2746],{},[180,2745,182],{}," library provides an object-oriented layer over the Zammad REST API:",[1287,2748,2752],{"className":2749,"code":2750,"language":2751,"meta":419,"style":419},"language-python shiki shiki-themes one-dark-pro","from zammad_py import ZammadAPI\n\nclient = ZammadAPI(\n    url=\"https:\u002F\u002Fhelpdesk.example.com\u002Fapi\u002Fv1\",\n    http_token=\"your_api_token\"\n)\n\n# Fetch tickets\nfor ticket in client.ticket.all():\n    print(f\"{ticket['number']}: {ticket['title']}\")\n\n# Create a ticket\nticket = client.ticket.create({\n    \"title\": \"Server Alert: CPU Load\",\n    \"group\": \"IT-Operations\",\n    \"customer\": \"monitoring@example.com\",\n    \"article\": {\n        \"subject\": \"Alert\",\n        \"body\": \"CPU usage exceeded 90% on server-01\",\n        \"type\": \"note\",\n        \"internal\": False\n    }\n})\n","python",[180,2753,2754,2769,2773,2787,2801,2811,2816,2820,2825,2845,2891,2896,2902,2918,2931,2944,2957,2966,2979,2998,3011,3022,3028],{"__ignoreMap":419},[1420,2755,2756,2760,2763,2766],{"class":1422,"line":1423},[1420,2757,2759],{"class":2758},"seHd6","from",[1420,2761,2762],{"class":1430}," zammad_py ",[1420,2764,2765],{"class":2758},"import",[1420,2767,2768],{"class":1430}," ZammadAPI\n",[1420,2770,2771],{"class":1422,"line":420},[1420,2772,1956],{"emptyLinePlaceholder":437},[1420,2774,2775,2778,2781,2784],{"class":1422,"line":426},[1420,2776,2777],{"class":1430},"client ",[1420,2779,2780],{"class":1928},"=",[1420,2782,2783],{"class":1938}," ZammadAPI",[1420,2785,2786],{"class":1430},"(\n",[1420,2788,2789,2793,2795,2798],{"class":1422,"line":1953},[1420,2790,2792],{"class":2791},"s_ZVi","    url",[1420,2794,2780],{"class":1928},[1420,2796,2797],{"class":1932},"\"https:\u002F\u002Fhelpdesk.example.com\u002Fapi\u002Fv1\"",[1420,2799,2800],{"class":1430},",\n",[1420,2802,2803,2806,2808],{"class":1422,"line":1959},[1420,2804,2805],{"class":2791},"    http_token",[1420,2807,2780],{"class":1928},[1420,2809,2810],{"class":1932},"\"your_api_token\"\n",[1420,2812,2813],{"class":1422,"line":1965},[1420,2814,2815],{"class":1430},")\n",[1420,2817,2818],{"class":1422,"line":1992},[1420,2819,1956],{"emptyLinePlaceholder":437},[1420,2821,2822],{"class":1422,"line":1997},[1420,2823,2824],{"class":1442},"# Fetch tickets\n",[1420,2826,2827,2830,2833,2836,2839,2842],{"class":1422,"line":2003},[1420,2828,2829],{"class":2758},"for",[1420,2831,2832],{"class":1430}," ticket ",[1420,2834,2835],{"class":2758},"in",[1420,2837,2838],{"class":1430}," client.ticket.",[1420,2840,2841],{"class":1938},"all",[1420,2843,2844],{"class":1430},"():\n",[1420,2846,2847,2850,2853,2856,2859,2862,2865,2868,2871,2874,2876,2878,2880,2883,2885,2887,2889],{"class":1422,"line":2015},[1420,2848,2849],{"class":1928},"    print",[1420,2851,2852],{"class":1430},"(",[1420,2854,2855],{"class":2758},"f",[1420,2857,2858],{"class":1932},"\"",[1420,2860,2861],{"class":1974},"{",[1420,2863,2864],{"class":1430},"ticket[",[1420,2866,2867],{"class":1932},"'number'",[1420,2869,2870],{"class":1430},"]",[1420,2872,2873],{"class":1974},"}",[1420,2875,1439],{"class":1932},[1420,2877,2861],{"class":1974},[1420,2879,2864],{"class":1430},[1420,2881,2882],{"class":1932},"'title'",[1420,2884,2870],{"class":1430},[1420,2886,2873],{"class":1974},[1420,2888,2858],{"class":1932},[1420,2890,2815],{"class":1430},[1420,2892,2894],{"class":1422,"line":2893},11,[1420,2895,1956],{"emptyLinePlaceholder":437},[1420,2897,2899],{"class":1422,"line":2898},12,[1420,2900,2901],{"class":1442},"# Create a ticket\n",[1420,2903,2905,2908,2910,2912,2915],{"class":1422,"line":2904},13,[1420,2906,2907],{"class":1430},"ticket ",[1420,2909,2780],{"class":1928},[1420,2911,2838],{"class":1430},[1420,2913,2914],{"class":1938},"create",[1420,2916,2917],{"class":1430},"({\n",[1420,2919,2921,2924,2926,2929],{"class":1422,"line":2920},14,[1420,2922,2923],{"class":1932},"    \"title\"",[1420,2925,1439],{"class":1430},[1420,2927,2928],{"class":1932},"\"Server Alert: CPU Load\"",[1420,2930,2800],{"class":1430},[1420,2932,2934,2937,2939,2942],{"class":1422,"line":2933},15,[1420,2935,2936],{"class":1932},"    \"group\"",[1420,2938,1439],{"class":1430},[1420,2940,2941],{"class":1932},"\"IT-Operations\"",[1420,2943,2800],{"class":1430},[1420,2945,2947,2950,2952,2955],{"class":1422,"line":2946},16,[1420,2948,2949],{"class":1932},"    \"customer\"",[1420,2951,1439],{"class":1430},[1420,2953,2954],{"class":1932},"\"monitoring@example.com\"",[1420,2956,2800],{"class":1430},[1420,2958,2960,2963],{"class":1422,"line":2959},17,[1420,2961,2962],{"class":1932},"    \"article\"",[1420,2964,2965],{"class":1430},": {\n",[1420,2967,2969,2972,2974,2977],{"class":1422,"line":2968},18,[1420,2970,2971],{"class":1932},"        \"subject\"",[1420,2973,1439],{"class":1430},[1420,2975,2976],{"class":1932},"\"Alert\"",[1420,2978,2800],{"class":1430},[1420,2980,2982,2985,2987,2990,2993,2996],{"class":1422,"line":2981},19,[1420,2983,2984],{"class":1932},"        \"body\"",[1420,2986,1439],{"class":1430},[1420,2988,2989],{"class":1932},"\"CPU usage exceeded 90",[1420,2991,2992],{"class":1974},"% o",[1420,2994,2995],{"class":1932},"n server-01\"",[1420,2997,2800],{"class":1430},[1420,2999,3001,3004,3006,3009],{"class":1422,"line":3000},20,[1420,3002,3003],{"class":1932},"        \"type\"",[1420,3005,1439],{"class":1430},[1420,3007,3008],{"class":1932},"\"note\"",[1420,3010,2800],{"class":1430},[1420,3012,3014,3017,3019],{"class":1422,"line":3013},21,[1420,3015,3016],{"class":1932},"        \"internal\"",[1420,3018,1439],{"class":1430},[1420,3020,3021],{"class":1974},"False\n",[1420,3023,3025],{"class":1422,"line":3024},22,[1420,3026,3027],{"class":1430},"    }\n",[1420,3029,3031],{"class":1422,"line":3030},23,[1420,3032,3033],{"class":1430},"})\n",[11,3035,3036,3039],{},[15,3037,3038],{},"Pros:"," Typical CRUD operations abstracted, error handling included, active community.",[11,3041,3042,3045],{},[15,3043,3044],{},"Limitations:"," Not all API features (e.g., Core Workflows, Object Manager changes) are mapped.",[77,3047,2708,3049],{"id":3048},"direct-rest-api-with-requests",[180,3050,2711],{},[11,3052,3053],{},"For advanced scenarios (webhooks, tags, time accounting), direct API access is recommended:",[1287,3055,3057],{"className":2749,"code":3056,"language":2751,"meta":419,"style":419},"import requests\n\nheaders = {\n    \"Authorization\": \"Bearer your_token\",\n    \"Content-Type\": \"application\u002Fjson\"\n}\n\n# Search with query\nresponse = requests.get(\n    \"https:\u002F\u002Fhelpdesk.example.com\u002Fapi\u002Fv1\u002Ftickets\u002Fsearch\",\n    headers=headers,\n    params={\"query\": \"state:new AND priority:3\", \"limit\": 50}\n)\n\n# Bulk update multiple tickets\ntickets = response.json()[\"assets\"][\"Ticket\"]\nfor ticket_id in tickets:\n    requests.put(\n        f\"https:\u002F\u002Fhelpdesk.example.com\u002Fapi\u002Fv1\u002Ftickets\u002F{ticket_id}\",\n        headers=headers,\n        json={\"state\": \"open\", \"owner\": \"admin@example.com\"}\n    )\n",[180,3058,3059,3066,3070,3080,3092,3102,3107,3111,3116,3131,3138,3148,3177,3181,3185,3190,3218,3230,3240,3259,3268,3297],{"__ignoreMap":419},[1420,3060,3061,3063],{"class":1422,"line":1423},[1420,3062,2765],{"class":2758},[1420,3064,3065],{"class":1430}," requests\n",[1420,3067,3068],{"class":1422,"line":420},[1420,3069,1956],{"emptyLinePlaceholder":437},[1420,3071,3072,3075,3077],{"class":1422,"line":426},[1420,3073,3074],{"class":1430},"headers ",[1420,3076,2780],{"class":1928},[1420,3078,3079],{"class":1430}," {\n",[1420,3081,3082,3085,3087,3090],{"class":1422,"line":1953},[1420,3083,3084],{"class":1932},"    \"Authorization\"",[1420,3086,1439],{"class":1430},[1420,3088,3089],{"class":1932},"\"Bearer your_token\"",[1420,3091,2800],{"class":1430},[1420,3093,3094,3097,3099],{"class":1422,"line":1959},[1420,3095,3096],{"class":1932},"    \"Content-Type\"",[1420,3098,1439],{"class":1430},[1420,3100,3101],{"class":1932},"\"application\u002Fjson\"\n",[1420,3103,3104],{"class":1422,"line":1965},[1420,3105,3106],{"class":1430},"}\n",[1420,3108,3109],{"class":1422,"line":1992},[1420,3110,1956],{"emptyLinePlaceholder":437},[1420,3112,3113],{"class":1422,"line":1997},[1420,3114,3115],{"class":1442},"# Search with query\n",[1420,3117,3118,3121,3123,3126,3129],{"class":1422,"line":2003},[1420,3119,3120],{"class":1430},"response ",[1420,3122,2780],{"class":1928},[1420,3124,3125],{"class":1430}," requests.",[1420,3127,3128],{"class":1938},"get",[1420,3130,2786],{"class":1430},[1420,3132,3133,3136],{"class":1422,"line":2015},[1420,3134,3135],{"class":1932},"    \"https:\u002F\u002Fhelpdesk.example.com\u002Fapi\u002Fv1\u002Ftickets\u002Fsearch\"",[1420,3137,2800],{"class":1430},[1420,3139,3140,3143,3145],{"class":1422,"line":2893},[1420,3141,3142],{"class":2791},"    headers",[1420,3144,2780],{"class":1928},[1420,3146,3147],{"class":1430},"headers,\n",[1420,3149,3150,3153,3155,3157,3160,3162,3165,3167,3170,3172,3175],{"class":1422,"line":2898},[1420,3151,3152],{"class":2791},"    params",[1420,3154,2780],{"class":1928},[1420,3156,2861],{"class":1430},[1420,3158,3159],{"class":1932},"\"query\"",[1420,3161,1439],{"class":1430},[1420,3163,3164],{"class":1932},"\"state:new AND priority:3\"",[1420,3166,18],{"class":1430},[1420,3168,3169],{"class":1932},"\"limit\"",[1420,3171,1439],{"class":1430},[1420,3173,3174],{"class":1974},"50",[1420,3176,3106],{"class":1430},[1420,3178,3179],{"class":1422,"line":2904},[1420,3180,2815],{"class":1430},[1420,3182,3183],{"class":1422,"line":2920},[1420,3184,1956],{"emptyLinePlaceholder":437},[1420,3186,3187],{"class":1422,"line":2933},[1420,3188,3189],{"class":1442},"# Bulk update multiple tickets\n",[1420,3191,3192,3195,3197,3200,3203,3206,3209,3212,3215],{"class":1422,"line":2946},[1420,3193,3194],{"class":1430},"tickets ",[1420,3196,2780],{"class":1928},[1420,3198,3199],{"class":1430}," response.",[1420,3201,3202],{"class":1938},"json",[1420,3204,3205],{"class":1430},"()[",[1420,3207,3208],{"class":1932},"\"assets\"",[1420,3210,3211],{"class":1430},"][",[1420,3213,3214],{"class":1932},"\"Ticket\"",[1420,3216,3217],{"class":1430},"]\n",[1420,3219,3220,3222,3225,3227],{"class":1422,"line":2959},[1420,3221,2829],{"class":2758},[1420,3223,3224],{"class":1430}," ticket_id ",[1420,3226,2835],{"class":2758},[1420,3228,3229],{"class":1430}," tickets:\n",[1420,3231,3232,3235,3238],{"class":1422,"line":2968},[1420,3233,3234],{"class":1430},"    requests.",[1420,3236,3237],{"class":1938},"put",[1420,3239,2786],{"class":1430},[1420,3241,3242,3245,3248,3250,3253,3255,3257],{"class":1422,"line":2981},[1420,3243,3244],{"class":2758},"        f",[1420,3246,3247],{"class":1932},"\"https:\u002F\u002Fhelpdesk.example.com\u002Fapi\u002Fv1\u002Ftickets\u002F",[1420,3249,2861],{"class":1974},[1420,3251,3252],{"class":1430},"ticket_id",[1420,3254,2873],{"class":1974},[1420,3256,2858],{"class":1932},[1420,3258,2800],{"class":1430},[1420,3260,3261,3264,3266],{"class":1422,"line":3000},[1420,3262,3263],{"class":2791},"        headers",[1420,3265,2780],{"class":1928},[1420,3267,3147],{"class":1430},[1420,3269,3270,3273,3275,3277,3280,3282,3285,3287,3290,3292,3295],{"class":1422,"line":3013},[1420,3271,3272],{"class":2791},"        json",[1420,3274,2780],{"class":1928},[1420,3276,2861],{"class":1430},[1420,3278,3279],{"class":1932},"\"state\"",[1420,3281,1439],{"class":1430},[1420,3283,3284],{"class":1932},"\"open\"",[1420,3286,18],{"class":1430},[1420,3288,3289],{"class":1932},"\"owner\"",[1420,3291,1439],{"class":1430},[1420,3293,3294],{"class":1932},"\"admin@example.com\"",[1420,3296,3106],{"class":1430},[1420,3298,3299],{"class":1422,"line":3024},[1420,3300,3301],{"class":1430},"    )\n",[11,3303,3304],{},[15,3305,3306],{},"Resources:",[40,3308,3309,3316],{},[43,3310,3311],{},[105,3312,3315],{"href":3313,"rel":3314},"https:\u002F\u002Fpypi.org\u002Fproject\u002Fzammad-py\u002F",[109],"zammad_py on PyPI",[43,3317,3318],{},[105,3319,3322],{"href":3320,"rel":3321},"https:\u002F\u002Fdocs.zammad.com\u002Fen\u002Flatest\u002Fapi\u002Fintro.html",[109],"Zammad REST API Docs",[398,3324],{},[28,3326,3328],{"id":3327},"otobo-znuny-the-opm-interface-and-genericinterface","OTOBO & Znuny: The OPM Interface and GenericInterface",[11,3330,3331,3332,3335],{},"OTOBO and Znuny (as OTRS forks) use a similar architecture: the ",[15,3333,3334],{},"GenericInterface"," provides REST\u002FSOAP web services that can be accessed via Python.",[77,3337,3339],{"id":3338},"pattern-session-based-authentication","Pattern: Session-Based Authentication",[1287,3341,3343],{"className":2749,"code":3342,"language":2751,"meta":419,"style":419},"import requests\n\n# 1. Obtain SessionToken\nsession_resp = requests.post(\n    \"https:\u002F\u002Fotobo.example.com\u002Fotobo\u002Frpc.pl\",\n    json={\n        \"UserLogin\": \"api_user\",\n        \"Password\": \"api_pass\"\n    }\n)\nsession_token = session_resp.json()[\"SessionID\"]\n\n# 2. Create ticket\nticket_create = requests.post(\n    \"https:\u002F\u002Fotobo.example.com\u002Fotobo\u002Fnph-genericinterface.pl\u002FWebservice\u002FTicketConnectorREST\u002FTicket\",\n    headers={\"Authorization\": f\"Token {session_token}\"},\n    json={\n        \"Ticket\": {\n            \"Title\": \"API-Generated Alert\",\n            \"Queue\": \"IT-Support\",\n            \"State\": \"new\",\n            \"Priority\": \"3 normal\",\n            \"CustomerUser\": \"monitoring\"\n        },\n        \"Article\": {\n            \"Subject\": \"Automated Alert\",\n            \"Body\": \"Alert details...\",\n            \"ContentType\": \"text\u002Fplain; charset=utf8\"\n        }\n    }\n)\n",[180,3344,3345,3351,3355,3360,3374,3381,3391,3403,3413,3417,3421,3440,3444,3449,3462,3469,3499,3507,3514,3526,3538,3550,3562,3572,3578,3586,3599,3612,3623,3629,3634],{"__ignoreMap":419},[1420,3346,3347,3349],{"class":1422,"line":1423},[1420,3348,2765],{"class":2758},[1420,3350,3065],{"class":1430},[1420,3352,3353],{"class":1422,"line":420},[1420,3354,1956],{"emptyLinePlaceholder":437},[1420,3356,3357],{"class":1422,"line":426},[1420,3358,3359],{"class":1442},"# 1. Obtain SessionToken\n",[1420,3361,3362,3365,3367,3369,3372],{"class":1422,"line":1953},[1420,3363,3364],{"class":1430},"session_resp ",[1420,3366,2780],{"class":1928},[1420,3368,3125],{"class":1430},[1420,3370,3371],{"class":1938},"post",[1420,3373,2786],{"class":1430},[1420,3375,3376,3379],{"class":1422,"line":1959},[1420,3377,3378],{"class":1932},"    \"https:\u002F\u002Fotobo.example.com\u002Fotobo\u002Frpc.pl\"",[1420,3380,2800],{"class":1430},[1420,3382,3383,3386,3388],{"class":1422,"line":1965},[1420,3384,3385],{"class":2791},"    json",[1420,3387,2780],{"class":1928},[1420,3389,3390],{"class":1430},"{\n",[1420,3392,3393,3396,3398,3401],{"class":1422,"line":1992},[1420,3394,3395],{"class":1932},"        \"UserLogin\"",[1420,3397,1439],{"class":1430},[1420,3399,3400],{"class":1932},"\"api_user\"",[1420,3402,2800],{"class":1430},[1420,3404,3405,3408,3410],{"class":1422,"line":1997},[1420,3406,3407],{"class":1932},"        \"Password\"",[1420,3409,1439],{"class":1430},[1420,3411,3412],{"class":1932},"\"api_pass\"\n",[1420,3414,3415],{"class":1422,"line":2003},[1420,3416,3027],{"class":1430},[1420,3418,3419],{"class":1422,"line":2015},[1420,3420,2815],{"class":1430},[1420,3422,3423,3426,3428,3431,3433,3435,3438],{"class":1422,"line":2893},[1420,3424,3425],{"class":1430},"session_token ",[1420,3427,2780],{"class":1928},[1420,3429,3430],{"class":1430}," session_resp.",[1420,3432,3202],{"class":1938},[1420,3434,3205],{"class":1430},[1420,3436,3437],{"class":1932},"\"SessionID\"",[1420,3439,3217],{"class":1430},[1420,3441,3442],{"class":1422,"line":2898},[1420,3443,1956],{"emptyLinePlaceholder":437},[1420,3445,3446],{"class":1422,"line":2904},[1420,3447,3448],{"class":1442},"# 2. Create ticket\n",[1420,3450,3451,3454,3456,3458,3460],{"class":1422,"line":2920},[1420,3452,3453],{"class":1430},"ticket_create ",[1420,3455,2780],{"class":1928},[1420,3457,3125],{"class":1430},[1420,3459,3371],{"class":1938},[1420,3461,2786],{"class":1430},[1420,3463,3464,3467],{"class":1422,"line":2933},[1420,3465,3466],{"class":1932},"    \"https:\u002F\u002Fotobo.example.com\u002Fotobo\u002Fnph-genericinterface.pl\u002FWebservice\u002FTicketConnectorREST\u002FTicket\"",[1420,3468,2800],{"class":1430},[1420,3470,3471,3473,3475,3477,3480,3482,3484,3487,3489,3492,3494,3496],{"class":1422,"line":2946},[1420,3472,3142],{"class":2791},[1420,3474,2780],{"class":1928},[1420,3476,2861],{"class":1430},[1420,3478,3479],{"class":1932},"\"Authorization\"",[1420,3481,1439],{"class":1430},[1420,3483,2855],{"class":2758},[1420,3485,3486],{"class":1932},"\"Token ",[1420,3488,2861],{"class":1974},[1420,3490,3491],{"class":1430},"session_token",[1420,3493,2873],{"class":1974},[1420,3495,2858],{"class":1932},[1420,3497,3498],{"class":1430},"},\n",[1420,3500,3501,3503,3505],{"class":1422,"line":2959},[1420,3502,3385],{"class":2791},[1420,3504,2780],{"class":1928},[1420,3506,3390],{"class":1430},[1420,3508,3509,3512],{"class":1422,"line":2968},[1420,3510,3511],{"class":1932},"        \"Ticket\"",[1420,3513,2965],{"class":1430},[1420,3515,3516,3519,3521,3524],{"class":1422,"line":2981},[1420,3517,3518],{"class":1932},"            \"Title\"",[1420,3520,1439],{"class":1430},[1420,3522,3523],{"class":1932},"\"API-Generated Alert\"",[1420,3525,2800],{"class":1430},[1420,3527,3528,3531,3533,3536],{"class":1422,"line":3000},[1420,3529,3530],{"class":1932},"            \"Queue\"",[1420,3532,1439],{"class":1430},[1420,3534,3535],{"class":1932},"\"IT-Support\"",[1420,3537,2800],{"class":1430},[1420,3539,3540,3543,3545,3548],{"class":1422,"line":3013},[1420,3541,3542],{"class":1932},"            \"State\"",[1420,3544,1439],{"class":1430},[1420,3546,3547],{"class":1932},"\"new\"",[1420,3549,2800],{"class":1430},[1420,3551,3552,3555,3557,3560],{"class":1422,"line":3024},[1420,3553,3554],{"class":1932},"            \"Priority\"",[1420,3556,1439],{"class":1430},[1420,3558,3559],{"class":1932},"\"3 normal\"",[1420,3561,2800],{"class":1430},[1420,3563,3564,3567,3569],{"class":1422,"line":3030},[1420,3565,3566],{"class":1932},"            \"CustomerUser\"",[1420,3568,1439],{"class":1430},[1420,3570,3571],{"class":1932},"\"monitoring\"\n",[1420,3573,3575],{"class":1422,"line":3574},24,[1420,3576,3577],{"class":1430},"        },\n",[1420,3579,3581,3584],{"class":1422,"line":3580},25,[1420,3582,3583],{"class":1932},"        \"Article\"",[1420,3585,2965],{"class":1430},[1420,3587,3589,3592,3594,3597],{"class":1422,"line":3588},26,[1420,3590,3591],{"class":1932},"            \"Subject\"",[1420,3593,1439],{"class":1430},[1420,3595,3596],{"class":1932},"\"Automated Alert\"",[1420,3598,2800],{"class":1430},[1420,3600,3602,3605,3607,3610],{"class":1422,"line":3601},27,[1420,3603,3604],{"class":1932},"            \"Body\"",[1420,3606,1439],{"class":1430},[1420,3608,3609],{"class":1932},"\"Alert details...\"",[1420,3611,2800],{"class":1430},[1420,3613,3615,3618,3620],{"class":1422,"line":3614},28,[1420,3616,3617],{"class":1932},"            \"ContentType\"",[1420,3619,1439],{"class":1430},[1420,3621,3622],{"class":1932},"\"text\u002Fplain; charset=utf8\"\n",[1420,3624,3626],{"class":1422,"line":3625},29,[1420,3627,3628],{"class":1430},"        }\n",[1420,3630,3632],{"class":1422,"line":3631},30,[1420,3633,3027],{"class":1430},[1420,3635,3637],{"class":1422,"line":3636},31,[1420,3638,2815],{"class":1430},[77,3640,3642],{"id":3641},"python-wrappers-for-otoboznuny","Python Wrappers for OTOBO\u002FZnuny",[11,3644,3645],{},"Compared to Zammad, there are fewer mature Python clients. Recommended approaches:",[608,3647,3648,3657],{},[43,3649,3650,3653,3654,3656],{},[15,3651,3652],{},"Custom Thin Client:"," 100-200 lines of wrapper code around ",[180,3655,2711],{}," for project-specific endpoints",[43,3658,3659,3662],{},[15,3660,3661],{},"Open Ticket AI:"," Framework with a unified ticket model for OTOBO, Znuny, and Zammad",[11,3664,3665],{},[15,3666,3306],{},[40,3668,3669,3676],{},[43,3670,3671],{},[105,3672,3675],{"href":3673,"rel":3674},"https:\u002F\u002Fdoc.otobo.org\u002Fmanual\u002Fdeveloper\u002Fstable\u002Fen\u002Fcontent\u002Fwebservices.html",[109],"OTOBO GenericInterface Docs",[43,3677,3678],{},[105,3679,3682],{"href":3680,"rel":3681},"https:\u002F\u002Fdoc.znuny.org\u002Fmanual\u002Fdeveloper\u002F7.0\u002Fen\u002Fhtml\u002Fwebservices.html",[109],"Znuny Developer Docs",[398,3684],{},[28,3686,3688],{"id":3687},"practical-automation-patterns","Practical Automation Patterns",[77,3690,3692],{"id":3691},"pattern-1-monitoring-ticket-inbound","Pattern 1: Monitoring → Ticket (Inbound)",[1287,3694,3696],{"className":2749,"code":3695,"language":2751,"meta":419,"style":419},"def create_ticket_from_alert(alert_data: dict, system: str):\n    \"\"\"Unified interface for Zammad\u002FOTOBO\u002FZnuny\"\"\"\n\n    if system == \"zammad\":\n        return zammad_client.ticket.create({\n            \"title\": alert_data[\"summary\"],\n            \"group\": \"Monitoring\",\n            \"article\": {\"body\": alert_data[\"details\"]}\n        })\n    elif system in [\"otobo\", \"znuny\"]:\n        return otobo_session.post(\n            f\"\u002FTicketConnectorREST\u002FTicket\",\n            json=map_alert_to_otobo(alert_data)\n        )\n",[180,3697,3698,3730,3735,3739,3755,3767,3781,3793,3812,3817,3840,3851,3861,3874],{"__ignoreMap":419},[1420,3699,3700,3703,3706,3708,3712,3714,3717,3719,3722,3724,3727],{"class":1422,"line":1423},[1420,3701,3702],{"class":2758},"def",[1420,3704,3705],{"class":1938}," create_ticket_from_alert",[1420,3707,2852],{"class":1430},[1420,3709,3711],{"class":3710},"sb9H8","alert_data",[1420,3713,1439],{"class":1430},[1420,3715,3716],{"class":1928},"dict",[1420,3718,18],{"class":1430},[1420,3720,3721],{"class":3710},"system",[1420,3723,1439],{"class":1430},[1420,3725,3726],{"class":1928},"str",[1420,3728,3729],{"class":1430},"):\n",[1420,3731,3732],{"class":1422,"line":420},[1420,3733,3734],{"class":1932},"    \"\"\"Unified interface for Zammad\u002FOTOBO\u002FZnuny\"\"\"\n",[1420,3736,3737],{"class":1422,"line":426},[1420,3738,1956],{"emptyLinePlaceholder":437},[1420,3740,3741,3744,3747,3750,3753],{"class":1422,"line":1953},[1420,3742,3743],{"class":2758},"    if",[1420,3745,3746],{"class":1430}," system ",[1420,3748,3749],{"class":1928},"==",[1420,3751,3752],{"class":1932}," \"zammad\"",[1420,3754,1431],{"class":1430},[1420,3756,3757,3760,3763,3765],{"class":1422,"line":1959},[1420,3758,3759],{"class":2758},"        return",[1420,3761,3762],{"class":1430}," zammad_client.ticket.",[1420,3764,2914],{"class":1938},[1420,3766,2917],{"class":1430},[1420,3768,3769,3772,3775,3778],{"class":1422,"line":1965},[1420,3770,3771],{"class":1932},"            \"title\"",[1420,3773,3774],{"class":1430},": alert_data[",[1420,3776,3777],{"class":1932},"\"summary\"",[1420,3779,3780],{"class":1430},"],\n",[1420,3782,3783,3786,3788,3791],{"class":1422,"line":1992},[1420,3784,3785],{"class":1932},"            \"group\"",[1420,3787,1439],{"class":1430},[1420,3789,3790],{"class":1932},"\"Monitoring\"",[1420,3792,2800],{"class":1430},[1420,3794,3795,3798,3801,3804,3806,3809],{"class":1422,"line":1997},[1420,3796,3797],{"class":1932},"            \"article\"",[1420,3799,3800],{"class":1430},": {",[1420,3802,3803],{"class":1932},"\"body\"",[1420,3805,3774],{"class":1430},[1420,3807,3808],{"class":1932},"\"details\"",[1420,3810,3811],{"class":1430},"]}\n",[1420,3813,3814],{"class":1422,"line":2003},[1420,3815,3816],{"class":1430},"        })\n",[1420,3818,3819,3822,3824,3826,3829,3832,3834,3837],{"class":1422,"line":2015},[1420,3820,3821],{"class":2758},"    elif",[1420,3823,3746],{"class":1430},[1420,3825,2835],{"class":2758},[1420,3827,3828],{"class":1430}," [",[1420,3830,3831],{"class":1932},"\"otobo\"",[1420,3833,18],{"class":1430},[1420,3835,3836],{"class":1932},"\"znuny\"",[1420,3838,3839],{"class":1430},"]:\n",[1420,3841,3842,3844,3847,3849],{"class":1422,"line":2893},[1420,3843,3759],{"class":2758},[1420,3845,3846],{"class":1430}," otobo_session.",[1420,3848,3371],{"class":1938},[1420,3850,2786],{"class":1430},[1420,3852,3853,3856,3859],{"class":1422,"line":2898},[1420,3854,3855],{"class":2758},"            f",[1420,3857,3858],{"class":1932},"\"\u002FTicketConnectorREST\u002FTicket\"",[1420,3860,2800],{"class":1430},[1420,3862,3863,3866,3868,3871],{"class":1422,"line":2904},[1420,3864,3865],{"class":2791},"            json",[1420,3867,2780],{"class":1928},[1420,3869,3870],{"class":1938},"map_alert_to_otobo",[1420,3872,3873],{"class":1430},"(alert_data)\n",[1420,3875,3876],{"class":1422,"line":2920},[1420,3877,3878],{"class":1430},"        )\n",[77,3880,3882],{"id":3881},"pattern-2-ticket-escalation-outbound","Pattern 2: Ticket Escalation (Outbound)",[1287,3884,3886],{"className":2749,"code":3885,"language":2751,"meta":419,"style":419},"def escalate_stale_tickets(system_client, hours_threshold: int = 24):\n    \"\"\"Finds and escalates tickets without agent activity\"\"\"\n\n    stale_tickets = system_client.search(\n        query=f\"state:open AND last_contact_agent:[* TO now-{hours_threshold}h]\"\n    )\n\n    for ticket in stale_tickets:\n        system_client.update(ticket[\"id\"], {\n            \"priority\": \"high\",\n            \"tags\": [\"auto-escalated\"],\n            \"note\": f\"Automatically escalated after {hours_threshold}h of inactivity\"\n        })\n",[180,3887,3888,3918,3923,3927,3942,3963,3967,3971,3983,4000,4012,4025,4046],{"__ignoreMap":419},[1420,3889,3890,3892,3895,3897,3900,3902,3905,3907,3910,3913,3916],{"class":1422,"line":1423},[1420,3891,3702],{"class":2758},[1420,3893,3894],{"class":1938}," escalate_stale_tickets",[1420,3896,2852],{"class":1430},[1420,3898,3899],{"class":3710},"system_client",[1420,3901,18],{"class":1430},[1420,3903,3904],{"class":3710},"hours_threshold",[1420,3906,1439],{"class":1430},[1420,3908,3909],{"class":1928},"int",[1420,3911,3912],{"class":1928}," =",[1420,3914,3915],{"class":1974}," 24",[1420,3917,3729],{"class":1430},[1420,3919,3920],{"class":1422,"line":420},[1420,3921,3922],{"class":1932},"    \"\"\"Finds and escalates tickets without agent activity\"\"\"\n",[1420,3924,3925],{"class":1422,"line":426},[1420,3926,1956],{"emptyLinePlaceholder":437},[1420,3928,3929,3932,3934,3937,3940],{"class":1422,"line":1953},[1420,3930,3931],{"class":1430},"    stale_tickets ",[1420,3933,2780],{"class":1928},[1420,3935,3936],{"class":1430}," system_client.",[1420,3938,3939],{"class":1938},"search",[1420,3941,2786],{"class":1430},[1420,3943,3944,3947,3949,3951,3954,3956,3958,3960],{"class":1422,"line":1959},[1420,3945,3946],{"class":2791},"        query",[1420,3948,2780],{"class":1928},[1420,3950,2855],{"class":2758},[1420,3952,3953],{"class":1932},"\"state:open AND last_contact_agent:[* TO now-",[1420,3955,2861],{"class":1974},[1420,3957,3904],{"class":1430},[1420,3959,2873],{"class":1974},[1420,3961,3962],{"class":1932},"h]\"\n",[1420,3964,3965],{"class":1422,"line":1965},[1420,3966,3301],{"class":1430},[1420,3968,3969],{"class":1422,"line":1992},[1420,3970,1956],{"emptyLinePlaceholder":437},[1420,3972,3973,3976,3978,3980],{"class":1422,"line":1997},[1420,3974,3975],{"class":2758},"    for",[1420,3977,2832],{"class":1430},[1420,3979,2835],{"class":2758},[1420,3981,3982],{"class":1430}," stale_tickets:\n",[1420,3984,3985,3988,3991,3994,3997],{"class":1422,"line":2003},[1420,3986,3987],{"class":1430},"        system_client.",[1420,3989,3990],{"class":1938},"update",[1420,3992,3993],{"class":1430},"(ticket[",[1420,3995,3996],{"class":1932},"\"id\"",[1420,3998,3999],{"class":1430},"], {\n",[1420,4001,4002,4005,4007,4010],{"class":1422,"line":2015},[1420,4003,4004],{"class":1932},"            \"priority\"",[1420,4006,1439],{"class":1430},[1420,4008,4009],{"class":1932},"\"high\"",[1420,4011,2800],{"class":1430},[1420,4013,4014,4017,4020,4023],{"class":1422,"line":2893},[1420,4015,4016],{"class":1932},"            \"tags\"",[1420,4018,4019],{"class":1430},": [",[1420,4021,4022],{"class":1932},"\"auto-escalated\"",[1420,4024,3780],{"class":1430},[1420,4026,4027,4030,4032,4034,4037,4039,4041,4043],{"class":1422,"line":2898},[1420,4028,4029],{"class":1932},"            \"note\"",[1420,4031,1439],{"class":1430},[1420,4033,2855],{"class":2758},[1420,4035,4036],{"class":1932},"\"Automatically escalated after ",[1420,4038,2861],{"class":1974},[1420,4040,3904],{"class":1430},[1420,4042,2873],{"class":1974},[1420,4044,4045],{"class":1932},"h of inactivity\"\n",[1420,4047,4048],{"class":1422,"line":2904},[1420,4049,3816],{"class":1430},[77,4051,4053],{"id":4052},"pattern-3-data-migration-cross-system","Pattern 3: Data Migration (Cross-System)",[1287,4055,4057],{"className":2749,"code":4056,"language":2751,"meta":419,"style":419},"# Zammad → OTOBO Migration\nfor ticket in zammad_client.ticket.all():\n    mapped_ticket = {\n        \"Title\": ticket[\"title\"],\n        \"Queue\": map_queue(ticket[\"group\"]),\n        \"State\": map_state(ticket[\"state\"]),\n        \"CustomerUser\": ticket[\"customer\"]\n    }\n    otobo_client.ticket.create(mapped_ticket)\n",[180,4058,4059,4064,4078,4087,4100,4118,4134,4146,4150],{"__ignoreMap":419},[1420,4060,4061],{"class":1422,"line":1423},[1420,4062,4063],{"class":1442},"# Zammad → OTOBO Migration\n",[1420,4065,4066,4068,4070,4072,4074,4076],{"class":1422,"line":420},[1420,4067,2829],{"class":2758},[1420,4069,2832],{"class":1430},[1420,4071,2835],{"class":2758},[1420,4073,3762],{"class":1430},[1420,4075,2841],{"class":1938},[1420,4077,2844],{"class":1430},[1420,4079,4080,4083,4085],{"class":1422,"line":426},[1420,4081,4082],{"class":1430},"    mapped_ticket ",[1420,4084,2780],{"class":1928},[1420,4086,3079],{"class":1430},[1420,4088,4089,4092,4095,4098],{"class":1422,"line":1953},[1420,4090,4091],{"class":1932},"        \"Title\"",[1420,4093,4094],{"class":1430},": ticket[",[1420,4096,4097],{"class":1932},"\"title\"",[1420,4099,3780],{"class":1430},[1420,4101,4102,4105,4107,4110,4112,4115],{"class":1422,"line":1959},[1420,4103,4104],{"class":1932},"        \"Queue\"",[1420,4106,1439],{"class":1430},[1420,4108,4109],{"class":1938},"map_queue",[1420,4111,3993],{"class":1430},[1420,4113,4114],{"class":1932},"\"group\"",[1420,4116,4117],{"class":1430},"]),\n",[1420,4119,4120,4123,4125,4128,4130,4132],{"class":1422,"line":1965},[1420,4121,4122],{"class":1932},"        \"State\"",[1420,4124,1439],{"class":1430},[1420,4126,4127],{"class":1938},"map_state",[1420,4129,3993],{"class":1430},[1420,4131,3279],{"class":1932},[1420,4133,4117],{"class":1430},[1420,4135,4136,4139,4141,4144],{"class":1422,"line":1992},[1420,4137,4138],{"class":1932},"        \"CustomerUser\"",[1420,4140,4094],{"class":1430},[1420,4142,4143],{"class":1932},"\"customer\"",[1420,4145,3217],{"class":1430},[1420,4147,4148],{"class":1422,"line":1997},[1420,4149,3027],{"class":1430},[1420,4151,4152,4155,4157],{"class":1422,"line":2003},[1420,4153,4154],{"class":1430},"    otobo_client.ticket.",[1420,4156,2914],{"class":1938},[1420,4158,4159],{"class":1430},"(mapped_ticket)\n",[398,4161],{},[28,4163,4165],{"id":4164},"error-handling-and-resilience","Error Handling and Resilience",[11,4167,4168],{},"Production automation requires robust error handling:",[1287,4170,4172],{"className":2749,"code":4171,"language":2751,"meta":419,"style":419},"from tenacity import retry, stop_after_attempt, wait_exponential\nimport logging\n\n@retry(\n    stop=stop_after_attempt(3),\n    wait=wait_exponential(multiplier=1, min=4, max=10)\n)\ndef safe_api_call(func, *args, **kwargs):\n    try:\n        return func(*args, **kwargs)\n    except requests.exceptions.HTTPError as e:\n        if e.response.status_code == 429:  # Rate Limit\n            raise  # Trigger retry\n        elif e.response.status_code == 401:\n            logging.error(\"Authentication failed - check API token\")\n            raise\n        else:\n            logging.error(f\"API Error: {e}\")\n            raise\n",[180,4173,4174,4186,4193,4197,4204,4222,4264,4268,4294,4301,4311,4325,4344,4352,4366,4381,4386,4393,4417],{"__ignoreMap":419},[1420,4175,4176,4178,4181,4183],{"class":1422,"line":1423},[1420,4177,2759],{"class":2758},[1420,4179,4180],{"class":1430}," tenacity ",[1420,4182,2765],{"class":2758},[1420,4184,4185],{"class":1430}," retry, stop_after_attempt, wait_exponential\n",[1420,4187,4188,4190],{"class":1422,"line":420},[1420,4189,2765],{"class":2758},[1420,4191,4192],{"class":1430}," logging\n",[1420,4194,4195],{"class":1422,"line":426},[1420,4196,1956],{"emptyLinePlaceholder":437},[1420,4198,4199,4202],{"class":1422,"line":1953},[1420,4200,4201],{"class":1938},"@retry",[1420,4203,2786],{"class":1430},[1420,4205,4206,4209,4211,4214,4216,4219],{"class":1422,"line":1959},[1420,4207,4208],{"class":2791},"    stop",[1420,4210,2780],{"class":1928},[1420,4212,4213],{"class":1938},"stop_after_attempt",[1420,4215,2852],{"class":1430},[1420,4217,4218],{"class":1974},"3",[1420,4220,4221],{"class":1430},"),\n",[1420,4223,4224,4227,4229,4232,4234,4237,4239,4241,4244,4247,4249,4252,4254,4257,4259,4262],{"class":1422,"line":1965},[1420,4225,4226],{"class":2791},"    wait",[1420,4228,2780],{"class":1928},[1420,4230,4231],{"class":1938},"wait_exponential",[1420,4233,2852],{"class":1430},[1420,4235,4236],{"class":2791},"multiplier",[1420,4238,2780],{"class":1928},[1420,4240,1732],{"class":1974},[1420,4242,4243],{"class":1430},",",[1420,4245,4246],{"class":2791}," min",[1420,4248,2780],{"class":1928},[1420,4250,4251],{"class":1974},"4",[1420,4253,4243],{"class":1430},[1420,4255,4256],{"class":2791}," max",[1420,4258,2780],{"class":1928},[1420,4260,4261],{"class":1974},"10",[1420,4263,2815],{"class":1430},[1420,4265,4266],{"class":1422,"line":1992},[1420,4267,2815],{"class":1430},[1420,4269,4270,4272,4275,4277,4280,4283,4286,4289,4292],{"class":1422,"line":1997},[1420,4271,3702],{"class":2758},[1420,4273,4274],{"class":1938}," safe_api_call",[1420,4276,2852],{"class":1430},[1420,4278,4279],{"class":3710},"func",[1420,4281,4282],{"class":1430},", *",[1420,4284,4285],{"class":3710},"args",[1420,4287,4288],{"class":1430},", **",[1420,4290,4291],{"class":3710},"kwargs",[1420,4293,3729],{"class":1430},[1420,4295,4296,4299],{"class":1422,"line":2003},[1420,4297,4298],{"class":2758},"    try",[1420,4300,1431],{"class":1430},[1420,4302,4303,4305,4308],{"class":1422,"line":2015},[1420,4304,3759],{"class":2758},[1420,4306,4307],{"class":1938}," func",[1420,4309,4310],{"class":1430},"(*args, **kwargs)\n",[1420,4312,4313,4316,4319,4322],{"class":1422,"line":2893},[1420,4314,4315],{"class":2758},"    except",[1420,4317,4318],{"class":1430}," requests.exceptions.HTTPError ",[1420,4320,4321],{"class":2758},"as",[1420,4323,4324],{"class":1430}," e:\n",[1420,4326,4327,4330,4333,4335,4338,4341],{"class":1422,"line":2898},[1420,4328,4329],{"class":2758},"        if",[1420,4331,4332],{"class":1430}," e.response.status_code ",[1420,4334,3749],{"class":1928},[1420,4336,4337],{"class":1974}," 429",[1420,4339,4340],{"class":1430},":  ",[1420,4342,4343],{"class":1442},"# Rate Limit\n",[1420,4345,4346,4349],{"class":1422,"line":2904},[1420,4347,4348],{"class":2758},"            raise",[1420,4350,4351],{"class":1442},"  # Trigger retry\n",[1420,4353,4354,4357,4359,4361,4364],{"class":1422,"line":2920},[1420,4355,4356],{"class":2758},"        elif",[1420,4358,4332],{"class":1430},[1420,4360,3749],{"class":1928},[1420,4362,4363],{"class":1974}," 401",[1420,4365,1431],{"class":1430},[1420,4367,4368,4371,4374,4376,4379],{"class":1422,"line":2933},[1420,4369,4370],{"class":1430},"            logging.",[1420,4372,4373],{"class":1938},"error",[1420,4375,2852],{"class":1430},[1420,4377,4378],{"class":1932},"\"Authentication failed - check API token\"",[1420,4380,2815],{"class":1430},[1420,4382,4383],{"class":1422,"line":2946},[1420,4384,4385],{"class":2758},"            raise\n",[1420,4387,4388,4391],{"class":1422,"line":2959},[1420,4389,4390],{"class":2758},"        else",[1420,4392,1431],{"class":1430},[1420,4394,4395,4397,4399,4401,4403,4406,4408,4411,4413,4415],{"class":1422,"line":2968},[1420,4396,4370],{"class":1430},[1420,4398,4373],{"class":1938},[1420,4400,2852],{"class":1430},[1420,4402,2855],{"class":2758},[1420,4404,4405],{"class":1932},"\"API Error: ",[1420,4407,2861],{"class":1974},[1420,4409,4410],{"class":1430},"e",[1420,4412,2873],{"class":1974},[1420,4414,2858],{"class":1932},[1420,4416,2815],{"class":1430},[1420,4418,4419],{"class":1422,"line":2981},[1420,4420,4385],{"class":2758},[398,4422],{},[28,4424,4426],{"id":4425},"gdpr-aspects-in-api-automation","GDPR Aspects in API Automation",[11,4428,4429],{},"Consider the following when accessing ticket data programmatically:",[483,4431,4432,4441],{},[486,4433,4434],{},[489,4435,4436,4438],{},[492,4437,1083],{},[492,4439,4440],{},"Recommendation",[499,4442,4443,4453,4463,4473,4483],{},[489,4444,4445,4450],{},[504,4446,4447],{},[15,4448,4449],{},"API Token Storage",[504,4451,4452],{},"Environment variables or secret manager, never in code",[489,4454,4455,4460],{},[504,4456,4457],{},[15,4458,4459],{},"Logging",[504,4461,4462],{},"Do not store PII (Personally Identifiable Information) in logs",[489,4464,4465,4470],{},[504,4466,4467],{},[15,4468,4469],{},"Access Rights",[504,4471,4472],{},"Service accounts with minimal privileges (Least Privilege)",[489,4474,4475,4480],{},[504,4476,4477],{},[15,4478,4479],{},"Rate Limiting",[504,4481,4482],{},"Respect limits to avoid overloading the system",[489,4484,4485,4490],{},[504,4486,4487],{},[15,4488,4489],{},"Pseudonymization",[504,4491,4492],{},"When forwarding to external systems (e.g., AI APIs)",[398,4494],{},[28,4496,4498],{"id":4497},"comparison-which-system-when","Comparison: Which System When?",[483,4500,4501,4513],{},[486,4502,4503],{},[489,4504,4505,4508,4511],{},[492,4506,4507],{},"Use Case",[492,4509,4510],{},"Recommended Approach",[492,4512,1683],{},[499,4514,4515,4528,4542,4553,4566],{},[489,4516,4517,4520,4525],{},[504,4518,4519],{},"New Python project, Zammad",[504,4521,4522,4524],{},[180,4523,182],{}," + REST as fallback",[504,4526,4527],{},"Community client covers 80%",[489,4529,4530,4533,4539],{},[504,4531,4532],{},"OTOBO\u002FZnuny integration",[504,4534,4535,4536,4538],{},"Custom ",[180,4537,2711],{}," wrapper",[504,4540,4541],{},"Use GenericInterface docs",[489,4543,4544,4547,4550],{},[504,4545,4546],{},"Multi-system automation",[504,4548,4549],{},"Open Ticket AI Framework",[504,4551,4552],{},"Unified data model",[489,4554,4555,4558,4563],{},[504,4556,4557],{},"Prototyping\u002FQuick tests",[504,4559,4560,4561],{},"Jupyter Notebook + ",[180,4562,2711],{},[504,4564,4565],{},"Direct API exploration",[489,4567,4568,4571,4578],{},[504,4569,4570],{},"Production cron jobs",[504,4572,4573,4574,4577],{},"Python script + ",[180,4575,4576],{},"python-dotenv"," + logging",[504,4579,4580],{},"Robustness over elegance",[398,4582],{},[28,4584,4586],{"id":4585},"conclusion-and-next-steps","Conclusion and Next Steps",[11,4588,4589,4590],{},"Python automation for ticketing systems is not an either-or choice between client libraries and direct REST usage. Most teams benefit from a ",[15,4591,4592],{},"hybrid approach:",[608,4594,4595,4601,4607],{},[43,4596,4597,4600],{},[15,4598,4599],{},"Official\u002Fcommunity libraries"," for standard operations",[43,4602,4603,4606],{},[15,4604,4605],{},"Direct REST calls"," for edge cases and debugging",[43,4608,4609,4612],{},[15,4610,4611],{},"Custom abstraction layer"," for cross-system consistency",[11,4614,4615,4616,4619],{},"If you want to dive deeper, check out our ",[105,4617,4618],{"href":382},"plugin directories"," for Zammad, OTOBO, and Znuny to find matching extensions that often include built-in Python integrations.",[398,4621],{},[11,4623,4624],{},[771,4625,4626],{},"This article is a practical technical summary. Please consult the respective official documentation for current API versions and breaking changes.",[2157,4628,4629],{},"html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .s_ZVi, html code.shiki .s_ZVi{--shiki-default:#E06C75;--shiki-default-font-style:italic}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sb9H8, html code.shiki .sb9H8{--shiki-default:#D19A66;--shiki-default-font-style:italic}",{"title":419,"searchDepth":420,"depth":420,"links":4631},[4632,4633,4638,4642,4647,4648,4649,4650],{"id":2670,"depth":420,"text":2671},{"id":2736,"depth":420,"text":2737,"children":4634},[4635,4636],{"id":2740,"depth":426,"text":2741},{"id":3048,"depth":426,"text":4637},"Direct REST API with requests",{"id":3327,"depth":420,"text":3328,"children":4639},[4640,4641],{"id":3338,"depth":426,"text":3339},{"id":3641,"depth":426,"text":3642},{"id":3687,"depth":420,"text":3688,"children":4643},[4644,4645,4646],{"id":3691,"depth":426,"text":3692},{"id":3881,"depth":426,"text":3882},{"id":4052,"depth":426,"text":4053},{"id":4164,"depth":420,"text":4165},{"id":4425,"depth":420,"text":4426},{"id":4497,"depth":420,"text":4498},{"id":4585,"depth":420,"text":4586},"2026-05-20","Overview of Python clients and REST API integrations for Zammad, OTOBO, and Znuny—from official libraries to custom automation scripts.",{"language":791},"\u002Fblog\u002Fpython-automation-ticketsysteme-rest-api",{"title":2650,"description":4652},"blog\u002Fpython-automation-ticketsysteme-rest-api","BNsvf3Lux7JDCOJWPyZ8es1rQ8I04A_ec1IxgksHI_4",{"id":4659,"title":4660,"body":4661,"date":4675,"description":4676,"draft":434,"extension":435,"meta":4677,"navigation":437,"path":4678,"seo":4679,"stem":4680,"__hash__":4681},"blogEn\u002Fblog\u002Fwarum-offene-it-sm-verzeichnisse-wichtig-sind.md","Why open ITSM directories matter",{"type":8,"value":4662,"toc":4673},[4663,4670],[11,4664,4665,4666,4669],{},"Open-source ticketing systems thrive on extensions: integrations, themes, and utility packages. Without good ",[15,4667,4668],{},"discoverability",", both users and developers waste time.",[11,4671,4672],{},"An open directory pools metadata, compatibility data, and links—without requiring the proprietary store infrastructure of a single vendor. This supports fair comparisons and predictability when planning migrations between systems like Znuny, OTOBO, or Zammad.",{"title":419,"searchDepth":420,"depth":420,"links":4674},[],"2026-04-15","A quick look at why a community-driven plugin directory benefits both teams and vendors.",{},"\u002Fblog\u002Fwarum-offene-it-sm-verzeichnisse-wichtig-sind",{"title":4660,"description":4676},"blog\u002Fwarum-offene-it-sm-verzeichnisse-wichtig-sind","ezd9VxclY4jgoSP4GIttXpXkvX_KRwr56q3y1pLzqrE",{"id":4683,"title":4684,"body":4685,"date":4700,"description":4701,"draft":434,"extension":435,"meta":4702,"navigation":437,"path":4703,"seo":4704,"stem":4705,"__hash__":4706},"blogEn\u002Fblog\u002Fwillkommen-open-itsm-hub.md","Welcome to the Open ITSM Hub Blog",{"type":8,"value":4686,"toc":4698},[4687,4693],[11,4688,4689,4690,4692],{},"This is the ",[15,4691,636],{}," blog. Here we occasionally publish updates about the directory, insights into the ITSM plugin landscape, and notes on Znuny, OTOBO, Zammad, and more.",[11,4694,4695,4696,230],{},"You can find all articles in the ",[105,4697,396],{"href":395},{"title":419,"searchDepth":420,"depth":420,"links":4699},[],"2026-05-01","News and short articles around open-source ITSM, plugins, and the directory.",{},"\u002Fblog\u002Fwillkommen-open-itsm-hub",{"title":4684,"description":4701},"blog\u002Fwillkommen-open-itsm-hub","jb3I0RwPke4HRb9Sq6ONHbFOidXB37GrNNQ8bvIuuPw",{"id":4708,"title":4709,"body":4710,"date":4893,"description":4894,"draft":434,"extension":435,"meta":4895,"navigation":437,"path":4896,"seo":4897,"stem":4898,"__hash__":4899},"blogEn\u002Fblog\u002Fzammad-7-openitsmhub.md","Zammad 7 & AI: Quick Overview for IT Teams",{"type":8,"value":4711,"toc":4887},[4712,4715,4721,4725,4780,4784,4791,4811,4814,4818,4838,4840,4844,4875,4877],[448,4713,4709],{"id":4714},"zammad-7-ai-quick-overview-for-it-teams",[11,4716,4717,4720],{},[15,4718,4719],{},"Zammad 7.0"," brings native AI features directly into the open-source helpdesk software. For IT teams already using or evaluating Zammad, one main thing changes: AI becomes configurable infrastructure rather than a closed SaaS add-on.",[28,4722,4724],{"id":4723},"the-three-core-elements","The Three Core Elements",[483,4726,4727,4739],{},[486,4728,4729],{},[489,4730,4731,4733,4736],{},[492,4732,494],{},[492,4734,4735],{},"What it does",[492,4737,4738],{},"Relevance for admins",[499,4740,4741,4754,4767],{},[489,4742,4743,4748,4751],{},[504,4744,4745],{},[15,4746,4747],{},"AI Ticket Summary",[504,4749,4750],{},"Compresses long ticket threads into structured overviews",[504,4752,4753],{},"Reduces onboarding time during escalations",[489,4755,4756,4761,4764],{},[504,4757,4758],{},[15,4759,4760],{},"AI Writing Assistant",[504,4762,4763],{},"Tone, grammar, translation directly in the editor",[504,4765,4766],{},"Fewer iterations when drafting replies",[489,4768,4769,4774,4777],{},[504,4770,4771],{},[15,4772,4773],{},"AI Agents",[504,4775,4776],{},"Automatic categorization, prioritization, reassessment",[504,4778,4779],{},"Less manual triage",[28,4781,4783],{"id":4782},"sovereignty-the-decisive-differentiator","Sovereignty: The Decisive Differentiator",[11,4785,4786,4787,4790],{},"Instead of tying you to a single LLM provider, Zammad 7 offers an ",[15,4788,4789],{},"AI API"," with free model choice:",[40,4792,4793,4799,4805],{},[43,4794,4795,4798],{},[15,4796,4797],{},"Cloud",": OpenAI, Anthropic, Google Gemini",[43,4800,4801,4804],{},[15,4802,4803],{},"EU Cloud",": Mistral AI",[43,4806,4807,4810],{},[15,4808,4809],{},"On-Premises",": Llama via Ollama, other open-source models",[11,4812,4813],{},"This enables compliance with the EU AI Act and GDPR—especially for healthcare, finance, and public authorities.",[28,4815,4817],{"id":4816},"who-is-the-upgrade-worth-for","Who Is the Upgrade Worth For?",[40,4819,4820,4826,4832],{},[43,4821,4822,4823],{},"Teams with ",[15,4824,4825],{},"data sovereignty requirements",[43,4827,4828,4829],{},"Regulated industries that prefer ",[15,4830,4831],{},"local LLMs",[43,4833,4834,4835],{},"Organizations that want to avoid ",[15,4836,4837],{},"vendor lock-in",[398,4839],{},[28,4841,4843],{"id":4842},"deep-dive-and-alternatives","Deep Dive and Alternatives",[40,4845,4846,4854],{},[43,4847,4848,4849],{},"Zammad AI Version 7 ",[105,4850,4853],{"href":4851,"rel":4852},"https:\u002F\u002Fmedium.com\u002F@softoft\u002Fopenticketai-for-zammad-the-real-on-prem-ai-layer-for-zammad-1f589a4c5c8d",[109],"Full overview on Medium (DE)",[43,4855,4856,4859,4860,18,4863,4866,4867,4870,4871],{},[15,4857,4858],{},"Advanced AI Layers",": If you want to run Zammad with ",[15,4861,4862],{},"custom models",[15,4864,4865],{},"RAG",", or ",[15,4868,4869],{},"fine-grained control",", you can find integrations at ",[105,4872,4874],{"href":1020,"rel":4873},[109],"openticketai.com",[398,4876],{},[11,4878,4879],{},[771,4880,4881,4882,230],{},"This article is a neutral ITSM Hub summary. For binding Zammad documentation, see ",[105,4883,4886],{"href":4884,"rel":4885},"https:\u002F\u002Fzammad.com\u002F",[109],"zammad.com",{"title":419,"searchDepth":420,"depth":420,"links":4888},[4889,4890,4891,4892],{"id":4723,"depth":420,"text":4724},{"id":4782,"depth":420,"text":4783},{"id":4816,"depth":420,"text":4817},{"id":4842,"depth":420,"text":4843},"2026-05-07","Neutral overview of Zammad 7 AI features – what's changing and which AI models are supported.",{"language":791},"\u002Fblog\u002Fzammad-7-openitsmhub",{"title":4709,"description":4894},"blog\u002Fzammad-7-openitsmhub","5WstSKAkZYIW-R9Iixen0XojGg04Wbx5JEO7wtxe4vI",{"id":4901,"title":4902,"body":4903,"date":5661,"description":5662,"draft":434,"extension":435,"meta":5663,"navigation":437,"path":5664,"seo":5665,"stem":5666,"__hash__":5667},"blogEn\u002Fblog\u002Fzammad-mcp-server-vergleich.md","The Best Zammad MCP Server? basher83 vs. Softoft-Orga in a Hard Test",{"type":8,"value":4904,"toc":5643},[4905,4908,4917,4932,4934,4938,4942,4945,4975,4979,4982,5004,5006,5010,5160,5162,5166,5170,5173,5282,5286,5289,5313,5317,5320,5340,5344,5364,5366,5370,5377,5381,5508,5512,5611,5613,5617,5620,5634,5640],[448,4906,4902],{"id":4907},"the-best-zammad-mcp-server-basher83-vs-softoft-orga-in-a-hard-test",[11,4909,924,4910,4913,4914,4916],{},[15,4911,4912],{},"Model Context Protocol (MCP)",", initiated by Anthropic, has rapidly established itself as the industry standard for connecting AI assistants (such as Claude Desktop, Cursor, or Copilot) with external data sources and APIs. For the popular open-source ticketing system ",[15,4915,66],{},", two outstanding MCP server implementations now exist, enabling AI models to interact directly with tickets, users, and organizations via natural language.",[11,4918,4919,4920,4923,4924,4927,4928,4931],{},"Since these integrations focus on different priorities, taking a close look at their architectures, licenses, and security features is worthwhile. In this post, we compare the community-driven server from ",[15,4921,4922],{},"basher83"," with the production-oriented solution from ",[15,4925,4926],{},"Softoft-Orga"," (",[180,4929,4930],{},"zammad-mcp-server",").",[398,4933],{},[28,4935,4937],{"id":4936},"the-candidates-at-a-glance","The Candidates at a Glance",[77,4939,4941],{"id":4940},"_1-zammad-mcp-by-basher83","1. Zammad MCP by basher83",[11,4943,4944],{},"This project is an established, highly interactive community solution. It features a wide range of functions tailored especially to power users and developers who want to access Zammad directly from their local LLM runtime environments.",[40,4946,4947,4957,4969],{},[43,4948,4949,1810,4952],{},[15,4950,4951],{},"GitHub Repository:",[105,4953,4956],{"href":4954,"rel":4955},"https:\u002F\u002Fgithub.com\u002Fbasher83\u002FZammad-MCP",[109],"basher83\u002FZammad-MCP",[43,4958,4959,1810,4962,4965,4966,1247],{},[15,4960,4961],{},"PyPI Package:",[180,4963,4964],{},"iflow-mcp-basher83-zammad"," (registered on our hub under ",[105,4967,4968],{"href":4968},"\u002Fpackages\u002Fiflow-mcpbasher83-zammad",[43,4970,4971,4974],{},[15,4972,4973],{},"License:"," AGPL-3.0-or-later (closely aligned with the open-source licensing of the Zammad core project)",[77,4976,4978],{"id":4977},"_2-zammad-mcp-server-by-softoft-orga","2. Zammad MCP Server by Softoft-Orga",[11,4980,4981],{},"This server is targeted at production-ready enterprise deployments. The focus lies on a fine-grained permission concept, flexible provisioning (SSE transport for distributed architectures), and modular connection to larger automation setups.",[40,4983,4984,4993,4999],{},[43,4985,4986,1810,4988],{},[15,4987,4951],{},[105,4989,4992],{"href":4990,"rel":4991},"https:\u002F\u002Fgithub.com\u002FSoftoft-Orga\u002Fzammad-mcp-server",[109],"Softoft-Orga\u002Fzammad-mcp-server",[43,4994,4995,1810,4997],{},[15,4996,4961],{},[180,4998,4930],{},[43,5000,5001,5003],{},[15,5002,4973],{}," MIT (extremely permissive license, ideal for commercial integrations and customizations)",[398,5005],{},[28,5007,5009],{"id":5008},"direct-feature-comparison","Direct Feature Comparison",[483,5011,5012,5025],{},[486,5013,5014],{},[489,5015,5016,5019,5022],{},[492,5017,5018],{"align":1082},"Feature \u002F Property",[492,5020,5021],{"align":1082},"basher83 (iflow-mcp-basher83-zammad)",[492,5023,5024],{"align":1082},"Softoft-Orga (zammad-mcp-server)",[499,5026,5027,5040,5059,5072,5101,5117,5134,5147],{},[489,5028,5029,5034,5037],{},[504,5030,5031],{"align":1082},[15,5032,5033],{},"License",[504,5035,5036],{"align":1082},"AGPL-3.0 (Copyleft)",[504,5038,5039],{"align":1082},"MIT (Permissive)",[489,5041,5042,5047,5053],{},[504,5043,5044],{"align":1082},[15,5045,5046],{},"Tool Naming",[504,5048,5049,5050,1247],{"align":1082},"Prefixed (e.g., ",[180,5051,5052],{},"zammad_search_tickets",[504,5054,5055,5056,1247],{"align":1082},"Flat\u002FClear (e.g., ",[180,5057,5058],{},"search_tickets",[489,5060,5061,5066,5069],{},[504,5062,5063],{"align":1082},[15,5064,5065],{},"Number of Tools",[504,5067,5068],{"align":1082},"~20 standard operations",[504,5070,5071],{"align":1082},"30+ tools (full API coverage)",[489,5073,5074,5079,5085],{},[504,5075,5076],{"align":1082},[15,5077,5078],{},"Access Control (ACL)",[504,5080,5081,5082],{"align":1082},"Simple blacklist via ",[180,5083,5084],{},"MCP_DENIED_TOOLS",[504,5086,5087,5088,18,5091,18,5094,18,5097,5100],{"align":1082},"Fine-grained tiers (",[180,5089,5090],{},"DENIED",[180,5092,5093],{},"READ_ONLY",[180,5095,5096],{},"WRITE",[180,5098,5099],{},"ADMIN","), category and group restrictions",[489,5102,5103,5108,5111],{},[504,5104,5105],{"align":1082},[15,5106,5107],{},"SSE Transport (Remote)",[504,5109,5110],{"align":1082},"Requires additional wrapper \u002F SSE proxy",[504,5112,5113,5114,1247],{"align":1082},"Built-in natively (",[180,5115,5116],{},"--transport sse --port 8000",[489,5118,5119,5124,5131],{},[504,5120,5121],{"align":1082},[15,5122,5123],{},"Resources & Prompts",[504,5125,5126,5127,5130],{"align":1082},"Comprehensive resources (",[180,5128,5129],{},"zammad:\u002F\u002Fticket\u002F{id}",") & prompt templates",[504,5132,5133],{"align":1082},"Focus on core APIs and programmatic integration",[489,5135,5136,5141,5144],{},[504,5137,5138],{"align":1082},[15,5139,5140],{},"Caching",[504,5142,5143],{"align":1082},"Caching for groups, priorities, and ticket states",[504,5145,5146],{"align":1082},"Intelligent caching of static system metadata",[489,5148,5149,5154,5157],{},[504,5150,5151],{"align":1082},[15,5152,5153],{},"Interface Coverage",[504,5155,5156],{"align":1082},"Tickets, articles, attachments (Base64), tags, users, orgs, groups, states, stats",[504,5158,5159],{"align":1082},"Tickets, articles, users, orgs, groups, caching, system health checks",[398,5161],{},[28,5163,5165],{"id":5164},"detailed-analysis-of-differences","Detailed Analysis of Differences",[77,5167,5169],{"id":5168},"_1-permissions-and-security-access-control","1. Permissions and Security (Access Control)",[11,5171,5172],{},"Companies granting AI models access to their internal ticketing system must enforce strict security guidelines. This is where both servers differ most significantly:",[40,5174,5175,5183],{},[43,5176,5177,5179,5180,5182],{},[15,5178,4922],{}," offers robust yet simple protection: Using the environment variable ",[180,5181,5084],{},", specific tools (such as deletion or update functions) can be disabled completely.",[43,5184,5185,5187,5188,5191,5192],{},[15,5186,4926],{}," implements a ",[15,5189,5190],{},"fine-grained permission concept",". Beyond a tool blacklist, access rights can be restricted at the category level (e.g., tickets read-only, users blocked) or even at the Zammad group level (e.g., granting access only to tickets in the \"Support\" and \"Sales\" groups). Furthermore, security policies can be adjusted declaratively in Python code:\n",[1287,5193,5195],{"className":2749,"code":5194,"language":2751,"meta":419,"style":419},"policy = AccessPolicy(\n    default_permission=Permission.READ_ONLY,\n    category_permissions={\n        ToolCategory.TICKETS: Permission.WRITE,\n        ToolCategory.ADMIN: Permission.DENIED,\n    },\n    denied_tools={\"delete_ticket\"},\n)\n",[180,5196,5197,5209,5223,5232,5247,5259,5264,5278],{"__ignoreMap":419},[1420,5198,5199,5202,5204,5207],{"class":1422,"line":1423},[1420,5200,5201],{"class":1430},"policy ",[1420,5203,2780],{"class":1928},[1420,5205,5206],{"class":1938}," AccessPolicy",[1420,5208,2786],{"class":1430},[1420,5210,5211,5214,5216,5219,5221],{"class":1422,"line":420},[1420,5212,5213],{"class":2791},"    default_permission",[1420,5215,2780],{"class":1928},[1420,5217,5218],{"class":1430},"Permission.",[1420,5220,5093],{"class":1974},[1420,5222,2800],{"class":1430},[1420,5224,5225,5228,5230],{"class":1422,"line":426},[1420,5226,5227],{"class":2791},"    category_permissions",[1420,5229,2780],{"class":1928},[1420,5231,3390],{"class":1430},[1420,5233,5234,5237,5240,5243,5245],{"class":1422,"line":1953},[1420,5235,5236],{"class":1430},"        ToolCategory.",[1420,5238,5239],{"class":1974},"TICKETS",[1420,5241,5242],{"class":1430},": Permission.",[1420,5244,5096],{"class":1974},[1420,5246,2800],{"class":1430},[1420,5248,5249,5251,5253,5255,5257],{"class":1422,"line":1959},[1420,5250,5236],{"class":1430},[1420,5252,5099],{"class":1974},[1420,5254,5242],{"class":1430},[1420,5256,5090],{"class":1974},[1420,5258,2800],{"class":1430},[1420,5260,5261],{"class":1422,"line":1965},[1420,5262,5263],{"class":1430},"    },\n",[1420,5265,5266,5269,5271,5273,5276],{"class":1422,"line":1992},[1420,5267,5268],{"class":2791},"    denied_tools",[1420,5270,2780],{"class":1928},[1420,5272,2861],{"class":1430},[1420,5274,5275],{"class":1932},"\"delete_ticket\"",[1420,5277,3498],{"class":1430},[1420,5279,5280],{"class":1422,"line":1997},[1420,5281,2815],{"class":1430},[77,5283,5285],{"id":5284},"_2-naming-conventions-and-tool-collisions","2. Naming Conventions and Tool Collisions",[11,5287,5288],{},"Running multiple MCP servers simultaneously in your AI client (e.g., Claude Desktop) can lead to tool name collisions:",[40,5290,5291,5304],{},[43,5292,5293,5295,5296,5299,5300,5303],{},[15,5294,4922],{}," uses the ",[180,5297,5298],{},"zammad_"," prefix for all offered tools (e.g., ",[180,5301,5302],{},"zammad_get_ticket","). This reliably prevents naming conflicts in the AI context.",[43,5305,5306,5308,5309,5312],{},[15,5307,4926],{}," relies on short, direct method names (e.g., ",[180,5310,5311],{},"get_ticket","). This is easier for dedicated, specialized AI agents to read, but requires attention when other MCP servers with similar generic tools run in parallel.",[77,5314,5316],{"id":5315},"_3-network-and-deployment-architecture","3. Network and Deployment Architecture",[11,5318,5319],{},"How is the MCP server started and connected?",[40,5321,5322,5331],{},[43,5323,5324,5326,5327,5330],{},[15,5325,4922],{}," is optimized for classic stdio scenarios (called directly via ",[180,5328,5329],{},"uvx"," or Docker on the same machine running the client). It sets up exceptionally well as a local assistant.",[43,5332,5333,5335,5336,5339],{},[15,5334,4926],{}," offers ",[15,5337,5338],{},"native SSE support"," (Server-Sent Events). This allows the server to run as a standalone web service within the corporate network. External clients or centralized agent platforms can connect via HTTP\u002FSSE instead of requiring the process to run locally on the desktop.",[77,5341,5343],{"id":5342},"_4-integration-into-ai-infrastructure","4. Integration into AI Infrastructure",[40,5345,5346,5359],{},[43,5347,924,5348,5350,5351,5354,5355,5358],{},[15,5349,4922],{}," server brings its own MCP prompts (such as ",[180,5352,5353],{},"analyze_ticket"," or ",[180,5356,5357],{},"draft_response",") and resource URIs directly. This enables the AI assistant to instantly know how to structure typical workflows.",[43,5360,924,5361,5363],{},[15,5362,4926],{}," server is designed as a modular building block and suits deployments in larger automation pipelines—such as classifying and answering tickets via on-premise models while agents make ad-hoc queries via MCP.",[398,5365],{},[28,5367,5369],{"id":5368},"configuration-examples","Configuration Examples",[11,5371,5372,5373,5376],{},"To test both servers directly, you can find the corresponding configurations for your ",[180,5374,5375],{},"claude_desktop_config.json"," or Cursor MCP settings below.",[77,5378,5380],{"id":5379},"configuration-for-basher83-via-pypiuvx","Configuration for basher83 (via PyPI\u002Fuvx)",[1287,5382,5385],{"className":5383,"code":5384,"language":3202,"meta":419,"style":419},"language-json shiki shiki-themes one-dark-pro","{\n  \"mcpServers\": {\n    \"zammad-community\": {\n      \"command\": \"uvx\",\n      \"args\": [\n        \"--from\",\n        \"git+https:\u002F\u002Fgithub.com\u002Fbasher83\u002Fzammad-mcp.git\",\n        \"mcp-zammad\"\n      ],\n      \"env\": {\n        \"ZAMMAD_URL\": \"https:\u002F\u002Fyour-instance.zammad.com\u002Fapi\u002Fv1\",\n        \"ZAMMAD_HTTP_TOKEN\": \"your_api_token\",\n        \"MCP_DENIED_TOOLS\": \"zammad_delete_attachment\"\n      }\n    }\n  }\n}\n",[180,5386,5387,5391,5398,5405,5417,5425,5432,5439,5444,5449,5456,5468,5480,5490,5495,5499,5504],{"__ignoreMap":419},[1420,5388,5389],{"class":1422,"line":1423},[1420,5390,3390],{"class":1430},[1420,5392,5393,5396],{"class":1422,"line":420},[1420,5394,5395],{"class":1426},"  \"mcpServers\"",[1420,5397,2965],{"class":1430},[1420,5399,5400,5403],{"class":1422,"line":426},[1420,5401,5402],{"class":1426},"    \"zammad-community\"",[1420,5404,2965],{"class":1430},[1420,5406,5407,5410,5412,5415],{"class":1422,"line":1953},[1420,5408,5409],{"class":1426},"      \"command\"",[1420,5411,1439],{"class":1430},[1420,5413,5414],{"class":1932},"\"uvx\"",[1420,5416,2800],{"class":1430},[1420,5418,5419,5422],{"class":1422,"line":1959},[1420,5420,5421],{"class":1426},"      \"args\"",[1420,5423,5424],{"class":1430},": [\n",[1420,5426,5427,5430],{"class":1422,"line":1965},[1420,5428,5429],{"class":1932},"        \"--from\"",[1420,5431,2800],{"class":1430},[1420,5433,5434,5437],{"class":1422,"line":1992},[1420,5435,5436],{"class":1932},"        \"git+https:\u002F\u002Fgithub.com\u002Fbasher83\u002Fzammad-mcp.git\"",[1420,5438,2800],{"class":1430},[1420,5440,5441],{"class":1422,"line":1997},[1420,5442,5443],{"class":1932},"        \"mcp-zammad\"\n",[1420,5445,5446],{"class":1422,"line":2003},[1420,5447,5448],{"class":1430},"      ],\n",[1420,5450,5451,5454],{"class":1422,"line":2015},[1420,5452,5453],{"class":1426},"      \"env\"",[1420,5455,2965],{"class":1430},[1420,5457,5458,5461,5463,5466],{"class":1422,"line":2893},[1420,5459,5460],{"class":1426},"        \"ZAMMAD_URL\"",[1420,5462,1439],{"class":1430},[1420,5464,5465],{"class":1932},"\"https:\u002F\u002Fyour-instance.zammad.com\u002Fapi\u002Fv1\"",[1420,5467,2800],{"class":1430},[1420,5469,5470,5473,5475,5478],{"class":1422,"line":2898},[1420,5471,5472],{"class":1426},"        \"ZAMMAD_HTTP_TOKEN\"",[1420,5474,1439],{"class":1430},[1420,5476,5477],{"class":1932},"\"your_api_token\"",[1420,5479,2800],{"class":1430},[1420,5481,5482,5485,5487],{"class":1422,"line":2904},[1420,5483,5484],{"class":1426},"        \"MCP_DENIED_TOOLS\"",[1420,5486,1439],{"class":1430},[1420,5488,5489],{"class":1932},"\"zammad_delete_attachment\"\n",[1420,5491,5492],{"class":1422,"line":2920},[1420,5493,5494],{"class":1430},"      }\n",[1420,5496,5497],{"class":1422,"line":2933},[1420,5498,3027],{"class":1430},[1420,5500,5501],{"class":1422,"line":2946},[1420,5502,5503],{"class":1430},"  }\n",[1420,5505,5506],{"class":1422,"line":2959},[1420,5507,3106],{"class":1430},[77,5509,5511],{"id":5510},"configuration-for-softoft-orga-via-pypiuvx","Configuration for Softoft-Orga (via PyPI\u002Fuvx)",[1287,5513,5515],{"className":5383,"code":5514,"language":3202,"meta":419,"style":419},"{\n  \"mcpServers\": {\n    \"zammad-enterprise\": {\n      \"command\": \"uvx\",\n      \"args\": [\n        \"zammad-mcp-server\"\n      ],\n      \"env\": {\n        \"ZAMMAD_URL\": \"https:\u002F\u002Fyour-instance.zammad.com\",\n        \"ZAMMAD_HTTP_TOKEN\": \"your_api_token\",\n        \"MCP_DENIED_TOOLS\": \"delete_ticket,delete_user,delete_organization\"\n      }\n    }\n  }\n}\n",[180,5516,5517,5521,5527,5534,5544,5550,5555,5559,5565,5576,5586,5595,5599,5603,5607],{"__ignoreMap":419},[1420,5518,5519],{"class":1422,"line":1423},[1420,5520,3390],{"class":1430},[1420,5522,5523,5525],{"class":1422,"line":420},[1420,5524,5395],{"class":1426},[1420,5526,2965],{"class":1430},[1420,5528,5529,5532],{"class":1422,"line":426},[1420,5530,5531],{"class":1426},"    \"zammad-enterprise\"",[1420,5533,2965],{"class":1430},[1420,5535,5536,5538,5540,5542],{"class":1422,"line":1953},[1420,5537,5409],{"class":1426},[1420,5539,1439],{"class":1430},[1420,5541,5414],{"class":1932},[1420,5543,2800],{"class":1430},[1420,5545,5546,5548],{"class":1422,"line":1959},[1420,5547,5421],{"class":1426},[1420,5549,5424],{"class":1430},[1420,5551,5552],{"class":1422,"line":1965},[1420,5553,5554],{"class":1932},"        \"zammad-mcp-server\"\n",[1420,5556,5557],{"class":1422,"line":1992},[1420,5558,5448],{"class":1430},[1420,5560,5561,5563],{"class":1422,"line":1997},[1420,5562,5453],{"class":1426},[1420,5564,2965],{"class":1430},[1420,5566,5567,5569,5571,5574],{"class":1422,"line":2003},[1420,5568,5460],{"class":1426},[1420,5570,1439],{"class":1430},[1420,5572,5573],{"class":1932},"\"https:\u002F\u002Fyour-instance.zammad.com\"",[1420,5575,2800],{"class":1430},[1420,5577,5578,5580,5582,5584],{"class":1422,"line":2015},[1420,5579,5472],{"class":1426},[1420,5581,1439],{"class":1430},[1420,5583,5477],{"class":1932},[1420,5585,2800],{"class":1430},[1420,5587,5588,5590,5592],{"class":1422,"line":2893},[1420,5589,5484],{"class":1426},[1420,5591,1439],{"class":1430},[1420,5593,5594],{"class":1932},"\"delete_ticket,delete_user,delete_organization\"\n",[1420,5596,5597],{"class":1422,"line":2898},[1420,5598,5494],{"class":1430},[1420,5600,5601],{"class":1422,"line":2904},[1420,5602,3027],{"class":1430},[1420,5604,5605],{"class":1422,"line":2920},[1420,5606,5503],{"class":1430},[1420,5608,5609],{"class":1422,"line":2933},[1420,5610,3106],{"class":1430},[398,5612],{},[28,5614,5616],{"id":5615},"conclusion-which-zammad-mcp-server-is-right-for-you","Conclusion: Which Zammad MCP Server Is Right for You?",[11,5618,5619],{},"Both projects impressively demonstrate the potential of MCP in the ITSM environment. Your choice primarily depends on your use case:",[40,5621,5622,5628],{},[43,5623,5624,5627],{},[15,5625,5626],{},"Choose the basher83 server"," if you are a developer or IT professional looking for a fast, feature-rich connection for your local Claude or Cursor client. The built-in prompts and prefixed tool names make daily hacking extremely comfortable.",[43,5629,5630,5633],{},[15,5631,5632],{},"Choose the Softoft-Orga server"," if you are connecting Zammad in an enterprise environment. When you need to enforce fine-grained access controls, run the server as a centralized SSE service in a Kubernetes cluster, or embed it into a larger automation pipeline, this server is the right choice.",[11,5635,5636,5637,230],{},"You can find further details on compatible extensions and plugins for Zammad in our ",[105,5638,5639],{"href":382},"Zammad plugin directory",[2157,5641,5642],{},"html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .s_ZVi, html code.shiki .s_ZVi{--shiki-default:#E06C75;--shiki-default-font-style:italic}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}",{"title":419,"searchDepth":420,"depth":420,"links":5644},[5645,5649,5650,5656,5660],{"id":4936,"depth":420,"text":4937,"children":5646},[5647,5648],{"id":4940,"depth":426,"text":4941},{"id":4977,"depth":426,"text":4978},{"id":5008,"depth":420,"text":5009},{"id":5164,"depth":420,"text":5165,"children":5651},[5652,5653,5654,5655],{"id":5168,"depth":426,"text":5169},{"id":5284,"depth":426,"text":5285},{"id":5315,"depth":426,"text":5316},{"id":5342,"depth":426,"text":5343},{"id":5368,"depth":420,"text":5369,"children":5657},[5658,5659],{"id":5379,"depth":426,"text":5380},{"id":5510,"depth":426,"text":5511},{"id":5615,"depth":420,"text":5616},"2026-05-27","A detailed comparison of the two open-source Model Context Protocol (MCP) servers for Zammad. Learn how to securely connect your AI assistants (Claude, Cursor) to your helpdesk.",{"language":791},"\u002Fblog\u002Fzammad-mcp-server-vergleich",{"title":4902,"description":5662},"blog\u002Fzammad-mcp-server-vergleich","ntpCKocRasmOsht_erUAKegF0DYvDVoTOpfMMf3x-ms",1787732993425]