> ## 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.

# Listar contactos

> Devuelve los contactos del tenant, del más reciente al más antiguo según su **fecha de creación**, paginados por `limit` y `offset`. Los contactos en la papelera y los del simulador no aparecen.

`updated_since` filtra pero no ordena: un contacto editado mientras recorres las páginas puede quedar fuera de la página que le correspondía. Para una sincronización incremental, solapa la ventana unos minutos con la corrida anterior en vez de partir exactamente donde terminó.



## OpenAPI

````yaml /openapi.json get /contacts/public/v1
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:
  /contacts/public/v1:
    get:
      tags:
        - Contactos
      summary: Listar contactos
      description: >-
        Devuelve los contactos del tenant, del más reciente al más antiguo según
        su **fecha de creación**, paginados por `limit` y `offset`. Los
        contactos en la papelera y los del simulador no aparecen.


        `updated_since` filtra pero no ordena: un contacto editado mientras
        recorres las páginas puede quedar fuera de la página que le
        correspondía. Para una sincronización incremental, solapa la ventana
        unos minutos con la corrida anterior en vez de partir exactamente donde
        terminó.
      operationId: listContacts
      parameters:
        - name: phone
          in: query
          required: false
          description: >-
            Busca por teléfono. Acepta las mismas grafías que el upsert, así que
            el número con que escribiste un contacto también lo encuentra.
          schema:
            type: string
            minLength: 1
        - name: email
          in: query
          required: false
          description: Busca por email, sin distinguir mayúsculas.
          schema:
            type: string
            format: email
        - name: updated_since
          in: query
          required: false
          description: >-
            Sólo contactos modificados desde esta fecha (ISO 8601 con zona
            horaria, por ejemplo `2026-09-01T00:00:00Z`).
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          required: false
          description: Tamaño de página.
          schema:
            default: 50
            type: integer
            minimum: 1
            maximum: 200
        - name: offset
          in: query
          required: false
          description: Cuántos resultados saltar.
          schema:
            default: 0
            type: integer
            minimum: 0
            maximum: 1000000
      responses:
        '200':
          description: Una página de contactos.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactList'
        '400':
          description: Un parámetro no es válido.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactsError'
        '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 usar esta ruta. Una API key sólo alcanza los
            endpoints documentados aquí; cualquier otra ruta de la API responde
            este código.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              example:
                ok: false
                error: Forbidden
                message: This endpoint is not available to API keys
        '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:
    ContactList:
      type: object
      properties:
        contacts:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
              phone_number:
                anyOf:
                  - type: string
                  - type: 'null'
              first_name:
                type: string
              last_name:
                type: string
              email:
                type: string
              created_at:
                type: string
                format: date-time
              updated_at:
                type: string
                format: date-time
            required:
              - id
              - phone_number
              - created_at
              - updated_at
            additionalProperties: true
          description: >-
            Ordenados del más reciente al más antiguo según su fecha de
            creación.
        has_more:
          type: boolean
          description: '`true` si hay más resultados después de esta página.'
      required:
        - contacts
        - has_more
      additionalProperties: false
      example:
        contacts:
          - id: 3f2b6c1e-8d4a-4f0b-9c2e-7a1d5e6f8b90
            phone_number: '+56912345678'
            first_name: Camila
            last_name: Rojas
            email: camila@ejemplo.cl
            created_at: '2026-08-12T14:03:22.000Z'
            updated_at: '2026-09-01T09:41:05.000Z'
            programa: Premium
            fecha_ultima_compra: '2026-08-30'
        has_more: false
    ContactsError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: string
          description: >-
            Etiqueta del código HTTP (`Bad Request`, `Conflict`, `Unprocessable
            Entity`…).
        message:
          type: string
          description: Explicación legible del problema.
        unknownAttributes:
          type: array
          items:
            type: string
          description: >-
            Presente en el `422` por atributos desconocidos: los nombres que el
            tenant no tiene definidos.
      required:
        - 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.

````