OTOBO / Znuny Web Services – REST API
W tej szczegółowej instrukcji dowiesz się, jak aktywować, skonfigurować i zintegrować API REST OTOBO (część Interfejsu Ogólnego) z własnymi aplikacjami.
1. Architektura i podstawy
OTOBO udostępnia swój Interfejs Ogólny poprzez usługi internetowe REST i SOAP. API REST komunikuje się za pomocą HTTP(S)/JSON i umożliwia:
- Operacje na zgłoszeniach: tworzenie, pobieranie, modyfikowanie, usuwanie
- Operacje na artykułach: dodawanie, zarządzanie załącznikami
- Historia i wyszukiwanie: historia zgłoszeń i złożone zapytania wyszukiwania
Uwaga: Standardowa instalacja nie zawiera wstępnie skonfigurowanych usług internetowych – należy je utworzyć samodzielnie w module administracyjnym „Procesy i Automatyzacja → Usługi internetowe”.
2. Konfiguracja
2.1 Aktywacja Interfejsu Ogólnego
- W panelu administracyjnym → SysConfig → GenericInterface.Transport ustaw wartość na REST (HTTP).
- W sekcji AdminGenericInterfaceTransportHTTPREST skonfiguruj limity czasu, nagłówki hosta i poziom debugowania.
- W GenericInterface.Operation utwórz i aktywuj żądane operacje (np.
TicketCreate
,TicketSearch
,TicketGet
,TicketUpdate
,TicketDelete
,TicketHistoryGet
).
2.2 Podstawowy adres URL i uwierzytelnianie
Podstawowy URL
https://TWÓJ-SERWER/otobo/nph-genericinterface.pl/Webservice/<NAZWA_USŁUGI>/
Uwierzytelnianie
- Ciągki sesji OTOBO
- Klucze API / tokeny (tworzone przez SysConfig)
- Zawsze używaj HTTPS!
3. Punkty końcowe i metody HTTP (szczegóły)
Poniżej znajdziesz szczegółowy przegląd parametrów, możliwych odpowiedzi i praktycznych przykładów dla każdego punktu końcowego.
3.1 TicketCreate (POST)
URL: /Webservice/<NazwaUsługi>/TicketCreate
Metoda: POST
Opis: Tworzy nowe zgłoszenie i jednocześnie artykuł.
Parametr | Typ | Wymagany | Opis |
---|---|---|---|
SessionID | Integer | Tak¹ | ID sesji lub para UserLogin+Password |
UserLogin | String | Tak² | Login agenta (w połączeniu z hasłem) |
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 | Początkowy stan (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: albo SessionID, albo para UserLogin+Password.
² Jeśli nie ma tokenu SessionID.
Przykład żądania:
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": "Proszę o ofertę cenową…",
"MimeType": "text/plain"
}
}
}
Przykład odpowiedzi:
{
"Success": 1,
"ErrorMessage": "",
"Data": {
"TicketID": "12345",
"ArticleID": "67890"
}
}
3.2 TicketSearch (GET)
URL: /Webservice/<NazwaUsługi>/TicketSearch
Metoda: 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 uwierzytelnionej sesji |
Title | String/String[] | Nie | Wyszukiwanie z użyciem symboli wieloznacznych (%Zamówienie% ) |
TicketNumber | String/String[] | Nie | Numer(y) zgłoszenia |
QueueIDs | Integer[] | Nie | ID kolejek |
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 itd.) |
¹ Wymagane: albo para UserLogin+Password, albo SessionID.
² Jeśli nie przekazano pary logowania.
Przykład żądania:
GET /Webservice/MyConnectorREST/TicketSearch?UserLogin=agent1&Password=geheim&Title=%25Zamówienie%25 HTTP/1.1
Host: demo.otobo.org
Przykład odpowiedzi:
{
"Success": 1,
"Data": {
"TicketID": [1001,1005,1012]
}
}
3.3 TicketGet (GET)
URL: /Webservice/<NazwaUsługi>/TicketGet
Metoda: 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 uwierzytelnionej sesji |
TicketID | String/String[] | Tak | Jedno lub więcej ID zgłoszeń (oddzielone przecinkiem 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 | Maks. liczba zwracanych artykułów |
Attachments | Boolean | Nie | 1 = osadź załączniki w Base64 |
GetAttachmentContents | Boolean | Nie | 1 = załaduj również treści załączników |
HTMLBodyAsAttachment | Boolean | Nie | 1 = dołącz wersję HTML artykułu jako załącznik |
¹ Wymagane: albo para UserLogin+Password, albo SessionID.
² Jeśli nie przekazano pary logowania.
Przykład żądania:
GET /Webservice/MyConnectorREST/TicketGet?SessionID=42&TicketID=12345&AllArticles=1&DynamicFields=1 HTTP/1.1
Host: demo.otobo.org
Przykład odpowiedzi (skrócony):
{
"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":"Proszę o ofertę cenową…",
"Attachment":[{"Filename":"Oferta.pdf","Content":"JVBERi0x…="}]
}]
}]
}
}
3.4 TicketUpdate (PUT)
URL: /Webservice/<NazwaUsługi>/TicketUpdate
Metoda: PUT
Opis: Aktualizuje pola istniejącego zgłoszenia i opcjonalnie tworzy nowy artykuł.
Parametr | Typ | Wymagany | Opis |
---|---|---|---|
SessionID | Integer | Tak¹ | Token lub para UserLogin+Password² |
TicketID | Integer | Tak | ID zgłoszenia do aktualizacji |
Ticket.Title | String | Nie | Nowy tytuł |
Ticket.State | String | Nie | Nowy stan |
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 | Dodanie nowych załączników |
¹ Wymagane: albo SessionID, albo para UserLogin+Password.
² Jeśli nie ma tokenu SessionID.
Przykład żądania:
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":"Przypomnienie ustawione","Body":"Zgłoszenie jest przetwarzane." }
}
}
Przykład odpowiedzi:
{ "Success":1, "ErrorMessage":"", "Data":{ "TicketID":12345, "ArticleID":67891 } }
3.5 TicketDelete (DELETE)
URL: /Webservice/<NazwaUsługi>/TicketDelete
Metoda: DELETE
Opis: Trwale usuwa jedno lub więcej zgłoszeń.
Parametr | Typ | Wymagany | Opis |
---|---|---|---|
SessionID | Integer | Tak¹ | Token lub para UserLogin+Password² |
TicketID | String/Array | Tak | Jedno lub więcej ID zgłoszeń |
Przykład żądania:
DELETE /Webservice/MyConnectorREST/TicketDelete?SessionID=42&TicketID=12345 HTTP/1.1
Host: demo.otobo.org
Przykład odpowiedzi:
{ "Success":1, "ErrorMessage":"", "Data":{} }
3.6 TicketHistoryGet (GET)
URL: /Webservice/<NazwaUsługi>/TicketHistoryGet
Metoda: GET
Opis: Pobiera historię jednego lub więcej zgłoszeń.
Parametr | Typ | Wymagany | Opis |
---|---|---|---|
SessionID | Integer | Tak¹ | Token lub para UserLogin+Password² |
TicketID | String/Array | Tak | Jedno lub więcej ID zgłoszeń |
Przykład żądania:
GET /Webservice/MyConnectorREST/TicketHistoryGet?SessionID=42&TicketID=12345 HTTP/1.1
Host: demo.otobo.org
5. Rozszerzenia i dostosowania
5.1 Definicja WADL
Nowe zasoby w pliku 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: /MyTest
6. Obsługa błędów i logowanie
- Wskaźnik sukcesu:
Success: 0|1
- Komunikat o błędzie:
ErrorMessage
w JSON - Debugowanie: Ustaw w oknie transportu
Poziom debugowania
naDebug
→ wpisy logu będą widoczne w bazie danych
7. Przypadki użycia
Scenariusz | Opis |
---|---|
Automatyzacja między systemami | Tworzenie zgłoszeń z narzędzi monitorujących (Nagios, Zabbix) |
Synchronizacja danych | Aktualizacje wsadowe 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. Dodatkowe elementy interfejsu i integracja
Klonowanie usługi internetowej
Moduł obsługi błędów
Podsumowanie
API REST OTOBO jest elastyczne, wydajne i dzięki Interfejsowi Ogólnemu wysoce rozbudowalne. Niezależnie od tego, czy chcesz stworzyć proste zgłoszenie, czy zautomatyzować złożone procesy – z kilkoma kliknięciami w panelu administracyjnym i standardowymi żądaniami JSON możesz osiągnąć bezproblemową integrację z dowolnym środowiskiem IT.
Biblioteka klienta Python dla OTOBO
Asynchroniczna biblioteka Python do komunikacji z API REST OTOBO. Zbudowana z wykorzystaniem httpx
i pydantic
dla bezpieczeństwa typów i łatwości użycia.
Funkcje
Asynchroniczne żądania HTTP przy użyciu
httpx.AsyncClient
Modele Pydantic do walidacji danych żądań i odpowiedzi
Pełne operacje CRUD na zgłoszeniach:
TicketCreate
TicketSearch
TicketGet
TicketUpdate
TicketHistoryGet
Obsługa błędów poprzez
OTOBOError
dla błędów APIMetoda pomocnicza
search_and_get
do łączenia wyników wyszukiwania z szczegółowym pobieraniem
Instalacja
Zainstaluj z PyPI:
pip install otobo
Szybki start
Skonfiguruj usługi internetowe OTOBO:
Utwórz nową usługę internetową 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::REST
Utwórz nowego agenta
Utwórz nowego agenta OTOBO z bezpiecznym hasłem i nadaj mu odpowiednie uprawnienia.
1. Skonfiguruj klienta
from otobo import TicketOperation, OTOBOClientConfig
from otobo import AuthData
config = OTOBOClientConfig(
base_url="https://your-otobo-server/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. Zainicjuj 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 cenowe...",
"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="%Zamówienie%")
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