POST /api/chat is the streaming endpoint used by Marco inside the Macro by
Mark app. It is session-aware, plan-aware, and source-aware.
Treat this as the product chat endpoint, not a stable external assistant API. It depends on signed-in session cookies, entitlement resolution, chat budget state, and the current product route.
Authentication and entitlement
The server resolves the caller's plan from the active session. The request body cannot set or upgrade the plan.
Signed-out callers are treated as visitor traffic. Signed-in callers use their server-resolved plan and user id for rate limiting and monthly budget checks.
Request body
messagesarraybodyrequiredUI messages from the chat client. The route keeps only the configured history window for the user's plan and caps text content before it reaches the model.
pathnamestringbodyCurrent app path, such as /indicators/headline-cpi or /dashboard. Marco uses
this for page help, guided tours, locale detection, and navigation context.
clientContextobjectbodyOptional page sidecar context from the client, such as visible chart title, series labels, units, date range, or dashboard route. This context helps Marco explain what is on screen. It is not proof of a latest value.
firstNamestringbodyOptional first name for the greeting. The server strips control characters, non-name characters, and long payloads before the value is used.
{
"messages": [
{
"id": "msg_1",
"role": "user",
"parts": [
{
"type": "text",
"text": "What does core PCE measure?"
}
]
}
],
"pathname": "/indicators/core-pce"
}
Response stream
The endpoint returns an AI SDK UI message stream. Assistant messages can include
Marco metadata under metadata.marco.
modestringThe request classification, such as LEARNING_MODE, INDICATOR_MODE,
DATA_VALUE_MODE, NEWS_CALENDAR_MODE, FORECASTING_WORKFLOW_MODE, or
DASHBOARD_WATCHLIST_MODE.
trustSignalstringgrounded, conceptual, or limited.
sourceRequirementstringThe source class required for the question, such as
OBSERVATION_DATA_REQUIRED, NEWS_OR_CALENDAR_REQUIRED, or
USER_PRIVATE_CONTEXT_REQUIRED.
sourcesarrayStructured source cards when the server has source context for the answer. Cards can represent product facts, indicator metadata, observations, forecast runs, news items, release events, dashboards, watchlists, saved workspace objects, model references, or page context.
unavailableSourcesarrayMissing source notes with a reason such as not_wired, no_match,
permission_denied, stale_source, or ambiguous.
monthlyBudgetobjectCurrent monthly chat budget state for the caller's plan, including whether more messages are available in the current period.
Source rules
Marco should not state current values, historical values, release dates, news items, forecast results, dashboards, watchlists, or saved workspace facts unless the server supplied a source card for that claim.
For example, a latest CPI answer needs an indicator_observation card. An
indicator metadata card can explain what CPI is, but it cannot prove the latest
CPI value.
Budget and rate-limit headers
The route keeps per-minute rate limits and monthly chat budgets. Budget headers are included when available.
x-marco-budget-state: ok
x-marco-budget-used-percent: 34
x-marco-budget-reset: 2026-06-01T00:00:00.000Z
Error responses
| Status | Error | Meaning |
|---|---|---|
| 400 | invalid_json | Request body was not valid JSON. |
| 400 | missing_messages | Request body did not include messages. |
| 400 | empty_messages | No usable user or assistant text remained after normalization. |
| 402 | monthly_budget_exceeded | The caller's monthly Marco budget is exhausted. |
| 429 | rate_limited | The caller exceeded the per-minute chat limit. |
| 500 | chat_failed | The route failed after validation. |
Privacy notes
The route does not accept user ids, plan names, backend tokens, or API keys from the browser payload. Private saved-object context is loaded only for signed-in users, only when the request needs that private context, and only through server-side authorization.
Marco may receive limited preference context such as locale, timezone, country, experience level, and focus areas. That context is used for language, formatting, explanation depth, and examples. It is not a source for data claims.