Activos en Codenica API
A continuación encontrarás ejemplos prácticos para trabajar con los activos almacenados en Codenica. En la API pública, el nombre técnico de este objeto es assets. Un activo puede representar un ordenador, un dispositivo, un programa, una licencia u otro elemento del inventario disponible en tu base de datos.
Antes de enviar la primera solicitud, crea la clave API descrita en el artículo Codenica API - introducción. En las secciones siguientes se explica el flujo completo de trabajo: comprobar el esquema y consultar listas, crear y editar registros, gestionar relaciones y archivos, utilizar operaciones por lotes y eliminar registros.
- lectura de activos individuales y listas paginadas;
- búsqueda y filtrado de campos del inventario;
- creación de registros y actualizaciones parciales;
- protección de cambios mediante ETag y reintentos seguros con Idempotency-Key;
- vinculación de activos con otros activos y objetos de Codenica;
- subida, descarga, asociación y eliminación de archivos;
- lectura de estadísticas y valores de campos y procesamiento de varias operaciones en una sola solicitud.
Los ejemplos utilizan itemType=computer. Cada base de datos puede tener un conjunto de campos diferente. Lee el esquema del tipo con el que vas a trabajar antes de guardar datos.
Activos - dirección de la API y modelo de instalación
Envía las solicitudes a la dirección pública en la que está disponible tu instalación de Codenica. No utilices la dirección de la base de datos, la de un contenedor ni un puerto accesible únicamente desde el interior del servidor. Las rutas de los activos comienzan por:
{BASE_URL}/api/v1/assetsEn Codenica Cloud utiliza el dominio público asignado a tu instalación:
export BASE_URL="https://tu-empresa.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 On-Premise mediante un dominio corporativo, un reverse proxy, HTTPS u otro puerto externo, utiliza la dirección exacta proporcionada para esa instalación:
export BASE_URL="https://api.tu-empresa.example"No intentes seleccionar la base de datos mediante un campo adicional en la cadena de consulta o en el cuerpo de la solicitud. La base correcta se selecciona a partir de la dirección del host. No utilices localhost si la aplicación que realiza la integración funciona en un ordenador distinto del servidor de la API. En producción utiliza HTTPS cuando la instalación esté publicada con un certificado.
Activos - scopes de la clave API
Crea la clave API en Codenica, en Ajustes - API - API Keys. Para una integración que trabaje con activos, selecciona únicamente los scopes que necesite. El acceso a la API no amplía los permisos del usuario representado por la clave ni el acceso a los datos configurado en tu base de datos.
Scopes básicos para los activos:
assets:read- listar y leer activos;assets:write- crear y editar activos;assets:delete- eliminar activos;assets:schema- leer campos, sus propiedades y los destinos de las relaciones;assets:stats- estadísticas y valores de campos utilizados para los filtros;assets:relationships:read- leer relaciones;assets:relationships:write- añadir y eliminar relaciones;assets:files:read- listar y descargar archivos;assets:files:write- subir, asociar, seleccionar el archivo principal y eliminar archivos;assets:technical:read- leer campos marcados como técnicos;assets:technical:write- escribir campos técnicos que sean modificables;assets:secrets:write- escribir campos secretos cuando el esquema los exponga.
Los campos técnicos y secretos no son necesarios para las lecturas o actualizaciones normales del inventario. Los secretos solo se guardan cuando está presente el scope correspondiente y no se devuelven en las respuestas.
Después de crear la clave, copia el Client ID y el Client Secret en el almacén seguro utilizado por la aplicación de integración. El secreto solo se muestra al crear o rotar la clave. La aplicación externa utiliza estos dos valores, no la sesión del panel ni un Bearer JWT.
Activos - autenticación y contexto
Envía las dos cabeceras de la clave API con cada solicitud:
export CLIENT_ID="cna_tu_client_id"
export CLIENT_SECRET="cns_tu_client_secret"
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"Antes de comenzar la integración real, lee /api/v1/context. Comprueba que la respuesta corresponde a la base de datos correcta, que caller.authentication tiene el valor api_key y que los scopes incluyen las operaciones necesarias.
En el objeto capabilities, confirma que assets está disponible y consulta los límites, entre ellos maxPageSize, maxUploadBytes y el límite de solicitudes. Conserva meta.requestId. Este identificador ayuda a localizar una solicitud concreta en los registros o al contactar con el administrador.
Si el contexto apunta a otra base de datos o no contiene un scope necesario, detén la integración y corrige la clave o la dirección de la API. No intentes cambiar de base de datos mediante los datos enviados en el cuerpo.
Activos - esquema de campos y relaciones
El esquema muestra qué se puede leer y escribir en la base de datos que estás utilizando. Obtenlo para el tipo de activo que necesites:
curl --request GET --url "$BASE_URL/api/v1/assets/schema?itemType=computer" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para cada campo comprueba, como mínimo:
- el nombre y el tipo de dato;
readableywritable;required;technicaly, si existe,secretWriteOnly;- los valores de
options; - la longitud máxima y la unicidad;
- la generación automática y los requisitos adicionales de la base de datos.
El esquema puede variar según itemType y la configuración del inventario. Por ejemplo, el campo category puede aceptar valores diferentes en dos bases de datos. No construyas la integración suponiendo que la lista de campos u opciones es fija.
El esquema también contiene el catálogo de destinos de las relaciones. Antes de enviar una relación, comprueba que el tipo de objeto elegido, su targetItemType y el tipo de relación coinciden con la respuesta.
Activos - endpoints disponibles
El siguiente mapa muestra las rutas principales que utiliza la integración. Sustituye {id}, {targetDataSet}, {targetId} y {fileId} por los identificadores correctos.
GET /api/v1/assets- lista de activos;GET /api/v1/assets/schema- esquema;GET /api/v1/assets/stats- estadísticas;GET /api/v1/assets/values- valores de campos;GET /api/v1/assets/{id}- activo individual;POST /api/v1/assets- creación;PATCH /api/v1/assets/{id}- actualización parcial;DELETE /api/v1/assets/{id}- eliminación;POST /api/v1/assets:batch- operaciones de creación, actualización y eliminación;GET /api/v1/assets/{id}/relationships- lista de relaciones;POST /api/v1/assets/{id}/relationships- añadir una relación;POST /api/v1/assets/{id}/relationships:batch- cambio agrupado de relaciones;DELETE /api/v1/assets/{id}/relationships/{targetDataSet}/{targetId}- eliminar una relación;GET /api/v1/assets/{id}/files- lista de archivos;POST /api/v1/assets/{id}/files- subir un archivo;POST /api/v1/assets/{id}/files/{fileId}- asociar un archivo existente;PUT /api/v1/assets/{id}/files/{fileId}/main- seleccionar el archivo principal;DELETE /api/v1/assets/{id}/files/{fileId}- eliminar un archivo;GET /api/v1/assets/{id}/files/{fileId}/content- descargar el contenido del archivo.
El scope necesario para cada ruta se deduce del nombre de la operación. Si recibes 403, comprueba primero los scopes de la clave y los permisos del usuario asociado a ella.
Activos - listas y paginación
Lee la lista por páginas. Esta solicitud devuelve los veinte primeros activos visibles de tipo computer:
curl --request GET --url "$BASE_URL/api/v1/assets?itemType=computer&page=1&pageSize=20" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La respuesta de una colección tiene una estructura similar a esta:
{
"data": {
"items": [
{
"id": "11111111-1111-1111-1111-111111111111",
"itemType": "computer",
"attributes": {
"customId": "CND-OFFICE-PC-01",
"name": "Equipo de oficina 01",
"category": "Hardware"
},
"meta": {
"dateUpdated": "2026-09-07T10:00:00Z",
"etag": "\"etag-v1\""
}
}
],
"page": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false
},
"meta": {
"requestId": "request-id-from-response"
}
}No supongas que la primera página contiene todos los datos. Continúa mientras hasNextPage sea true o utiliza totalPages. No establezcas pageSize por encima del límite devuelto en el contexto.
Activos - búsqueda y filtros
Utiliza search para una búsqueda sencilla. Para seleccionar campos con mayor precisión, utiliza los parámetros abreviados o el parámetro filter:
curl --request GET --url "$BASE_URL/api/v1/assets?itemType=computer&search=office&page=1&pageSize=50" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"
curl --request GET --url "$BASE_URL/api/v1/assets?customId=CND-OFFICE-PC-01" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"
curl --request GET --url "$BASE_URL/api/v1/assets?filter=category:contains:Hardware" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Puedes utilizar, entre otros, los parámetros itemType, ids, search, name, category, status, location, department, manufacturer, model, serialNumber, inventoryNumber, customId, tag, createdAfter, createdBefore, updatedAfter y updatedBefore.
El parámetro filter admite, entre otros, estos operadores:
eq- igual a;ne- distinto de;in- uno de los valores indicados;contains- contiene un fragmento;startsWithyendsWith- comienza o termina con el texto indicado;emptyynotEmpty- campo vacío o no vacío;gt,gte,lt,lte- comparaciones.
filter=status:eq:In service
filter=serialNumber:contains:ABC
filter=category:in:Hardware,Software
filter=description:notEmpty:Si un valor contiene espacios o caracteres especiales, codifícalo según las reglas de URL. Al filtrar por identificadores, recuerda que ids limita el resultado a los UUID indicados.
Activos - selección de campos e inclusión de datos
El parámetro fields limita los campos que se devuelven en la respuesta. Es útil cuando la integración solo necesita algunos valores:
curl --request GET --url "$BASE_URL/api/v1/assets?fields=id,itemType,name,category,status" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Utiliza include para leer datos relacionados. En el caso de los activos están disponibles files y relationships:
curl --request GET --url "$BASE_URL/api/v1/assets/$ASSET_ID?include=files,relationships" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La clave debe permitir los scopes necesarios para los datos incluidos. Si no tiene assets:files:read o assets:relationships:read, lee el registro sin esa inclusión o amplía la clave siguiendo el principio de privilegio mínimo.
fields=* no revela campos secretos. No utilices la selección de campos para intentar eludir los permisos. Los campos técnicos y secretos solo aparecen cuando lo permiten los scopes y el esquema.
Activos - crear un registro
Utiliza POST /api/v1/assets para crear un registro. Envía el tipo técnico itemType y los campos modificables dentro del objeto attributes. Este ejemplo crea un equipo de oficina:
export IDEMPOTENCY_KEY="asset-create-20260907-0001"
curl --request POST --url "$BASE_URL/api/v1/assets" \
--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": "computer",
"attributes": {
"customId": "CND-OFFICE-PC-01",
"name": "Equipo de oficina 01",
"category": "Hardware",
"manufacturer": "Lenovo",
"model": "ThinkCentre",
"location": "Madrid",
"status": "In service"
}
}'En el modelo básico, como mínimo se requieren name y category, pero tu base de datos puede tener requisitos adicionales, valores de selección o reglas de unicidad. Compara siempre el cuerpo con el esquema actual.
Una respuesta correcta tiene el estado 201 Created. Guarda data.id, data.meta.etag y la cabecera HTTP ETag. Ejemplo de una parte de la respuesta:
{
"data": {
"id": "11111111-1111-1111-1111-111111111111",
"itemType": "computer",
"attributes": {
"customId": "CND-OFFICE-PC-01",
"name": "Equipo de oficina 01",
"category": "Hardware"
},
"meta": {
"customId": "CND-OFFICE-PC-01",
"dateCreated": "2026-09-07T10:00:00Z",
"dateUpdated": "2026-09-07T10:00:00Z",
"etag": "\"etag-v1\""
}
},
"meta": {
"requestId": "request-id-from-response",
"etag": "\"etag-v1\""
}
}No envíes tu propio id, salvo que el esquema y la integración requieran un UUID controlado. Si utilizas un identificador propio, debe estar libre y cumplir los requisitos de la API.
Activos - repetir una creación de forma segura
Después de un timeout es posible que no sepas si el servidor llegó a crear el registro. No generes a ciegas una nueva clave de idempotencia. Envía exactamente la misma solicitud con el mismo Idempotency-Key y un cuerpo idéntico:
curl --request POST --url "$BASE_URL/api/v1/assets" \
--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": "computer",
"attributes": {
"customId": "CND-OFFICE-PC-01",
"name": "Equipo de oficina 01",
"category": "Hardware",
"manufacturer": "Lenovo",
"model": "ThinkCentre",
"location": "Madrid",
"status": "In service"
}
}'Repetir la misma operación reproduce la primera respuesta y no crea un segundo registro. La misma clave no puede describir después otro cuerpo, endpoint o intención. Si se reutiliza de esa forma, la API devuelve 422 idempotency_key_reused.
La idempotencia también se aplica a las demás solicitudes que modifican datos: actualizaciones, cambios de relaciones, operaciones con archivos y eliminaciones. Utiliza un valor nuevo para cada nueva intención.
Activos - leer un registro
Después de crear o encontrar un activo, léelo mediante su UUID:
export ASSET_ID="11111111-1111-1111-1111-111111111111"
curl --request GET --url "$BASE_URL/api/v1/assets/$ASSET_ID?include=files,relationships" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La respuesta contiene id, el itemType técnico, los campos dentro de attributes y los metadatos dentro de meta. Encontrarás el ETag en la cabecera HTTP y normalmente también en data.meta.etag y en la envoltura meta.etag.
Lee de nuevo el activo antes de cada cambio. Esto incluye editar campos, gestionar relaciones, subir archivos, cambiar el archivo principal, eliminar un archivo y eliminar el registro completo. Así la operación utiliza la versión actual y no un valor guardado anteriormente en la memoria de la integración.
Activos - actualización parcial con ETag
PATCH cambia únicamente los campos incluidos en el cuerpo. No es necesario enviar el registro completo. Añade un ETag reciente obtenido en la última lectura y una nueva clave de idempotencia:
export ASSET_ETAG='"etag-v1"'
export IDEMPOTENCY_KEY="asset-update-20260907-0001"
curl --request PATCH --url "$BASE_URL/api/v1/assets/$ASSET_ID" \
--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" \
--header "If-Match: $ASSET_ETAG" \
--data-raw '{
"attributes": {
"name": "Equipo de oficina 01 - actualizado",
"description": "Activo actualizado por la integración."
}
}'Después de una operación correcta, la respuesta tiene el estado 200 OK e incluye un ETag nuevo. Sustituye el valor anterior antes de la siguiente operación. Enviar null limpia un campo si no es obligatorio y el esquema permite un valor vacío.
El cuerpo debe contener un cambio real en un campo modificable, un valor personalizado o una relación. Un campo de solo lectura, técnico o secreto puede requerir un scope o endpoint independiente.
Activos - protección frente a versiones desactualizadas
ETag evita que un registro sobrescriba cambios realizados entretanto por otra persona o integración. Hay que tratar por separado dos situaciones:
428 if_match_required- falta la cabeceraIf-Matchobligatoria o, en una operación de modificación,Idempotency-Key;412 if_match_failed- el ETag enviado ya no es el actual.
Ejemplo de respuesta con un ETag antiguo:
{
"type": "https://docs.codenica.com/errors/if_match_failed",
"title": "Precondition failed.",
"status": 412,
"detail": "The supplied ETag is not the current asset version.",
"instance": "/api/v1/assets/11111111-1111-1111-1111-111111111111",
"code": "if_match_failed",
"requestId": "request-id-from-response"
}Después de un 412, vuelve a leer el activo, compara los valores actuales con el cambio que quieres realizar y solo entonces envía un nuevo PATCH con el ETag actualizado. No repitas indefinidamente la misma solicitud con un ETag antiguo. En una integración se recomienda enviar un valor concreto en If-Match. El valor * corresponde a un escenario controlado y no debe sustituir el control de versiones en una sincronización normal.
Activos - añadir relaciones
Una relación vincula un activo con otro objeto visible. Entre los destinos disponibles se encuentran:
assets, clients, documents, tickets, changes, problems, releases,
notes, worktasks, confirmations, requesteditemsEste ejemplo vincula dos ordenadores. Si envías targetItemType, debe corresponder al tipo real del destino:
export TARGET_ASSET_ID="22222222-2222-2222-2222-222222222222"
export IDEMPOTENCY_KEY="asset-relation-add-20260907-0001"
curl --request POST --url "$BASE_URL/api/v1/assets/$ASSET_ID/relationships" \
--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" \
--header "If-Match: $ASSET_ETAG" \
--data-raw '{
"targetId": "22222222-2222-2222-2222-222222222222",
"targetDataSet": "assets",
"targetItemType": "computer",
"relationshipType": "related"
}'El destino debe existir y ser visible para el usuario asignado a la clave. Un activo no puede apuntarse a sí mismo. Según el destino, la API puede guardar relationshipType. Para notes, worktasks y requesteditems no envíes este campo, porque el modelo actual de esas relaciones no lo guarda.
Añadir una relación cambia la versión del activo de origen. Después de recibir 201 Created, vuelve a leer el origen y utiliza el nuevo ETag en el siguiente cambio.
Activos - leer y eliminar relaciones
Lee las relaciones mediante la colección y, si lo necesitas, limita el resultado a un conjunto de destinos:
curl --request GET --url "$BASE_URL/api/v1/assets/$ASSET_ID/relationships?targetDataSet=assets&page=1&pageSize=50" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Un elemento de relación puede incluir targetId, targetDataSet, targetItemType, relationshipType, customId y name. La lectura de la relación no devuelve el objeto de destino completo, salvo que hagas una lectura independiente o utilices include=relationships.
Para eliminar una relación necesitas un ETag reciente del origen:
export IDEMPOTENCY_KEY="asset-relation-delete-20260907-0001"
curl --request DELETE --url "$BASE_URL/api/v1/assets/$ASSET_ID/relationships/assets/$TARGET_ASSET_ID?relationshipType=related" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--header "If-Match: $ASSET_ETAG"Una eliminación correcta devuelve 200 OK con data: true. Al eliminar mediante el endpoint directo, el valor de relationshipType en la consulta debe coincidir con la relación que quieres eliminar. Después de la operación, vuelve a leer la colección y el activo de origen.
Activos - cambio agrupado de relaciones
Utiliza relationships:batch cuando necesites añadir o eliminar varias relaciones. Una solicitud puede incluir los arrays add y remove:
export IDEMPOTENCY_KEY="asset-relations-batch-20260907-0001"
curl --request POST --url "$BASE_URL/api/v1/assets/$ASSET_ID/relationships:batch" \
--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" \
--header "If-Match: $ASSET_ETAG" \
--data-raw '{
"add": [
{
"targetId": "22222222-2222-2222-2222-222222222222",
"targetDataSet": "assets",
"targetItemType": "computer",
"relationshipType": "related"
}
],
"remove": [
{
"targetId": "33333333-3333-3333-3333-333333333333",
"targetDataSet": "clients",
"relationshipType": "owner"
}
]
}'La respuesta 200 OK contiene los contadores added, removed y skipped. Si vuelves a enviar una relación que ya existe, puede contabilizarse como skipped. Un batch de relaciones también cambia el ETag del origen, por lo que debes volver a leer el activo después de la operación.
En los elementos que se refieren a notes, worktasks y requesteditems, omite relationshipType. Cada destino debe ser visible y coincidir con el catálogo de relaciones devuelto por el esquema.
Activos - listar y subir archivos
Los archivos se almacenan junto al activo y tienen sus propios identificadores. Primero puedes consultar la lista actual:
curl --request GET --url "$BASE_URL/api/v1/assets/$ASSET_ID/files?page=1&pageSize=50" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Un elemento de la lista incluye, entre otros, id, name, fileName, contentType, size, relationshipType, isMain y downloadUrl.
La subida utiliza multipart/form-data. Para modificar el activo necesitas un ETag reciente y una nueva clave de idempotencia:
curl --request POST --url "$BASE_URL/api/v1/assets/$ASSET_ID/files?makeMain=true&relationshipType=documentation" \
--header "Accept: application/json, application/problem+json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: asset-file-upload-20260907-0001" \
--header "If-Match: $ASSET_ETAG" \
--form "file=@./asset-manual.txt;type=text/plain"makeMain=true selecciona el archivo subido como archivo principal. El parámetro relationshipType describe la finalidad del archivo, por ejemplo documentation o manual. El límite de subida predeterminado es de 20 MiB, pero comprueba el valor actual de maxUploadBytes en el contexto.
El nombre del archivo no puede contener una ruta ni un segmento ... No guardes secretos en el nombre, los metadatos o el contenido del archivo salvo que sea necesario.
La subida devuelve 201 Created y un objeto de archivo. Vuelve a leer el activo después de la operación porque su ETag ha cambiado.
Activos - descargar y seleccionar el archivo principal
Descarga el contenido mediante el endpoint /content. La respuesta contiene contenido binario, no una envoltura JSON:
export FILE_ID="44444444-4444-4444-4444-444444444444"
curl --request GET --url "$BASE_URL/api/v1/assets/$ASSET_ID/files/$FILE_ID/content" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--output ./asset-file-download.txtEn el objeto de archivo, downloadUrl es una dirección relativa. Añádele el host de la instalación y utiliza las mismas cabeceras de autenticación.
Si un activo tiene varios archivos, puedes seleccionar el archivo principal. Esta operación modifica el activo y requiere su ETag actual:
curl --request PUT --url "$BASE_URL/api/v1/assets/$ASSET_ID/files/$FILE_ID/main" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: asset-set-main-20260907-0001" \
--header "If-Match: $ASSET_ETAG"Una respuesta correcta tiene el estado 200 OK y normalmente devuelve data: true. Después del cambio, consulta la lista de archivos y comprueba que el elemento elegido tiene isMain=true y el archivo principal anterior tiene isMain=false. A continuación, lee el nuevo ETag del activo.
En la interfaz, un archivo pequeño puede aparecer redondeado como 0 MB. Comprueba el tamaño real en el campo size o contando los bytes descargados.
Activos - asociar un archivo existente
Si un archivo ya está guardado en el sistema, puedes asociarlo a otro activo sin volver a subir su contenido:
export TARGET_ASSET_ID="55555555-5555-5555-5555-555555555555"
export TARGET_ASSET_ETAG='"target-etag-v1"'
curl --request POST --url "$BASE_URL/api/v1/assets/$TARGET_ASSET_ID/files/$FILE_ID?makeMain=true&relationshipType=manual" \
--header "Accept: application/json, application/problem+json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: asset-attach-file-20260907-0001" \
--header "If-Match: $TARGET_ASSET_ETAG"La respuesta 201 Created contiene el identificador del archivo asociado y sus metadatos. Si has utilizado makeMain=true, vuelve a leer la lista y comprueba que isMain sea true.
Asociar un archivo también cambia la versión del activo de destino. Lee el ETag actual del destino antes de la siguiente operación con archivos. Elimina un archivo de un activo solo después de comprobar que ya no es necesario en ese lugar ni en sus demás relaciones.
Activos - eliminar un archivo
Eliminar un archivo modifica el activo. Lee el ETag actual y utiliza una clave de idempotencia independiente:
curl --request DELETE --url "$BASE_URL/api/v1/assets/$ASSET_ID/files/$FILE_ID" \
--header "Accept: application/json, application/problem+json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: asset-file-delete-20260907-0001" \
--header "If-Match: $ASSET_ETAG"Una respuesta correcta tiene el estado 200 OK y contiene data: true. Después de cada eliminación, vuelve a leer la lista de archivos y el ETag del activo. Si eliminas varios archivos, el ETag de la siguiente operación debe proceder del cambio anterior ya completado.
Eliminar un archivo no elimina el activo completo. Intentar descargar el contenido eliminado devuelve 404 file_not_found. Si un archivo está asociado a varios activos, comprueba antes de eliminarlo que la operación afecta a la relación correcta y que el archivo ya no es necesario.
Activos - estadísticas y valores de campos
El endpoint stats ayuda a crear un resumen de los datos visibles. Puedes limitar el resultado a un tipo de activo e indicar el campo cuyos valores quieres obtener:
curl --request GET --url "$BASE_URL/api/v1/assets/stats?itemType=computer&field=category&limit=20" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"La respuesta puede incluir el número total de activos visibles, el reparto por itemType, el nombre del campo y sus valores:
{
"data": {
"total": 11,
"byItemType": {
"computer": 11
},
"field": "category",
"values": [
"Laptop",
"Desktop",
"Hardware"
]
},
"meta": {
"requestId": "request-id-from-response"
}
}El endpoint values devuelve valores útiles para construir listas de filtros:
curl --request GET --url "$BASE_URL/api/v1/assets/values?field=category&itemType=computer&search=hard&limit=20" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para la búsqueda hard, el resultado puede contener Hardware. Ambos endpoints son de solo lectura, requieren assets:stats y no requieren ETag. Los resultados solo incluyen datos visibles para el usuario.
Activos - operaciones por lotes
Batch permite combinar la creación, actualización y eliminación en una sola solicitud. Cada elemento tiene su propia operación, y update y delete envían su ETag en el campo ifMatch:
curl --request POST --url "$BASE_URL/api/v1/assets:batch" \
--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: assets-batch-20260907-0001" \
--data-raw '{
"items": [
{
"operation": "create",
"create": {
"itemType": "computer",
"attributes": {
"customId": "CND-BATCH-PC-01",
"name": "Equipo creado en lote",
"category": "Hardware"
}
}
},
{
"operation": "update",
"id": "11111111-1111-1111-1111-111111111111",
"ifMatch": "\"current-etag\"",
"update": {
"attributes": {
"description": "Descripción actualizada en lote."
}
}
},
{
"operation": "delete",
"id": "22222222-2222-2222-2222-222222222222",
"ifMatch": "\"current-etag\""
}
]
}'Si todos los elementos terminan correctamente, la respuesta tiene el estado 200 OK. El resultado incluye succeeded, failed y el resultado de cada elemento con su index, operation y status.
Batch no es una transacción de todo o nada. Si solo algunos elementos tienen éxito, la API devuelve 207 Multi-Status y no revierte los elementos correctos. Comprueba cada posición. Si el batch crea registros nuevos, guarda sus ID y ETag en los resultados individuales.
Cada elemento requiere el scope correspondiente a su operación. Una solicitud batch no amplía los permisos de la clave.
Activos - eliminar un registro
Vuelve a leer el activo antes de eliminarlo y utiliza su ETag actual:
export IDEMPOTENCY_KEY="asset-delete-20260907-0001"
curl --request DELETE --url "$BASE_URL/api/v1/assets/$ASSET_ID" \
--header "Accept: application/json, application/problem+json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--header "If-Match: $ASSET_ETAG"Una eliminación correcta devuelve 200 OK con data: true. Una lectura posterior del UUID devuelve 404 asset_not_found. La eliminación ejecuta la limpieza de dominio existente, pero la API pública no elimina automáticamente los objetos de negocio relacionados, como documentos, tickets o clientes.
Después de eliminarlo, quita el identificador del índice local de la integración o marca el registro como inactivo. No intentes actualizar de nuevo el UUID eliminado.
Activos - errores, límites y seguridad
Los errores de la API utilizan el formato Problem Details con campos adicionales de Codenica:
{
"type": "https://docs.codenica.com/errors/asset_not_found",
"title": "Asset not found.",
"status": 404,
"detail": "The asset does not exist or is outside the caller's access scope.",
"instance": "/api/v1/assets/11111111-1111-1111-1111-111111111111",
"code": "asset_not_found",
"requestId": "request-id-from-response"
}En la lógica de la aplicación utiliza principalmente status y code. El texto de detail es una indicación para las personas y puede cambiar.
400- cuerpo, parámetro o valor de campo no válido;401- autenticación ausente o no válida;403- falta un scope o un permiso del usuario;404- el activo, archivo o destino de relación no existe o no es visible;409- conflicto de datos o del estado de negocio;412- ETag desactualizado;413- la subida o el cuerpo son demasiado grandes;428- se requiere ETag o Idempotency-Key;429- se ha superado el límite de solicitudes;500o503- error del servidor o indisponibilidad temporal.
Lee X-RateLimit-Limit, X-RateLimit-Remaining y, para 429, Retry-After. Utiliza reintentos controlados con esperas crecientes. Nunca guardes el Client Secret en un repositorio, URL, código enviado al navegador, historial de comandos o registros.
Activos - flujo completo de integración
- Determina la dirección correcta de la API. En On-Premise, comprueba que la integración pueda llegar a
http://codenica.local:5150o a la dirección publicada por el administrador. - Crea una clave API independiente para esta integración y selecciona los scopes mínimos necesarios.
- Guarda el Client ID y el Client Secret en un almacén seguro.
- Envía
GET /api/v1/contexty comprueba que la respuesta corresponde a la base de datos correcta. Comprueba también el caller, los scopes y los límites. - Envía
GET /api/v1/assets/schema?itemType=computery adapta el cuerpo a los campos actuales. - Lee la lista con paginación, búsqueda o filtros.
- Crea un activo mediante
POSTcon un nuevoIdempotency-Key. - Guarda el UUID y el ETag.
- Lee el registro actual antes de cada cambio.
- Realiza las ediciones, relaciones, operaciones con archivos y eliminaciones con un ETag concreto y una nueva clave de idempotencia.
- Después de cada modificación correcta, guarda el nuevo ETag y vuelve a leer el resultado cuando sea necesario.
- Después de un
412, lee el registro, resuelve el conflicto y solo entonces repite la operación. - Para un número mayor de cambios, utiliza batch, pero comprueba cada elemento porque batch no es una transacción.
- Gestiona
429y no registres secretos. - Elimina la clave API cuando la integración deje de utilizarse.
Con este flujo, la integración puede utilizar los datos del inventario sin depender de la estructura interna de la base de datos. Si cambian la configuración de campos, los permisos o la dirección de la instalación, vuelve a leer el contexto y el esquema en lugar de basarte en suposiciones antiguas.
