Ir al contenido

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.

POST/api/v1/orgs/{orgUlid}/tags

Requiere el permiso de escritura de etiquetas (que tienen owner/admin/member); un viewer recibe 403 forbidden.

CampoObligatorioNotas
namesí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.

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.

Ventana de terminal
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"
  • 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. Smoke y smoke son dos etiquetas distintas y pueden coexistir; solo una repetición exacta tras el recorte devuelve 409 conflict. El mismo nombre se acepta en otra organización.
GET/api/v1/orgs/{orgUlid}/tags

Sin 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ámetroNotas
pageNúmero de página (base 1, por defecto 1)
pageSizeElementos por página (por defecto 50, máximo 200)
qBúsqueda de subcadena en el nombre, sin distinguir mayúsculas, máximo 80 caracteres
authorUlidULIDs 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.

200 con { items, page, pageSize, total }. Cada ítem sigue el formato de respuesta.

Ventana de terminal
curl -sS \
-H "Authorization: Bearer $PROBARA_API_TOKEN" \
"https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags?q=smoke&pageSize=100"
PATCH/api/v1/orgs/{orgUlid}/tags/{tagUlid}

Requiere el permiso de escritura de etiquetas (que tienen owner/admin/member); un viewer recibe 403 forbidden.

CampoObligatorioNotas
namesí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.

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.

Ventana de terminal
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"
DELETE/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.

Ventana de terminal
curl -sS -X DELETE \
-H "Authorization: Bearer $PROBARA_API_TOKEN" \
"https://app.probara.net/api/v1/orgs/01JXXXXXXXXXXXXXXXXXXXXXXXXX/tags/01JTAGXXXXXXXXXXXXXXXXXXXXX"
POST/api/v1/orgs/{orgUlid}/tags/bulk-delete

Requiere el permiso de eliminación de etiquetas (que tienen owner/admin); tanto un member como un viewer reciben 403 forbidden.

CampoObligatorioNotas
ulidssíDe 1 a 100 ULIDs de etiqueta. Un arreglo vacío o excedido devuelve 422 validation_failed

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.

Ventana de terminal
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"

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.

CampoTipoNotas
ulidstring (ULID)Identificador único asignado por el servidor
namestringEl nombre de la etiqueta, tal cual lo llevan las entidades
createdByobject | nullResumen del autor, o null (ver Autor)
caseCountnumberCasos de prueba que llevan la etiqueta (ver Contadores de uso)
runCountnumberEjecuciones que llevan la etiqueta
defectCountnumberDefectos que llevan la etiqueta
createdAtnumberMilisegundos desde epoch Unix
updatedAtnumberMilisegundos desde epoch Unix

createdBy, cuando existe, lleva ulid, displayName, avatarKey, avatarVersion y positionTitle.

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 0 e 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.

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 un null enviado) vacía el conjunto, y la entidad se lee de vuelta con tags: null, no con tags: []. 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.

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.