Problemas en Codenica API
Para trabajar con problemas mediante Codenica API, empieza por crear una clave en los ajustes de Codenica. Si todavía no has creado una clave, abre en una pestaña nueva Codenica API - introducción. Allí encontrarás las reglas comunes para emitir claves, guardar el secreto y autenticar las solicitudes.
El nombre técnico del módulo es problems y el tipo de un objeto individual es problem. Un problema sirve para registrar la causa o el origen de incidentes recurrentes. Además de los datos descriptivos, cuenta con los campos de diagnóstico isKnown, symptoms, rootCause e impactInfo.
En las secciones siguientes encontrarás la dirección, los scopes, el esquema, las listas, los filtros, la creación, la edición, ETag, las operaciones batch, las relaciones, los usuarios, los archivos, las acciones de flujo de trabajo, el escalado, la aprobación y la eliminación de problemas.
Los ejemplos utilizan el prefijo PUBLIC-API-PROBLEM-20260905131727. En tu integración, sustitúyelo por tu propio identificador y adapta las direcciones de correo, los identificadores y los valores de los campos a los datos de tu base.
Problemas - dirección de la API y modelo de instalación
Todas las rutas relacionadas con los problemas comienzan por:
{BASE_URL}/api/v1/problemsEn Codenica Cloud, utiliza el dominio público asignado a la instalación correspondiente:
export BASE_URL="https://twoja-firma.codenica.com"En la instalación On-Premise predeterminada, la dirección registrada localmente por Codenica Discovery es:
export BASE_URL="http://codenica.local:5150"Si el administrador ha publicado la instalación con un dominio de empresa, mediante un proxy inverso, con HTTPS o en otro puerto, utiliza la dirección exacta proporcionada para esa instalación:
export BASE_URL="https://api.twoja-firma.example"No utilices localhost si la integración se ejecuta en un equipo distinto de la API. No envíes tenantId en el body ni en la query string. La base de datos correcta se selecciona a partir de la dirección del host al que se conecta la integración.
Problemas - clave API y límites de licencia
Crea una clave API en Codenica, en Ajustes - API - API Keys. El secreto solo se muestra una vez, justo después de crear o rotar la clave. En ese momento, guarda el Client ID y el Client Secret en el almacén seguro que utilice la integración.
Codenica API está disponible con las licencias Plus y Enterprise. Plus permite crear hasta 50 claves activas y Enterprise hasta 100. Starter no ofrece Codenica API. Crea una clave independiente para cada aplicación y entorno para poder limitar sus scopes, rotar el secreto o eliminar el acceso por separado.
La validez predeterminada de una clave es de 90 días si no estableces otra fecha en el panel. El plazo máximo de validez es de 5 años. Las claves caducadas o inactivas no ocupan un slot activo, pero siguen visibles hasta que utilices la opción Eliminar. La eliminación del registro es permanente.
Problemas - autenticación y solicitudes seguras
Autentica cada solicitud de Codenica API con las dos cabeceras de la clave:
export CLIENT_ID="cna_twoj_client_id"
export CLIENT_SECRET="cns_twoj_client_secret"
curl --request GET --url "$BASE_URL/api/v1/problems?page=1&pageSize=25" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Una integración externa no necesita el JWT del administrador ni las cookies del panel de Codenica. No incluyas la clave en un repositorio, en código enviado al navegador, en una URL, en el historial de comandos ni en los registros. Fuera de las pruebas locales, utiliza HTTPS.
Conserva meta.requestId de la respuesta. Sirve para diagnosticar una solicitud concreta, pero no sustituye al identificador del problema ni debe utilizarse como secreto.
Problemas - comprobación del contexto de conexión
Obtén el contexto antes del primer registro. Así podrás comprobar que la dirección lleva a la base correcta y que la clave seleccionada tiene los scopes necesarios:
curl --request GET --url "$BASE_URL/api/v1/context" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"En la respuesta, verifica:
data.apiVersionydata.contractVersion;data.tenant.id,data.tenant.nameydata.tenant.resolvedDomain;data.caller.authenticationigual aapi_key;- la presencia de
problemsendata.capabilities.resources; - los scopes asignados a la clave;
- los límites de páginas, batch, archivos y solicitudes.
Si el contexto indica otra base o no contiene un scope necesario, detén la integración y corrige la dirección o la clave. Los scopes no se pueden añadir a una solicitud individual.
Problemas - scopes de permisos
La gestión completa de problemas requiere los scopes correspondientes a las operaciones que vayas a utilizar:
problems:read
problems:write
problems:delete
problems:schema
problems:stats
problems:relationships:read
problems:relationships:write
problems:users:read
problems:users:write
problems:files:read
problems:files:write
problems:technical:read
problems:technical:write
problems:pin:write
problems:spam:write
problems:reopen:write
problems:rating:write
problems:escalation:write
problems:approval:writePara una lectura normal basta con problems:read. El esquema y las estadísticas requieren los scopes independientes problems:schema y problems:stats. La lectura de relaciones, usuarios y archivos requiere los scopes de lectura correspondientes. Las operaciones de escritura utilizan los scopes :write equivalentes.
Las relaciones con otros módulos también requieren acceso de lectura al módulo indicado, por ejemplo assets:read, documents:read, tickets:read o solutions:read. Para crear una aprobación y registrar su decisión, añade los scopes necesarios para el propio módulo approvals. Concede los scopes siguiendo el principio de mínimo privilegio.
Problemas - esquema y campos de diagnóstico
El esquema muestra qué campos se pueden leer y escribir en una base concreta. Obtenlo antes de preparar un formulario o un mapeo:
curl --request GET --url "$BASE_URL/api/v1/problems/schema" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para cada campo, comprueba entre otros readable, writable, required, technical, unique y maxLength. El esquema también devuelve los diccionarios y los destinos de relación disponibles.
Actualmente, el registro mínimo de un problema requiere subject y requesterEmail. Los problemas tienen su propio grupo de diagnóstico:
subject, requesterEmail, description, commentstype, status, priority, impact, urgency, severityisKnown, symptoms, rootCause, impactInfosource, services, tags, externalNumber, referenceNumberLos campos pin e isSpam son técnicos y se modifican mediante acciones específicas. Los campos del sistema y los de solo lectura, incluidos los datos de valoración y escalado, no deben enviarse en un PATCH normal. Los problemas no admiten los campos de costes currency, estimatedCost y totalValue conocidos de otros módulos.
Problemas - endpoints básicos
Estas son las rutas de problemas más utilizadas:
GET /api/v1/problems- lista de problemas;GET /api/v1/problems/{id}- problema individual;POST /api/v1/problems- creación;PATCH /api/v1/problems/{id}- edición parcial;DELETE /api/v1/problems/{id}- eliminación;GET /api/v1/problems/schema- esquema de campos y relaciones;GET /api/v1/problems/stats- estadísticas;GET /api/v1/problems/values- valores utilizados en los filtros;POST /api/v1/problems:batch- operaciones de creación, actualización y eliminación.
Las relaciones, los usuarios, los archivos, las acciones de flujo de trabajo y las aprobaciones tienen rutas independientes. Así, la integración puede recibir únicamente los permisos que realmente necesita.
Problemas - listado y paginación
Obtén la lista por páginas. Incluso con pocos registros, indica expresamente el número y el tamaño de la página:
curl --request GET --url "$BASE_URL/api/v1/problems?page=1&pageSize=25" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La respuesta contiene data.items y los datos page, pageSize, totalItems, totalPages y hasNextPage. Obtén las páginas siguientes mientras hasNextPage tenga el valor true:
curl --request GET --url "$BASE_URL/api/v1/problems?page=2&pageSize=25&sort=dateUpdated&direction=desc" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para la sincronización, normalmente resulta más práctico ordenar por dateUpdated y guardar los últimos registros procesados. No establezcas pageSize por encima del límite devuelto en el contexto.
Problemas - búsqueda, filtros y ordenación
Puedes combinar los parámetros de la lista. El ejemplo siguiente busca un registro por identificador, limita el resultado al tipo problem y a los problemas conocidos, y después lo ordena por fecha de actualización:
curl --get --url "$BASE_URL/api/v1/problems" \
--data-urlencode "itemType=problem" \
--data-urlencode "customId=PUBLIC-API-PROBLEM-20260905131727-SOURCE" \
--data-urlencode "isKnown=true" \
--data-urlencode "sort=dateUpdated" \
--data-urlencode "direction=desc" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=25" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para la sincronización diaria también son útiles los parámetros search, status, priority, subject, requesterEmail, source, externalNumber, referenceNumber, symptoms, rootCause, impactInfo, createdAfter, createdBefore, updatedAfter y updatedBefore, siempre que estén disponibles en el esquema actual.
El filtro estructural tiene el formato field:operator:value. Los operadores disponibles son eq, ne, in, contains, startsWith, endsWith, empty, notEmpty, gt, gte, lt y lte:
curl --get --url "$BASE_URL/api/v1/problems" \
--data-urlencode "filter=status:eq:Closed" \
--data-urlencode "filter=rootCause:contains:connection" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=25" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Codifica los valores de texto y las fechas según las reglas de las URL. No des por hecho que el diccionario es idéntico en dos bases.
Problemas - selección de campos y datos incluidos
El parámetro fields limita la respuesta a los campos que necesita la integración. El parámetro include añade datos relacionados:
curl --get --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}" \
--data-urlencode "fields=subject,requesterEmail,status,priority,isKnown,symptoms,rootCause,impactInfo" \
--data-urlencode "include=files,relationships,users" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para leer el modelo completo puedes utilizar fields=*. Incluir archivos, relaciones y usuarios requiere los scopes de lectura correspondientes. fields no evita el control de acceso ni muestra campos técnicos para los que la clave no tiene permisos.
En la respuesta, presta atención a data.id, data.itemType, data.attributes y data.meta. Lee los campos técnicos, como pin o isSpam, pero modifícalos mediante las acciones específicas descritas más adelante.
Problemas - estadísticas y valores de diccionario
Las estadísticas permiten, por ejemplo, contar los problemas según el campo isKnown. Es una operación de lectura y no modifica los registros:
curl --get --url "$BASE_URL/api/v1/problems/stats" \
--data-urlencode "field=isKnown" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Obtén por separado los valores del campo rootCause cuando los necesites para sugerencias o filtros:
curl --get --url "$BASE_URL/api/v1/problems/values" \
--data-urlencode "field=rootCause" \
--data-urlencode "search=connection" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Obtén primero el diccionario y envía el valor en el body solo después. Esto es especialmente importante para status, priority, type y los campos de diagnóstico configurados en la base concreta.
Problemas - creación de un registro
Crea un problema nuevo mediante POST /api/v1/problems. Incluye el tipo técnico problem en el body y los campos modificables dentro de attributes. El ejemplo contiene datos descriptivos, clasificación, información de integración y el grupo de diagnóstico completo:
export IDEMPOTENCY_KEY="public-api-problem-create-20260905131727"
curl --request POST --url "$BASE_URL/api/v1/problems" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--data-raw '{
"itemType": "problem",
"attributes": {
"customId": "PUBLIC-API-PROBLEM-20260905131727-SOURCE",
"subject": "Problema de integración de Codenica API",
"requesterEmail": "[email protected]",
"description": "Problema creado mediante la integración de Codenica API.",
"comments": "Ejemplo de diagnóstico para el módulo Problems.",
"source": "Codenica API",
"type": "Standard",
"status": "Closed",
"priority": "High",
"impact": "Medium",
"urgency": "High",
"severity": "High",
"services": "Codenica API",
"tags": "codenica-api,problem",
"externalNumber": "EXT-CODENICA-API-PROBLEM-20260905131727",
"referenceNumber": "REF-CODENICA-API-PROBLEM-20260905131727",
"isKnown": true,
"symptoms": "Los usuarios no pueden completar la sincronización.",
"rootCause": "Error de conexión con el servicio externo.",
"impactInfo": "La sincronización del grupo de datos afectado se ha retrasado."
},
"customValues": [
{
"name": "description",
"valuePattern": "[problem-test] PUBLIC-API-PROBLEM-20260905131727"
}
]
}'El mínimo requerido es subject y requesterEmail, salvo que el esquema imponga requisitos adicionales. Una creación correcta devuelve HTTP 201, el identificador data.id y un ETag en la cabecera y en data.meta.etag. El secreto de la clave no forma parte de la respuesta del objeto.
Problemas - idempotencia de la creación
Repetir la misma solicitud con el mismo Idempotency-Key debe devolver el mismo resultado lógico y no crear un segundo problema:
curl --request POST --url "$BASE_URL/api/v1/problems" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: public-api-problem-create-20260905131727" \
--data-binary @problem.jsonDespués de un resultado de red incierto, puedes repetir la misma clave de forma segura únicamente para esa misma solicitud. No utilices una clave para dos operaciones diferentes. Genera una clave nueva para un body nuevo.
Idempotency-Key es obligatorio en todas las solicitudes que modifican datos, incluidas la edición, las relaciones, los archivos, las acciones de flujo de trabajo y la eliminación. Reutilizar la misma clave con otra ruta u otro body provoca un conflicto de idempotencia.
Problemas - lectura y ETag
Lee un problema individual con sus datos incluidos de la siguiente manera:
curl --get --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}" \
--data-urlencode "fields=*" \
--data-urlencode "include=files,relationships,users" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Conserva el ETag de la cabecera de respuesta. Debe coincidir con data.meta.etag y meta.etag dentro del envoltorio de respuesta. Después de cada escritura, acción, cambio de relación u operación de archivos, obtén o vuelve a leer el ETag actualizado.
Un ETag representa la versión de un problema concreto. No utilices el ETag obtenido para un problema para modificar otro.
Problemas - edición con If-Match
La edición es parcial. Envía únicamente los campos que quieras cambiar:
curl --request PATCH --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-update-20260905131727" \
--data-raw '{
"attributes": {
"description": "Descripción actualizada mediante la integración.",
"status": "Closed",
"priority": "High",
"isKnown": false,
"symptoms": "Síntomas tras una nueva observación.",
"rootCause": "Análisis actualizado de la causa raíz.",
"impactInfo": "Impacto después de aplicar la solución alternativa."
}
}'No modifiques mediante un PATCH normal los campos de solo lectura, como rating, dateRating, dateFeedback, dateReopened y dateEscalated. Pin, spam, reopen, rating, escalado y approval tienen endpoints específicos.
Después de una edición correcta recibirás HTTP 200 y un ETag nuevo. Guárdalo antes de la siguiente operación.
Problemas - control de un If-Match desactualizado
Toda mutación, excepto la creación, requiere el ETag actual. Se rechazan tanto la ausencia de la cabecera como un valor desactualizado:
curl --request PATCH --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: public-api-problem-missing-if-match-20260905131727" \
--data-raw '{"attributes":{"isKnown":false}}'La ausencia de If-Match devuelve HTTP 428 con el código if_match_required. Si envías un ETag anterior, recibirás HTTP 412 con el código if_match_failed. Una solicitud rechazada no debe modificar el problema.
Después de HTTP 412, vuelve a obtener el registro, lee el ETag nuevo y decide entonces si puedes repetir la edición. No sobrescribas sin comprobar los cambios realizados por otro usuario o proceso.
Problemas - operaciones batch
Batch sirve para gestionar varios elementos independientes. Una solicitud puede contener operaciones de create, update y delete:
curl --request POST --url "$BASE_URL/api/v1/problems:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: public-api-problem-batch-20260905131727" \
--data-raw '{
"items": [
{
"operation": "create",
"create": {
"itemType": "problem",
"attributes": {
"customId": "PUBLIC-API-PROBLEM-20260905131727-BATCH-A",
"subject": "Problema del batch A",
"requesterEmail": "[email protected]",
"source": "Codenica API",
"type": "Standard",
"status": "Open",
"priority": "Medium",
"isKnown": true,
"symptoms": "Síntomas del problema A",
"rootCause": "Causa raíz del problema A",
"impactInfo": "Impacto del problema A"
}
}
},
{
"operation": "update",
"id": "PROBLEM_UUID",
"ifMatch": "\"CURRENT_ETAG\"",
"update": {
"attributes": {
"isKnown": false,
"rootCause": "Nuevo análisis de la causa raíz"
}
}
},
{
"operation": "delete",
"id": "OTHER_PROBLEM_UUID",
"ifMatch": "\"OTHER_CURRENT_ETAG\""
}
]
}'En batch update y delete, utiliza el ETag del registro concreto. La clave de idempotencia identifica toda la solicitud batch, no cada elemento. Comprueba la respuesta elemento por elemento, según su índice, estado, identificador y error. El éxito completo suele devolver HTTP 200 y un resultado parcial HTTP 207 Multi-Status. Batch no es una transacción all-or-nothing.
Problemas - relaciones con objetos
Los destinos de relación disponibles se devuelven en /api/v1/problems/schema. El contrato actual puede incluir:
assets
documents
changes
tickets
problems
solutions
releases
notes
approvals
worktasks
requesteditemsQue un destino aparezca en el esquema no significa que exista un registro accesible en la base concreta. Antes de añadir una relación, comprueba el identificador, targetDataSet, targetItemType y los permisos de lectura del destino.
Para assets, documents, problems, changes, tickets, solutions y releases, utiliza un relationshipType permitido por el esquema, por ejemplo related. Para notes, approvals, worktasks y requesteditems, deja relationshipType en null. No fuerces related cuando no esté admitido.
Añadir varias relaciones:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/relationships:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-relationships-20260905131727" \
--data-raw '{
"add": [
{
"targetId": "ASSET_UUID",
"targetDataSet": "assets",
"targetItemType": "computer",
"relationshipType": "related"
},
{
"targetId": "DOCUMENT_UUID",
"targetDataSet": "documents",
"targetItemType": "invoice",
"relationshipType": "related"
},
{
"targetId": "NOTE_UUID",
"targetDataSet": "notes",
"targetItemType": "note",
"relationshipType": null
}
],
"remove": []
}'La respuesta HTTP 200 contiene los contadores added, removed y skipped. skipped no es un error de transporte, por lo que después de la operación debes obtener la colección de relaciones y comprobar su contenido.
Problemas - lectura y eliminación de relaciones
Obtén la lista de relaciones de esta forma:
curl --request GET --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/relationships?page=1&pageSize=100" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Elimina una relación individual con el ETag actual del problema de origen. Para un destino que conserve relationshipType, indícalo en la query string:
curl --request DELETE --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/relationships/tickets/{TICKET_ID}?relationshipType=related" \
--header "Accept: application/json, application/problem+json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-relationship-delete-20260905131727"Para un destino como notes, cuyo esquema indica que no utiliza tipo de relación, omite el parámetro relationshipType. También puedes eliminar una relación mediante una edición parcial:
curl --request PATCH --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-relationship-patch-20260905131727" \
--data-raw '{
"relationshipsToRemove": [
{
"targetId": "TICKET_UUID",
"targetDataSet": "tickets",
"targetItemType": "ticket",
"relationshipType": "related"
}
]
}'Eliminar una relación no elimina el registro que era su destino. Después de cada cambio, vuelve a obtener la colección y guarda el ETag nuevo del problema.
Problemas - relaciones con usuarios
Un problema puede tener las siguientes relaciones de usuario:
agent- persona responsable de la gestión;watcher- observador;appUserRequester- usuario de la aplicación que comunicó el problema.
Para Problems, no des por supuesta una relación clientRequester. Los destinos son usuarios activos y están sujetos a los controles de acceso de ubicación y departamento.
Asignar un agente:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/user-relationships" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-agent-20260905131727" \
--data-raw '{
"targetId": "USER_UUID",
"targetDataSet": "users",
"relationshipType": "agent"
}'Añadir un observador mediante batch:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/user-relationships:batch" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-watcher-20260905131727" \
--data-raw '{
"add": [
{
"targetId": "WATCHER_USER_UUID",
"targetDataSet": "users",
"relationshipType": "watcher"
}
],
"remove": []
}'Leer y eliminar relaciones:
curl --request GET --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/user-relationships?page=1&pageSize=100" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"
curl --request DELETE --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/user-relationships/users/{USER_ID}?relationshipType=agent" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-agent-delete-20260905131727"También puedes eliminar un observador mediante batch dejando add vacío e incluyendo la entrada en remove. Lee el ETag nuevo después de cada cambio.
Problemas - archivos
Antes de operar con un archivo, lee el problema actual y su ETag. Para enviar un archivo se necesita una solicitud multipart/form-data:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/files?relationshipType=documentation" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-file-one-20260905131727" \
--form "[email protected];type=text/plain"Lista de archivos:
curl --request GET --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/files?page=1&pageSize=100" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Cada elemento de la lista contiene, entre otros, id, name, fileName, contentType, size, relationshipType, isMain y downloadUrl. Trata downloadUrl como una ruta de la API, no como un enlace público anónimo. En Problems, isMain siempre es false.
Descarga el contenido como datos binarios:
curl --request GET --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/files/{FILE_ID}/content" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--output problem-evidence.txtPuedes asociar un archivo existente a otro problema. En ese caso, el ETag corresponde al problema de destino:
curl --request POST --url "$BASE_URL/api/v1/problems/{OTHER_PROBLEM_ID}/files/{FILE_ID}?relationshipType=manual" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $OTHER_PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-file-attach-20260905131727"Eliminar un archivo:
curl --request DELETE --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/files/{FILE_ID}" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-file-delete-20260905131727"Lee el límite de tamaño de archivo en context antes de subirlo. No cargues un archivo grande en memoria sin comprobar antes el límite.
Problemas - fijar, spam y reabrir
Fijar, marcar como spam y reabrir son acciones independientes. Cada acción requiere el ETag actual y una clave de idempotencia nueva.
Fijar un problema:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/pin" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-pin-20260905131727" \
--data-raw '{"pin":2}'El valor de pin puede ser un número del 0 al 3 o null, según el esquema. Marcar y desmarcar como spam:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/spam" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-spam-on-20260905131727" \
--data-raw '{"isSpam":true}'
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/spam" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-spam-off-20260905131727" \
--data-raw '{"isSpam":false}'Reabrir un problema cerrado:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/reopen" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-reopen-20260905131727"Los scopes necesarios son, respectivamente, problems:pin:write, problems:spam:write y problems:reopen:write. Obtén de nuevo el problema después de cada acción y guarda el ETag actualizado.
Problemas - valoración y escalado
La valoración se guarda mediante un endpoint independiente. Puedes incluir una solicitud de escalado:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/rating" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-rating-20260905131727" \
--data-raw '{
"rating": 4,
"feedback": "Valoración de la integración de Codenica API.",
"isEscalationRequested": true,
"escalationRequestReason": "El problema requiere el análisis del equipo de segundo nivel."
}'La valoración va de 0 a 5 y requiere el scope problems:rating:write. Añadir una solicitud de escalado requiere además problems:escalation:write y los permisos adecuados para el usuario. Si solo guardas una valoración, omite los campos de escalado. Después de guardarla, vuelve a leer al menos rating, feedback, las fechas de valoración y escalationRequestReason.
Problemas - aprobación y decisión
Puedes crear una aprobación como objeto approval independiente y relacionarla con el problema. La persona indicada en approverId debe tener permiso para tomar la decisión:
curl --request POST --url "$BASE_URL/api/v1/approvals" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: public-api-problem-approval-create-20260905131727" \
--data-raw '{
"itemType": "approval",
"approverId": "APPROVER_USER_UUID",
"attributes": {
"customId": "PUBLIC-API-PROBLEM-20260905131727-APPROVAL",
"category": "Codenica API",
"description": "Aprobación del análisis del problema."
},
"relationships": [
{
"targetId": "PROBLEM_UUID",
"targetDataSet": "problems",
"targetItemType": "problem"
}
]
}'Después de crearla, lee la aprobación y registra la decisión mediante la ruta del problema. APPROVAL_ID es el identificador de la aprobación, no el de un usuario:
curl --request POST --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}/approvals/{APPROVAL_ID}" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-approval-decision-20260905131727" \
--data-raw '{
"approve": true,
"remark": "Aprobado mediante la integración de Codenica API."
}'Para rechazarla, envía approve con el valor false y tu propio comentario. Después de la decisión, vuelve a leer la aprobación y comprueba su estado o la fecha de decisión. A continuación, actualiza el problema, porque la decisión puede cambiar su ETag y el estado del proceso.
Problemas - eliminación de un registro
Antes de eliminarlo, vuelve a obtener el problema y utiliza su ETag actual:
curl --request DELETE --url "$BASE_URL/api/v1/problems/{PROBLEM_ID}" \
--header "Accept: application/json, application/problem+json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "If-Match: $PROBLEM_ETAG" \
--header "Idempotency-Key: public-api-problem-delete-20260905131727"Después de HTTP 200, realiza un GET de control con el mismo UUID. Espera HTTP 404 con el código problem_not_found u otro código indicado en el contrato. Si el problema tiene relaciones, archivos o una aprobación, comprueba antes las consecuencias en el esquema y los requisitos de tu base.
Eliminar un problema no debe sustituir al archivado del historial. Si el registro debe permanecer en la documentación, cambia su estado o traslada los datos a un sistema destinado a conservar el historial.
Problemas - errores, límites y seguridad
Los errores se devuelven en formato application/problem+json. Ejemplo de respuesta:
{
"type": "https://docs.codenica.com/errors/problem_not_found",
"title": "Problem not found.",
"status": 404,
"detail": "The problem does not exist or is outside the caller's access scope.",
"instance": "/api/v1/problems/PROBLEM_UUID",
"code": "problem_not_found",
"requestId": "request-id-from-response"
}En la lógica de integración, utiliza principalmente status y code. El campo detail está pensado para las personas y su texto puede cambiar.
Lee las cabeceras X-RateLimit-Limit y X-RateLimit-Remaining. Después de 429, aplica un retraso progresivo y respeta el posible Retry-After. En los registros guarda el método, el endpoint, el estado y requestId, pero nunca el Client Secret ni las cabeceras de autenticación completas.
Los datos de problemas pueden contener información operativa, personal y de diagnóstico. Limita los campos, utiliza HTTPS y restringe el acceso de la integración a la base concreta.
Problemas - flujo de integración
- Establece
BASE_URLpara la instalación Cloud u On-Premise correcta. - Crea una clave independiente en Ajustes - API - API Keys y selecciona los scopes mínimos.
- Guarda Client ID y Client Secret en un almacén seguro.
- Envía
GET /api/v1/contexty comprueba la base, el caller y los límites. - Obtén
GET /api/v1/problems/schemay crea el mapeo de los campos de diagnóstico. - Obtén la lista de problemas o crea uno nuevo con
POSTy unIdempotency-Keyúnico. - Guarda el UUID del problema y su ETag.
- Actualiza el ETag antes de cada mutación y utiliza una clave de idempotencia nueva.
- Añade relaciones, usuarios y archivos solo después de comprobar los destinos en el esquema.
- Ejecuta pin, spam, rating, escalado, reopen y las decisiones de aprobación como operaciones independientes.
- Ante un
412, obtén el registro, resuelve el conflicto y repite la operación de forma consciente. - En batch, comprueba el resultado de cada elemento, porque un error parcial no tiene por qué deshacer los éxitos.
- Gestiona
429, guardarequestIdsin secretos y elimina la clave cuando la integración deje de utilizarse. - Antes de eliminar, confirma el ETag actual y comprueba después HTTP
404.
Este flujo permite sincronizar los problemas y su análisis con otro sistema sin depender de la estructura interna de la base. Si cambia la configuración de los campos, la dirección de la instalación o los scopes de la clave, vuelve a leer el contexto y el esquema.
