API de etiquetas
Las etiquetas son un vocabulario de toda la organización, compartido por casos de prueba, defectos y ejecuciones. Hay un solo catálogo por organización, montado bajo /api/v1/orgs/{orgUlid}/tags. Cada etiqueta tiene un ULID asignado por el servidor, un nombre único dentro de la organización, un autor y tres contadores de uso.
Las entidades nunca referencian una etiqueta por ULID. Un caso de prueba, un defecto y una ejecución llevan todos tags: string[] — los nombres — y el servidor resuelve o crea la fila del catálogo detrás de ellos. Ver Asociar etiquetas a entidades.
/api/v1/orgs/{orgUlid}/tagsRequiere el permiso de escritura de etiquetas (que tienen owner/admin/member); un viewer recibe 403 forbidden.
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»| Campo | Obligatorio | Notas |
|---|---|---|
name | sí | Recortado, 1–80 caracteres. Debe ser único dentro de la organización (ver Reglas de nombre) |
El cuerpo es estricto: cualquier otra clave devuelve 422 validation_failed.
Respuesta
Sección titulada «Respuesta»201 con la etiqueta creada. Sus tres contadores valen 0: una etiqueta recién creada no está asociada a nada. Ver Campos de respuesta.
Un nombre duplicado devuelve 409 conflict.
Ejemplo
Sección titulada «Ejemplo»curl -sS -X POST \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"smoke"}' \ "https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags"Reglas de nombre
Sección titulada «Reglas de nombre»- El nombre se recorta antes de guardarse y antes de compararse, así que
" smoke "y"smoke"son la misma etiqueta. - La longitud se mide después del recorte: de 1 a 80 caracteres. Un nombre compuesto solo de espacios devuelve
422 validation_failed. - La unicidad es por organización y distingue mayúsculas.
Smokeysmokeson dos etiquetas distintas y pueden coexistir; solo una repetición exacta tras el recorte devuelve409 conflict. El mismo nombre se acepta en otra organización.
/api/v1/orgs/{orgUlid}/tagsSin control de permisos: cualquier miembro de la organización puede leer el catálogo. Paginación por página.
El orden es name ascendente y es fijo: no hay parámetros de ordenación.
Parámetros de consulta
Sección titulada «Parámetros de consulta»| Parámetro | Notas |
|---|---|
page | Número de página (base 1, por defecto 1) |
pageSize | Elementos por página (por defecto 50, máximo 200) |
q | Búsqueda de subcadena en el nombre, sin distinguir mayúsculas, máximo 80 caracteres |
authorUlid | ULIDs de usuario separados por coma; coincide con las etiquetas creadas por cualquiera de ellos. Un ULID que no resuelve a ningún miembro no aporta nada, y un filtro que no resuelve a ningún miembro no coincide con nada en lugar de degradar a un listado sin filtrar |
La consulta es estricta: un parámetro mal escrito (authorUlids, pageSizes) devuelve 422 validation_failed en vez de descartarse en silencio.
Respuesta
Sección titulada «Respuesta»200 con { items, page, pageSize, total }. Cada ítem sigue el formato de respuesta.
Ejemplo
Sección titulada «Ejemplo»curl -sS \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ "https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags?q=smoke&pageSize=100"Actualizar
Sección titulada «Actualizar»/api/v1/orgs/{orgUlid}/tags/{tagUlid}Requiere el permiso de escritura de etiquetas (que tienen owner/admin/member); un viewer recibe 403 forbidden.
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»| Campo | Obligatorio | Notas |
|---|---|---|
name | sí | El nuevo nombre. Mismas reglas de recorte, longitud y unicidad que al crear |
name es el único campo, así que un cuerpo vacío devuelve 422 validation_failed.
Respuesta
Sección titulada «Respuesta»200 con la etiqueta renombrada, con la misma forma que devuelve POST — y con los contadores reales de la etiqueta, no ceros. El cambio de nombre alcanza a todos los casos de prueba, defectos y ejecuciones que la llevan, sin desasociar ni modificar ninguno.
Un nombre que ya tiene otra etiqueta devuelve 409 conflict. Un {tagUlid} fuera de la organización devuelve 404 not_found; uno mal formado devuelve 422 validation_failed.
Ejemplo
Sección titulada «Ejemplo»curl -sS -X PATCH \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"smoke-suite"}' \ "https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags/01JTAGXXXXXXXXXXXXXXXXXXXXX"Eliminar
Sección titulada «Eliminar»/api/v1/orgs/{orgUlid}/tags/{tagUlid}Requiere el permiso de eliminación de etiquetas (que tienen owner/admin); tanto un member como un viewer reciben 403 forbidden. La separación es deliberada: eliminar una etiqueta la desasocia de todos los casos de prueba, defectos y ejecuciones que la llevan, y eso llega más lejos que ampliar el vocabulario.
Devuelve 204. Las entidades quedan intactas: solo se eliminan la fila de la etiqueta y sus asociaciones. Un {tagUlid} fuera de la organización devuelve 404 not_found.
Ejemplo
Sección titulada «Ejemplo»curl -sS -X DELETE \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ "https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags/01JTAGXXXXXXXXXXXXXXXXXXXXX"Borrado en lote
Sección titulada «Borrado en lote»/api/v1/orgs/{orgUlid}/tags/bulk-deleteRequiere el permiso de eliminación de etiquetas (que tienen owner/admin); tanto un member como un viewer reciben 403 forbidden.
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»| Campo | Obligatorio | Notas |
|---|---|---|
ulids | sí | De 1 a 100 ULIDs de etiqueta. Un arreglo vacío o excedido devuelve 422 validation_failed |
Respuesta
Sección titulada «Respuesta»200 con { deleted: number }: cuántas filas se eliminaron realmente. El lote es tolerante por diseño: un ULID que esta organización no posee, o uno que un borrado concurrente ya se llevó, se omite en lugar de hacer fallar la petición. Por eso deleted no siempre coincide con el tamaño del lote, y es la única señal de que tu selección contenía algo que no te pertenece.
Cada borrado desasocia la etiqueta exactamente igual que el DELETE individual.
Ejemplo
Sección titulada «Ejemplo»curl -sS -X POST \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"ulids":["01JTAGAXXXXXXXXXXXXXXXXXXXX","01JTAGBXXXXXXXXXXXXXXXXXXXX"]}' \ "https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags/bulk-delete"Campos de respuesta
Sección titulada «Campos de respuesta»POST, PATCH y cada ítem del listado devuelven un objeto de etiqueta con los siguientes campos. El objeto es estricto: no viaja ninguna otra clave.
| Campo | Tipo | Notas |
|---|---|---|
ulid | string (ULID) | Identificador único asignado por el servidor |
name | string | El nombre de la etiqueta, tal cual lo llevan las entidades |
createdBy | object | null | Resumen del autor, o null (ver Autor) |
caseCount | number | Casos de prueba que llevan la etiqueta (ver Contadores de uso) |
runCount | number | Ejecuciones que llevan la etiqueta |
defectCount | number | Defectos que llevan la etiqueta |
createdAt | number | Milisegundos desde epoch Unix |
updatedAt | number | Milisegundos desde epoch Unix |
createdBy, cuando existe, lleva ulid, displayName, avatarKey, avatarVersion y positionTitle.
Contadores de uso
Sección titulada «Contadores de uso»Los tres contadores no son totales de toda la organización. Hay dos propiedades que le importan a un integrador:
- Están acotados a los proyectos que quien llama puede leer. Una etiqueta asociada a un caso de un proyecto al que quien llama no tiene acceso no se cuenta para esa credencial. Dos credenciales pueden leer contadores distintos para la misma etiqueta con toda legitimidad, y ninguno está desactualizado.
- Incluyen los casos de prueba archivados (en la papelera). Es deliberado: una etiqueta cuyo único uso está archivado no debe marcar
0e invitar a un borrado que le quitaría la etiqueta al caso en cuanto se restaure.
Un 0 significa entonces «nada visible para quien llama lleva la etiqueta», no «la etiqueta no se usa».
createdBy es null cuando la etiqueta no tiene un autor resoluble. Hay dos casos distintos que lo producen:
- La etiqueta la creó un token de API o un agente MCP. Una etiqueta así no tiene autor humano por diseño.
- La cuenta del autor fue borrada.
Una etiqueta cuyo autor simplemente dejó la organización sigue llevando su resumen.
Asociar etiquetas a entidades
Sección titulada «Asociar etiquetas a entidades»Los casos de prueba, los defectos y las ejecuciones llevan tags: string[] — nombres, no ULIDs — tanto en la petición como en la respuesta. Las ejecuciones ganaron el campo junto con este catálogo: como máximo 50 nombres por ejecución, de 1 a 80 caracteres cada uno, en POST, en PATCH y en la respuesta de la ejecución.
El servidor resuelve cada nombre enviado contra el catálogo y crea la fila cuando el nombre es nuevo, así que enviar un nombre que el catálogo nunca vio acuña la etiqueta: no hace falta un POST /tags aparte. El arreglo del cuerpo de creación asocia; un arreglo en PATCH reemplaza el conjunto completo de etiquetas de la entidad.
De este contrato basado en nombres se desprenden dos consecuencias que conviene contemplar en el código:
- Un
[]enviado (y unnullenviado) vacía el conjunto, y la entidad se lee de vuelta contags: null, no contags: []. Omitir la clave deja el conjunto existente intacto. - El arreglo devuelto siempre viene en orden alfabético, nunca en el orden de envío. No lo compares por posición con lo que enviaste.
Eliminar una etiqueta del catálogo la quita de todas las entidades que la llevaban; las entidades quedan intactas por lo demás y sus arreglos tags simplemente vuelven más cortos.
Herramientas MCP
Sección titulada «Herramientas MCP»Las mismas cinco operaciones se exponen a los clientes MCP como list_tags, create_tag, update_tag, delete_tag y bulk_delete_tags. Cada una toma org_id (de get_current_organization) y aplica los mismos permisos que la ruta HTTP que tiene detrás. Una etiqueta creada por un agente MCP tiene createdBy: null, como describe Autor. Ver Herramientas MCP.