Turn your OTOBO API idea into a working integration
Get professional help with API design, Generic Interface configuration, implementation, testing, and handover.

In this guide: Activate, configure, and integrate the OTOBO REST API (Generic Interface) into your applications.
Related: Extend the Generic Interface · Web Services overview · OpenID Connect · Performance tuning · OTOBO automation & integration by Softoft
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.
Most teams looking for the OTOBO API want to connect another system or automate a ticket workflow. Softoft can design and implement Generic Interface web services, TicketCreate and TicketSearch flows, ERP or CRM synchronization, custom operations, authentication, and production-ready error handling.
Turn your OTOBO API idea into a working integration
Get professional help with API design, Generic Interface configuration, implementation, testing, and handover.
Book a 15-minute introductory call if you already have a concrete integration or automation requirement.
OTOBO provides its Generic Interface via REST and SOAP web services. The REST API communicates via HTTP(S)/JSON and enables:
Note: A standard installation does not contain preconfigured web services – you create them yourself in the admin module “Processes & Automation → Web Services”.
TicketCreate, TicketSearch, TicketGet, TicketUpdate, TicketDelete, TicketHistoryGet).Base URL
https://YOUR-SERVER/otobo/nph-genericinterface.pl/Webservice/<YourServiceName>/Authentication
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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| SessionID | Integer | Yes¹ | Session ID or UserLogin+Password |
| UserLogin | String | Yes² | Agent login (in combination with password) |
| Password | String | Yes² | Password (in combination with UserLogin) |
| Ticket.Title | String | Yes | Subject of the ticket |
| Ticket.Queue | String | Yes | Queue name or Ticket.QueueID |
| Ticket.State | String | Yes | Initial state (e.g., new) |
| Ticket.Priority | String | Yes | Priority (e.g., 3 normal) |
| Ticket.CustomerUser | String | Yes | Customer email or login |
| Article.Subject | String | Yes | Subject of the first article |
| Article.Body | String | Yes | Content of the first article |
| Article.MimeType | String | Yes | text/plain or text/html |
¹ Either SessionID OR UserLogin+Password required. ² If no SessionID token is available.
Example Request:
POST /Webservice/MyConnectorREST/TicketCreate HTTP/1.1Host: demo.otobo.orgContent-Type: application/jsonX-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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| UserLogin, Password | String,String | Yes¹ | Agent credentials or SessionID² |
| SessionID | Integer | Yes² | Token for authenticated sessions |
| Title | String/String[] | No | Wildcard search in title (%Order%) |
| TicketNumber | String/String[] | No | Ticket number(s) |
| QueueIDs | Integer[] | No | Queue IDs |
| States | String[] | No | States (new, open, …) |
| StateType | String/String[] | No | Open/Closed category |
| DynamicField_Name.Op | Mixed | No | Dynamic 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.1Host: demo.otobo.orgExample 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| UserLogin, Password | String,String | Yes¹ | Agent credentials or SessionID² |
| SessionID | Integer | Yes² | Token for authenticated sessions |
| TicketID | String/String[] | Yes | One or more ticket IDs (comma-separated or array) |
| DynamicFields | Boolean (0/1) | No | 1 = Dynamic fields in result, default = 0 |
| Extended | Boolean | No | 1 = Extended metadata (e.g., FirstResponse) |
| AllArticles | Boolean | No | 1 = Return all articles |
| ArticleLimit | Integer | No | Max. number of returned articles |
| Attachments | Boolean | No | 1 = Embed attachments in Base64 |
| GetAttachmentContents | Boolean | No | 1 = Also load attachment contents |
| HTMLBodyAsAttachment | Boolean | No | 1 = 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.1Host: demo.otobo.orgExample 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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| SessionID | Integer | Yes¹ | Token or UserLogin+Password² |
| TicketID | Integer | Yes | ID of the ticket to update |
| Ticket.Title | String | No | New title |
| Ticket.State | String | No | New state |
| Ticket.Owner | String/ID | No | New owner |
| Ticket.PendingTime | Hash / Diff | No | New pending time |
| Article.Subject | String | No | Creates a new article |
| Article.Body | String | No | Content of the new article |
| DynamicField… | Array | No | Update dynamic fields |
| Attachment… | Array | No | Add new attachments |
¹ Either SessionID OR UserLogin+Password. ² If no SessionID token is available.
Example Request:
PUT /Webservice/MyConnectorREST/TicketUpdate HTTP/1.1Host: demo.otobo.orgContent-Type: application/jsonX-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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| SessionID | Integer | Yes¹ | Token or UserLogin+Password² |
| TicketID | String/Array | Yes | One or more ticket IDs |
Example Request:
DELETE /Webservice/MyConnectorREST/TicketDelete?SessionID=42&TicketID=12345 HTTP/1.1Host: demo.otobo.orgExample Response:
{ "Success": 1, "ErrorMessage": "", "Data": {} }URL: /Webservice/<ServiceName>/TicketHistoryGet
Method: GET
Description: Retrieves the history of one or more tickets.
| Parameter | Type | Required | Description |
|---|---|---|---|
| SessionID | Integer | Yes¹ | Token or UserLogin+Password² |
| TicketID | String/Array | Yes | One or more ticket IDs |
Example Request:
GET /Webservice/MyConnectorREST/TicketHistoryGet?SessionID=42&TicketID=12345 HTTP/1.1Host: demo.otobo.orgExample Response (abbreviated):
{ "Success": 1, "ErrorMessage": "", "Data": { "TicketID": 12345, "History": [ { "HistoryType": "NewTicket", "Name": "New ticket created", "CreateTime": "2025-01-23 09:15:00" }, { "HistoryType": "StateUpdate", "Name": "Changed state to open", "CreateTime": "2025-01-23 10:02:11" } ] }}Need an endpoint that the stock ticket operations do not cover? The dedicated developer guide to custom OTOBO Generic Interface operations explains the complete implementation path: Perl backend, SysConfig registration, REST route, package lifecycle, security, and testing.
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::ModuleTransport: Config:RouteOperationMapping: MyTest: RequestMethod: [GET] Route: /MyTestSuccess: 0|1ErrorMessage in JSONDebug-Level to Debug in the transport dialog → Log entries visible in DB| Scenario | Description |
|---|---|
| Cross-system automation | Create tickets from monitoring tools (Nagios, Zabbix) |
| Data synchronization | Batch updates of ticket fields from external CRM |
| Self-service portals | Customers create their own tickets via REST |
| Mobile apps | Native iOS/Android apps communicate via REST |
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.
No. A standard installation has no preconfigured web services. You create them yourself under Processes & Automation → Web Services (or import a YAML definition like the one shown above).
You authenticate either with a SessionID (created via a SessionCreate operation) or by passing UserLogin + Password with each request. Always use HTTPS so credentials and tokens are never sent in clear text.
https://YOUR-SERVER/otobo/nph-genericinterface.pl/Webservice/<YourServiceName>/. Each operation (e.g. TicketCreate) is then mapped to a route you define in the transport configuration.
Out of the box you can configure TicketCreate, TicketSearch, TicketGet, TicketUpdate, TicketDelete, and TicketHistoryGet. You can add custom operations via the GenericInterface.
Yes — the open-source otobo package provides an async, typed client built on httpx and pydantic. See the quickstart below.
otoboThe OpenTicketAI package otobo is an asynchronous Python client for the OTOBO GenericInterface REST API. It uses httpx and pydantic for typed requests, response models, and ticket workflow helpers. See the full OpenTicketAI OTOBO Python SDK documentation for setup details.
Asynchronous HTTP requests using httpx.AsyncClient
Pydantic models for request and response data validation
Full CRUD operations for tickets:
TicketCreateTicketSearchTicketGetTicketUpdateTicketHistoryGetError handling via OTOBOError for API errors
Utility method search_and_get to combine search results with detailed retrieval
Install the package from PyPI:
pip install otoboCreate a new web service in OTOBO with the following configuration:
---Debugger: DebugThreshold: debug TestMode: "0"Description: ""FrameworkVersion: 11.0.5Provider: 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::RESTRemoteSystem: ""Requester: Transport: Type: HTTP::RESTCreate 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, OTOBOClientConfigfrom 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 loggingfrom 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
The examples above provide the building blocks. A reliable production integration also needs a stable API contract, least-privilege authentication, retries, monitoring, deployment, and documentation. Softoft can deliver the complete OTOBO REST API integration—from the first workflow design to production handover.
Need an OTOBO REST API specialist?
Tell us which system or workflow you want to connect. We will turn the requirement into a maintainable OTOBO automation.
Prefer a short first conversation? Book a 15-minute call.
Create and activate a web service in Admin → Web Services using the Generic Interface with the HTTP::REST transport.
TicketCreate, TicketUpdate, TicketGet, TicketSearch, and TicketHistoryGet are typical REST operations for integrations.
Integrations usually authenticate with a dedicated technical user (SessionCreate or BasicAuth), configured on the web service.