> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revem.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Actualizar un ticket

> Modifica uno o más campos de un ticket. Sólo se tocan las claves presentes en el cuerpo.

No se puede crear ni eliminar un ticket por la API: se abren desde una conversación y se conservan para auditoría. Tampoco se puede pasar a `postponed`, porque posponer programa una reapertura que sólo la app arma.



## OpenAPI

````yaml /openapi.json patch /tickets/public/v1/{id}
openapi: 3.1.0
info:
  title: Revem API
  version: 1.0.0
  description: >-
    La API pública de Revem para integraciones de servidor a servidor:
    contactos, tickets y el canal de webchat. Se autentica con la API key de tu
    organización.
  contact:
    name: Soporte Revem
    email: soporte@revem.ai
    url: https://revem.ai
servers:
  - url: https://api.revem.ai
    description: Producción
security:
  - apiKey: []
tags:
  - name: Contactos
    description: >-
      Sincroniza tu base de clientes con Revem. Los contactos se identifican por
      teléfono al crearlos y por id después.
  - name: Tickets
    description: Lee y actualiza los tickets de tu embudo desde tu sistema de gestión.
  - name: Webchat
    description: >-
      Conecta el chat de tu sitio con Revem: registra lo que escribe el
      visitante y lee las respuestas del equipo o del agente.
paths:
  /tickets/public/v1/{id}:
    patch:
      tags:
        - Tickets
      summary: Actualizar un ticket
      description: >-
        Modifica uno o más campos de un ticket. Sólo se tocan las claves
        presentes en el cuerpo.


        No se puede crear ni eliminar un ticket por la API: se abren desde una
        conversación y se conservan para auditoría. Tampoco se puede pasar a
        `postponed`, porque posponer programa una reapertura que sólo la app
        arma.
      operationId: updateTicket
      parameters:
        - name: id
          in: path
          required: true
          description: Id del ticket.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TicketUpdateBody'
            example:
              status: won
              funnelStageId: 14
      responses:
        '200':
          description: El ticket actualizado.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Ticket'
        '204':
          description: >-
            La actualización se aplicó, pero quien llama ya no puede leer el
            ticket resultante. Con una API key no ocurre en la práctica; se
            documenta porque forma parte del contrato.
        '400':
          description: >-
            El cuerpo está vacío, no cumple el esquema, o referencia una etapa,
            contacto o perfil que no pertenece al tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketsError'
        '401':
          description: Sin credencial, o la API key no existe o fue revocada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              example:
                error: Unauthorized
                message: Invalid API key
        '403':
          description: La credencial no puede modificar este ticket.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketsError'
        '404':
          description: No existe un ticket con ese id en el tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketsError'
        '429':
          description: >-
            La key superó su límite de solicitudes por minuto. El header
            `retry-after` indica cuánto esperar.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'
              example:
                ok: false
                error: Too many requests. Retry in 1 minute.
          headers:
            retry-after:
              description: Segundos que esperar antes de reintentar.
              schema:
                type: integer
            x-ratelimit-limit:
              description: Solicitudes permitidas por minuto.
              schema:
                type: integer
            x-ratelimit-remaining:
              description: Solicitudes que quedan en la ventana actual.
              schema:
                type: integer
            x-ratelimit-reset:
              description: Segundos hasta que la ventana se reinicia.
              schema:
                type: integer
components:
  schemas:
    TicketUpdateBody:
      type: object
      properties:
        title:
          type: string
          minLength: 1
          description: Título del ticket.
        funnelStageId:
          type: integer
          description: Etapa del embudo. Debe pertenecer al tenant.
        status:
          type: string
          enum:
            - active
            - won
            - lost
          description: >-
            `active`, `won` o `lost`. No se acepta `postponed`: posponer
            programa una reapertura y sólo se hace desde la app.
        assignedToProfileId:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: Perfil a asignar, o `null` para desasignar.
        pointOfContact:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: Id de contacto, o `null` para desvincular.
        account:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: Id de contacto que actúa como cuenta, o `null` para desvincular.
        lossReason:
          anyOf:
            - type: string
            - type: 'null'
          description: 'Motivo de pérdida. Suele acompañar a `status: "lost"`.'
        customAttributes:
          type: object
          additionalProperties: true
          description: >-
            Atributos personalizados del ticket, por id de definición. Reemplaza
            el conjunto completo.
      description: Todos los campos son opcionales, pero el cuerpo debe traer al menos uno.
    Ticket:
      type: object
      properties:
        id:
          type: string
          format: uuid
        title:
          type: string
        status:
          type: string
          enum:
            - active
            - postponed
            - won
            - lost
          description: >-
            `active`, `postponed`, `won` o `lost`. `postponed` sólo se alcanza
            desde la app; la API no puede posponer.
        funnelStageId:
          type: integer
          description: Etapa del embudo en que está el ticket.
        funnelId:
          type: string
          format: uuid
          description: Embudo al que pertenece la etapa. Derivado, no editable.
        assignedToProfileId:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: Perfil del equipo asignado, o `null`.
        createdByProfileId:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
        pointOfContact:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: Contacto principal del ticket (un id de contacto), o `null`.
        account:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          description: Contacto que actúa como cuenta u organización, o `null`.
        customAttributes:
          type: object
          additionalProperties: true
          description: >-
            Atributos personalizados del ticket, identificados por el id de su
            definición.
        lossReason:
          anyOf:
            - type: string
            - type: 'null'
          description: Motivo de pérdida cuando `status` es `lost`.
        visibility:
          type: string
          enum:
            - OWNER
            - OWNER_AND_GROUPS
            - TENANT
          description: >-
            Modelo de visibilidad para las personas del equipo. Una API key ve
            todos los tickets del tenant sin importar este valor.
        visibilityGroupId:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
        postponedUntil:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: Fecha de reapertura cuando el ticket está pospuesto.
        closedAt:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: Fecha de cierre cuando `status` es `won` o `lost`.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        conversations:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              channelType:
                type: string
                enum:
                  - WhatsApp
                  - Gmail
                  - Outlook
                  - Instagram
                  - Messenger
                  - Webchat
            required:
              - id
              - channelType
            additionalProperties: false
          description: Conversaciones enlazadas al ticket. Puede haber más de una.
      required:
        - id
        - title
        - status
        - funnelStageId
        - funnelId
        - assignedToProfileId
        - createdByProfileId
        - pointOfContact
        - account
        - customAttributes
        - lossReason
        - visibility
        - visibilityGroupId
        - postponedUntil
        - closedAt
        - createdAt
        - updatedAt
        - conversations
      additionalProperties: false
      example:
        id: c0a8012e-5b3d-4e7f-9a1b-2c3d4e5f6a7b
        title: Cotización plan anual
        status: active
        funnelStageId: 12
        funnelId: f1e2d3c4-b5a6-4978-8a9b-0c1d2e3f4a5b
        assignedToProfileId: 9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d
        createdByProfileId: null
        pointOfContact: 3f2b6c1e-8d4a-4f0b-9c2e-7a1d5e6f8b90
        account: null
        customAttributes:
          origen: web
        lossReason: null
        visibility: TENANT
        visibilityGroupId: null
        postponedUntil: null
        closedAt: null
        createdAt: '2026-09-02T12:00:00.000Z'
        updatedAt: '2026-09-03T08:15:30.000Z'
        conversations:
          - id: a1d2c3b4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
            channelType: Webchat
    TicketsError:
      type: object
      properties:
        ok:
          type: boolean
        error:
          type: string
          description: Explicación legible del problema.
      required:
        - ok
        - error
      additionalProperties: false
    AuthError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
          description: Presente sólo en el `403`.
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
    RateLimitError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: string
          description: Incluye cuánto esperar antes de reintentar.
      required:
        - ok
        - error
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        La API key de tu organización, con la forma `rvm_<prefijo>.<secreto>`,
        enviada como `Authorization: Bearer rvm_…`. Revem la emite y sólo se
        muestra una vez; si la pierdes se reemplaza, no se recupera.

````