API REST

Issues

Buscar, crear, editar, comentar, adjuntar, mover, vincular e importar issues.

  • GET /issues (tracker:read): búsqueda. Query: project, status (claves del flujo del proyecto), category (todo, in_progress, done), severity, priority, type, nature (problem, improvement, task: la naturaleza del tipo, que vale en cualquier proyecto) (listas separadas por coma), label, assignee (me, none o id), open_only (true), blocked_only (true: solo las que tienen la marca de bloqueo), mine (true: solo las de la persona del token como responsable o QA, como "Mis tareas" en la pantalla), watching (true: solo las que sigue), q (texto libre: código, título, descripción y comentarios), query (consulta avanzada, escrita en portugués, ej.: projeto = MOB e status = Aberto e responsavel = eu), saved_filter (nombre de un filtro guardado), created_from y created_to (AAAA-MM-DD), limit (hasta 50), offset, sort (code, title, status, severity, assignee o updated), order (asc o desc) y done_last (true: las completadas, grupo done, al final, antes del orden pedido). Sin sort, las más recientes primero. La API no oculta nada por defecto: sin filtro de estado, vienen también las completadas. La lista de tareas de la pantalla oculta las completadas hasta que la persona pide "Mostrar completadas" (y entonces las muestra al final); para reproducirlo, usa open_only=true o done_last=true. En el MCP, los mismos open_only y done_last de search_issues. Cada issue viene con close_reason (en Cerrado), blocked y blocked_reason (la marca de bloqueo), retest_failed (rechazada en el último retest y todavía no aprobada), assignee, qa_owner, sprint, release, releases (todas las entregas como "GOP 1.4.8-ota002", la principal primero), module, parent y epic (códigos), labels, start_date, due_date, external_id y edit_version (para PATCH y el lote, sin abrir cada issue); include=description,custom_fields agrega la descripción y los campos personalizados.
  • GET /search?q=<texto> (tracker:read): "¿ya pasó antes?". Búsqueda híbrida, por significado y por palabras, en issues (con los comentarios) y, con kinds=issue,ticket, en los tickets de la Mesa de ayuda (solo para quien atiende). issue=<código> en lugar de q busca las parecidas a esa issue, sin ella. project, open_only (true) y limit (hasta 30, por defecto 8). Cada resultado trae kind, code, title, status_label, open, project, score (0 a 1), similarity (del vector, cuando la encontró por significado), matched_by (text, meaning), likely_duplicate y url; mode es hybrid o text (solo por palabras); semantic dice si la búsqueda por significado está activada en la empresa: on, indexed (cuántos elementos ya están en el índice; crece cada minuto mientras el índice se arma) y, desactivada, reason (no_vector: la búsqueda por significado no está disponible en este servidor; no_key: aqua desactivada, clave propia de la empresa o sin créditos de IA). Con on true y mode text, la búsqueda por significado no respondió a tiempo o la persona pasó el límite de búsquedas por significado. Con issue, la búsqueda parte de la ficha de contexto que aqua escribe de cada issue (aqua_context de GET /issues/{ref}). explain (por defecto true; false devuelve solo la lista de la búsqueda, más rápida) hace que aqua compare cada hallazgo con la referencia: quita lo que solo comparte palabras y completa relation (same: el mismo problema; related: relacionado) y reason (la relación en una frase); explained dice si lo comparó (sin aqua activada, false y la lista de la búsqueda). Antes de crear una issue, busca aquí para no duplicar (ver "¿Ya pasó antes?" arriba). En el MCP: search_similar.
  • GET /issues/{código o id} (tracker:read): la issue con status (key, label, category, close_reason en Cerrado con key y label, y retest_failed_at cuando se rechazó en el último retest), blocked (since y reason, o null), releases (todas las entregas, la principal primero con primary: true), padre y epic (el padre, o el padre del padre en una subtarea), hijas, sprint, puntos, estimación, fechas, campos personalizados, etiquetas, vínculos, quién la sigue, comentarios, historial (from/to con los valores guardados y text, como en la pantalla: nombres de releases, personas y sprints; from_label/to_label cuando la pantalla muestra de/a), aqua_summary (el último resumen de la conversación hecho por aqua en la pantalla: happened, pending, ball con quién tiene la pelota y outdated cuando hubo comentarios o cambios después; null sin resumen), aqua_context (la ficha de contexto que aqua escribe sola, en segundo plano, para "¿Ya pasó antes?": summary con el problema en palabras neutras, area, terms, generated_at y outdated cuando la issue cambió y la ficha todavía se va a rehacer; null con aqua desactivada o antes de la primera ficha) y edit_version (para PATCH). ?fields=status,releases trae solo esas partes (id, code, url y edit_version siempre): sirve para revisar muchas issues sin traer comentarios e historial.
  • GET /issues/{código o id}/comments (tracker:read): todos los comentarios, cada uno con id, author, text, at, edited_at, deleted (quién lo eliminó y cuándo; el texto viene vacío), mentions y las respuestas (replies).
  • POST /issues/{código o id}/comments (tracker:write): comenta, {"text": "...", "parent_id": "<id del comentario respondido>"}. @Nome menciona a alguien del proyecto. "attachments": [{"file_name": "informe.md", "content_base64": "..."}, {"url": "https://..."}] adjunta hasta 5 archivos al comentario (14 MB sumados), con las reglas de los adjuntos de abajo; un adjunto con problemas rechaza el comentario entero. 201 con el id y los attachments. En el GET, cada comentario trae sus attachments (id, name, type, size_bytes, download_url).
  • GET /issues/{código o id}/evidences (tracker:read): los adjuntos (evidencias) de la issue, del más antiguo al más nuevo, cada uno con id, name, type, size_bytes, description, comment_id (cuando vino en un comentario) y download_url. GET /evidences/{id} (tracker:read) descarga el archivo, con el mismo token (acepta Range). Por el MCP, cuyo token no vale aquí, get_attachment lee el contenido: texto (md, csv, txt, log, json) e imagen (png, jpg, webp, gif hasta 5 MB); vale también para los adjuntos de los chats.
  • POST /issues/{código o id}/evidences (tracker:write): adjunta un archivo, de tres formas: multipart/form-data con el archivo en el campo file (y description y comment_id opcionales, en texto); JSON {"file_name": "evaluacion.md", "content_base64": "...", "description": "..."} (acepta el prefijo data:...;base64,); o JSON {"url": "https://ejemplo.com/captura.png"}, que tracker descarga (solo https y dirección pública, hasta 3 redirecciones y 20 s; la URL no se guarda; file_name opcional cambia el nombre). Formatos por la extensión del nombre: png, jpg, jpeg, webp, gif, mp4, mov, pdf, json, txt, log, md, csv, zip; hasta 15 MB por archivo y 60 archivos por hora por persona. comment_id pone el archivo debajo de un comentario tuyo de la issue. PO/PM, QA, dev o admin (403 para los demás). 201 con attachment (como en el GET). No hay URL prefirmada: el bucket es privado y todo archivo pasa por tracker, que revisa el formato y el tamaño. DELETE /issues/{código o id}/evidences/{id} lo quita (quien lo envió o un admin del proyecto; el archivo de una versión de aprobación se queda). En el MCP: attach_file, remove_attachment y attachments en add_comment; los adjuntos aparecen en get_issue (evidences).
  • PATCH /issues/{código o id}/comments/{id} (tracker:write): corrige el texto, {"text": "..."}. Solo quien lo escribió (403 para los demás); el texto anterior queda guardado para el admin. DELETE en la misma dirección lo elimina: el comentario queda en su lugar, sin el texto (quien lo escribió o un admin de la empresa).
  • GET /issues/{código o id}/history (tracker:read): el historial completo, el más reciente primero (limit hasta 200, offset), con total y cada evento con at, by, action, field, text y, cuando los hay, from y to ya con nombre.
  • POST /issues/{código o id}/move (tracker:write): lleva la issue a otro proyecto de la misma organización, {"project": "CHG", "confirm": true}. Sin confirm, solo devuelve la vista previa (moved: false, avisos de lo que no tiene equivalente en el destino, subtareas que van juntas); con confirm: true, la mueve y devuelve el código nuevo (code) y el anterior (previous_code), que sigue encontrando la issue. 409 si la issue cambió en el medio: léela de nuevo y repite. Exige editar la issue y crear issues en el destino.
  • POST /issues/{código o id}/links (tracker:write): la vincula a otra issue, {"target": "MOB-0007", "type": "blocks"} (blocks, relates_to, el de por defecto, o duplicates). Exige editar la issue. 201 con los vínculos de la issue (links, cada uno con id). DELETE /issues/{ref}/links/{id} quita un vínculo.
  • GET /issues/{código o id}/proofs (tracker:read): aprobación de piezas (Design). Las versiones enviadas, de la más nueva a la más antigua, con status (pending, approved, changes_requested, superseded), nota, decisión con comentario y el archivo (download_url). pending es el id de la versión que espera decisión.
  • POST /issues/{código o id}/proofs (tracker:write): envía la versión siguiente, en multipart/form-data con file y note opcional (mismos formatos y tamaño que las evidencias). La que esperaba decisión queda reemplazada. PO/PM, QA, dev o admin. 201 con version y las versiones.
  • POST /issues/{código o id}/proofs/{id}/decision (tracker:write): {"decision": "approve"} o {"decision": "changes", "feedback": "qué cambiar"}. PO/PM, QA, admin o el cliente del proyecto (stakeholder). Con el flujo de Design, enviar lleva la issue a En aprobación, aprobar a Aprobado y pedir ajustes a Ajustes. 422 cuando la versión ya se decidió o fue reemplazada.
  • GET /issues/{código o id}/watchers (tracker:read): quién sigue la issue (recibe los avisos de estado y de comentario nuevo), con watching para la persona del token. POST agrega y DELETE quita (tracker:write): sin nada, la propia persona; {"person": "[email protected]"} en el POST o ?person=... en el DELETE para otra persona del proyecto, lo que exige editar la issue. La respuesta trae person (a quién se agregó o quitó), watching y watchers. GET /issues/{ref} también trae watchers.
  • POST /issues/{código o id}/status (tracker:write): cambia el estado de la issue, {"status": "<clave>"}. Vale el flujo del proyecto y el perfil de la persona en él (422 cuando la transición no está permitida). Para closed (Cerrado, plantilla QA), manda también close_reason: duplicated, cancelled, not_reproduced o wont_fix; con la issue ya en closed, el mismo pedido cambia solo el motivo.
  • POST /issues/{código o id}/block (tracker:write): marca la issue como bloqueada, {"reason": "lo que lo impide"} (opcional; de nuevo cambia el motivo). La marca vale en cualquier estado y sale sola cuando la issue se completa. DELETE en la misma dirección la quita. Todo perfil del proyecto menos stakeholder; una issue completada no queda bloqueada (422). Devuelve blocked (since, reason) o null. En el MCP: block_issue.
  • DELETE /issues/{código o id} (tracker:write): elimina la issue (admin o PO/PM del proyecto; 403 para los demás perfiles). Desaparece de listas, búsqueda y API y se puede restaurar durante 30 días (en la pantalla, en Issues → Eliminadas, o con POST /issues/{ref}/restore). Una issue con issues dentro (épica, subtareas) no se elimina (422).
  • POST /issues/{código o id}/restore (tracker:write): restaura una issue eliminada en los últimos 30 días, con comentarios, evidencias e historial. Admin o PO/PM del proyecto. GET /issues/deleted (tracker:read, project opcional) lista las que la persona puede restaurar (las 200 más recientes), con restore_until. Después de 30 días la restauración devuelve 422.
  • POST /issues/{código o id}/duplicate (tracker:write): crea una copia en el mismo proyecto, como el Duplicar de la pantalla (contenido, clasificación, padre, puntos, campos y etiquetas; sin comentarios, evidencias, vínculos, personas, sprint, release ni registro técnico). 201 con el code de la copia. Exige crear issues en el proyecto.
  • POST /issues (tracker:write): crea una issue. 201 cuando la crea; 200 cuando ya existía una con el mismo external_id en el proyecto. assignee y qa_owner (me, id, correo o nombre de quien participa en el proyecto) ya asignan al crear: PO/PM y admins asignan a cualquiera, dev la toma como responsable y QA como QA responsable (403 fuera de eso; 422 cuando la persona no es del proyecto, sin crear la issue). Dev crea solo tipos de nivel subtarea, con el padre. Con ?similar=true, la respuesta de la issue creada trae también similar: las parecidas que aqua confirmó (code, title, status_label, open, relation, reason, likely_duplicate, url), para vincular.
  • PATCH /issues/{código o id} (tracker:write): edita la issue. Solo cambian los campos enviados; null quita el valor. Acepta los campos de texto, title, type, severity, priority, module, custom_fields (solo cambian las claves enviadas; una clave que no existe en el proyecto se rechaza), assignee y qa_owner (me, id, correo o nombre de quien participa en el proyecto), el registro técnico (root_cause, fix_notes, fixed_version, fixed_build), parent, story_points, sprint (nombre o id de un sprint abierto; null vuelve al backlog), release (la principal: versión o id; de otro proyecto de la empresa, "PLT backend-1a2b3c", cuando la corrección sale solo allá), add_releases/remove_releases (otras entregas de la misma corrección, incluso de otro proyecto: id, versión en el proyecto de la issue, "GOP 1.4.8-ota002" o {"project": "GOP", "version": "1.4.8-ota002"}, en lista o en un texto separado por comas; exige vincular releases en los dos proyectos) y add_labels/remove_labels. Cada grupo exige el perfil adecuado en el proyecto (403 cuando no puede). Los grupos se guardan en secuencia: si uno falla, la respuesta trae applied con los que ya se guardaron. Para no sobrescribir la edición de otra persona, manda edit_version (el valor leído en GET /issues/{ref}): si alguien cambió la issue después (campos, personas, registro técnico, padre, puntos, sprint, release, etiquetas, estimación o fechas; estado, comentarios y horas no cuentan), no se guarda nada y la respuesta es 409 (conflict); léela de nuevo y vuelve a aplicar. La respuesta de éxito trae la edit_version nueva.
  • GET /issues/{código o id}/time (tracker:read): estimación, inicio, plazo, repetición (recurrence y next_occurrence), total registrado, restante y los registros de horas.
  • POST /issues/{código o id}/time (tracker:write): registra horas trabajadas, {"duration": "1h30", "work_date": "AAAA-MM-DD", "comment": "..."} (o minutes en lugar de duration; sin work_date, hoy). Perfiles PO/PM, QA, dev y admin.
  • PATCH /issues/{código o id}/plan (tracker:write): {"estimate": "8h", "start_date": "AAAA-MM-DD", "due_date": "AAAA-MM-DD", "recurrence": "monthly"}. Un campo omitido queda como está; null quita el valor. recurrence (weekly, monthly, quarterly, yearly) hace que la issue se repita: al completarse, nace la próxima ocurrencia con inicio y plazo adelantados, los mismos responsables y etiquetas; time.next_occurrence apunta a ella. También vale en POST /issues y en cada elemento de POST /issues/import; null, "" o "none" quita la repetición.
  • GET /issues/{código o id}/code (tracker:read): PRs (GitHub), MRs (GitLab) y commits vinculados a la issue, con id, repositorio, estado (open, draft, merged, closed), rama, autor y enlace.
  • POST /issues/{código o id}/code (tracker:write): vincula un PR o commit por el enlace, {"url": "https://github.com/dueno/repo/pull/12", "title": "..."} (MR o commit de GitLab también, incluso self-hosted). No cambia el estado. 409 cuando ya está vinculado (commit por el sha corto o completo). En un repositorio conectado, el webhook después actualiza el título y el estado. Perfiles PO/PM, QA, dev y admin.
  • DELETE /issues/{código o id}/code?link_id=<id> (o ?url=<enlace>, o lo mismo en el cuerpo JSON) (tracker:write): desvincula. 404 cuando no estaba vinculado.
  • GET /time (tracker:read): informe de horas. Query: from y to (AAAA-MM-DD; por defecto, el mes en curso), project (prefijo, slug o id) y person (me o id); un filtro que no coincide es error. Totales por persona, por proyecto y por issue, y los registros.
  • POST /issues/bulk (tracker:write): la misma acción en hasta 100 issues, {"issues": ["MOB-0012", "MOB-0013"], "action": "status", "value": "done"}. action: status, assignee (solo PO/PM o admin; me, id, correo o nombre; none quita), priority, severity, label, unlabel, release (versión o id; none quita), watch, unwatch y delete (las tres últimas sin value). Cada issue sigue la regla de la acción individual; la respuesta trae requested (issues distintas pedidas), updated y failed (code y error de cada una que no cambió). Sin value en una acción que lo pide: 422.
  • POST /issues/batch (tracker:write): lote por issue, hasta 50, para cerrar una entrega en una llamada: {"items": [{"issue": "MOB-0045", "fixed_version": "backend 4e8998ac", "fix_notes": "...", "code_links": ["https://github.com/org/repo/pull/251"], "status": "ready_for_qa"}]}. Cada elemento acepta los campos del PATCH /issues/{ref} (incluso edit_version), code_links (enlaces, o {url, title}; un enlace ya vinculado no es error) y status, aplicados en ese orden con las reglas de las llamadas individuales. Un elemento que falla no detiene a los demás; la respuesta trae requested, succeeded, failed y results (por elemento: ok, code, updated, linked, status y, si falló, failed_at con issue (no encontrada, o cambió después de la edit_version), fields, code_links o status, y error; los pasos anteriores quedan guardados). Sin otros campos, la edit_version protege los enlaces y el estado.
  • POST /issues/import (tracker:write): hasta 100 issues por pedido, {"project": "MOB", "issues": [...]} (cada elemento puede traer su propio project). Elemento por elemento: uno rechazado no deshace los demás. La respuesta trae created, existing, failed y results (index, ok, code, url o error).

Campos de una issue: project (prefijo, slug o id), title (obligatorio), type (clave del tipo), severity (S1 a S4, por defecto S3), priority (urgent, high, medium, low; solo PO/PM y admin, los demás quedan con medium), module (nombre), description, environment, app_version, build, device, operating_system, preconditions, steps_to_reproduce, actual_result, expected_result, impact, suggested_solution, parent (código o id de la issue padre: la épica de una issue común, o la issue de una subtarea; el nivel viene del tipo), story_points (número de 0 a 1000), start_date y due_date (inicio y plazo, AAAA-MM-DD; el inicio no viene después del plazo), custom_fields (objeto por la clave del campo), labels (hasta 10 nombres; la que no existe se crea) y external_id (id en el origen, hasta 200 caracteres).

Plantillas por tipo: description, preconditions, steps_to_reproduce, actual_result, expected_result, impact y suggested_solution omitidos vienen completados con la plantilla del tipo (el template en GET /projects). Manda "" para dejar uno de esos campos vacío.

Usa external_id en el CI: con el nombre de la prueba que falló, por ejemplo, volver a correr el pipeline no duplica la issue.