VitrinaAPI

Find out why the AI went quiet

One endpoint answers fifteen possible reasons; two more only show in the inbox.

A customer wrote and nobody answered. Before suspecting the model, an endpoint exists built exactly for this question. It answers with a code that can be alerted on, and with a sentence that can be read.

Trap

Not every silence_reason means the AI is silent

Two of the fifteen reasons are not real silence. awaiting_human_reply describes a conversation handed to a person, on a channel configured to keep answering until that person replies. The exact text reads "The AI is NOT silent, it still answers the next inbound message". awaiting_payment depends on the workspace's mode: under strict wait it does stay quiet; under the default mode it keeps answering, with only the payment confirmation blocked. Filtering by "a reason exists, so it is silent" misclassifies both cases.

Before you start

  • conversations:read to check the status and the history.
  • messaging_accounts:read to inspect the channel behind the conversation.
  • The id or display_id (C-163) of the conversation in question.

1. Ask directly

curl https://api.vitrinadev.com/api/v1/conversations/01a0ce15-c122-7148-98b3-4dfefe93756e/ai-status \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": {
    "silence_reason": "handler_is_human",
    "explanation": "A teammate replied, so this conversation is handled by a human. The AI stays silent until it is explicitly returned to the AI."
  }
}

explanation always arrives in English; the inbox localises it when it shows it, this call does not. When the next inbound message will get a real reply, silence_reason comes back null:

curl https://api.vitrinadev.com/api/v1/conversations/01a0cbf4-d541-736b-915d-a5875e7caa46/ai-status \
  -H "Authorization: Bearer $VITRINA_KEY"
{ "data": { "silence_reason": null, "explanation": null } }

A clean null confirms that if there is a problem, it lives somewhere else: the model, the channel or the provider. The next steps narrow down which.

2. Read the exact reason when setup is missing

Some reasons name an incomplete setup, not a decision anyone made:

{
  "data": {
    "silence_reason": "webchat_account_missing",
    "explanation": "This web conversation has no messaging account, so the webchat AI opt-in cannot be read and the AI fails closed. This is a wiring bug."
  }
}

A webchat conversation with no messaging_account attached gets no AI reply. If you see this reason, contact support.

All fifteen values, at a glance:

silence_reasonWhat it means
handler_is_humanA person already replied; return-to-ai brings it back
awaiting_human_replyHanded off, but the channel keeps answering until a person writes. Not real silence
outside_ai_availabilityOutside the window configured for this channel
channel_ai_disabledThe channel is disabled
channel_account_missingThe conversation lost its readable messaging_account
kept_with_humanSomeone marked the conversation to stay with people
human_took_overA person took control by hand
ai_handed_offThe AI handed it off, and does not reclaim it in the same window
availability_covering_humanStill assigned to a person; the AI window covers pending replies meanwhile
webchat_ai_disabledThe widget has AI turned off, with an agent configured anyway
webchat_account_missingThe webchat is missing its messaging_account
no_agent_configuredNo agent at all: no stage agent, no channel agent, no workspace default
contact_bot_disabledSomeone turned the AI off for this contact, on every channel
big_account_contactThe Instagram account is over the workspace's follower threshold
awaiting_paymentDepends on the workspace's mode; see the box above

3. Cross-check the reason against the channel and the agent

ai-status explains the symptom; the channel and the agent explain the cause. When the reason points at the channel (channel_ai_disabled, no_agent_configured), the same data is published under messaging-accounts:

curl https://api.vitrinadev.com/api/v1/messaging-accounts/00000000-0000-4000-8000-000000005001 \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": {
    "name": "WhatsApp · Acme",
    "enabled": true,
    "assignee_ai_agent_id": null,
    "default_team_id": null
  }
}

enabled: false would explain channel_ai_disabled without guessing. assignee_ai_agent_id reading null is not an error: the conversation falls back to the workspace's is_default agent, confirmed at GET /ai-agents. With none marked is_default: true, the reason becomes no_agent_configured.

GET /messaging-accounts/{id}/health fills in delivery, not the decision to answer:

curl https://api.vitrinadev.com/api/v1/messaging-accounts/00000000-0000-4000-8000-000000005001/health \
  -H "Authorization: Bearer $VITRINA_KEY"
{ "data": { "channel": "whatsapp", "identity": { "display_name": "+56911112222" }, "webhook": null } }

A silence_reason: null paired with a health showing delivery trouble points at the provider, not at the AI's configuration.

4. Rebuild the timeline

Every handoff writes itself into the thread, with sender_type: "system" and a metadata.event_kind naming what happened (handoff, returned_to_ai, and so on). Reply, book and hand off when the AI goes off script shows the exact shape of those messages through GET /conversations/{id}/messages. For this recipe, it is enough to know they exist: before assuming nobody acted, check whether a person or the platform already did.

What the API does not answer

Three things read through the public API: the reason (ai-status), the channel (messaging-accounts) and the agent (ai-agents). A fourth does not. The availability window itself, its exact hours, is read-only from the app. outside_ai_availability confirms the window is the reason; which window that is, and when it opens again, gets checked in Settings → AI agents → Availability.

When it fails

A 404 on ai-status means the conversation id does not exist in this workspace. A 403 means the key lacks conversations:read. If silence_reason is null and the message still sits unanswered, the question changes: it is no longer whether the AI should have replied, but whether it replied and delivery failed afterward. In that case, check the channel's provider.

On this page