Skip to content

OTOBO Web Services – REST API

OTOBO REST API

In this comprehensive guide, you will learn how to activate, configure, and integrate the OTOBO REST API (part of the Generic Interface) into your own applications.

OTOBO provides its Generic Interface via REST and SOAP web services. The REST API communicates via HTTP(S)/JSON and enables:

  • Ticket Operations: Create, Retrieve, Update, Delete
  • Article Operations: Post, Manage Attachments
  • History & Search: Ticket history and complex search queries

Note: A standard installation does not contain preconfigured web services – you create them yourself in the admin module “Processes & Automation → Web Services”.

  1. In the Admin area → SysConfigGenericInterface.Transport, change to REST (HTTP).
  2. Under AdminGenericInterfaceTransportHTTPREST, set timeouts, host headers, and debug levels.
  3. In GenericInterface.Operation, create and activate the desired operations (e.g., TicketCreate, TicketSearch, TicketGet, TicketUpdate, TicketDelete, TicketHistoryGet).

Add Web Service Web Service Provider

  • Base URL

    https://YOUR-SERVER/otobo/nph-genericinterface.pl/Webservice/<YourServiceName>/
  • Authentication

    • OTOBO session cookies
    • API keys / tokens (create via SysConfig)
    • Always use HTTPS!

Set up REST Requester

For each endpoint, you will find a detailed overview of parameters, possible responses, and practical examples here.

URL: /Webservice/<ServiceName>/TicketCreate Method: POST

Description: Creates a new ticket and simultaneously creates an article.

ParameterTypeRequiredDescription
SessionIDIntegerYes¹Session ID or UserLogin+Password
UserLoginStringYes²Agent login (in combination with password)
PasswordStringYes²Password (in combination with UserLogin)
Ticket.TitleStringYesSubject of the ticket
Ticket.QueueStringYesQueue name or Ticket.QueueID
Ticket.StateStringYesInitial state (e.g., new)
Ticket.PriorityStringYesPriority (e.g., 3 normal)
Ticket.CustomerUserStringYesCustomer email or login
Article.SubjectStringYesSubject of the first article
Article.BodyStringYesContent of the first article
Article.MimeTypeStringYestext/plain or text/html

¹ Either SessionID OR UserLogin+Password required. ² If no SessionID token is available.

Example Request:

POST /Webservice/MyConnectorREST/TicketCreate HTTP/1.1
Host: demo.otobo.org
Content-Type: application/json
X-API-Key: abc123
{
"Data": {
"SessionID": 42,
"Ticket": {
"Title": "New Order",
"Queue": "Sales",
"State": "new",
"Priority": "3 normal",
"CustomerUser": "max.mustermann@example.com"
},
"Article": {
"Subject": "Purchase Inquiry – Product XY",
"Body": "Please provide a price quote…",
"MimeType": "text/plain"
}
}
}

Example Response:

{
"Success": 1,
"ErrorMessage": "",
"Data": {
"TicketID": "12345",
"ArticleID": "67890"
}
}

URL: /Webservice/<ServiceName>/TicketSearch Method: GET

Description: Searches for tickets based on various filter criteria.

ParameterTypeRequiredDescription
UserLogin, PasswordString,StringYes¹Agent credentials or SessionID²
SessionIDIntegerYes²Token for authenticated sessions
TitleString/String[]NoWildcard search in title (%Order%)
TicketNumberString/String[]NoTicket number(s)
QueueIDsInteger[]NoQueue IDs
StatesString[]NoStates (new, open, …)
StateTypeString/String[]NoOpen/Closed category
DynamicField_Name.OpMixedNoDynamic fields with operator (Equals, Like, GreaterThan …)

¹ Either UserLogin+Password OR SessionID. ² If no login pair is provided.

Example Request:

GET /Webservice/MyConnectorREST/TicketSearch?UserLogin=agent1&Password=secret&Title=%25Order%25 HTTP/1.1
Host: demo.otobo.org

Example Response:

{
"Success": 1,
"Data": {
"TicketID": [1001,1005,1012]
}
}

URL: /Webservice/<ServiceName>/TicketGet Method: GET

Description: Returns detailed ticket data including articles, attachments, and dynamic fields.

ParameterTypeRequiredDescription
UserLogin, PasswordString,StringYes¹Agent credentials or SessionID²
SessionIDIntegerYes²Token for authenticated sessions
TicketIDString/String[]YesOne or more ticket IDs (comma-separated or array)
DynamicFieldsBoolean (0/1)No1 = Dynamic fields in result, default = 0
ExtendedBooleanNo1 = Extended metadata (e.g., FirstResponse)
AllArticlesBooleanNo1 = Return all articles
ArticleLimitIntegerNoMax. number of returned articles
AttachmentsBooleanNo1 = Embed attachments in Base64
GetAttachmentContentsBooleanNo1 = Also load attachment contents
HTMLBodyAsAttachmentBooleanNo1 = Attach HTML version of the article as attachment

¹ Either UserLogin+Password OR SessionID. ² If no login pair is provided.

Example Request:

GET /Webservice/MyConnectorREST/TicketGet?SessionID=42&TicketID=12345&AllArticles=1&DynamicFields=1 HTTP/1.1
Host: demo.otobo.org

Example Response (abbreviated):

{
"Success":1,
"Data":{
"Ticket":[{
"TicketID":12345,
"TicketNumber":"202501230001",
"Title":"New Order",
"State":"open",
"DynamicField":[{"Name":"Urgency","Value":"high"}],
"Article":[{
"ArticleID":67890,
"Subject":"Purchase Inquiry…",
"Body":"Please provide a price quote…",
"Attachment":[{"Filename":"Quote.pdf","Content":"JVBERi0x…="}]
}]
}]
}
}

URL: /Webservice/<ServiceName>/TicketUpdate Method: PUT

Description: Updates fields of an existing ticket and optionally creates a new article.

ParameterTypeRequiredDescription
SessionIDIntegerYes¹Token or UserLogin+Password²
TicketIDIntegerYesID of the ticket to update
Ticket.TitleStringNoNew title
Ticket.StateStringNoNew state
Ticket.OwnerString/IDNoNew owner
Ticket.PendingTimeHash / DiffNoNew pending time
Article.SubjectStringNoCreates a new article
Article.BodyStringNoContent of the new article
DynamicField…ArrayNoUpdate dynamic fields
Attachment…ArrayNoAdd new attachments

¹ Either SessionID OR UserLogin+Password. ² If no SessionID token is available.

Example Request:

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 set","Body":"Ticket is being processed." }
}
}

Example Response:

{ "Success":1, "ErrorMessage":"", "Data":{ "TicketID":12345, "ArticleID":67891 } }

URL: /Webservice/<ServiceName>/TicketDelete Method: DELETE

Description: Permanently deletes one or more tickets.

ParameterTypeRequiredDescription
SessionIDIntegerYes¹Token or UserLogin+Password²
TicketIDString/ArrayYesOne or more ticket IDs

Example Request:

DELETE /Webservice/MyConnectorREST/TicketDelete?SessionID=42&TicketID=12345 HTTP/1.1
Host: demo.otobo.org

Example Response:

{ "Success":1, "ErrorMessage":"", "Data":{} }

URL: /Webservice/<ServiceName>/TicketHistoryGet Method: GET

Description: Retrieves the history of one or more tickets.

ParameterTypeRequiredDescription
SessionIDIntegerYes¹Token or UserLogin+Password²
TicketIDString/ArrayYesOne or more ticket IDs

Example Request:

GET /Webservice/MyConnectorREST/TicketHistoryGet?SessionID=42&TicketID=12345,

New resources in GenericTicketConnectorREST.wadl:

<resource path="MyTest" id="MyTest">
<method name="GET" id="GET_MyTest">
<response status="200">
<representation mediaType="application/json"/>
</response>
</method>
</resource>

Alternatively via YAML in development/webservices/GenericTicketConnectorREST.yml:

Provider:
Operation:
MyTest:
Description: "Test operation"
MappingInbound: { }
MappingOutbound: { }
Type: Test::Module
Transport:
Config:
RouteOperationMapping:
MyTest:
RequestMethod: [ GET ]
Route: /MyTest

Add SOAP Provider


  • Success indicator: Success: 0|1
  • Error message: ErrorMessage in JSON
  • Debugging: Set Debug-Level to Debug in the transport dialog → Log entries visible in DB

Webservice Debugger


ScenarioDescription
Cross-system automationCreate tickets from monitoring tools (Nagios, Zabbix)
Data synchronizationBatch updates of ticket fields from external CRM
Self-service portalsCustomers create their own tickets via REST
Mobile appsNative iOS/Android apps communicate via REST

Clone web service Error Handling Module

The OTOBO REST API is flexible, performant, and highly extensible thanks to the Generic Interface. Whether for simple ticket creation or complex workflow automation – with just a few clicks in the admin area and standard JSON requests, you can realize seamless integrations into any IT landscape.

An asynchronous Python client for interacting with the OTOBO REST API. Built with httpx and pydantic for type safety and ease of use.

  • Asynchronous HTTP requests using httpx.AsyncClient

  • Pydantic models for request and response data validation

  • Full CRUD operations for tickets:

    • TicketCreate
    • TicketSearch
    • TicketGet
    • TicketUpdate
    • TicketHistoryGet
  • Error handling via OTOBOError for API errors

  • Utility method search_and_get to combine search results with detailed retrieval

Install from PyPI:

Terminal window
pip install otobo

Create a new web service in OTOBO with the following configuration:

---
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

Create a new Otobo Agent with a secure password and give it the permissions needed for the thing you want to accomplish.

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",
}
)
import logging
from otobo import OTOBOClient
logging.basicConfig(level=logging.INFO)
client = OTOBOClient(config)
from otobo import (TicketOperation, OTOBOClientConfig, AuthData, TicketSearchParams, TicketCreateParams,
TicketHistoryParams, TicketUpdateParams, \
TicketGetParams, OTOBOClient, OTOBOTicketCreateResponse)
payload = TicketCreateParams(
Ticket={
"Title": "New Order",
"Queue": "Sales",
"State": "new",
"Priority": "3 normal",
"CustomerUser": "customer@example.com"
},
Article={
"Subject": "Product Inquiry",
"Body": "Please send pricing details...",
"MimeType": "text/plain"
}
)
response: OTOBOTicketCreateResponse = await client.create_ticket(payload)
print(response.TicketID, response.TicketNumber)
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])
from otobo import TicketUpdateParams
update_params = TicketUpdateParams(
TicketID=response.TicketID,
Ticket={"State": "closed"}
)
await client.update_ticket(update_params)
from otobo import TicketHistoryParams
history_params = TicketHistoryParams(TicketID=str(response.TicketID))
history_res = await client.get_ticket_history(history_params)
print(history_res.History)
from otobo import FullTicketSearchResponse
full_res: FullTicketSearchResponse = await client.search_and_get(search_params)

MIT © Softoft, Tobias A. Bueck