API de defectos
Los defectos son registros de bugs por proyecto con numeración secuencial (defectNumber, mostrado como D-<n> en la interfaz). El reporter se deriva del actor autenticado al crear y no puede enviarse en el cuerpo de la petición.
/api/v1/projects/{projectId}/defects{projectId} es el código del proyecto (por ejemplo ACME).
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»| Campo | Obligatorio | Notas |
|---|---|---|
title | sí | Cadena no vacía |
description | no | Texto Markdown |
assigneeUlid | no | ULID de miembro de la organización |
tags | no | Arreglo de cadenas |
milestoneUlid | no | Hito del mismo proyecto |
customFieldValues | no | Arreglo de { fieldUlid, value } para campos de defecto visibles. Los campos de sistema Severity y Priority son obligatorios con opciones por defecto de la organización; si omites valores que siguen siendo el predeterminado, el servidor los persiste. Otras claves omitidas se satisfacen al crear si el campo tiene un valor por defecto almacenado no vacío; en caso contrario el create devuelve 422 validation_failed. |
reporter, resolvedAt y closedAt se rechazan si el cliente los envía.
Ejemplo
Sección titulada «Ejemplo»curl -sS -X POST \ -H "Authorization: Bearer $PROBARA_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title":"El login falla con contraseña expirada"}' \ "https://probara.net/api/v1/projects/ACME/defects"/api/v1/projects/{projectId}/defectsPaginación por página (page, pageSize), los más recientes primero. La respuesta sigue el formato de los listados de tabla (items, page, pageSize, total), donde total cuenta todos los defectos que coinciden con los filtros activos y q. Cada ítem incluye los campos del defecto más occurrenceCount, lastSeenAt (agregados desde intentos vinculados) y systemFieldValues (solo entradas de severidad/prioridad del sistema). Sin fields, los ítems del listado no incluyen customFieldValues.
Pasa fields como lista separada por comas de ULIDs de campos personalizados de defecto visibles en el proyecto para embeber customFieldValues en cada ítem (valor guardado o predeterminado materializado, mismo formato que el detalle). Un campo fuera del alcance del proyecto devuelve 422 validation_failed.
Filtros de consulta
Sección titulada «Filtros de consulta»Los filtros se combinan con AND entre parámetros y se evalúan en el servidor. Los
parámetros con valores de conjunto severity, priority y assigneeUlid aceptan un
conjunto de ULID separados por comas y se combinan con OR dentro de cada
parámetro; un valor único se acepta como un conjunto de un elemento, por lo que las
URL anteriores con un solo valor siguen funcionando.
| Parámetro | Notas |
|---|---|
status | Conjunto separado por comas, p. ej. open,in_progress |
severity | Conjunto separado por comas de ULID de opción del campo de sistema defect_severity (OR dentro; coincide con defectos que tengan cualquiera) |
priority | Conjunto separado por comas de ULID de opción del campo de sistema defect_priority (OR dentro) |
assigneeUlid | Conjunto separado por comas de ULID de miembros de la organización (OR dentro); un ULID que no resuelve a ningún miembro se ignora, y el filtro no coincide con nada solo cuando ninguno resuelve |
q | Subcadena del título, o número de defecto con D-<n> o entero |
aging | Antigüedad de defectos abiertos: d0_7, d7_14, d14_30, d30plus (por created_at) |
fields | ULIDs de campos personalizados separados por comas para embeber por ítem (customFieldValues) |
cf | Filtro repetible por campo personalizado: <fieldUlid>:<valor[,valor…]> (ver abajo) |
Valores de status inválidos devuelven 422 validation_failed.
Filtros de campos personalizados (cf)
Sección titulada «Filtros de campos personalizados (cf)»Repite el parámetro cf una vez por campo. Varias entradas cf se combinan con AND. Dentro de un campo, los valores separados por comas se combinan con OR.
Tipos admitidos: select, select_multi, checkbox y user_picker. Otros tipos (incluido paragraph) devuelven 422 validation_failed. Los filtros coinciden solo con filas de valor guardadas — un predeterminado materializado en lectura no satisface un filtro por opción hasta persistirse.
| Token de valor | Significado |
|---|---|
| ULID de opción | Defecto guardado con esa opción (select) o que la contiene (select_multi) |
true / false | Valor guardado de casilla |
| ULID de miembro | Miembro guardado en user_picker |
empty | Sin fila guardada para el campo (incluidos defectos que mostrarían un predeterminado en detalle) |
Ejemplo — defectos en Staging o Production (mismo campo, OR por comas):
GET /api/v1/projects/ACME/defects?cf=01HENVFIELD:01HSTAGING,01HPRODEjemplo — sin valor de Environment o Staging, y casilla Risk aceptado:
GET /api/v1/projects/ACME/defects?cf=01HENVFIELD:empty,01HSTAGING&cf=01HRISKFIELD:trueEjemplo — embeber columnas Environment y Owner:
GET /api/v1/projects/ACME/defects?fields=01HENVFIELD,01HOWNERFIELDMétricas del tablero
Sección titulada «Métricas del tablero»/api/v1/projects/{projectId}/defects/metricsRespuesta única para la franja de métricas del listado y la insignia de la barra
lateral. Todas las cifras usan la organización y el proyecto activos; peticiones
fuera del inquilino devuelven 404 not_found.
| Campo | Definición |
|---|---|
totalOpen | Defectos en open o in_progress |
openBySeverity | Objeto con options (arreglo de { optionUlid, systemKey, name, icon, color, count } en orden de opción, incluyendo ceros) y unset (defectos abiertos sin fila de severidad) |
aging | Población abierta por antigüedad desde created_at: d0_7, d7_14, d14_30, d30plus |
reopenRate | Defectos distintos con ≥1 evento defect.reopened ÷ defectos distintos resueltos alguna vez (defect.status_changed con to resolved o closed); null si el denominador es 0 |
mttrMs | Media de resolved_at − created_at sobre defectos actualmente resolved/closed con resolved_at no nulo; null si no hay ninguno |
byMilestone | Población abierta por hito (ulid, name, count) más unassigned |
Defectos vinculados a una ejecución
Sección titulada «Defectos vinculados a una ejecución»/api/v1/runs/{runUlid}/defectsLista defectos distintos vinculados a cualquier intento de la ejecución (join
defect_result_links → test_results de la ejecución). Cada ítem incluye los
campos públicos del defecto más linkCountInRun (solo vínculos en esta ejecución) y systemFieldValues de severidad/prioridad.
Devuelve { items: [...] } (sin paginación). Ejecuciones desconocidas o fuera del
inquilino devuelven 404 not_found. Funciona en ejecuciones abiertas y cerradas.
Detalle
Sección titulada «Detalle»/api/v1/defects/{defectUlid}Devuelve el payload completo del defecto: vocabulario, ULIDs de personas, etiquetas, hito, referencia duplicate-of, marcas de tiempo del ciclo de vida, el resumen derivado (occurrenceCount, lastSeenAt, affectedCaseCount) y customFieldValues embebidos para cada campo de defecto visible en el proyecto (valor guardado o predeterminado materializado, con enriquecimiento de opciones cuando aplica). El listado de defectos del proyecto incluye customFieldValues solo cuando se solicita con fields.
Valores de campos personalizados
Sección titulada «Valores de campos personalizados»Las definiciones con alcance de defecto se gestionan en GET/POST/PATCH/DELETE /api/v1/orgs/{orgUlid}/custom-fields con entity: defect. Los valores se almacenan por par (campo, defecto).
Reemplazar todos los valores visibles
Sección titulada «Reemplazar todos los valores visibles»/api/v1/defects/{defectUlid}/custom-field-valuesCuerpo: { "values": [ { "fieldUlid": "...", "value": ... }, ... ] } — una entrada por campo visible. Los campos obligatorios deben estar en el conjunto de escritura. Emite defect.updated con metadata.customFieldChanges (no un evento custom_field.* aparte).
Parchear un campo
Sección titulada «Parchear un campo»/api/v1/defects/{defectUlid}/custom-field-values/{fieldUlid}Cuerpo: { "value": ... }. En tipos anulables, null borra el valor; los obligatorios rechazan vaciados con 422 validation_failed. Devuelve el arreglo embebido completo customFieldValues del defecto.
Actualizar
Sección titulada «Actualizar»/api/v1/defects/{defectUlid}Actualización parcial de title, description, status, resolution, assigneeUlid, tags, milestoneUlid y duplicateOfUlid. Severidad y prioridad se editan con los endpoints de valores de campo personalizado, no con este PATCH.
Las transiciones de estado siguen un mapa guiado (open/in_progress → resolved/closed; resolved → closed/open; closed → open). Las transiciones ilegales devuelven 422 validation_failed con ruta de campo status. Los parches sin cambio de estado aplican otros campos sin emitir evento de estado.
- Pasar a
resolvedoclosedexigeresolution. resolution = duplicateexigeduplicateOfUlid; las cadenas se aplanan al raíz canónico al escribir.- Reabrir a
opendesderesolvedoclosedlimpiaresolution,duplicateOfUlidy las marcas gestionadas; emitedefect.reopeneden lugar dedefect.status_changed. duplicateOfUliddebe apuntar a otro defecto del mismo proyecto cuando se usa.
Requiere rol owner, admin o member en la organización; un viewer recibe 403 forbidden antes de cualquier escritura.
Devuelve 404 not_found si el defecto no pertenece a la organización activa.
Eliminar
Sección titulada «Eliminar»/api/v1/defects/{defectUlid}Elimina el defecto de forma permanente. Responde 204 si tiene éxito; un GET posterior devuelve 404 not_found.
Vincular con resultados de prueba
Sección titulada «Vincular con resultados de prueba»Los defectos pueden vincularse a intentos inmutables de ejecución (filas de test_results). El par (defecto, resultado) es único; repetir la misma petición devuelve el vínculo existente con 200.
Crear o re-vincular
Sección titulada «Crear o re-vincular»/api/v1/defects/{defectUlid}/result-links| Campo | Obligatorio | Notas |
|---|---|---|
resultUlid | sí | Resultado de una ejecución del mismo proyecto que el defecto |
stepSnapshotUlid | no | Instantánea de paso congelada perteneciente a ese resultado |
Responde 201 en el primer vínculo y 200 si el par ya existía.
Listar ocurrencias
Sección titulada «Listar ocurrencias»/api/v1/defects/{defectUlid}/result-linksPaginación por cursor (limit, cursor). Cada ítem incluye el vínculo, el autor, el estado/executedAt del resultado y el contexto de ejecución y caso.
Desvincular
Sección titulada «Desvincular»/api/v1/defects/{defectUlid}/result-links/{linkUlid}Responde 204. El vínculo debe pertenecer al defecto indicado.
Sugerencias para un caso de prueba
Sección titulada «Sugerencias para un caso de prueba»/api/v1/test-cases/{caseUlid}/defectsLista defectos vinculados previamente a cualquier resultado del caso, con occurrenceCount y lastSeenAt acotados al caso. Los defectos abiertos o en progreso aparecen antes que los resueltos o cerrados.
Casos de prueba afectados
Sección titulada «Casos de prueba afectados»/api/v1/defects/{defectUlid}/affected-casesPaginación por cursor (limit, cursor). Devuelve casos de prueba distintos vinculados mediante asociaciones de resultado. Cada ítem incluye testCaseUlid, testCaseTitle, caseNumber, displayId (la referencia del caso en el repositorio, {PROJECT_CODE}-{caseNumber}), occurrenceCount, lastLinkedAt, latestResult (la ejecución más reciente del caso en general, o null si nunca se ejecutó) y verification.
Cuando el estado del defecto es resolved, verification puede ser:
| Valor | Significado |
|---|---|
verified | El último resultado es passed con executedAt posterior a resolvedAt |
failed_after_resolve | El último resultado es failed o blocked después de resolvedAt |
pending | No hay ejecución cualificada tras la resolución |
Para defectos no resueltos, verification es null. Devuelve 404 not_found entre inquilinos.
Eventos de auditoría
Sección titulada «Eventos de auditoría»Las mutaciones emiten defect.created, defect.updated, defect.status_changed, defect.reopened, defect.deleted, defect.linked y defect.unlinked en el feed de actividad de la organización (los eventos de vínculo también aparecen en el feed de la ejecución mediante run_id). Las mutaciones de evidencia y discusión también emiten defect.attachment_added, defect.attachment_deleted, defect.commented, defect.comment_updated y defect.comment_deleted. Las resoluciones duplicado incluyen duplicateOfUlid y una etiqueta D-<n> en los metadatos de defect.status_changed. Ver Eventos de auditoría.
Historial por defecto
Sección titulada «Historial por defecto»/api/v1/defects/{defectUlid}/audit-eventsPaginación por cursor (limit, cursor) sobre eventos con entityType defect y entityUlid igual al defecto. La respuesta coincide con el endpoint de auditoría de ejecuciones (events, nextCursor). Devuelve 404 not_found si el defecto no pertenece a la organización activa.
Adjuntos de evidencia
Sección titulada «Adjuntos de evidencia»Las imágenes de evidencia se almacenan bajo el prefijo R2 de la organización. Tipos permitidos: PNG, JPEG, WebP. Máximo 10 MiB por archivo, hasta 10 archivos por solicitud de subida. Las subidas cargan el contador de almacenamiento defect_attachment de la organización.
Los visualizadores pueden listar adjuntos; solo miembros y roles superiores pueden subir o eliminar.
/api/v1/defects/{defectUlid}/attachmentsDevuelve { attachments: [...] } en orden de subida (más antiguos primero). Cada ítem incluye ulid, mime, dimensiones, byteSize, originalFilename, uploadedBy, url, thumbUrl y createdAt.
/api/v1/defects/{defectUlid}/attachmentsmultipart/form-data con una o más partes file. Devuelve 201 con { attachments: [...] }. MIME no permitido o tamaño excesivo devuelve 422 validation_failed. Emite defect.attachment_added.
Eliminar
Sección titulada «Eliminar»/api/v1/defects/{defectUlid}/attachments/{attachmentUlid}Devuelve 204. Elimina la fila, ambos objetos R2 y reembolsa bytes de almacenamiento. Emite defect.attachment_deleted. Un ULID de adjunto de otro defecto devuelve 404 not_found.
Al eliminar un defecto se quitan todos los objetos de evidencia y se reembolsan los bytes antes del cascade.
Comentarios de discusión
Sección titulada «Comentarios de discusión»Los comentarios son texto plano (recortado, no vacío, máximo 5000 caracteres) y admiten un nivel de respuestas en hilo, fijado y resolución de menciones @. La superficie de comentarios de defectos es estructuralmente idéntica a los comentarios de casos de prueba — consulta esa página para la referencia completa (semántica de respuestas, reglas de fijado, resolución de menciones, forma de la respuesta y eliminación en cascada). Esta sección solo lista las rutas y acciones de auditoría específicas de defectos.
Los visualizadores pueden listar comentarios; solo miembros y roles superiores pueden crear, editar, eliminar o fijar/desfijar. El listado usa paginación por cursor sobre comentarios de primer nivel (parentUlid ausente), con orden predeterminado del más antiguo al más reciente; el arreglo replies[] de cada elemento se mantiene cronológico sin importar el orden.
/api/v1/defects/{defectUlid}/commentsConsulta: limit (predeterminado 50, máximo 200), cursor, sort (oldest | newest, predeterminado oldest). Cada elemento lleva parentUlid, pinnedAt, pinnedBy, replyCount, mentions, y replies[] en línea; el pinned[] de la respuesta contiene el conjunto completo de fijados para el defecto. Las respuestas no se enumeran en el items[] plano — ver comentarios de casos de prueba para la forma completa de la respuesta y la advertencia sobre las respuestas.
/api/v1/defects/{defectUlid}/comments| Campo | Obligatorio | Notas |
|---|---|---|
body | sí | Texto recortado, 1–5000 caracteres |
parentUlid | no | Responde a un comentario de primer nivel existente en el mismo defecto (solo profundidad 1) |
Devuelve 201. Emite defect.commented con un extracto de 140 caracteres.
/api/v1/defects/{defectUlid}/comments/{commentUlid}| Campo | Obligatorio | Notas |
|---|---|---|
body | sí | Misma validación que en crear |
Solo el autor — los administradores no pueden editar el comentario de otro miembro (403 forbidden). Establece editedAt al tener éxito y vuelve a resolver las menciones. Emite defect.comment_updated.
Eliminar
Sección titulada «Eliminar»/api/v1/defects/{defectUlid}/comments/{commentUlid}Devuelve 204. El autor puede eliminar su propio comentario. Los administradores de la organización pueden eliminar cualquier comentario. Otros miembros reciben 403. Eliminar un comentario de primer nivel elimina en cascada sus respuestas, purgando sus adjuntos. Emite defect.comment_deleted (una vez por el comentario eliminado, más una vez por cada respuesta eliminada en cascada).
Fijar / desfijar
Sección titulada «Fijar / desfijar»POST / DELETE /api/v1/defects/{defectUlid}/comments/{commentUlid}/pin
Cualquier miembro o rol superior puede fijar o desfijar cualquier comentario de primer nivel, sin importar la autoría; los visualizadores reciben 403. Fijar una respuesta devuelve 422 validation_failed. No hay límite de comentarios fijados por defecto. Emite defect.comment_pinned / defect.comment_unpinned.