VitrinaAPI

Mis notificaciones

Lo que ve quien llama: el feed de notificaciones del workspace activo y sus preferencias de aviso, por preset o celda por celda.

Beta
Puede cambiar en cualquier momento, con una entrada en el changelog y aviso a quienes la llamaron recientemente — ver versionado.

Descarga la proyección completa de la API pública: openapi.json.

MétodoRutaQué hace
GET/me/notification-preferencesThe caller’s notification preferences, generated from the registry
PUT/me/notification-preferencesChange notification preferences (preset and/or single cells)
GET/me/notificationsIn-app notification feed for the active workspace (keyset-paginated)

GET /me/notification-preferences

The caller’s notification preferences, generated from the registry

Every notification type this member can receive in this workspace (filtered by role and vertical), grouped by category, with the state of each channel — bell (in_app), email, push, whatsapp: on/off (their choice, or the default when they never chose), locked (mandatory, with locked_reason), always (the bell of a type they must act on) or unavailable. WhatsApp is available only for types the workspace armed for staff WhatsApp. preset is important (the defaults), all or custom. Requires a workspace member; an sk_* API key gets 403.

curl https://api.vitrinadev.com/api/v1/me/notification-preferences \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "preset": "important",
    "push_enabled": true,
    "categories": [
      "inbox",
      "agenda",
      "sales",
      "followups",
      "approvals",
      "payments",
      "agents",
      "integrations",
      "safety",
      "account"
    ],
    "types": [
      {
        "key": "assigned",
        "category": "inbox",
        "slug": "assigned",
        "mandatory": false,
        "locked_reason": null,
        "bell_mutable": false,
        "delivery": "immediate",
        "channels": {
          "in_app": {
            "state": "always",
            "default": "on"
          },
          "email": {
            "state": "off",
            "default": "off"
          },
          "push": {
            "state": "on",
            "default": "on"
          },
          "whatsapp": {
            "state": "on",
            "default": "workspace"
          }
        }
      },
      {
        "key": "agenda_booked",
        "category": "agenda",
        "slug": "agenda_booked",
        "mandatory": false,
        "locked_reason": null,
        "bell_mutable": false,
        "delivery": "immediate",
        "channels": {
          "in_app": {
            "state": "always",
            "default": "on"
          },
          "email": {
            "state": "on",
            "default": "on"
          },
          "push": {
            "state": "on",
            "default": "on"
          },
          "whatsapp": {
            "state": "unavailable",
            "default": null
          }
        }
      },
      {
        "key": "payment_review_needed",
        "category": "payments",
        "slug": "payment_review_needed",
        "mandatory": true,
        "locked_reason": "customer_waiting",
        "bell_mutable": false,
        "delivery": "immediate",
        "channels": {
          "in_app": {
            "state": "locked",
            "default": "locked"
          },
          "email": {
            "state": "on",
            "default": "on"
          },
          "push": {
            "state": "on",
            "default": "on"
          },
          "whatsapp": {
            "state": "on",
            "default": "workspace"
          }
        }
      }
    ]
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

PUT /me/notification-preferences

Change notification preferences (preset and/or single cells)

JSON-merged: only the cells named change, everything else is kept. preset: important returns to the defaults (clears every per-type choice); all switches every switchable cell on; any changes entry without a preset makes the preset custom. 400 for an unknown type, a channel the type does not use, a mandatory (locked) cell, or the bell of a type that always appears in the bell. Returns the fresh catalog.

curl -X PUT https://api.vitrinadev.com/api/v1/me/notification-preferences \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "changes": [
      {
        "key": "agenda_booked",
        "channel": "email",
        "enabled": false
      },
      {
        "key": "coach.finding_ready",
        "channel": "in_app",
        "enabled": false
      }
    ]
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "preset": "important",
    "push_enabled": true,
    "categories": [
      "inbox",
      "agenda",
      "sales",
      "followups",
      "approvals",
      "payments",
      "agents",
      "integrations",
      "safety",
      "account"
    ],
    "types": [
      {
        "key": "assigned",
        "category": "inbox",
        "slug": "assigned",
        "mandatory": false,
        "locked_reason": null,
        "bell_mutable": false,
        "delivery": "immediate",
        "channels": {
          "in_app": {
            "state": "always",
            "default": "on"
          },
          "email": {
            "state": "off",
            "default": "off"
          },
          "push": {
            "state": "on",
            "default": "on"
          },
          "whatsapp": {
            "state": "on",
            "default": "workspace"
          }
        }
      },
      {
        "key": "agenda_booked",
        "category": "agenda",
        "slug": "agenda_booked",
        "mandatory": false,
        "locked_reason": null,
        "bell_mutable": false,
        "delivery": "immediate",
        "channels": {
          "in_app": {
            "state": "always",
            "default": "on"
          },
          "email": {
            "state": "on",
            "default": "on"
          },
          "push": {
            "state": "on",
            "default": "on"
          },
          "whatsapp": {
            "state": "unavailable",
            "default": null
          }
        }
      },
      {
        "key": "payment_review_needed",
        "category": "payments",
        "slug": "payment_review_needed",
        "mandatory": true,
        "locked_reason": "customer_waiting",
        "bell_mutable": false,
        "delivery": "immediate",
        "channels": {
          "in_app": {
            "state": "locked",
            "default": "locked"
          },
          "email": {
            "state": "on",
            "default": "on"
          },
          "push": {
            "state": "on",
            "default": "on"
          },
          "whatsapp": {
            "state": "on",
            "default": "workspace"
          }
        }
      }
    ]
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

GET /me/notifications

In-app notification feed for the active workspace (keyset-paginated)

The caller’s own bell, newest first. Only the last 14 days are returned (older rows expire and are deleted after 30 days); meta.unreadCount counts unread items inside that same window. Every row carries a typed target — where a click leads: record (one subject), list (a filtered list, e.g. the Búsquedas a daily summary counted) or page (a fixed screen) — never a URL. A live row is a standing condition (a broken channel, the approvals queue) refreshed in place and marked read when it ends. Requires a workspace member (a session or a personal token acting as one); an sk_* API key gets 403.

ParámetroEnTipoObligatorioRestricciones
cursorquerystringnomáx. 80
limitqueryintegerno≥ 1, ≤ 50
curl https://api.vitrinadev.com/api/v1/me/notifications \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": [
    {
      "id": "019a3b1c-2d4e-7f00-8a1b-2c3d4e5f6a70",
      "type": "busqueda.daily_summary",
      "category": "followups",
      "actor_id": null,
      "entity_type": "tenant",
      "entity_id": "7b1f0c52-3e4a-4d8b-9c21-5a6b7c8d9e0f",
      "data": {
        "sent": 4,
        "failed": 1,
        "customers": [
          "Camila Rojas",
          "Diego Muñoz",
          "Paula Soto"
        ],
        "from": "2026-10-07T12:00:00.000Z",
        "to": "2026-10-08T12:00:00.000Z"
      },
      "target": {
        "kind": "list",
        "screen": "busquedas",
        "filter": {
          "notified_from": "2026-10-07T12:00:00.000Z",
          "notified_to": "2026-10-08T12:00:00.000Z",
          "status": "any"
        }
      },
      "secondary_target": {
        "kind": "list",
        "screen": "busquedas",
        "filter": {
          "notified_from": "2026-10-07T12:00:00.000Z",
          "notified_to": "2026-10-08T12:00:00.000Z",
          "notice": "failed",
          "status": "any"
        }
      },
      "live": false,
      "read_at": null,
      "created_at": "2026-10-08T12:00:04.512Z"
    },
    {
      "id": "019a3a77-90ab-7c00-9d1e-2f3a4b5c6d7e",
      "type": "agenda_booked",
      "category": "agenda",
      "actor_id": null,
      "entity_type": "appointment",
      "entity_id": "c4d5e6f7-0819-4a2b-8c3d-4e5f60718293",
      "data": {},
      "target": {
        "kind": "record",
        "record": "appointment",
        "id": "c4d5e6f7-0819-4a2b-8c3d-4e5f60718293"
      },
      "secondary_target": null,
      "live": false,
      "read_at": "2026-10-08T09:15:00.000Z",
      "created_at": "2026-10-07T21:40:11.003Z"
    }
  ],
  "meta": {
    "pagination": {
      "nextCursor": null
    },
    "unreadCount": 1
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

En esta página