Releases en Codenica API
Para trabajar con releases 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í se explican las reglas comunes para emitir claves, guardar el secreto y autenticar las solicitudes.
El nombre técnico del módulo es releases y el tipo de un objeto individual es release. Un release describe la publicación o el despliegue planificado de cambios en un entorno de TI. Además de los datos descriptivos, cuenta con un grupo propio de campos para planificar la compilación, las pruebas, sus resultados y la implementación.
En las secciones siguientes encontrarás la dirección, los scopes, el esquema, las listas, los filtros, la creación, la edición, los ETags, las operaciones batch, las relaciones, los usuarios, los archivos, las acciones de workflow, las aprobaciones y el borrado de releases.
Los ejemplos utilizan el identificador PUBLIC-API-RELEASE-20260905133117. 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 de datos.
Releases - dirección de la API y elección de la instalación
Todas las rutas de releases empiezan por:
{BASE_URL}/api/v1/releasesEn Codenica Cloud, utiliza la dirección pública asignada a la base de datos correspondiente:
export BASE_URL="https://tu-empresa.codenica.com"En la instalación On-Premise predeterminada, la dirección que registra localmente Codenica Discovery es:
export BASE_URL="http://codenica.local:5150"Si el administrador ha publicado la instalación bajo el dominio de la empresa, mediante un reverse proxy, con HTTPS o en otro puerto, utiliza la dirección exacta indicada para esa instalación:
export BASE_URL="https://api.tu-empresa.example"No uses localhost si el programa de integración se ejecuta en otro 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 utilizada por la integración.
Releases - clave API y límites de licencia
Crea una clave API en Codenica, en Ajustes - API - API Keys. El secreto se muestra una sola 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 utilizado por 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 incluye Codenica API. Crea una clave independiente para cada aplicación y entorno, de modo que puedas gestionar por separado sus scopes, la rotación del secreto y el acceso.
Las claves caducadas o inactivas permanecen visibles hasta que se utiliza la opción Borrar, pero no ocupan una plaza activa del límite. Borrar una clave es permanente. Si no estableces una fecha de finalización, el periodo de actividad predeterminado es de 90 días y el periodo máximo de una clave es de 5 años.
Releases - autenticación y solicitudes seguras
Autentica cada solicitud de Codenica API con las dos cabeceras de la clave:
export CLIENT_ID="cna_tu_client_id"
export CLIENT_SECRET="cns_tu_client_secret"
curl --request GET --url "$BASE_URL/api/v1/releases?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 guardes la clave en un repositorio, en código que se entregue al navegador, en una URL, en el historial de comandos ni en los logs. 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 release y no debe utilizarse como secreto.
Releases - comprobar el contexto de la conexión
Lee el contexto antes de realizar la primera escritura. Así comprobarás que la dirección lleva a la base de datos correcta y que la clave elegida 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"Comprueba en la respuesta:
data.apiVersionydata.contractVersion;data.tenant.id,data.tenant.nameydata.tenant.resolvedDomain;data.caller.authenticationigual aapi_key;- la presencia de
releasesendata.capabilities.resources; - los scopes asignados a la clave;
- los límites de páginas, batch, archivos y solicitudes.
Si el contexto apunta a otra base de datos o no contiene un scope necesario, detén la integración y corrige la dirección o la clave. Los scopes no se pueden conceder mediante una solicitud individual.
Releases - scopes de permisos
Elige los scopes de la clave según las operaciones que deba realizar la integración. La gestión completa de releases puede utilizar el siguiente conjunto:
releases:read
releases:write
releases:delete
releases:schema
releases:stats
releases:relationships:read
releases:relationships:write
releases:users:read
releases:users:write
releases:files:read
releases:files:write
releases:technical:read
releases:technical:write
releases:pin:write
releases:spam:write
releases:reopen:write
releases:rating:write
releases:escalation:write
releases:approval:writePara una lectura normal necesitas releases:read. El esquema y las estadísticas requieren respectivamente releases:schema y releases:stats. Las relaciones, los usuarios y los archivos tienen scopes de lectura y escritura independientes. Las acciones pin, spam, reopen, rating, escalation y approval requieren sus propios scopes operativos.
Una relación con otro objeto también requiere acceso de lectura al módulo indicado, por ejemplo assets:read, documents:read, tickets:read o notes:read. Concede los scopes siguiendo el principio de mínimo privilegio.
Releases - esquema y campos de planificación
El esquema muestra qué campos se pueden leer y escribir en una base de datos concreta. Consúltalo antes de preparar un formulario o un mapeo de campos:
curl --request GET --url "$BASE_URL/api/v1/releases/schema" \
--header "Accept: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para cada campo, comprueba propiedades como readable, writable, required, technical, unique y maxLength. El esquema también devuelve diccionarios, objetivos de relación disponibles y acciones.
Actualmente, la escritura mínima de un release requiere los campos subject y requesterEmail. Los releases disponen de un grupo adicional de campos para describir la preparación y el plan de despliegue:
datePlannedStartdatePlannedEndbuildPlantestPlantestResultsimplementationPlanEnvía los campos de fecha en formato ISO 8601. No copies en una solicitud de release los campos de diagnóstico de problems ni campos financieros de otros módulos. Compara siempre el payload con el esquema de Releases.
Releases - endpoints principales
Las rutas de release más utilizadas son:
GET /api/v1/releases- lista de releases;GET /api/v1/releases/{id}- un release;POST /api/v1/releases- creación;PATCH /api/v1/releases/{id}- edición parcial;DELETE /api/v1/releases/{id}- borrado;GET /api/v1/releases/schema- esquema de campos y relaciones;GET /api/v1/releases/stats- estadísticas;GET /api/v1/releases/values- valores utilizados por los filtros;POST /api/v1/releases:batch- operaciones de creación, edición y borrado.
Las relaciones, los usuarios, los archivos, las acciones de workflow y las aprobaciones tienen rutas independientes. De este modo, la integración puede recibir únicamente los permisos que realmente necesita.
Releases - listado y paginación
Obtén la lista página por página. Aunque haya pocos registros, indica explícitamente el número y el tamaño de la página:
curl --request GET --url "$BASE_URL/api/v1/releases?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 valores page, pageSize, totalItems, totalPages y hasNextPage. Solicita las páginas siguientes mientras hasNextPage sea true:
curl --request GET --url "$BASE_URL/api/v1/releases?page=2&pageSize=25&sort=dateUpdated&direction=desc" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Para sincronizar, suele ser 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.
Releases - búsqueda, filtros y ordenación
Puedes combinar los parámetros de la lista. El siguiente ejemplo busca un release por su identificador de integración, limita el resultado al tipo release y a un estado, selecciona campos y después ordena por la fecha de actualización:
curl --get --url "$BASE_URL/api/v1/releases" \
--data-urlencode "itemType=release" \
--data-urlencode "customId=PUBLIC-API-RELEASE-20260905133117-SOURCE" \
--data-urlencode "status=Closed" \
--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 resultan útiles los parámetros search, status, priority, subject, requesterEmail, source, externalNumber, referenceNumber, createdAfter, createdBefore, updatedAfter y updatedBefore, siempre que estén disponibles en el esquema actual.
Un filtro estructural utiliza 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/releases" \
--data-urlencode "filter=status:eq:Closed" \
--data-urlencode "filter=buildPlan:contains:paquete" \
--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 de acuerdo con las reglas de las URL. No des por hecho que los diccionarios son idénticos en dos bases de datos.
Releases - selección de campos e inclusión de datos
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/releases/{RELEASE_ID}" \
--data-urlencode "fields=subject,requesterEmail,status,priority,datePlannedStart,datePlannedEnd,buildPlan,testPlan,testResults,implementationPlan" \
--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 expone campos técnicos para los que la clave no tiene permiso.
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.
Releases - estadísticas y valores de diccionario
Las estadísticas permiten, por ejemplo, comprobar la distribución de releases por estado. Es una operación de lectura que no modifica los registros:
curl --get --url "$BASE_URL/api/v1/releases/stats" \
--data-urlencode "field=status" \
--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 buildPlan cuando necesites crear sugerencias o filtros:
curl --get --url "$BASE_URL/api/v1/releases/values" \
--data-urlencode "field=buildPlan" \
--data-urlencode "limit=20" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Primero obtén el diccionario y después envía el valor elegido en el body. Esto es especialmente importante para status, priority, type y los campos de planificación configurados en la base de datos correspondiente.
Releases - crear un registro
Crea un release nuevo mediante POST /api/v1/releases. Incluye el tipo técnico release en el body y los campos modificables dentro de attributes. El ejemplo contiene datos descriptivos, clasificación, identificadores de integración y el grupo completo de planificación:
curl --request POST --url "$BASE_URL/api/v1/releases" \
--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: public-api-release-create-20260905133117" \
--data-raw '{
"itemType": "release",
"attributes": {
"customId": "PUBLIC-API-RELEASE-20260905133117-SOURCE",
"subject": "Release de integración de Codenica API",
"requesterEmail": "[email protected]",
"description": "Release creado mediante la integración con Codenica Public API.",
"comments": "Ejemplo de plan de despliegue para el módulo Releases.",
"source": "Public API",
"type": "Standard",
"status": "Closed",
"priority": "High",
"impact": "Medium",
"urgency": "High",
"severity": "High",
"services": "Codenica Public API",
"tags": "public-api,release",
"externalNumber": "EXT-PUBLIC-API-RELEASE-20260905133117",
"referenceNumber": "REF-PUBLIC-API-RELEASE-20260905133117",
"datePlannedStart": "2026-09-05T08:00:00Z",
"datePlannedEnd": "2026-09-05T10:00:00Z",
"buildPlan": "Preparación del paquete del release.",
"testPlan": "Pruebas funcionales antes de la publicación.",
"testResults": "Pruebas de demostración completadas correctamente.",
"implementationPlan": "Despliegue gradual con posibilidad de reversión."
},
"customValues": [
{
"name": "description",
"valuePattern": "[release-integration] PUBLIC-API-RELEASE-20260905133117"
}
]
}'El mínimo es subject y requesterEmail, salvo que el esquema imponga requisitos adicionales. Después de crearlo, guarda data.id y el ETag devuelto en la cabecera y en data.meta.etag. El secreto de la clave no forma parte de la respuesta del release.
Releases - repetir la creación de forma segura
Si el resultado de una solicitud es incierto, repite exactamente el mismo payload con el mismo Idempotency-Key. Así la integración no creará un segundo release:
curl --request POST --url "$BASE_URL/api/v1/releases" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header "Idempotency-Key: public-api-release-create-20260905133117" \
--data-binary @release.jsonUtiliza la misma clave únicamente para la misma intención y el mismo body. Genera una clave nueva para otro release o para un payload nuevo. Después de un timeout, no cambies la clave antes de comprobar si la primera escritura terminó en el servidor.
Releases - leer un registro y su ETag
Lee un release con todos los campos y los datos incluidos:
curl --get --url "$BASE_URL/api/v1/releases/{RELEASE_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 de la envoltura de respuesta. Después de cada escritura, acción, cambio de relación u operación con archivos, obtén o vuelve a leer el ETag nuevo.
Un ETag representa la versión de un release concreto. No utilices el ETag leído para un release para modificar otro.
Releases - editar con If-Match
Las ediciones son parciales. Envía solamente los campos que deben cambiar y coloca el ETag actual en la cabecera If-Match:
curl --request PATCH --url "$BASE_URL/api/v1/releases/{RELEASE_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 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-update-20260905133117" \
--data-raw '{
"attributes": {
"description": "Descripción actualizada por la integración.",
"status": "Closed",
"priority": "High",
"datePlannedStart": "2026-09-05T09:00:00Z",
"datePlannedEnd": "2026-09-05T11:00:00Z",
"buildPlan": "Plan actualizado de preparación del paquete.",
"testPlan": "Escenario de pruebas actualizado.",
"testResults": "Resultados de las pruebas después de la corrección.",
"implementationPlan": "Plan de implementación actualizado."
}
}'Un valor If-Match válido devuelve HTTP 200 y un ETag nuevo. No envíes en un PATCH normal campos de solo lectura ni campos técnicos gestionados por acciones específicas.
Releases - gestionar un If-Match obsoleto
Un release puede cambiar al mismo tiempo desde el panel o mediante otra integración. La API lo protege frente a sobrescrituras accidentales:
curl --request PATCH --url "$BASE_URL/api/v1/releases/{RELEASE_ID}" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "etag-antiguo"' \
--header "Idempotency-Key: public-api-release-stale-update-20260905133117" \
--data-raw '{"attributes":{"description":"Este cambio requiere una nueva lectura."}}'- 428 Precondition Required con el código
if_match_requiredsignifica que falta la cabeceraIf-Matchobligatoria. - 412 Precondition Failed con el código
if_match_failedsignifica que el ETag enviado ya no es el actual.
Una solicitud rechazada no debería modificar el release. Después de HTTP 412, vuelve a leer el registro, obtén el ETag nuevo y decide si deseas repetir el cambio. No sobrescribas sin comprobar los cambios realizados por otra persona o proceso.
Releases - operaciones batch
El endpoint batch permite gestionar varios elementos independientes en una sola solicitud. El siguiente ejemplo crea dos releases:
curl --request POST --url "$BASE_URL/api/v1/releases: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: public-api-release-batch-create-20260905133117" \
--data-raw '{
"items": [
{
"operation": "create",
"create": {
"itemType": "release",
"attributes": {
"customId": "PUBLIC-API-RELEASE-20260905133117-BATCH-A",
"subject": "Release batch A",
"requesterEmail": "[email protected]",
"source": "Public API",
"type": "Standard",
"status": "Open",
"priority": "Medium",
"datePlannedStart": "2026-09-05T11:00:00Z",
"datePlannedEnd": "2026-09-05T12:00:00Z",
"buildPlan": "Plan de build del release A",
"testPlan": "Plan de pruebas del release A",
"testResults": "Resultados de las pruebas del release A",
"implementationPlan": "Plan de implementación del release A"
}
}
},
{
"operation": "create",
"create": {
"itemType": "release",
"attributes": {
"customId": "PUBLIC-API-RELEASE-20260905133117-BATCH-B",
"subject": "Release batch B",
"requesterEmail": "[email protected]",
"source": "Public API",
"type": "Standard",
"status": "Open",
"priority": "Low",
"datePlannedStart": "2026-09-05T13:00:00Z",
"datePlannedEnd": "2026-09-05T14:00:00Z",
"buildPlan": "Plan de build del release B",
"testPlan": "Plan de pruebas del release B",
"testResults": "Resultados de las pruebas del release B",
"implementationPlan": "Plan de implementación del release B"
}
}
}
]
}'Comprueba la respuesta batch elemento por elemento. No consideres HTTP 200 una prueba de que todos los elementos han terminado correctamente. Revisa succeeded, failed, los identificadores y los errores de cada elemento.
La edición y el borrado utilizan el mismo endpoint:
{
"items": [
{
"operation": "update",
"id": "{RELEASE_ID}",
"ifMatch": "\"{CURRENT_ETAG}\"",
"update": {
"attributes": {
"datePlannedStart": "2026-09-05T09:30:00Z",
"buildPlan": "Plan actualizado de preparación del paquete"
}
}
},
{
"operation": "delete",
"id": "{OTHER_RELEASE_ID}",
"ifMatch": "\"{OTHER_CURRENT_ETAG}\""
}
]
}Para editar y borrar, utiliza el ETag obtenido para el registro correspondiente. La clave de idempotencia identifica toda la solicitud batch, no un elemento individual. Un batch no es una transacción, así que procesa por separado el resultado de cada elemento.
Releases - relaciones con objetos
Los objetivos de relación disponibles aparecen en /api/v1/releases/schema. El esquema puede indicar, entre otras, las colecciones assets, documents, changes, tickets, problems, releases, notes, approvals, worktasks y requesteditems.
Que un objetivo aparezca en el esquema no significa que exista un registro utilizable en la base de datos actual. Antes de añadir una relación, comprueba los permisos, el identificador del objetivo y su itemType. Para assets, documents, tickets, changes, problems y releases, utiliza el tipo de relación indicado por el esquema, por ejemplo related. Para notes, approvals, worktasks y requesteditems, relationshipType puede ser null. No fuerces related si el esquema no lo indica.
Añadir varias relaciones mediante batch:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_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: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-relationship-batch-20260905133117" \
--data-raw '{
"add": [
{
"targetId": "{ASSET_ID}",
"targetDataSet": "assets",
"targetItemType": "computer",
"relationshipType": "related"
},
{
"targetId": "{DOCUMENT_ID}",
"targetDataSet": "documents",
"targetItemType": "document",
"relationshipType": "related"
},
{
"targetId": "{NOTE_ID}",
"targetDataSet": "notes",
"targetItemType": "note",
"relationshipType": null
}
],
"remove": []
}'La respuesta HTTP 200 contiene los contadores added, removed y skipped. Después de la operación, recupera la colección de relaciones y comprueba que el resultado coincide con lo esperado.
Releases - leer y eliminar relaciones
Obtén la colección de relaciones mediante su propia ruta:
curl --request GET --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/relationships?page=1&pageSize=100" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"Puedes añadir una relación sin batch y eliminarla después utilizando el ETag actual:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/relationships" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-relationship-20260905133117" \
--data-raw '{"targetId":"{TICKET_ID}","targetDataSet":"tickets","targetItemType":"ticket","relationshipType":"related"}'
curl --request DELETE --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/relationships/tickets/{TICKET_ID}?relationshipType=related" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-relationship-delete-20260905133117"Si el esquema devuelve relationshipType: null para un objetivo, omite el parámetro relationshipType de la ruta de borrado. También puedes eliminar relaciones mediante una edición parcial del release:
curl --request PATCH --url "$BASE_URL/api/v1/releases/{RELEASE_ID}" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-relationship-patch-20260905133117" \
--data-raw '{"relationshipsToRemove":[{"targetId":"{TICKET_ID}","targetDataSet":"tickets","targetItemType":"ticket","relationshipType":"related"}]}'Después de cambiar las relaciones, vuelve a obtener el release o la colección de relaciones. El ETag puede cambiar, por lo que no debes utilizar el ETag antiguo para la acción siguiente.
Releases - relaciones con usuarios
Un release puede tener las relaciones de usuario agent, watcher y appUserRequester. La primera identifica a la persona responsable de gestionarlo, la segunda a un observador y la tercera al usuario de la aplicación que lo solicitó. No añadas relaciones que el esquema no devuelva.
Asignar un agente:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_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: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-agent-20260905133117" \
--data-raw '{"targetId":"{USER_ID}","targetDataSet":"users","relationshipType":"agent"}'Añadir un observador mediante batch:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_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: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-watcher-20260905133117" \
--data-raw '{"add":[{"targetId":"{WATCHER_ID}","targetDataSet":"users","relationshipType":"watcher"}],"remove":[]}'Leer y eliminar relaciones:
curl --request GET --url "$BASE_URL/api/v1/releases/{RELEASE_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/releases/{RELEASE_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: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-agent-delete-20260905133117"También puedes eliminar un observador mediante user-relationships:batch, enviando un array add vacío y una entrada en remove. Lee el ETag nuevo después de cada cambio.
Releases - archivos
Antes de realizar una operación con un archivo, lee el release actual y su ETag. La carga de un archivo requiere el formato multipart/form-data:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/files?relationshipType=documentation" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-file-20260905133117" \
--form "[email protected];type=text/plain"Lista de archivos y descarga del contenido:
curl --request GET --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/files?page=1&pageSize=100" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET"
curl --request GET --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/files/{FILE_ID}/content" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--output release-evidence.txtUn elemento de la lista contiene, entre otros valores, 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.
Puedes adjuntar un archivo existente a otro release y después eliminar su relación:
curl --request POST --url "$BASE_URL/api/v1/releases/{OTHER_RELEASE_ID}/files/{FILE_ID}?relationshipType=manual" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{OTHER_RELEASE_CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-file-attach-20260905133117"
curl --request DELETE --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/files/{FILE_ID}" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-file-delete-20260905133117"Antes de borrar, verifica el release, el fileId y el ETag actual. Obtén el límite de tamaño desde el contexto. No cargues un archivo en memoria antes de comprobar ese límite.
Releases - fijar, marcar como spam y reabrir
Las acciones de workflow tienen endpoints independientes. No las sustituyas por un PATCH normal cuando la API ofrezca una acción específica. Cada acción requiere el ETag actual y su propia clave de idempotencia.
Fijar un release y marcarlo como spam:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/pin" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-pin-20260905133117" \
--data-raw '{"pin":2}'
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/spam" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-spam-on-20260905133117" \
--data-raw '{"isSpam":true}'Para deshacer la marca de spam, envía {"isSpam":false} a la misma ruta. Reabre un release de la siguiente manera:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/reopen" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-reopen-20260905133117"Las acciones pueden cambiar el ETag. Después de cada una, lee la respuesta y el release actual antes de ejecutar la siguiente.
Releases - valoración y escalado
Una valoración puede enviar comentarios y registrar al mismo tiempo una solicitud de escalado:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_ID}/rating" \
--header "Content-Type: application/json" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-rating-20260905133117" \
--data-raw '{
"rating": 4,
"feedback": "Valoración enviada por una integración de Public API.",
"isEscalationRequested": true,
"escalationRequestReason": "El release requiere un análisis del equipo de segundo nivel."
}'Para una valoración necesitas releases:rating:write; una solicitud de escalado requiere además releases:escalation:write. Después de la operación, vuelve a leer el release y comprueba los campos guardados de valoración y escalado. No supongas que HTTP 200 por sí solo significa que se han guardado todos los valores.
Releases - aprobación y decisión
Una aprobación es un objeto independiente que se puede relacionar con un release. Para crearla necesitas los scopes del módulo approvals y releases:approval:write:
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-release-approval-create-20260905133117" \
--data-raw '{
"itemType": "approval",
"approverId": "{APPROVER_USER_ID}",
"attributes": {
"customId": "PUBLIC-API-RELEASE-20260905133117-APPROVAL",
"category": "Public API",
"description": "Aprobación del plan del release."
},
"relationships": [
{
"targetId": "{RELEASE_ID}",
"targetDataSet": "releases",
"targetItemType": "release"
}
]
}'Después de crearla, lee la aprobación mediante su endpoint y guarda la decisión utilizando el endpoint del release:
curl --request POST --url "$BASE_URL/api/v1/releases/{RELEASE_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: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-approval-decision-20260905133117" \
--data-raw '{"approve":true,"remark":"El plan del release fue aprobado mediante la integración de Public API."}'Después de la decisión, vuelve a leer la aprobación y comprueba su estado o dateApproved. Así confirmarás que la decisión se ha guardado y no solo que el servidor ha aceptado la solicitud.
Releases - borrar un registro
El borrado requiere el ETag actual y una clave de idempotencia:
curl --request DELETE --url "$BASE_URL/api/v1/releases/{RELEASE_ID}" \
--header "X-Codenica-Client-Id: $CLIENT_ID" \
--header "X-Codenica-Client-Secret: $CLIENT_SECRET" \
--header 'If-Match: "{CURRENT_ETAG}"' \
--header "Idempotency-Key: public-api-release-delete-20260905133117"Después de HTTP 200, realiza un GET de verificación. El release borrado debería devolver HTTP 404 con el código release_not_found o con el equivalente indicado en el contrato. Si el objeto tiene relaciones o archivos, comprueba las consecuencias en el esquema y en la política de tu base de datos antes de borrarlo.
Releases - errores, límites y seguridad
Las respuestas correctas devuelven los datos en data; la información técnica, como requestId y a veces el ETag, aparece en meta. Los errores utilizan el formato Problem Details con status, code, detail y requestId.
400- body, parámetro o valor de campo no válido;401- autenticación ausente o no válida;403- falta un scope o el acceso a la base de datos;404- el release, el archivo o el objetivo de relación no existe o no es visible;409- conflicto de datos o de idempotencia;412- ETag obsoleto;413- la carga o el body es demasiado grande;428- se requiere ETag o Idempotency-Key;429- se ha superado el límite de solicitudes;500o503- error del servidor o indisponibilidad temporal.
Respeta los límites devueltos en el contexto para pageSize, elementos batch, archivos, relaciones y rate limit. Lee X-RateLimit-Limit, X-RateLimit-Remaining y, para 429, Retry-After. Utiliza reintentos controlados con una espera creciente.
Para las operaciones que cambian datos, utiliza siempre un Idempotency-Key único, el If-Match actual cuando el endpoint lo requiera y el ETag nuevo después de un cambio correcto. Tras un timeout, reconstruye primero el resultado con un GET o repite la misma solicitud con la misma clave. Guarda Client ID y Client Secret fuera del código fuente, no los escribas en los logs y no los envíes en conversaciones o tickets.
Releases - orden de trabajo de la integración
- Determina la dirección correcta de Cloud o la dirección real de la instalación On-Premise.
- Crea una clave independiente para la aplicación y el entorno en Ajustes - API - API Keys.
- Concede únicamente los scopes necesarios para releases y las relaciones previstas.
- Envía
GET /api/v1/contexty comprueba la base de datos, el caller, los scopes y los límites. - Obtén
GET /api/v1/releases/schemay crea el mapeo de campos. - Obtén la lista con paginación, búsqueda o filtros.
- Crea un release mediante
POSTcon unIdempotency-Keynuevo. - Guarda el UUID y el ETag.
- Antes de cada cambio, lee el registro actual y su ETag.
- Realiza ediciones, relaciones, operaciones de archivos y acciones de workflow con el ETag concreto y una clave de idempotencia nueva.
- Después de cada mutación correcta, guarda el ETag nuevo y vuelve a leer el resultado.
- Después de
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 el estado de cada elemento porque un batch no es una transacción.
- En una aprobación, comprueba su estado después de la decisión.
- Para borrar, utiliza el ETag actual y confirma después HTTP 404 con un GET.
Este flujo permite sincronizar la planificación y el despliegue de releases sin depender de suposiciones accidentales sobre campos, relaciones o la dirección de la instalación.
