VitrinaAPI
MCP

Herramientas del conector

Las herramientas que tu cliente de IA ve al conectarse a Vitrina, por paquete. Todas son de solo lectura.

Esto es lo que responde tools/list en https://api.vitrinadev.com/mcp cuando el que pregunta es un conector. Son 87 en total, repartidas en los paquetes de abajo, y ninguna escribe: no hay una sola herramienta que cree, edite, borre ni envíe nada.

Tu cliente no ve las cuatro. Ve la base, más el paquete de tu rubro, más el de costos si lo autorizaste.

Los títulos y las descripciones están en inglés a propósito: son el texto exacto que recibe el modelo para decidir qué herramienta usar, y traducirlo aquí sería escribir una segunda versión de lo que hace cada una.

Base — en todos los workspaces

Cuándo aparece. Siempre. No depende del rubro ni de ninguna casilla.

ads_funnel_get

Anuncios: embudo de personas

Las personas cuyo primer contacto fue en el período y cuántas llegaron a cada etapa: escribieron → agendaron → asistieron → recibieron presupuesto → aceptaron → pagaron, separadas entre anuncios y otros orígenes. Solo conteos. Úsalo para «¿dónde se pierde la gente?»: un paso sano de escribir a agendar ronda el 10–15 %. Los resultados uno a uno están en call_operation ads_feed_list (en una clínica, los pacientes con seudónimo), y el envío de resultados a Meta en ads_conversion_sync_status_list.

ads_monthly_return_get

Anuncios: pagado vs gasto, mes a mes

Por mes calendario: lo que pagaron los pacientes que llegaron por anuncios (primer pago y cuotas posteriores) frente al gasto en anuncios de ese mes. Los meses anteriores al inicio de la medición vienen en null (sin medir, nunca 0). Por defecto, los últimos seis meses. Úsalo para «¿se pagan mis anuncios?» o para ver la tendencia.

ads_overview_get

Anuncios: resumen del período

El resumen de Vitrina Ads para un período: gasto en anuncios, retorno total de los pacientes que llegaron por anuncios (lo que pagaron, primer pago más cuotas, dividido por el gasto), el retorno en primer pago, presupuestos aceptados, personas que escribieron desde anuncios y el período anterior para comparar. «Pacientes» son solo quienes pagaron; quienes solo escribieron son «personas». Úsalo primero para «¿cómo van mis anuncios?».

ads_performance_list

Anuncios: rendimiento por campaña o por anuncio

El rendimiento del período, por campaña (by: campaign, por defecto) o por anuncio (by: ad). Por campaña: gasto, personas que escribieron, citas, presupuestos aceptados y el retorno total de sus pacientes (primer pago más cuotas), el costo por cita y por paciente que pagó, y best_campaign: LA mejor campaña (una sola definición, con su regla). Por anuncio: el ranking de Vitrina con el veredicto de cada anuncio (mejor, rinde, refrescar, pausar, vigilar, pocos datos), el mismo de todas sus pantallas. Úsalo para «¿qué campaña rinde más?», «¿qué anuncio pauso?» o «¿cuál es mi mejor anuncio?». Las acciones propuestas con su porqué están en call_operation ads_actions_list (screen=resumen), los creativos en ventana móvil en ads_creatives_list, y quiénes pagaron por campaña (un paciente por fila: total pagado, pagos, RUT y teléfono si tu acceso lo permite) en ads_attributed_sales_list (campaign_id = campaign_external_id; ad_id opcional).

agent_knowledge_list

List an agent's knowledge files

The files attached to one agent — what its search_knowledge_base reads — each with a snippet of its first indexed chunk (null = the agent cannot find that file yet).

agent_skills_list

List an agent's skills

Return the skills attached to one agent as summaries (no body; content_chars instead). Use skills_get for the content.

ai_agents_change_request_get

Get one change request

The whole row: verbatim, reporter, confirmed conversation refs, the linked scenario and the FAILED run that is its red-gate evidence, the proposals it produced, any forced-publish override, and the tenant-facing message when it terminated in harness.

ai_agents_change_requests_list

List an agent's change requests

The agent's «Solicitudes»: what the tenant asked to change, in the client's own words, newest first, each with its display id (SR-n), status, reporter and any linked scenario / evidence run. NOT the Mejoras list — a finding is something the platform observed, a change request is something a person required. Filter by status (received | grounded | reproduced | proposed | applied | verified | ya_cumple | harness), or by conversation_id to answer 'which turns of this conversation already have a request'.

ai_agents_get

Get an AI agent

Return one AI agent by id.

ai_agents_list

List AI agents

Return all AI agents for the caller tenant as summaries: every field except the prompt texts, which are reported as system_prompt_chars / draft_system_prompt_chars (and the voice pair). Use ai_agents_get for the prompt itself.

ai_agents_metrics_get

One agent's rolling performance

How this agent has done over the last days (default 7, max 90), ending now. conversations counts conversations in which the agent posted a REAL turn — a template or reminder send is not a turn. resolved_without_human is those with no human reply at all; handoffs those a human joined; each pct is a fraction of conversations and is null (not 0) when there were none. first_response_seconds is the MEDIAN wait from a customer's first message to this agent's first reply, over conversations started in the window, null when nothing pairs. appointments_booked counts completed booking-tool calls. An agent with no traffic answers zeros and nulls, not an error.

ai_agents_publish_gate_get

Would publishing this agent be refused by its evals?

Reads the agent's enabled GOLDEN suite. none = no golden suite (never blocks); pending = a golden run is in flight (warn only); stale = the last completed run predates the current draft; blocked = hard fails or a pass rate under the policy's floor; ready otherwise. blocked and stale make POST /ai-agents/:id/publish answer 409 unless the body carries force: true. failing lists the red scenarios with their run ids.

ai_agents_scenario_run_get

Get one eval run

detail=summary (default): the verdict in full — every check result with evidence, hard fails, judge, score, error, timings — and the transcript reduced to one entry per turn {index, customer, fixed, text, tool_calls[{name, args}], latency_ms, error?}: no reasoning, parts or tool results, no customer_trace, no final_state (final_state_keys lists what full adds). detail=full: the whole run row — transcript with tool results and reasoning, the simulator customer_trace, the sandbox final_state — 80k–230k chars on a real run; ask for it only when the summary is not enough.

ai_agents_scenario_runs_list

List eval runs (summaries)

Newest first, SUMMARY rows only: status, score, hard_fail_count, check_summary {passed, failed, hard_failed}, stop_reason, agent_version_kind, timings, error. Read one run (ai_agents_scenario_run_get) for its transcript, checks and judge. Filter by scenario_id, batch_id or status. stale is true when a DRAFT run's verdict describes a configuration that no longer exists; cache_key / up_to_date — up_to_date is true when the run is a completed verdict about exactly the current scenario content and agent configuration of its side (a default ai_agents_scenarios_run skips such a scenario). A cancelled run is terminal and is not a verdict: error says draft_changed or cancelled_by_user.

ai_agents_scenario_suites_list

List an agent's eval suites

Named sets of the agent's scenarios plus a policy. kind: golden gates publish, nightly notifies on a cron, exploratory does neither, on_change is the opt-in CI re-run (fired, debounced, whenever the agent's draft fingerprint moves — its schedule holds { debounce_minutes } instead of a cron). Each row carries scenario_count (what the filter resolves to right now) and last_run (the newest suite run with its summary and delta).

ai_agents_scenarios_list

List an agent's eval scenarios

The agent's Evals: every scenario (persona, world, checks) with its latest run's verdict and score. Filter by status (draft|active|archived) or family.

appointment_types_list

List appointment types / services

The bookable catalog: test drives, general types, and priced services (cambio de aceite, mantenimiento). Filter by kind — kind=["service"] returns just the servicios, with the price the agent quotes. q is free text over name and description and NARROWS the other filters rather than replacing them. Types the tenant ELIMINATED from its catalog are never returned (a deactivated one still is, with is_active=false).

appointments_get

Get an appointment

Return one appointment by uuid or A- display id.

appointments_list

List appointments

List appointments for the tenant, newest starts_at first, filterable by status/kind/date/vehicle/owner. Returns { rows, next_cursor }: pass next_cursor back as cursor for the next page (null when exhausted). The cursor is the same opaque token GET /appointments uses.

call_operation

Call a public API operation

Run one operation of the Vitrina public API and return its response body. Pass path and query parameters together in params, by the names describe_operation lists, and a JSON request body in body for anything that is not a GET. The call goes through the same API as any other client with this same credential, so it does exactly what this credential is allowed to do and no more. Writes are granted per domain when the workspace authorises this connection, so search_operations is the honest list of what is available — an operation missing from it is not available here. REPEATS ARE PROTECTED BY DEFAULT: an identical call (same operation, same params, same body) replays the first response instead of writing twice, so a retry after a timeout is safe. To make a deliberate second identical write, pass a different idempotency_key.

coach_finding_get

Get one finding with evidence and proposals

Mirrors GET /ai-agents/:id/findings/:findingId.

coach_findings_list

List an agent's findings (recurring issues)

Mejoras: recurring issues the conversation reviewer detected for one AI agent, with 7-day / prior-28-day conversation counts and a direction. Mirrors GET /ai-agents/:id/findings.

coach_proposals_list

List improvement proposals

List improvement proposals, optionally by ai_agent_id and status.

coach_reviews_list

List recent conversation reviews for an agent

Completed conversation reviews for one AI agent, newest first; with_handoff narrows to the ones that recorded a handoff. Mirrors GET /ai-agents/:id/reviews.

contacts_get

Get a contact by id

Search the contact directory

ilike across name/email/phone/external_id, narrowable by lifecycle_stage (one stage, or a comma-separated list such as 'customer,repeat_customer', validated against unknown|prospect|qualified_prospect|customer|repeat_customer|inactive|blocked) / channel / lead_source / tag_id / company_id (a company id, or the literal 'none' for contacts belonging to no company) / instagram (EXACT Instagram handle, case-insensitive, leading @ optional — q does not search handles). Hides merged secondaries unless include_merged is true. Each row also carries channels[] (how to reach the contact) and lead_sources[] (where the contact came from — the distinct lead.source values of their leads), so origin needs no follow-up leads_list call. The result reports total — the number of MATCHES, not the page size — so a model can tell "these are all of them" from "these are the first 25"; page with offset.

contacts_stats

Contact directory facet counts

Tenant-wide counts over LIVE contacts (unmerged, unarchived): total, by_lifecycle, by_channel (distinct contacts per contact_channel kind), by_lead_source (distinct contacts per ORIGIN — the contact's lead.source values, or its declared origin_channel when it has no leads), email_reachable, phone_reachable, and duplicate_candidates (contacts sharing a lowercased email or digits-only phone with another contact). Takes no filters. Use this instead of paging contacts_search to count — these are real GROUP BYs, not a tally of one page.

conversations_linked_records

Linked ticket/lead pipeline context

The conversation's ticket and open lead with pipeline, current stage and the ordered stage list (each stage flagged allowed per the transition whitelist). Mirrors GET /conversations/:id/linked-records.

conversations_list

List conversations

Paginated inbox page. Filters: channel, status (ticket lifecycle), search, source (portal provenance), from_ad (only threads a Meta ad opened), from_campaign (only threads a campaign send was stored in), from_date / to_date (opened between, ISO), pipeline_id / stage_id (board / column of the ticket), handler (bot · human · external), unassigned, ai_replied (the AI sent at least one message), waiting (a customer is waiting on a human, team-wide; "closed" = the threads left out because the customer closed the chat, paid / is in the store, or a follow-up we promised is not due yet; rows carry waiting_since, waiting_state, waiting_due_at); attributes (conversation-attribute conditions, ANDed), tag_ids (any of), view_id (a saved inbox view); sort (wait = urgent first, then longest wait) + order. Answers \{ conversations, total \}. fields defaults to summary — per row only id, display_id, channel, source, status, handler, assignee_user_id, contact_id, contact_name, ticket_id, ticket_status, current_stage_id, awaiting_human_since, first_ai_message_at, last_message_date, created_at, ad_origin; fields: "full" is the whole inbox row (contact, ticket, lastMessage, tags …, ~7k characters each). Mirrors GET /conversations.

describe_operation

Describe one public API operation

The full contract of one operation: its parameters, their types and which are required, the request body schema when it takes one, and the response shape — straight from the OpenAPI document, so it is what the server actually enforces. destructive: true means the operation ends something that cannot be brought back; check with the person before calling one. Pass the operation_id search_operations returned; the raw method-and-path form it lists under aliases works too.

entitlements_list

List add-on entitlements

The add-on catalog (Sitio del dealer, Tasador, Vitrina Ads — access mode + monthly price in UF (flatUfMonth) or whole CLP (flatClpMonth)) and this workspace's entitlement rows (status, cancel-at-period-end, billed_by: vitrina or the party that covers the add-on instead, in which case Vitrina charges nothing; waiver_until: the last free day of a time-boxed waiver, with waiver_active true while it still covers the add-on), offers (per add-on: available, or why not — sandbox for a demonstration workspace, vertical for an add-on not sold to this type of business) and activators (the owners and admins, by name, who can activate an add-on). READ-ONLY mirror of GET /entitlements: activating or cancelling an add-on is a self-serve REST action (it can accrue a charge), never an agent tool.

followups_list

List follow-ups (Seguimientos) with waiting counts

followups_overview

Follow-ups overview: recipes, channel enablement/connection, WhatsApp template readiness

help_center_articles_list

List articles in a help center

help_centers_list

List help centers

insights_agents_get

Per-HUMAN-agent breakdown: conversations, replies, response/resolution times

One row per human agent who touched a conversation in the window: conversations, replies, avg first-response/resolution/customer-wait times and resolutions. An ARRAY, one row per agent — never a total. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/agents.

insights_ai_agents_get

Per-AI-AGENT breakdown: automation rate, handoffs, latency

One row per AI agent (not per human): conversations, responses, automated_conversations (no human reply), handoffs, resolutions, tool_calls and avg generation latency. An ARRAY, one row per AI agent. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/ai-agents.

insights_bots_get

AI agents in aggregate: deflection rate, handoff rate

The whole bot/AI-agent surface as ONE total (the per-agent breakdown is insights_ai_agents_get): deflection_rate (automated_conversations / total_conversations), handoff_rate, resolved_by_bot/human/auto, avg_gen_latency_ms and two time series (resolutions, handoff). Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/bots.

insights_calls_get

Voice call outcomes, durations and voice-to-voice latency

Call outcome/duration/AMD aggregates plus the voice-to-voice and voice-LLM latency percentiles the voice quality gate (ADR-0017) is measured against. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/calls.

insights_channels_get

Conversations broken down by channel (WhatsApp, IG, …)

One row per messaging channel: conversations, avg first-response/resolution/customer-wait times and resolutions. An ARRAY, one row per channel. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/channels.

insights_conversations_get

Conversations, messages, response/resolution times, facturables

Conversation/message counts, first-response and resolution time distributions, and facturables — billable conversations in the window, from the SAME getBillableCount the invoice rollup uses, so this can never disagree with an invoice. solo_humano is conversations.total - facturables, clamped at 0. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/conversations.

insights_csat_get

AI-estimated customer satisfaction

satisfaction_score (positive / total), response_rate, positive/neutral/negative counts, recommend_rate, avg_confidence, the satisfaction/resolution-quality/agent-performance distributions and the most recent individual responses. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/csat.

insights_leads_get

Lead funnel: open/won/lost/unqualified, win rate, cycle time

open/won/lost/unqualified counts, total_value_open/won, win_rate (won / (won + lost) — unqualified is EXCLUDED from that denominator, VIT-451), avg_cycle_seconds, three time series (created/won/revenue) and the per-stage funnel (open_count, total_value, median_time_in_stage_hours). Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/leads.

insights_overview_heatmap_get

When: traffic and resolutions by day × hour

Two day×hour grids over the window — inbound traffic and resolutions — in the caller's IANA timezone (tz, defaults to UTC) so the buckets match a wall clock rather than UTC. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/overview/heatmap.

insights_overview_live_get

Right now: open, unattended, unassigned, pending — and who is online

The live state of the inbox: open/unattended/unassigned/pending conversation counts and agent presence (online/busy/offline), AS OF THIS INSTANT. Not a period — meta.window declares \{kind: "instant"\} rather than a range, so "12 open" can never be misread as "12 opened this month". Takes no arguments. Mirrors GET /insights/overview/live.

insights_sla_get

SLA compliance: first-response and resolution targets

has_policies/policy_count, the tenant's first-response and resolution targets, tracked/breached/hit_rate overall and per dimension, a per-policy breakdown (by_policy) and the individual breaching tickets (breaches). A ticket is "tracked" only when an applicable policy has an evaluable dimension; business-hours-only policies count business hours in the tenant's schedule/timezone. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/sla.

insights_sources_get

Conversations broken down by origin (Mercado Libre, Yapo, …)

One row per conversation.source: conversations, avg first-response/resolution/customer-wait times and resolutions. Identical row shape to insights_channels_get, but grouped by where the conversation CAME FROM rather than which messaging account carried it — marketplace leads share one WhatsApp number, so the channel view cannot separate them. An ARRAY, one row per origin; __none__ is the no-origin bucket. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/sources.

insights_storefront_get

The dealer's own storefront: traffic, leads, conversion

Visits, per-vehicle view counts, and storefront-originated leads for the tenant's OWN Vitrina-built website — distinct from every other channel (WhatsApp, marketplaces, ...). conversion is storefront_leads / storefront_visits, reported ALONGSIDE its numerator and denominator (each named with its own count) so the ratio can never be misread as counting two different populations — the exact failure a rival tool’s "433.3% conversion" KPI demonstrates. top_vehicles is ordered by views so a listing with traffic and ZERO lead_submit_events is identifiable at a glance — the car buyers look at and ignore. visits_series / leads_series give one point per DEALERSHIP calendar day (zero-filled, and never past today — a future day is not a measurement). recent_leads lists the ten most recent storefront leads inside the window, newest first; contact_name and contact_phone are ABSENT (the keys are removed, not nulled) unless the caller also holds contacts:read — an absent key means "you may not read this", a null means "this lead has none on file". Windowed by CALENDAR MONTH only ('YYYY-MM', defaults to the current month in America/Santiago) — the response's own window field states exactly which month was used, and window.as_of when the figures were read (there is no sync job; events land in real time). Mirrors GET /insights/storefront.

insights_tags_get

Conversations broken down by tag

One row per tag: conversations, avg first-response/resolution/customer-wait times and resolutions. An ARRAY, one row per tag. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/tags.

insights_teams_get

Conversations broken down by team

One row per team: conversations, avg first-response/resolution/customer-wait times and resolutions. An ARRAY, one row per team. Which period to report over. A rolling preset (24h/7d/30d/90d); calendar_month (optionally month: "YYYY-MM", defaults to the current one); calendar_year (optionally year: "YYYY", defaults to the current one); or custom (requires both from and to as ISO instants). Same vocabulary GET /insights/* accepts as ?window= (ERP S12-2). Mirrors GET /insights/teams.

kb_files_get_text

Read the indexed text of a knowledge file

The full extracted text of one file, in chunk order — literally what search_knowledge_base searches. text is null while nothing is indexed (still ingesting, failed, or an image without OCR).

kb_files_list

List knowledge files

Every knowledge file in the workspace library with its ingestion status (ready → ingesting → ingested | failed), size, content type, the agents it is attached to, and a snippet of the first indexed chunk. ready means stored, not yet searchable.

lead_conversations_list

List the conversations a lead spans

Every conversation linked to one opportunity, newest link first: conversation_id, C-NNN display id, channel, status, last_message_date, plus is_primary (this lead owns the thread) and is_origin (the conversation the opportunity started in). Accepts a lead UUID or L-NNN display id. Mirrors GET /leads/{id}/conversations.

lead_interests_list

List what a lead concretely wants

Polymorphic interests on a lead (vehicle/property/product/service/repair_order/custom). Accepts a lead UUID or L-NNN display id.

leads_kanban

The sales boards, or one board in full

CALL IT WITH NO ARGUMENTS FIRST to list this workspace's SALES boards with their stages — \{pipelines: [\{id, name, slug, is_fallback, stages: [\{id, name, position\}]\}]\}. That is how you turn a name a person said ("Ventas", "Contactado", "Cierre") into the pipeline_id / stage_id every other board tool needs, and is_fallback marks the board a new lead lands on when nobody names one. NEVER ask a person for a uuid: call this instead. Pass pipeline_id to get that board IN FULL: every stage of the pipeline, in position order, each with the leads sitting on it (up to 200 per board) plus won/terminal flags. This is the board an operator drags cards on; pair it with leads_move_stage to move one. Mirrors GET /leads/kanban. On a clinic (healthcare) workspace, value_amount on a WON lead is cash the patient paid, credited to that lead; before won it is the open presupuesto (a quote), not a sale. For return, ROAS, paid per ad or which ad brought paying patients, call ads_attributed_sales_list; never sum lead values.

locations_list

List locations

Multi-branch locations (sucursales / stores / clinics / offices) for the tenant. Soft-deleted rows are hidden unless include_inactive is true.

pipelines_list

List pipelines

All pipelines for the tenant with their stages. Pass include: "counts" to add card_count to every row: THE WORK IN FLIGHT on that board — open leads on a sales board, un-resolved/un-closed tickets on a ticket board (pending and snoozed still count), and currently-placed cars on a vehicle board. It is NOT a historical total, so a busy old funnel reads as 0. Omit it and the response is exactly what it always was. Mirrors GET /pipelines.

Search product stock

Deterministic search over the canonical product table (non-vehicle goods) for the caller tenant (cheapest-first, in-stock by default).

search_operations

Search the public API

Find operations of the Vitrina public API this credential can call. Returns operation ids for describe_operation and call_operation, each with its method, whether it writes and whether it is destructive. Only what this connection is actually allowed to do is listed: writes appear when the workspace granted that domain. Search by words from the path, the resource name or the summary — e.g. "stock", "webhook deliveries", "locations". Call it with no query to see everything available.

skills_get

Get a skill

Return one skill by id.

skills_list

List skills

Return all skills (reusable behavioral playbooks) for the caller tenant as summaries — name, description (the trigger), status, version, attachment counts, content_chars — without the body. Use skills_get for the content.

stages_list

List stages for a pipeline

teams_list

List teams in this tenant

tickets_by_stage

The tickets sitting on one stage of a board

One COLUMN of a ticket board, paged: every ticket whose current stage is stage_id, newest first by default, with the conversation it started in. The ticket twin of leads_kanban — pair it with tickets_move_stage to move a card. Mirrors GET /tickets/stage/{stageId}.

tickets_list_conversations

List every conversation linked to a ticket

A ticket can own N conversations across channels. Returns each one with channel, contact, and messaging account.

versions_list

List AI agent versions

History of every published snapshot, newest first, as summaries: version number, label, model, who published, system_prompt_chars, and the skill / kb / tool snapshot COUNTS. The full snapshot (prompt text, skill bodies) is GET /ai-agents/\{id\}/versions/\{v\}.

Automotora

Cuándo aparece. Cuando el workspace es de rubro automotora.

dealer_alerts_list

The dealership’s alerts & suggestions feed

The dealership’s standing to-do list, evaluated server-side once a day: ALERTS (something is wrong — a car sold with no cost recorded, cars in stock that are «Sin costo» because they entered with no compra, consignación or parte de pago, consigned cars whose mandato was emitted but has no signed copy uploaded, a lead nobody ever reached) and SUGGESTIONS (something could be better — cars on the floor and on no portal). Each entry carries the rule that raised it, the evidence it fired on, and the screen that resolves it (action_route + action_params — a route KEY, never a URL). A lot-wide pile entry (evidence.view) carries its count AS OF NOW — the same number the Stock tile for that view shows. Entries persist until the condition heals or a human dismisses them, and a dismissal survives re-evaluation, so this is a backlog rather than an event stream. Read-only: dismissing is a human judgement about the business and is deliberately not exposed here. Mirrors GET /dealer-alerts.

insights_inventory_ageing_get

How old is the stock, and what is tied up in it?

The state of the yard RIGHT NOW (not a period): unidades, días promedio en stock, días promedio en la etapa actual, the obsoleto count, the BR-2682 ageing rungs (0-30 / 31-60 / 61-90 / 91-180 / +180 días) each carrying its own unit and obsoleto counts, and the propio vs consignación split. Under economics: capital inmovilizado per rung, per tenencia and for the obsoleto pile. ⚠ NEVER RE-DERIVE THESE NUMBERS. days_in_stock counts from vehicle.created_at — the instant the unit entered THE SYSTEM, not the date on its acquisition document (BR-2684), so a re-imported car looks newer than it is; the payload says so in days_in_stock.basis_label. Ageing RUNGS are a pure clock; is_stale / stale_unit_count is the obsoleto rule (≥ stale_days días AND zero interest AND not vendido). They STACK: a 200-day car three people asked about this week is in the 180_mas rung and is NOT obsoleto. Never quote one as the other. ⚠ days_in_current_stage IS AVERAGED OVER units_on_a_board ONLY. Most cars are on no preparación board at all (units_off_every_board), and a car off every board does not have zero días en etapa — it has none. Quote the denominator with the average or do not quote the average. Every peso figure sits under economics. If that key is ABSENT the caller does not hold dealership_economics:read — report the counts and the días and say the money is not available to you; NEVER estimate, reconstruct or infer a cost or a margin from the figures that are present. Inside it, capital totals sum ONLY units with a complete cost basis (incomplete_unit_count says how many were excluded rather than counted as zero), and deals_missing_margin counts deals whose margin was NOT RECORDED and therefore excluded from the totals. Mirrors GET /insights/inventory/ageing.

insights_inventory_rotation_get

How fast does the yard turn, and what should we buy more of?

Rotation over a window: días promedio para vender (the headline), the rotación ratio with its annualised form and días de inventario, the daily stock curve behind the denominator, and ONE marca/modelo dataset carrying unidades vendidas, unidades en stock and speed-to-sell — the answer to "más vendidas" and "más rápidas". Under economics, the same grain carries margen bruto, Utilidad del negocio and Utilidad promedio — "mayor margen" and "más rentables". Every KPI ships its own formula, formula_id, window_label and window_days: quote the formula with the number. ⚠ THERE ARE TWO "SOLD" FACTS AND THEY DO NOT COINCIDE, ON PURPOSE. sold.unit_count counts UNITS marked vendido (vehicle.sold_at) inside the window — the same stock basis as the denominator, which is why rotation uses it. sold.deals_count counts non-voided NOTAS DE VENTA issued inside the window — the only basis a margin exists on. A nota issued but not approved gives margin with no sale; a unit marked vendido by hand or by import gives a sale with no margin. sold.units_sold_without_deal is exactly that residual and is a data-quality alarm worth surfacing, not a rounding error. Never add the two counts together and never present one as the other. Every peso figure sits under economics. If that key is ABSENT the caller does not hold dealership_economics:read — report the counts and the días and say the money is not available to you; NEVER estimate, reconstruct or infer a cost or a margin from the figures that are present. Inside it, capital totals sum ONLY units with a complete cost basis (incomplete_unit_count says how many were excluded rather than counted as zero), and deals_missing_margin counts deals whose margin was NOT RECORDED and therefore excluded from the totals. The window is the SAME vocabulary every Insights report takes. Mirrors GET /insights/inventory/rotation.

price_approvals_get

Read one price approval

ONE price-approval record, complete: which document it authorises, what price was asked for, what the unit's prices were at that moment, WHO asked, the status, and — once decided — WHO decided, when and why. ⚠ The floor-price snapshot is a cost figure and is absent without dealership_economics:read. Mirrors GET /price-approvals/{id}.

price_approvals_list

List price approval requests

The price-approval QUEUE: requests to sell a unit below the reference price this organisation approves against, OLDEST FIRST (this is an ageing list — the request that has waited longest is the one that matters). Filter status: "pending" for what is still waiting, or subject_kind + subject_id for everything asked about one document. Each row carries the requested price and the unit's list price AS THEY WERE WHEN THE REQUEST WAS RAISED — snapshots, not today's numbers. ⚠ The unit's FLOOR price is a cost figure and is ABSENT unless the caller also holds dealership_economics:read; do not report it as null or missing data. Mirrors GET /price-approvals.

vehicle_interest

Who asked about this car

Interest rollup for ONE vehicle (S8 Historial) — answers "how many people asked about this car". Returns distinct contacts, named-lead count, a per-portal (yapo/chileautos/...) breakdown from lead.source, and first/last contact, plus días en stock from created_at. A vendido car has no active demand so it rolls up empty (ADR 0030). No contact ids are returned.

vehicles_kanban

The reconditioning boards, or one board in full

CALL IT WITH NO ARGUMENTS FIRST to list this workspace's reconditioning boards with their columns — \{pipelines: [\{id, name, slug, stages: [\{id, name, position\}]\}]\}. That is how you turn a name a person said ("Preparación de vehículos", "En preparación", "Publicado") into the pipeline_id / stage_id every other board tool needs. NEVER ask a person for a uuid: call this instead. Pass pipeline_id to get that board IN FULL: every column in position order, each with the cars sitting on it and how long each has been there (stage_entered_at) plus the column's own ageing threshold (sla_days, days; null = no limit) — which is what makes a card "atrasado". Cards are a MINIMAL projection (make/model/version/year, patente, one photo, commercial status) and carry no pricing or cost. Up to 500 cars per board; the response says whether that cap was hit. A pipeline of any other kind is refused. Mirrors GET /vehicles/kanban.

Search vehicle stock

Deterministic search over the canonical vehicle table for the caller tenant (cheapest-first).

vehicles_stats

Stock health counts

Aggregate health counts for the tenant lot (S7 header): total, active, by estado comercial, publicados (>=1 live publication), con error (>=1 error publication), sin publicar (active without a live publication), sin_costo («Sin costo»: active, not sold, with no compra, consignación or parte de pago recorded — its cost is unknown; only returned to a caller holding dealership_economics:read), mandato_sin_firmar (consigned cars whose mandato was emitted but has no signed copy uploaded — list them with view=mandato_sin_firmar), and the Stock «por completar» counts: needs_review («Revisar marca/modelo»: marca or modelo not matched to the catalogue), sin_sucursal («Sin sucursal»), sin_estacionamiento («Sin estacionamiento»: no patio position; a count only, never which position) and source_deactivated («Retirados del portal»: the portal withdrew it and nobody has said whether it sold), plus papers_expired («Papeles vencidos»: cars in stock with a SOAP, permiso de circulación, revisión técnica or named paper past its «Vence» day) and papers_expiring («Papeles por vencer»: due within 30 days) — list those papers with vehicle_papers_list and expiring_within_days. Whole lot, within the caller’s sucursales. Overlapping by design.

Clínica

Cuándo aparece. Cuando el workspace es de rubro salud.

clinic_agenda_list

List the clinic agenda for a date window

The clinic's citas between from (inclusive) and to (EXCLUSIVE), both bare YYYY-MM-DD days in the clinic's timezone — a single day is from=D, to=D+1. At most 8 days per call. Read from the local mirror, so it costs the clinic's API budget nothing; it is NOT availability (a slot with no cita is simply absent — use the availability tool for free slots). Cancelled citas ARE included, marked by status. Optional profesional_id / sucursal_id are the CLINIC's ids (as returned in profesional_id / sucursal_id), not Vitrina uuids.

clinic_agenda_profesionales

List the professionals with citas in a window

The distinct dentists/professionals holding at least one cita between from (inclusive) and to (EXCLUSIVE) — the agenda grid's column set, and the id space clinic_agenda_list's profesional_id filter accepts. At most 8 days per call. Read off the mirrored citas, so it works even when the clinic's token cannot read its own professionals catalog.

clinic_professional_get

Get one clinic professional

One professional with the full vendor payload (data) and citas_next_7d — the live (pending/confirmed) citas they hold over the next seven days, counted off the mirrored shadow rows. A native professional (no vendor id) always reports 0: it can hold no mirrored citas.

clinic_professionals_list

List the clinic's professionals

The clinic's own staff roster from the local tables (never the clinic API). search (min 2 chars) matches the name accent-insensitively OR the primary/secondary specialties. active is OPTIONAL — omitting it returns EVERY row, active and retired, because a professional who left still names mirrored citas. schedule is the weekly working hours keyed mon..sun; null means the schedule read has not landed, NOT that they work no days.

clinic_services_list

List the clinic's services

The clinic's price list from the local tables. search (min 2 chars) matches nombre, código or categoría accent-insensitively. active is OPTIONAL — omitting it returns every row. precio is the vendor LIST price BEFORE previsión and convenios: correct for an operator reading their own catalog, wrong more often than right if quoted to a patient (which is why the AI agent is given no price at all).

clinic_statuses_list

List the clinic's appointment statuses

The custom appointment-status layer: the clinic's own statuses (synced vendor estados and native ones), each mapped to a Vitrina bucket (pending_hold|confirmed|cancelled|completed|no_show). active is OPTIONAL — omit it to return every status, retired ones included. is_name_editable is true only for the clinic's own (native) statuses.

Costos, márgenes y comisiones

Cuándo aparece. Solo si marcaste la casilla de datos económicos al conectar. Si no, estas herramientas no existen para tu cliente de IA: no aparecen en la lista y no se pueden llamar.

capital_inmovilizado_report

Capital tied up in stock — ageing × real cost

The whole lot as immobilised capital rather than a list: one row per unit (identity, days on the floor, obsoleto standing, the unit's S3-5 cost roll-up) plus the total the dealership itself has tied up, with a stale/not-stale subtotal mirroring the Stock list's own vocabulary. Each row's age and obsoleto flag are the SAME numbers the Stock list's 'stale' saved view uses (días on the floor with ZERO interest, named or anonymous) — never a private re-derivation. Each row’s cost is the S3-5 roll-up for that unit (acquisition net + Σ expenses − Σ incomes, split by who bears it), embedded whole. dealership_cost_clp — on the report AND on each stale/not_stale bucket — is summed ONLY over units whose cost_rollup.complete is true: a unit with an unrecorded acquisition or an unallocated cost line still appears in units, flagged via cost_rollup.complete/cost_rollup.gaps, but its (partial) cost is excluded from every total rather than silently counted as if the basis were finished. incomplete_unit_count says how many rows were excluded. This is the dealership's own money and is deliberately unavailable to the conversational agent. Mirrors GET /capital-inmovilizado; there is no query surface on either side (no Sucursal filter, no date window) — the report covers the whole active, non-vendido lot.

margin_deal_get

Did we make money on this deal?

The margin of ONE closed deal (one nota de venta): its revenue terms, its cost of sales, the gross margin, every named deduction and the Utilidad del negocio — plus the unit’s S3-5 cost roll-up embedded whole. MARGEN BRUTO = ingresos − costo de venta. UTILIDAD DEL NEGOCIO (margen_neto_clp) = margen bruto − gastos adicionales − comisiones vendedores; its monthly sum net of fixed overhead is the UTILIDAD DEL PERÍODO (margen_neto_periodo_clp). In Spanish call it «Utilidad»: in Chile «neto» reads as «sin IVA». All figures are whole CLP pesos and NET of IVA end to end — they are the «cifras del negocio» (ADR 0114 §2.2); the buyer’s gross figures (the nota de venta, the compraventa, the Cuadre) are never added to them, and when you quote an afecto sale’s price next to them say «$5.806.723 neto · $6.910.000 con IVA». Report the numbers this tool returns and do NOT reproduce the arithmetic yourself from the components: there is exactly one server-side definition (BR-640 — two implementations of a margin formula always diverge), and the components are published so a reader can SEE the walk, not so a caller can re-derive it. ⚠ OWNED AND CONSIGNED UNITS ARE DIFFERENT ECONOMICS AND ARE SEPARABLE EVERYWHERE. For an OWNED unit (regime: 'propia') revenue is the net sale price plus the add-ons the dealership KEEPS (a financing fee), and costo_venta_clp («Costo de compra») is the nota de compra’s precio acordado: the payout to the seller plus the retenciones withheld from it and paid to third parties on the seller’s behalf (cost_terms.payout_clp + cost_terms.retenciones_clp). A retención is never a unit expense (deductions.gastos_unidad_clp excludes it); restated 2026-10-01, Utilidad unchanged. A «Cobro por cuenta del comprador» — an add-on the buyer pays through the dealer at exact cost (the transfer tax, arancel, notaría) — is NOT revenue and NOT an expense: it is revenue_terms.pass_through_clp (cobrado) / pass_through_paid_out_clp (rendido) and is in no figure of the walk, so «Margen bruto» equals the commission base. Past periods are restated under this one definition (2026-09-28). For a CONSIGNED unit (regime: 'consignacion') the dealership sold somebody else's car under a mandato con representación: the price belongs to the dueño, the dealership’s revenue is what the LIQUIDACIÓN says it kept (revenue_terms.dealer_take_clp = venta − payout − deducciones), and costo_venta_clp is 0 because it never bought the car. Never quote a consigned deal’s precio_venta_clp as the dealership’s revenue — it is published only so the settlement can be reconciled against it. ⚠ FIXED OVERHEAD IS A PERIOD FIGURE AND IS NEVER ALLOCATED TO A UNIT. On a deal or a unit, deductions.gastos_fijos_clp is ALWAYS null and means NOT ALLOCABLE (rent and wages attach to the dealership and to no vehicle, and no key in this domain says how to split them). Only the period report carries a real gastos_fijos_clp, and only margen_neto_periodo_clp is net of it — margen_neto_clp is the sum of the deals and is BEFORE overhead. ⚠ CHECK complete BEFORE QUOTING A NUMBER. false means an input was NOT RECORDED and the figure it feeds is null rather than a plausible peso amount: an unrecorded acquisition (the cost basis is unknown, NOT zero — a margin over it would report the whole sale price as profit), a consigned sale with no liquidación (the dealership’s take is unknown), or a participation with no recorded commission (the NET is not computable; the GROSS still is). gaps names which input and why — say «Sin costo», «Sin liquidación» or «Sin comisión», and its Utilidad is «—». On the period report EVERY sale counts: deal_count and sales_ingresos_clp («Ingresos») cover every sale of the month, complete or not — the same figures the Ranking de ventas shows — while the walk from ingresos_clp down to margen_neto_clp sums the COMPLETE deals only; incomplete_deal_count and incomplete_by_gap say how many are incomplete and why. A «Sin comisión» sale is fixed with sale_participations_record_commission; a «Sin costo» one by recording the car’s cost. ⚠ salesperson_id NAMES THE CLOSER AND IS NOT A COMMISSION SPLIT. It is sale_note.salesperson_id verbatim, and it is null on a document that never recorded one (which is NOT a gap — the margin does not depend on who closed the deal, so complete stays true). Who is PAID on a sale is the participation set — a closer and any number of collaborators — and their money is already in deductions.comisiones_vendedores_clp. So group deals by this field to answer "whose deals are these?", and never present the result as margin earned BY a person: nothing in this domain splits one deal’s margin between two participants. A VOIDED nota de venta has no margin and is NOT FOUND here, deliberately — it is still readable everywhere else. Takes the document uuid or its folio (V-47). Mirrors GET /margin/deals/{id}.

margin_period_report

Margin for a month — ventas, costo, margen bruto y utilidad

The whole month as one walk: Ventas Totales, Costo de Ventas, Margen Bruto, then the Desglose down through Comisiones Vendedores and Gastos Adicionales to the Utilidad del negocio, and finally Gastos Fijos to the Utilidad del período. by_regime splits every one of those figures into owned and consigned. MARGEN BRUTO = ingresos − costo de venta. UTILIDAD DEL NEGOCIO (margen_neto_clp) = margen bruto − gastos adicionales − comisiones vendedores; its monthly sum net of fixed overhead is the UTILIDAD DEL PERÍODO (margen_neto_periodo_clp). In Spanish call it «Utilidad»: in Chile «neto» reads as «sin IVA». All figures are whole CLP pesos and NET of IVA end to end — they are the «cifras del negocio» (ADR 0114 §2.2); the buyer’s gross figures (the nota de venta, the compraventa, the Cuadre) are never added to them, and when you quote an afecto sale’s price next to them say «$5.806.723 neto · $6.910.000 con IVA». Report the numbers this tool returns and do NOT reproduce the arithmetic yourself from the components: there is exactly one server-side definition (BR-640 — two implementations of a margin formula always diverge), and the components are published so a reader can SEE the walk, not so a caller can re-derive it. ⚠ OWNED AND CONSIGNED UNITS ARE DIFFERENT ECONOMICS AND ARE SEPARABLE EVERYWHERE. For an OWNED unit (regime: 'propia') revenue is the net sale price plus the add-ons the dealership KEEPS (a financing fee), and costo_venta_clp («Costo de compra») is the nota de compra’s precio acordado: the payout to the seller plus the retenciones withheld from it and paid to third parties on the seller’s behalf (cost_terms.payout_clp + cost_terms.retenciones_clp). A retención is never a unit expense (deductions.gastos_unidad_clp excludes it); restated 2026-10-01, Utilidad unchanged. A «Cobro por cuenta del comprador» — an add-on the buyer pays through the dealer at exact cost (the transfer tax, arancel, notaría) — is NOT revenue and NOT an expense: it is revenue_terms.pass_through_clp (cobrado) / pass_through_paid_out_clp (rendido) and is in no figure of the walk, so «Margen bruto» equals the commission base. Past periods are restated under this one definition (2026-09-28). For a CONSIGNED unit (regime: 'consignacion') the dealership sold somebody else's car under a mandato con representación: the price belongs to the dueño, the dealership’s revenue is what the LIQUIDACIÓN says it kept (revenue_terms.dealer_take_clp = venta − payout − deducciones), and costo_venta_clp is 0 because it never bought the car. Never quote a consigned deal’s precio_venta_clp as the dealership’s revenue — it is published only so the settlement can be reconciled against it. ⚠ FIXED OVERHEAD IS A PERIOD FIGURE AND IS NEVER ALLOCATED TO A UNIT. On a deal or a unit, deductions.gastos_fijos_clp is ALWAYS null and means NOT ALLOCABLE (rent and wages attach to the dealership and to no vehicle, and no key in this domain says how to split them). Only the period report carries a real gastos_fijos_clp, and only margen_neto_periodo_clp is net of it — margen_neto_clp is the sum of the deals and is BEFORE overhead. ⚠ CHECK complete BEFORE QUOTING A NUMBER. false means an input was NOT RECORDED and the figure it feeds is null rather than a plausible peso amount: an unrecorded acquisition (the cost basis is unknown, NOT zero — a margin over it would report the whole sale price as profit), a consigned sale with no liquidación (the dealership’s take is unknown), or a participation with no recorded commission (the NET is not computable; the GROSS still is). gaps names which input and why — say «Sin costo», «Sin liquidación» or «Sin comisión», and its Utilidad is «—». On the period report EVERY sale counts: deal_count and sales_ingresos_clp («Ingresos») cover every sale of the month, complete or not — the same figures the Ranking de ventas shows — while the walk from ingresos_clp down to margen_neto_clp sums the COMPLETE deals only; incomplete_deal_count and incomplete_by_gap say how many are incomplete and why. A «Sin comisión» sale is fixed with sale_participations_record_commission; a «Sin costo» one by recording the car’s cost. ⚠ salesperson_id NAMES THE CLOSER AND IS NOT A COMMISSION SPLIT. It is sale_note.salesperson_id verbatim, and it is null on a document that never recorded one (which is NOT a gap — the margin does not depend on who closed the deal, so complete stays true). Who is PAID on a sale is the participation set — a closer and any number of collaborators — and their money is already in deductions.comisiones_vendedores_clp. So group deals by this field to answer "whose deals are these?", and never present the result as margin earned BY a person: nothing in this domain splits one deal’s margin between two participants. The month is REQUIRED and is the dealership's calendar month (America/Santiago), the same one the sellers’ commissions were resolved in; there is deliberately no whole-history dump and no per-seller or per-sucursal filter. Mirrors GET /margin?period=YYYY-MM.

margin_unit_get

What one car has earned, across every deal

The margin of ONE UNIT across every non-voided deal it was sold on, plus the total over them. ⚠ totals IS THE SUM AND NEVER THE MEAN. A car sold, taken back and resold has two deals, and the correct answer for that plate is the TOTAL of the two (the recovered system plotted sum / count and understated every repeated plate — BR-643). MARGEN BRUTO = ingresos − costo de venta. UTILIDAD DEL NEGOCIO (margen_neto_clp) = margen bruto − gastos adicionales − comisiones vendedores; its monthly sum net of fixed overhead is the UTILIDAD DEL PERÍODO (margen_neto_periodo_clp). In Spanish call it «Utilidad»: in Chile «neto» reads as «sin IVA». All figures are whole CLP pesos and NET of IVA end to end — they are the «cifras del negocio» (ADR 0114 §2.2); the buyer’s gross figures (the nota de venta, the compraventa, the Cuadre) are never added to them, and when you quote an afecto sale’s price next to them say «$5.806.723 neto · $6.910.000 con IVA». Report the numbers this tool returns and do NOT reproduce the arithmetic yourself from the components: there is exactly one server-side definition (BR-640 — two implementations of a margin formula always diverge), and the components are published so a reader can SEE the walk, not so a caller can re-derive it. ⚠ OWNED AND CONSIGNED UNITS ARE DIFFERENT ECONOMICS AND ARE SEPARABLE EVERYWHERE. For an OWNED unit (regime: 'propia') revenue is the net sale price plus the add-ons the dealership KEEPS (a financing fee), and costo_venta_clp («Costo de compra») is the nota de compra’s precio acordado: the payout to the seller plus the retenciones withheld from it and paid to third parties on the seller’s behalf (cost_terms.payout_clp + cost_terms.retenciones_clp). A retención is never a unit expense (deductions.gastos_unidad_clp excludes it); restated 2026-10-01, Utilidad unchanged. A «Cobro por cuenta del comprador» — an add-on the buyer pays through the dealer at exact cost (the transfer tax, arancel, notaría) — is NOT revenue and NOT an expense: it is revenue_terms.pass_through_clp (cobrado) / pass_through_paid_out_clp (rendido) and is in no figure of the walk, so «Margen bruto» equals the commission base. Past periods are restated under this one definition (2026-09-28). For a CONSIGNED unit (regime: 'consignacion') the dealership sold somebody else's car under a mandato con representación: the price belongs to the dueño, the dealership’s revenue is what the LIQUIDACIÓN says it kept (revenue_terms.dealer_take_clp = venta − payout − deducciones), and costo_venta_clp is 0 because it never bought the car. Never quote a consigned deal’s precio_venta_clp as the dealership’s revenue — it is published only so the settlement can be reconciled against it. ⚠ CHECK complete BEFORE QUOTING A NUMBER. false means an input was NOT RECORDED and the figure it feeds is null rather than a plausible peso amount: an unrecorded acquisition (the cost basis is unknown, NOT zero — a margin over it would report the whole sale price as profit), a consigned sale with no liquidación (the dealership’s take is unknown), or a participation with no recorded commission (the NET is not computable; the GROSS still is). gaps names which input and why — say «Sin costo», «Sin liquidación» or «Sin comisión», and its Utilidad is «—». On the period report EVERY sale counts: deal_count and sales_ingresos_clp («Ingresos») cover every sale of the month, complete or not — the same figures the Ranking de ventas shows — while the walk from ingresos_clp down to margen_neto_clp sums the COMPLETE deals only; incomplete_deal_count and incomplete_by_gap say how many are incomplete and why. A «Sin comisión» sale is fixed with sale_participations_record_commission; a «Sin costo» one by recording the car’s cost. ⚠ salesperson_id NAMES THE CLOSER AND IS NOT A COMMISSION SPLIT. It is sale_note.salesperson_id verbatim, and it is null on a document that never recorded one (which is NOT a gap — the margin does not depend on who closed the deal, so complete stays true). Who is PAID on a sale is the participation set — a closer and any number of collaborators — and their money is already in deductions.comisiones_vendedores_clp. So group deals by this field to answer "whose deals are these?", and never present the result as margin earned BY a person: nothing in this domain splits one deal’s margin between two participants. A unit that has never been sold answers with an empty deals and a zeroed total — that is a fact about the car, not a missing record. Mirrors GET /margin/units/{vehicleId}.

vehicle_cost_rollup_get

What one vehicle cost

The rolled-up cost of ONE unit: its acquisition basis plus its whole expense and income ledger, with the split showing who bears each peso. THE TOTAL IS acquisition net + Σ expenses − Σ incomes, in whole CLP pesos. The acquisition figure is the NET payout (what actually left the till, retentions already deducted) and EVERY ledger line is added back on top of it — retained and not alike. That pairing is the point: the net already has the retained lines taken out of it, so adding them back counts them exactly once. Do NOT filter by retained and do NOT try to reproduce this sum yourself from vehicle_cost_entries_list; report the number this tool returns. ⚠ THERE ARE TWO TOTALS AND THEY ARE DIFFERENT QUESTIONS. total_cost_clp is what the UNIT cost — every peso spent on it, whoever paid. dealership_cost_clp is what the AUTOMOTORA bore, which excludes whatever the dueño (consignor) or the cliente bears and takes only HALF of a 50/50 shared line. A margin is computed against dealership_cost_clp; quoting total_cost_clp as the house’s cost overstates it. by_party shows the whole split so the two reconcile. ⚠ CHECK complete BEFORE QUOTING THE NUMBER. false means an input was NOT RECORDED — most often the unit has no acquisition record at all, in which case acquisition_net_clp is null (NOT zero: nobody has said what the car cost, which is not the same as it having been free) and the total covers the cost ledger only. gaps names each missing input and, for a line whose split does not account for it, the line id. Say the total is provisional and say what is missing; never present an incomplete roll-up as the unit cost. This is the dealership’s own money and is deliberately unavailable to the conversational agent. There is no whole-lot version and no date window — ask per unit. Mirrors GET /vehicle-cost-rollup/{vehicleId}.

vehicle_timeline_get

One unit's timeline — money and state, one feed

The merged "Línea de tiempo" for ONE vehicle: every lifecycle event (created, updated, published, unpublished, closed ads, deleted — with the actor who did it, the AI agent distinguishable from a person) interleaved with every money event (the compra, the cost ledger, the venta), ordered newest first. Money rows carry a SIGNED whole-CLP amount (negative = cash left the dealership; positive = cash came in) and, for cost lines, the borne_by split — a cliente-borne line is shown but excluded from totals.gastos_clp. The totals block states ingresos_clp / gastos_clp / utilidad_total_clp plus the applied IVA régimen (S0-10) — gastos_clp is the same dealership_cost_clp vehicle_cost_rollup_get reports, never recomputed here. filter narrows the rows to income or costs only; all (the default) shows everything, including lifecycle rows.

Esta página se genera desde mcp-connector-catalogue.json, que a su vez se construye levantando el catálogo real. No se edita a mano.

En esta página

Base — en todos los workspacesads_funnel_getads_monthly_return_getads_overview_getads_performance_listagent_knowledge_listagent_skills_listai_agents_change_request_getai_agents_change_requests_listai_agents_getai_agents_listai_agents_metrics_getai_agents_publish_gate_getai_agents_scenario_run_getai_agents_scenario_runs_listai_agents_scenario_suites_listai_agents_scenarios_listappointment_types_listappointments_getappointments_listcall_operationcoach_finding_getcoach_findings_listcoach_proposals_listcoach_reviews_listcontacts_getcontacts_searchcontacts_statsconversations_linked_recordsconversations_listdescribe_operationentitlements_listfollowups_listfollowups_overviewhelp_center_articles_listhelp_centers_listinsights_agents_getinsights_ai_agents_getinsights_bots_getinsights_calls_getinsights_channels_getinsights_conversations_getinsights_csat_getinsights_leads_getinsights_overview_heatmap_getinsights_overview_live_getinsights_sla_getinsights_sources_getinsights_storefront_getinsights_tags_getinsights_teams_getkb_files_get_textkb_files_listlead_conversations_listlead_interests_listleads_kanbanlocations_listpipelines_listproducts_searchsearch_operationsskills_getskills_liststages_listteams_listtickets_by_stagetickets_list_conversationsversions_listAutomotoradealer_alerts_listinsights_inventory_ageing_getinsights_inventory_rotation_getprice_approvals_getprice_approvals_listvehicle_interestvehicles_kanbanvehicles_searchvehicles_statsClínicaclinic_agenda_listclinic_agenda_profesionalesclinic_professional_getclinic_professionals_listclinic_services_listclinic_statuses_listCostos, márgenes y comisionescapital_inmovilizado_reportmargin_deal_getmargin_period_reportmargin_unit_getvehicle_cost_rollup_getvehicle_timeline_get