OTOBO / Znuny Web Services – API REST

En esta guía detallada, aprenderá cómo activar, configurar e integrar la API REST de OTOBO (parte de la Interfaz Genérica) en sus propias aplicaciones.
1. Arquitectura y Fundamentos
OTOBO proporciona su Interfaz Genérica a través de servicios web REST y SOAP. La API REST se comunica vía HTTP(S)/JSON y permite:
- Operaciones de Tickets: Crear, Obtener, Modificar, Eliminar
- Operaciones de Artículos: Publicar, Gestionar adjuntos
- Historial y Búsqueda: Historial de tickets y consultas de búsqueda complejas
Nota: Una instalación estándar no incluye servicios web preconfigurados; usted los crea en el módulo de administración "Procesos y Automatización → Servicios Web".
2. Configuración
2.1 Activar Interfaz Genérica
- En el área de Administración → SysConfig → GenericInterface.Transport, cambie a REST (HTTP).
- En AdminGenericInterfaceTransportHTTPREST, configure los tiempos de espera, la cabecera del host y el nivel de depuración.
- En GenericInterface.Operation, cree y active las operaciones deseadas (por ejemplo,
TicketCreate,TicketSearch,TicketGet,TicketUpdate,TicketDelete,TicketHistoryGet).
2.2 URL Base y Autenticación
URL Base
https://SU-SERVIDOR/otobo/nph-genericinterface.pl/Webservice/<SuServiceName>/Autenticación
- Cookies de sesión de OTOBO
- Claves API / Tokens (crear a través de SysConfig)
- ¡Usar siempre HTTPS!
3. Puntos Finales y Métodos HTTP (Detalle)
Para cada punto final, encontrará aquí una descripción detallada de los parámetros, posibles respuestas y ejemplos prácticos.
3.1 TicketCreate (POST)
URL: /Webservice/<ServiceName>/TicketCreateMétodo: POST
Descripción: Crea un nuevo ticket y genera un artículo al mismo tiempo.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| SessionID | Integer | Sí¹ | ID de sesión o UserLogin+Password |
| UserLogin | String | Sí² | Inicio de sesión del agente (con Password) |
| Password | String | Sí² | Contraseña (con UserLogin) |
| Ticket.Title | String | Sí | Asunto del ticket |
| Ticket.Queue | String | Sí | Nombre de la cola o Ticket.QueueID |
| Ticket.State | String | Sí | Estado inicial (por ejemplo, new) |
| Ticket.Priority | String | Sí | Prioridad (por ejemplo, 3 normal) |
| Ticket.CustomerUser | String | Sí | Correo electrónico o inicio de sesión del cliente |
| Article.Subject | String | Sí | Asunto del primer artículo |
| Article.Body | String | Sí | Contenido del primer artículo |
| Article.MimeType | String | Sí | text/plain o text/html |
¹ Se requiere SessionID O UserLogin+Password. ² Si no se proporciona un token SessionID.
Ejemplo de Solicitud:
POST /Webservice/MyConnectorREST/TicketCreate HTTP/1.1
Host: demo.otobo.org
Content-Type: application/json
X-API-Key: abc123
{
"Data": {
"SessionID": 42,
"Ticket": {
"Title": "Nuevo pedido",
"Queue": "Ventas",
"State": "new",
"Priority": "3 normal",
"CustomerUser": "max.mustermann@example.com"
},
"Article": {
"Subject": "Solicitud de compra – Producto XY",
"Body": "Solicito oferta de precio…",
"MimeType": "text/plain"
}
}
}Ejemplo de Respuesta:
{
"Success": 1,
"ErrorMessage": "",
"Data": {
"TicketID": "12345",
"ArticleID": "67890"
}
}3.2 TicketSearch (GET)
URL: /Webservice/<ServiceName>/TicketSearchMétodo: GET
Descripción: Busca tickets utilizando diversos criterios de filtro.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| UserLogin, Password | String,String | Sí¹ | Credenciales de agente o SessionID² |
| SessionID | Integer | Sí² | Token para sesiones autenticadas |
| Title | String/String[] | No | Búsqueda con comodines en el título (%Pedido%) |
| TicketNumber | String/String[] | No | Número(s) de ticket |
| QueueIDs | Integer[] | No | IDs de cola |
| States | String[] | No | Estados (new, open, …) |
| StateType | String/String[] | No | Categoría Abierto/Cerrado |
| DynamicField_Name.Op | Mixed | No | Campos dinámicos con operador (Equals, Like, GreaterThan …) |
¹ Se requiere UserLogin+Password O SessionID. ² Si no se proporciona un par de inicio de sesión.
Ejemplo de Solicitud:
GET /Webservice/MyConnectorREST/TicketSearch?UserLogin=agente1&Password=secreto&Title=%25Pedido%25 HTTP/1.1
Host: demo.otobo.orgEjemplo de Respuesta:
{
"Success": 1,
"Data": {
"TicketID": [1001,1005,1012]
}
}3.3 TicketGet (GET)
URL: /Webservice/<ServiceName>/TicketGetMétodo: GET
Descripción: Devuelve datos detallados del ticket, incluyendo artículos, adjuntos y campos dinámicos.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| UserLogin, Password | String,String | Sí¹ | Credenciales de agente o SessionID² |
| SessionID | Integer | Sí² | Token para sesiones autenticadas |
| TicketID | String/String[] | Sí | Uno o más IDs de ticket (separados por coma o array) |
| DynamicFields | Boolean (0/1) | No | 1 = Campos dinámicos en el resultado, Predeterminado = 0 |
| Extended | Boolean | No | 1 = Metadatos extendidos (por ejemplo, FirstResponse) |
| AllArticles | Boolean | No | 1 = Devolver todos los artículos |
| ArticleLimit | Integer | No | Número máximo de artículos a devolver |
| Attachments | Boolean | No | 1 = Incrustar adjuntos en Base64 |
| GetAttachmentContents | Boolean | No | 1 = Cargar también los contenidos de los adjuntos |
| HTMLBodyAsAttachment | Boolean | No | 1 = Añadir la versión HTML del artículo como adjunto |
¹ Se requiere UserLogin+Password O SessionID. ² Si no se proporciona un par de inicio de sesión.
Ejemplo de Solicitud:
GET /Webservice/MyConnectorREST/TicketGet?SessionID=42&TicketID=12345&AllArticles=1&DynamicFields=1 HTTP/1.1
Host: demo.otobo.orgEjemplo de Respuesta (abreviado):
{
"Success":1,
"Data":{
"Ticket":[{
"TicketID":12345,
"TicketNumber":"202501230001",
"Title":"Nuevo pedido",
"State":"open",
"DynamicField":[{"Name":"Urgency","Value":"high"}],
"Article":[{
"ArticleID":67890,
"Subject":"Solicitud de compra…",
"Body":"Solicito oferta de precio…",
"Attachment":[{"Filename":"Oferta.pdf","Content":"JVBERi0x…="}]
}]
}]
}
}3.4 TicketUpdate (PUT)
URL: /Webservice/<ServiceName>/TicketUpdateMétodo: PUT
Descripción: Actualiza campos de un ticket existente y opcionalmente crea un nuevo artículo.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| SessionID | Integer | Sí¹ | Token o UserLogin+Password² |
| TicketID | Integer | Sí | ID del ticket a actualizar |
| Ticket.Title | String | No | Nuevo título |
| Ticket.State | String | No | Nuevo estado |
| Ticket.Owner | String/ID | No | Nuevo propietario |
| Ticket.PendingTime | Hash / Diff | No | Nueva hora de espera |
| Article.Subject | String | No | Crea un nuevo artículo |
| Article.Body | String | No | Contenido del nuevo artículo |
| DynamicField… | Array | No | Actualizar campos dinámicos |
| Attachment… | Array | No | Añadir nuevos adjuntos |
¹ Se requiere SessionID O UserLogin+Password. ² Si no se proporciona un token SessionID.
Ejemplo de Solicitud:
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":"Recordatorio establecido","Body":"El ticket está siendo procesado." }
}
}Ejemplo de Respuesta:
{ "Success":1, "ErrorMessage":"", "Data":{ "TicketID":12345, "ArticleID":67891 } }3.5 TicketDelete (DELETE)
URL: /Webservice/<ServiceName>/TicketDeleteMétodo: DELETE
Descripción: Elimina permanentemente uno o varios tickets.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| SessionID | Integer | Sí¹ | Token o UserLogin+Password² |
| TicketID | String/Array | Sí | Uno o varios IDs de ticket |
Ejemplo de Solicitud:
DELETE /Webservice/MyConnectorREST/TicketDelete?SessionID=42&TicketID=12345 HTTP/1.1
Host: demo.otobo.orgEjemplo de Respuesta:
{ "Success":1, "ErrorMessage":"", "Data":{} }3.6 TicketHistoryGet (GET)
URL: /Webservice/<ServiceName>/TicketHistoryGetMétodo: GET
Descripción: Recupera el historial de uno o varios tickets.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| SessionID | Integer | Sí¹ | Token o UserLogin+Password² |
| TicketID | String/Array | Sí | Uno o varios IDs de ticket |
Ejemplo de Solicitud:
GET /Webservice/MyConnectorREST/TicketHistoryGet?SessionID=42&TicketID=12345,5. Extensión y Personalización
5.1 Definición WADL
Nuevos recursos en 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 Importación YAML
Alternativamente, vía YAML en development/webservices/GenericTicketConnectorREST.yml:
Provider:
Operation:
MyTest:
Description: "Operación de prueba"
MappingInbound: { }
MappingOutbound: { }
Type: Test::Module
Transport:
Config:
RouteOperationMapping:
MyTest:
RequestMethod: [ GET ]
Route: /MyTest6. Manejo de Errores y Registro
- Indicador de Éxito:
Success: 0|1 - Mensaje de Error:
ErrorMessageen el JSON - Depuración: Establezca
Debug-LevelenDebugen el diálogo de transporte → Entradas de registro visibles en la base de datos
7. Casos de Uso
| Escenario | Descripción |
|---|---|
| Automatización Inter-Sistemas | Crear tickets desde herramientas de monitorización (Nagios, Zabbix) |
| Sincronización de Datos | Actualizaciones por lotes de campos de tickets desde CRM externo |
| Portales de Autoservicio | Los clientes crean sus propios tickets vía REST |
| Aplicaciones Móviles | Aplicaciones nativas iOS/Android se comunican vía REST |
8. Otros Elementos de UI e Integración
Clonar Servicio Web
Módulo de Manejo de Errores
Conclusión
La API REST de OTOBO es flexible, eficiente y altamente extensible gracias a la Interfaz Genérica. Ya sea para la creación simple de tickets o para la automatización de flujos de trabajo complejos, con unos pocos clics en la administración y solicitudes JSON estándar, puede lograr integraciones perfectas en cualquier panorama de TI.
Biblioteca Cliente Python para OTOBO
Una biblioteca cliente Python asíncrona para interactuar con la API REST de OTOBO. Construida con httpx y pydantic para seguridad de tipos y facilidad de uso.
Características
Solicitudes HTTP asíncronas usando
httpx.AsyncClientModelos Pydantic para validación de datos de solicitud y respuesta
Operaciones CRUD completas para tickets:
TicketCreateTicketSearchTicketGetTicketUpdateTicketHistoryGet
Método de utilidad
search_and_getpara combinar resultados de búsqueda con recuperación detalladaManejo de errores a través de
OTOBOErrorpara errores de API
Instalación
Instalar desde PyPI:
pip install otoboInicio Rápido
Configurar Servicios Web de OTOBO:
Cree un nuevo servicio web en OTOBO con la siguiente configuración:
---
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::RESTCrear un nuevo Agente
Cree un nuevo Agente de Otobo con una contraseña segura y asígnele los permisos necesarios para la tarea que desea realizar.
1. Configurar el cliente
from otobo import TicketOperation, OTOBOClientConfig
from otobo import AuthData
config = OTOBOClientConfig(
base_url="https://su-servidor-otobo/nph-genericinterface.pl",
service="OTOBO",
auth=AuthData(UserLogin="usuario1", Password="ContraseñaSegura"),
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. Inicializar el cliente
import logging
from otobo import OTOBOClient
logging.basicConfig(level=logging.INFO)
client = OTOBOClient(config)3. Crear un ticket
from otobo import (TicketOperation, OTOBOClientConfig, AuthData, TicketSearchParams, TicketCreateParams,
TicketHistoryParams, TicketUpdateParams, \
TicketGetParams, OTOBOClient, OTOBOTicketCreateResponse)
payload = TicketCreateParams(
Ticket={
"Title": "Nuevo Pedido",
"Queue": "Ventas",
"State": "new",
"Priority": "3 normal",
"CustomerUser": "cliente@ejemplo.com"
},
Article={
"Subject": "Consulta de Producto",
"Body": "Por favor, envíen detalles de precios...",
"MimeType": "text/plain"
}
)
response: OTOBOTicketCreateResponse = await client.create_ticket(payload)
print(response.TicketID, response.TicketNumber)4. Buscar y recuperar tickets
from otobo import TicketSearchParams, TicketGetParams
search_params = TicketSearchParams(Title="%Pedido%")
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. Actualizar un ticket
from otobo import TicketUpdateParams
update_params = TicketUpdateParams(
TicketID=response.TicketID,
Ticket={"State": "closed"}
)
await client.update_ticket(update_params)6. Obtener historial de tickets
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. Búsqueda y obtención combinadas
from otobo import FullTicketSearchResponse
full_res: FullTicketSearchResponse = await client.search_and_get(search_params)Licencia
MIT © Softoft, Tobias A. Bueck