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,noneo 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_fromycreated_to(AAAA-MM-DD),limit(hasta 50),offset,sort(code,title,status,severity,assigneeoupdated),order(ascodesc) ydone_last(true: las completadas, grupodone, al final, antes del orden pedido). Sinsort, 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, usaopen_only=trueodone_last=true. En el MCP, los mismosopen_onlyydone_lastdesearch_issues. Cada issue viene conclose_reason(en Cerrado),blockedyblocked_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,parentyepic(códigos),labels,start_date,due_date,external_idyedit_version(paraPATCHy el lote, sin abrir cada issue);include=description,custom_fieldsagrega 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, conkinds=issue,ticket, en los tickets de la Mesa de ayuda (solo para quien atiende).issue=<código>en lugar deqbusca las parecidas a esa issue, sin ella.project,open_only(true) ylimit(hasta 30, por defecto 8). Cada resultado traekind,code,title,status_label,open,project,score(0 a 1),similarity(del vector, cuando la encontró por significado),matched_by(text,meaning),likely_duplicateyurl;modeeshybridotext(solo por palabras);semanticdice 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). Conontrue ymodetext, la búsqueda por significado no respondió a tiempo o la persona pasó el límite de búsquedas por significado. Conissue, la búsqueda parte de la ficha de contexto que aqua escribe de cada issue (aqua_contextdeGET /issues/{ref}).explain(por defecto true;falsedevuelve 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 completarelation(same: el mismo problema;related: relacionado) yreason(la relación en una frase);explaineddice si lo comparó (sin aqua activada,falsey 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 constatus(key,label,category,close_reasonen Cerrado conkeyylabel, yretest_failed_atcuando se rechazó en el último retest),blocked(sinceyreason, onull),releases(todas las entregas, la principal primero conprimary: true), padre yepic(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/tocon los valores guardados ytext, como en la pantalla: nombres de releases, personas y sprints;from_label/to_labelcuando la pantalla muestra de/a),aqua_summary(el último resumen de la conversación hecho por aqua en la pantalla:happened,pending,ballcon quién tiene la pelota youtdatedcuando hubo comentarios o cambios después;nullsin resumen),aqua_context(la ficha de contexto que aqua escribe sola, en segundo plano, para "¿Ya pasó antes?":summarycon el problema en palabras neutras,area,terms,generated_atyoutdatedcuando la issue cambió y la ficha todavía se va a rehacer;nullcon aqua desactivada o antes de la primera ficha) yedit_version(paraPATCH).?fields=status,releasestrae solo esas partes (id,code,urlyedit_versionsiempre): sirve para revisar muchas issues sin traer comentarios e historial.GET /issues/{código o id}/comments(tracker:read): todos los comentarios, cada uno conid,author,text,at,edited_at,deleted(quién lo eliminó y cuándo; el texto viene vacío),mentionsy las respuestas (replies).POST /issues/{código o id}/comments(tracker:write): comenta,{"text": "...", "parent_id": "<id del comentario respondido>"}.@Nomemenciona 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 elidy losattachments. En elGET, cada comentario trae susattachments(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 conid,name,type,size_bytes,description,comment_id(cuando vino en un comentario) ydownload_url.GET /evidences/{id}(tracker:read) descarga el archivo, con el mismo token (aceptaRange). Por el MCP, cuyo token no vale aquí,get_attachmentlee 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-datacon el archivo en el campofile(ydescriptionycomment_idopcionales, en texto); JSON{"file_name": "evaluacion.md", "content_base64": "...", "description": "..."}(acepta el prefijodata:...;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_nameopcional 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_idpone el archivo debajo de un comentario tuyo de la issue. PO/PM, QA, dev o admin (403 para los demás). 201 conattachment(como en elGET). 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_attachmentyattachmentsenadd_comment; los adjuntos aparecen enget_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.DELETEen 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 (limithasta 200,offset), contotaly cada evento conat,by,action,field,texty, cuando los hay,fromytoya 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}. Sinconfirm, solo devuelve la vista previa (moved: false, avisos de lo que no tiene equivalente en el destino, subtareas que van juntas); conconfirm: 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, oduplicates). Exige editar la issue. 201 con los vínculos de la issue (links, cada uno conid).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, constatus(pending,approved,changes_requested,superseded), nota, decisión con comentario y el archivo (download_url).pendinges 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 confileynoteopcional (mismos formatos y tamaño que las evidencias). La que esperaba decisión queda reemplazada. PO/PM, QA, dev o admin. 201 conversiony 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), conwatchingpara la persona del token.POSTagrega yDELETEquita (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 traeperson(a quién se agregó o quitó),watchingywatchers.GET /issues/{ref}también traewatchers.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). Paraclosed(Cerrado, plantilla QA), manda tambiénclose_reason:duplicated,cancelled,not_reproducedowont_fix; con la issue ya enclosed, 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.DELETEen la misma dirección la quita. Todo perfil del proyecto menos stakeholder; una issue completada no queda bloqueada (422). Devuelveblocked(since,reason) onull. 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 conPOST /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,projectopcional) lista las que la persona puede restaurar (las 200 más recientes), conrestore_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 elcodede 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 mismoexternal_iden el proyecto.assigneeyqa_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énsimilar: 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;nullquita 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),assigneeyqa_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;nullvuelve 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) yadd_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 traeappliedcon los que ya se guardaron. Para no sobrescribir la edición de otra persona, mandaedit_version(el valor leído enGET /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 laedit_versionnueva.GET /issues/{código o id}/time(tracker:read): estimación, inicio, plazo, repetición (recurrenceynext_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": "..."}(ominutesen lugar deduration; sinwork_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á;nullquita 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_occurrenceapunta a ella. También vale enPOST /issuesy en cada elemento dePOST /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, conid, 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:fromyto(AAAA-MM-DD; por defecto, el mes en curso),project(prefijo, slug o id) yperson(meo 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;nonequita),priority,severity,label,unlabel,release(versión o id;nonequita),watch,unwatchydelete(las tres últimas sinvalue). Cada issue sigue la regla de la acción individual; la respuesta traerequested(issues distintas pedidas),updatedyfailed(codeyerrorde cada una que no cambió). Sinvalueen 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 delPATCH /issues/{ref}(inclusoedit_version),code_links(enlaces, o{url, title}; un enlace ya vinculado no es error) ystatus, aplicados en ese orden con las reglas de las llamadas individuales. Un elemento que falla no detiene a los demás; la respuesta traerequested,succeeded,failedyresults(por elemento:ok,code,updated,linked,statusy, si falló,failed_atconissue(no encontrada, o cambió después de laedit_version),fields,code_linksostatus, yerror; los pasos anteriores quedan guardados). Sin otros campos, laedit_versionprotege los enlaces y el estado.POST /issues/import(tracker:write): hasta 100 issues por pedido,{"project": "MOB", "issues": [...]}(cada elemento puede traer su propioproject). Elemento por elemento: uno rechazado no deshace los demás. La respuesta traecreated,existing,failedyresults(index,ok,code,urloerror).
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.