Workspace settings
The workspace's general identity (name, time zone, language, currency, website) and its Vitrina Ads choices: how the tag step was answered and the monthly goal.
Download the full API pública projection: openapi.json.
| Method | Path | What it does |
|---|---|---|
GET | /tenant/modules | Read the workspace modules (Proyectos / Corretaje) |
PUT | /tenant/modules | Set the workspace modules (Proyectos / Corretaje) |
GET | /tenant/settings | Read tenant-level settings |
PUT | /tenant/settings | Patch tenant-level settings |
GET /tenant/modules
Read the workspace modules (Proyectos / Corretaje)
The halves of its vertical the workspace runs. Real estate offers projects (Módulo Proyectos, an inmobiliaria) and brokerage (Módulo Corretaje, a corredora); a workspace may run both. modules is the EFFECTIVE set: a real-estate workspace that never chose reads as ["brokerage"], and a vertical without modules reads as []. A module-specific route refuses a workspace without its module with 403 MODULE_NOT_ENABLED.
curl https://api.vitrinadev.com/api/v1/tenant/modules \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": {
"vertical": "real-estate",
"modules": [
"brokerage"
],
"available": [
"projects",
"brokerage"
]
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
PUT /tenant/modules
Set the workspace modules (Proyectos / Corretaje)
Replaces the module set (at least one; only modules the vertical offers — 400 otherwise) and brings the boards in line: a module turned on gets its board (projects → «Proyectos», Lead → Visita agendada → Visita realizada → Cotización → Reserva → Promesa → Escritura → Entrega, with Desistimiento as the lost stage; brokerage → «Corretaje»), reported in pipelines.added. A module turned off loses its board only while the board is empty (pipelines.removed); a board holding leads is kept (pipelines.in_use). When the sales fallback sat on a module turned off it moves to a module still on (pipelines.fallback_moved_to). Idempotent.
Body
| Field | Type | Required | Constraints |
|---|---|---|---|
modules | projects \ | brokerage[] | yes |
curl -X PUT https://api.vitrinadev.com/api/v1/tenant/modules \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"modules": [
"projects"
]
}'Example response (200)
{
"data": {
"vertical": "real-estate",
"modules": [
"projects"
],
"available": [
"projects",
"brokerage"
],
"pipelines": {
"added": [
{
"module": "projects",
"template_key": "real_estate_developer_sales",
"pipeline_id": "6f1c2b8e-3d4a-4b5c-9e7f-1a2b3c4d5e6f"
}
],
"removed": [
{
"module": "brokerage",
"template_key": "real_estate_sales",
"pipeline_id": "0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d"
}
],
"in_use": [],
"fallback_moved_to": {
"module": "projects",
"template_key": "real_estate_developer_sales",
"pipeline_id": "6f1c2b8e-3d4a-4b5c-9e7f-1a2b3c4d5e6f"
}
}
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
GET /tenant/settings
Read tenant-level settings
The stored settings object, as saved through PUT /tenant/settings. Among its keys, ads holds the Vitrina Ads wizard choice: \{ tag_choice: "site" | "no_site" | null, tag_choice_at: string | null \} (tag_choice_at is stamped by the server on every write); absent when the workspace never answered the «Instalar el tag» step. Only the keys documented here are part of the API pública: the workspace's general identity (name, timezone, language, currency, date_format, website) and the Vitrina Ads choices under ads, the template voice under voice, the AI agent's banned terms under agent_language, and the notification rails under notifications (arming a staff WhatsApp rail submits its template to Meta and wires it on approval; the read-only staff_rails reports each rail template state). Every API credential (API key, personal token, connected app, and the MCP) receives exactly those keys. Secrets are write-only: slack_webhook_url is never returned — a read answers •••• plus slack_webhook_configured. Connected apps write only ads, voice, agent_language and notifications: any other key, slack_webhook_url included, is refused with 403, so a connected app cannot send the mask back either. For a workspace's own API key or personal token with tenant:write, writing •••• back keeps the stored webhook, a new URL replaces it, and null or an empty string clears it. The webhook receives only the workspace's own alerts (pricing alerts and digests, reminders about its listings, consignments, credit applications and post-sale obligations, SLA breaches and safety holds); Vitrina never posts its internal alerts to it.
curl https://api.vitrinadev.com/api/v1/tenant/settings \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": {
"name": "Automotora Demo",
"timezone": "America/Santiago",
"language": "es",
"currency": "CLP",
"website": "https://www.automotora-demo.cl",
"ads": {
"tag_choice": "site",
"tag_choice_at": "2026-09-23T15:00:00.000Z",
"goal": {
"kind": "outcomes",
"target": 30,
"period": "month"
},
"goal_at": "2026-09-01T12:00:00.000Z",
"goal_by": "20000000-0000-4000-8000-000000000001"
},
"slack_webhook_configured": false
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
PUT /tenant/settings
Patch tenant-level settings
Shallow-merges the body into the stored settings and answers the result. ads is merged key by key (a write that sends only ads.tag_choice keeps ads.goal), and the server stamps tag_choice_at / goal_at / goal_by — a client never sends them (400). A connected app may write only ads; any other key is refused with 403 and nothing is written. Requires tenant:write, or ads:write for a body that carries only ads. Only the keys documented here are part of the API pública: the workspace's general identity (name, timezone, language, currency, date_format, website) and the Vitrina Ads choices under ads, the template voice under voice, the AI agent's banned terms under agent_language, and the notification rails under notifications (arming a staff WhatsApp rail submits its template to Meta and wires it on approval; the read-only staff_rails reports each rail template state). Every API credential (API key, personal token, connected app, and the MCP) receives exactly those keys. Secrets are write-only: slack_webhook_url is never returned — a read answers •••• plus slack_webhook_configured. Connected apps write only ads, voice, agent_language and notifications: any other key, slack_webhook_url included, is refused with 403, so a connected app cannot send the mask back either. For a workspace's own API key or personal token with tenant:write, writing •••• back keeps the stored webhook, a new URL replaces it, and null or an empty string clears it. The webhook receives only the workspace's own alerts (pricing alerts and digests, reminders about its listings, consignments, credit applications and post-sale obligations, SLA breaches and safety holds); Vitrina never posts its internal alerts to it.
curl -X PUT https://api.vitrinadev.com/api/v1/tenant/settings \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"ads": {
"tag_choice": "site"
}
}'Example response (200)
{
"data": {
"name": "Automotora Demo",
"timezone": "America/Santiago",
"language": "es",
"currency": "CLP",
"website": "https://www.automotora-demo.cl",
"ads": {
"tag_choice": "site",
"tag_choice_at": "2026-09-24T12:00:00.000Z"
},
"slack_webhook_configured": false
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429