OTOBO / Znuny Web Services – REST API

W tym obszernym przewodniku dowiesz się, jak aktywować, konfigurować i integrować OTOBO REST API (część Generic Interface) z własnymi aplikacjami.
1. Architektura i Podstawy
OTOBO udostępnia swoje Generic Interface poprzez usługi sieciowe REST i SOAP. REST API komunikuje się za pomocą HTTP(S)/JSON i umożliwia:
- Operacje na zgłoszeniach: Tworzenie, pobieranie, modyfikowanie, usuwanie
- Operacje na artykułach: Publikowanie, zarządzanie załącznikami
- Historia i wyszukiwanie: Historia zgłoszeń i złożone zapytania wyszukiwania
Uwaga: Standardowa instalacja nie zawiera prekonfigurowanych usług sieciowych – tworzysz je samodzielnie w module administracyjnym „Procesy i Automatyzacja → Usługi sieciowe”.
2. Konfiguracja
2.1 Aktywacja Generic Interface
- W obszarze administracyjnym → SysConfig → GenericInterface.Transport zmień na REST (HTTP).
- W AdminGenericInterfaceTransportHTTPREST ustaw limity czasowe, nagłówek hosta i poziom debugowania.
- W GenericInterface.Operation utwórz i aktywuj pożądane operacje (np.
TicketCreate,TicketSearch,TicketGet,TicketUpdate,TicketDelete,TicketHistoryGet).
2.2 Podstawowy URL i Uwierzytelnianie
Podstawowy URL
https://TWÓJ-SERWER/otobo/nph-genericinterface.pl/Webservice/<NazwaTwojejUsługi>/Uwierzytelnianie
- Ciasteczka sesji OTOBO
- Klucze API / Tokeny (tworzone przez SysConfig)
- Zawsze używaj HTTPS!
3. Punkty końcowe i Metody HTTP (Szczegóły)
Dla każdego punktu końcowego znajdziesz tutaj szczegółowy przegląd parametrów, możliwych odpowiedzi i praktycznych przykładów.
3.1 TicketCreate (POST)
URL: /Webservice/<NazwaUsługi>/TicketCreateMetoda: POST
Opis: Tworzy nowe zgłoszenie i jednocześnie artykuł.
| Parametr | Typ | Wymagany | Opis |
|---|---|---|---|
| SessionID | Integer | Tak¹ | ID sesji lub UserLogin+Password |
| UserLogin | String | Tak² | Login agenta (w połączeniu z Password) |
| Password | String | Tak² | Hasło (w połączeniu z UserLogin) |
| Ticket.Title | String | Tak | Temat zgłoszenia |
| Ticket.Queue | String | Tak | Nazwa kolejki lub Ticket.QueueID |
| Ticket.State | String | Tak | Stan początkowy (np. new) |
| Ticket.Priority | String | Tak | Priorytet (np. 3 normal) |
| Ticket.CustomerUser | String | Tak | E-mail lub login klienta |
| Article.Subject | String | Tak | Temat pierwszego artykułu |
| Article.Body | String | Tak | Treść pierwszego artykułu |
| Article.MimeType | String | Tak | text/plain lub text/html |
¹ Wymagane jest SessionID LUB UserLogin+Password. ² Jeśli nie ma tokenu SessionID.
Przykładowe żądanie:
POST /Webservice/MyConnectorREST/TicketCreate HTTP/1.1
Host: demo.otobo.org
Content-Type: application/json
X-API-Key: abc123
{
"Data": {
"SessionID": 42,
"Ticket": {
"Title": "Nowe zamówienie",
"Queue": "Sales",
"State": "new",
"Priority": "3 normal",
"CustomerUser": "max.mustermann@example.com"
},
"Article": {
"Subject": "Zapytanie o zakup – Produkt XY",
"Body": "Prośba o ofertę cenową…",
"MimeType": "text/plain"
}
}
}Przykładowa odpowiedź:
{
"Success": 1,
"ErrorMessage": "",
"Data": {
"TicketID": "12345",
"ArticleID": "67890"
}
}3.2 TicketSearch (GET)
URL: /Webservice/<NazwaUsługi>/TicketSearchMetoda: GET
Opis: Wyszukuje zgłoszenia na podstawie różnych kryteriów filtrowania.
| Parametr | Typ | Wymagany | Opis |
|---|---|---|---|
| UserLogin, Password | String,String | Tak¹ | Dane uwierzytelniające agenta lub SessionID² |
| SessionID | Integer | Tak² | Token dla uwierzytelnionych sesji |
| Title | String/String[] | Nie | Wyszukiwanie z symbolem wieloznacznym w temacie (%Zamówienie%) |
| TicketNumber | String/String[] | Nie | Numer(y) zgłoszenia |
| QueueIDs | Integer[] | Nie | ID kolejki |
| States | String[] | Nie | Stany (new, open, …) |
| StateType | String/String[] | Nie | Kategoria Open/Closed |
| DynamicField_Name.Op | Mixed | Nie | Pola dynamiczne z operatorem (Equals, Like, GreaterThan …) |
¹ Wymagane UserLogin+Password LUB SessionID. ² Jeśli nie zostanie przekazana para logowania.
Przykładowe żądanie:
GET /Webservice/MyConnectorREST/TicketSearch?UserLogin=agent1&Password=geheim&Title=%25Zamówienie%25 HTTP/1.1
Host: demo.otobo.orgPrzykładowa odpowiedź:
{
"Success": 1,
"Data": {
"TicketID": [1001,1005,1012]
}
}3.3 TicketGet (GET)
URL: /Webservice/<NazwaUsługi>/TicketGetMetoda: GET
Opis: Zwraca szczegółowe dane zgłoszenia, w tym artykuły, załączniki i pola dynamiczne.
| Parametr | Typ | Wymagany | Opis |
|---|---|---|---|
| UserLogin, Password | String,String | Tak¹ | Dane uwierzytelniające agenta lub SessionID² |
| SessionID | Integer | Tak² | Token dla uwierzytelnionych sesji |
| TicketID | String/String[] | Tak | Jedno lub więcej ID zgłoszeń (oddzielone przecinkami lub tablica) |
| DynamicFields | Boolean (0/1) | Nie | 1 = Pola dynamiczne w wyniku, Domyślnie = 0 |
| Extended | Boolean | Nie | 1 = Rozszerzone metadane (np. FirstResponse) |
| AllArticles | Boolean | Nie | 1 = Zwróć wszystkie artykuły |
| ArticleLimit | Integer | Nie | Maksymalna liczba zwracanych artykułów |
| Attachments | Boolean | Nie | 1 = Osadź załączniki w Base64 |
| GetAttachmentContents | Boolean | Nie | 1 = Pobierz również zawartość załączników |
| HTMLBodyAsAttachment | Boolean | Nie | 1 = Dodaj wersję HTML artykułu jako załącznik |
¹ Wymagane UserLogin+Password LUB SessionID. ² Jeśli nie zostanie przekazana para logowania.
Przykładowe żądanie:
GET /Webservice/MyConnectorREST/TicketGet?SessionID=42&TicketID=12345&AllArticles=1&DynamicFields=1 HTTP/1.1
Host: demo.otobo.orgPrzykładowa odpowiedź (skrócona):
{
"Success":1,
"Data":{
"Ticket":[{
"TicketID":12345,
"TicketNumber":"202501230001",
"Title":"Nowe zamówienie",
"State":"open",
"DynamicField":[{"Name":"Urgency","Value":"high"}],
"Article":[{
"ArticleID":67890,
"Subject":"Zapytanie o zakup…",
"Body":"Prośba o ofertę cenową…",
"Attachment":[{"Filename":"Oferta.pdf","Content":"JVBERi0x…="}]
}]
}]
}
}3.4 TicketUpdate (PUT)
URL: /Webservice/<NazwaUsługi>/TicketUpdateMetoda: PUT
Opis: Aktualizuje pola istniejącego zgłoszenia i opcjonalnie tworzy nowy artykuł.
| Parametr | Typ | Wymagany | Opis |
|---|---|---|---|
| SessionID | Integer | Tak¹ | Token lub UserLogin+Password² |
| TicketID | Integer | Tak | ID zgłoszenia do aktualizacji |
| Ticket.Title | String | Nie | Nowy temat |
| Ticket.State | String | Nie | Nowy status |
| Ticket.Owner | String/ID | Nie | Nowy właściciel |
| Ticket.PendingTime | Hash / Diff | Nie | Nowy czas oczekiwania |
| Article.Subject | String | Nie | Tworzy nowy artykuł |
| Article.Body | String | Nie | Treść nowego artykułu |
| DynamicField… | Array | Nie | Aktualizacja pól dynamicznych |
| Attachment… | Array | Nie | Dodawanie nowych załączników |
¹ Wymagane SessionID LUB UserLogin+Password. ² Jeśli nie ma tokenu SessionID.
Przykładowe żądanie:
PUT /Webservice/MyConnectorREST/TicketUpdate HTTP/1.1
Host: demo.otobo.org
Content-Type: application/json
X-API-Key: abc123
{
"Data":{
"SessionID":42,
"TicketID":12345,
"Ticket":{ "State":"pending reminder","PendingTime":{"Diff":1440} },
"Article":{ "Subject":"Reminder ustawiony","Body":"Zgłoszenie jest przetwarzane." }
}
}Przykładowa odpowiedź:
{ "Success":1, "ErrorMessage":"", "Data":{ "TicketID":12345, "ArticleID":67891 } }3.5 TicketDelete (DELETE)
URL: /Webservice/<NazwaUsługi>/TicketDeleteMetoda: DELETE
Opis: Trwale usuwa jedno lub więcej zgłoszeń.
| Parametr | Typ | Wymagany | Opis |
|---|---|---|---|
| SessionID | Integer | Tak¹ | Token lub UserLogin+Password² |
| TicketID | String/Array | Tak | Jedno lub więcej ID zgłoszeń |
Przykładowe żądanie:
DELETE /Webservice/MyConnectorREST/TicketDelete?SessionID=42&TicketID=12345 HTTP/1.1
Host: demo.otobo.orgPrzykładowa odpowiedź:
{ "Success":1, "ErrorMessage":"", "Data":{} }3.6 TicketHistoryGet (GET)
URL: /Webservice/<NazwaUsługi>/TicketHistoryGetMetoda: GET
Opis: Pobiera historię jednego lub więcej zgłoszeń.
| Parametr | Typ | Wymagany | Opis |
|---|---|---|---|
| SessionID | Integer | Tak¹ | Token lub UserLogin+Password² |
| TicketID | String/Array | Tak | Jedno lub więcej ID zgłoszeń |
Przykładowe żądanie:
GET /Webservice/MyConnectorREST/TicketHistoryGet?SessionID=42&TicketID=12345,5. Rozszerzenie i Dostosowanie
5.1 Definicja WADL
Nowe zasoby w GenericTicketConnectorREST.wadl:
<resource path="MyTest" id="MyTest">
<method name="GET" id="GET_MyTest">
<response status="200">
<representation mediaType="application/json"/>
</response>
</method>
</resource>5.2 Import YAML
Alternatywnie przez YAML w development/webservices/GenericTicketConnectorREST.yml:
Provider:
Operation:
MyTest:
Description: "Operacja testowa"
MappingInbound: { }
MappingOutbound: { }
Type: Test::Module
Transport:
Config:
RouteOperationMapping:
MyTest:
RequestMethod: [ GET ]
Route: /MyTest6. Obsługa błędów i Logowanie
- Wskaźnik sukcesu:
Success: 0|1 - Komunikat o błędzie:
ErrorMessagew JSON - Debugowanie: Ustaw
Debug-LevelnaDebugw oknie transportu → wpisy logów widoczne w bazie danych
7. Przypadki użycia
| Scenariusz | Opis |
|---|---|
| Automatyzacja między systemami | Tworzenie zgłoszeń z narzędzi monitorowania (Nagios, Zabbix) |
| Synchronizacja danych | Masowe aktualizacje pól zgłoszeń z zewnętrznego CRM |
| Portale samoobsługowe | Klienci tworzą własne zgłoszenia przez REST |
| Aplikacje mobilne | Natywne aplikacje iOS/Android komunikują się przez REST |
8. Inne elementy UI i Integracja
Klonowanie usługi sieciowej
Moduł obsługi błędów
Podsumowanie
OTOBO REST API jest elastyczne, wydajne i wysoce rozszerzalne dzięki Generic Interface. Niezależnie od tego, czy chodzi o proste tworzenie zgłoszeń, czy złożoną automatyzację przepływu pracy – za pomocą kilku kliknięć w panelu administracyjnym i standardowych żądań JSON można zrealizować płynne integracje w każdym środowisku IT.
Biblioteka klienta Python dla OTOBO
Asynchroniczna biblioteka klienta Python do interakcji z OTOBO REST API. Zbudowana z użyciem httpx i pydantic dla bezpieczeństwa typów i łatwości użycia.
Funkcje
Asynchroniczne żądania HTTP przy użyciu
httpx.AsyncClientModele Pydantic do walidacji danych żądań i odpowiedzi
Pełne operacje CRUD dla zgłoszeń:
TicketCreateTicketSearchTicketGetTicketUpdateTicketHistoryGet
Obsługa błędów za pomocą
OTOBOErrordla błędów APIMetoda pomocnicza
search_and_getdo łączenia wyników wyszukiwania ze szczegółowym pobieraniem
Instalacja
Zainstaluj z PyPI:
pip install otoboSzybki start
Konfiguracja usług sieciowych OTOBO:
Utwórz nową usługę sieciową w OTOBO z następującą konfiguracją:
---
Debugger:
DebugThreshold: debug
TestMode: '0'
Description: ''
FrameworkVersion: 11.0.5
Provider:
Operation:
session-create:
Description: ''
IncludeTicketData: '0'
MappingInbound:
Type: Simple
MappingOutbound:
Type: Simple
Type: Session::SessionCreate
ticket-create:
Description: ''
IncludeTicketData: '1'
MappingInbound:
Type: Simple
MappingOutbound:
Type: Simple
Type: Ticket::TicketCreate
ticket-get:
Description: ''
IncludeTicketData: '0'
MappingInbound:
Config:
KeyMapDefault:
MapTo: ''
MapType: Keep
ValueMapDefault:
MapTo: ''
MapType: Keep
Type: Simple
MappingOutbound:
Type: Simple
Type: Ticket::TicketGet
ticket-history-get:
Description: ''
IncludeTicketData: '0'
MappingInbound:
Type: Simple
MappingOutbound:
Type: Simple
Type: Ticket::TicketHistoryGet
ticket-search:
Description: ''
IncludeTicketData: '0'
MappingInbound:
Type: Simple
MappingOutbound:
Type: Simple
Type: Ticket::TicketSearch
ticket-update:
Description: ''
IncludeTicketData: '1'
MappingInbound:
Type: Simple
MappingOutbound:
Type: Simple
Type: Ticket::TicketUpdate
Transport:
Config:
AdditionalHeaders: ~
KeepAlive: '1'
MaxLength: '16000'
RouteOperationMapping:
session-create:
RequestMethod:
- HEAD
- OPTIONS
- PATCH
- POST
- PUT
Route: /session
ticket-create:
RequestMethod:
- HEAD
- OPTIONS
- POST
Route: /ticket
ticket-get:
RequestMethod:
- HEAD
- OPTIONS
- POST
Route: /ticket/get
ticket-history-get:
RequestMethod:
- HEAD
- OPTIONS
- POST
Route: /ticket/history
ticket-search:
RequestMethod:
- HEAD
- OPTIONS
- POST
Route: /ticket/search
ticket-update:
RequestMethod:
- HEAD
- OPTIONS
- PATCH
- PUT
Route: /ticket
Type: HTTP::REST
RemoteSystem: ''
Requester:
Transport:
Type: HTTP::RESTUtwórz nowego agenta
Utwórz nowego agenta OTOBO z bezpiecznym hasłem i nadaj mu uprawnienia potrzebne do wykonania zamierzonego zadania.
1. Konfiguracja klienta
from otobo import TicketOperation, OTOBOClientConfig
from otobo import AuthData
config = OTOBOClientConfig(
base_url="https://twój-serwer-otobo/nph-genericinterface.pl",
service="OTOBO",
auth=AuthData(UserLogin="user1", Password="SecurePassword"),
operations={
TicketOperation.CREATE.value: "ticket",
TicketOperation.SEARCH.value: "ticket/search",
TicketOperation.GET.value: "ticket/get",
TicketOperation.UPDATE.value: "ticket",
TicketOperation.HISTORY_GET.value: "ticket/history",
}
)2. Inicjalizacja klienta
import logging
from otobo import OTOBOClient
logging.basicConfig(level=logging.INFO)
client = OTOBOClient(config)3. Utwórz zgłoszenie
from otobo import (TicketOperation, OTOBOClientConfig, AuthData, TicketSearchParams, TicketCreateParams,
TicketHistoryParams, TicketUpdateParams, \
TicketGetParams, OTOBOClient, OTOBOTicketCreateResponse)
payload = TicketCreateParams(
Ticket={
"Title": "Nowe zamówienie",
"Queue": "Sales",
"State": "new",
"Priority": "3 normal",
"CustomerUser": "customer@example.com"
},
Article={
"Subject": "Zapytanie o produkt",
"Body": "Proszę o szczegóły dotyczące cen...",
"MimeType": "text/plain"
}
)
response: OTOBOTicketCreateResponse = await client.create_ticket(payload)
print(response.TicketID, response.TicketNumber)4. Wyszukaj i pobierz zgłoszenia
from otobo import TicketSearchParams, TicketGetParams
search_params = TicketSearchParams(Title="%Order%")
search_res = await client.search_tickets(search_params)
ids = search_res.TicketID
for ticket_id in ids:
get_params = TicketGetParams(TicketID=ticket_id, AllArticles=1)
details = await client.get_ticket(get_params)
print(details.Ticket[0])5. Zaktualizuj zgłoszenie
from otobo import TicketUpdateParams
update_params = TicketUpdateParams(
TicketID=response.TicketID,
Ticket={"State": "closed"}
)
await client.update_ticket(update_params)6. Pobierz historię zgłoszenia
from otobo import TicketHistoryParams
history_params = TicketHistoryParams(TicketID=str(response.TicketID))
history_res = await client.get_ticket_history(history_params)
print(history_res.History)7. Połączone wyszukiwanie i pobieranie
from otobo import FullTicketSearchResponse
full_res: FullTicketSearchResponse = await client.search_and_get(search_params)Licencja
MIT © Softoft, Tobias A. Bueck