Support Assistant
Ask Ana, the Zernio support agent, why a post failed or what is wrong with a connected account, and get the answer by webhook. What it does, use cases, pricing and how to integrate it.
The Support Assistant lets your code ask Zernio support a question and get the answer back, without opening a chat. Send a question about a post, a connected account or a profile in your workspace: Ana, the Zernio support agent, looks into it and answers, usually within one to three minutes. When the problem is on Zernio's side, she hands it to the Zernio team and a teammate follows up by email.
What you can use it for
- Explain a failed post. When your backend receives
post.failed, ask why with thepostIdand show your user the answer instead of a raw platform error. - Diagnose a connected account. Ask why an account stopped publishing or needs reconnecting, with its
accountId. - Check a profile's setup. Ask about the accounts and settings under a
profileId. - Add a help button to your product. Forward your users' questions with the ids involved and show the answer in your own UI.
- Give your AI agent a support line. Let an agent or automation ask when it hits something it cannot explain.
First question
You need an API key with full access, a usage-based plan and a card on file (payment method). This asks why a post failed and waits for the answer. In production, receive the answer by webhook instead of polling.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: run } = await zernio.supportassistant.askSupportQuestion({
headers: { 'Idempotency-Key': 'why-failed-64f0a1b2c3d4e5f6a7b8c9d0' },
body: {
message: 'Why did my Instagram post fail to publish?',
context: { postId: '64f0a1b2c3d4e5f6a7b8c9d0' },
},
});
let { data: result } = await zernio.supportassistant.getSupportAnswer({ path: { runId: run.runId } });
while (result.status === 'queued' || result.status === 'running') {
await new Promise((resolve) => setTimeout(resolve, (result.pollAfterSeconds ?? 5) * 1000));
({ data: result } = await zernio.supportassistant.getSupportAnswer({ path: { runId: run.runId } }));
}
console.log(result.status, result.answer);The first call answers 202 right away with the ids to follow:
{ "runId": "64f0a1b2c3d4e5f6a7b8c9d1", "threadId": "64f0a1b2c3d4e5f6a7b8c9d2", "status": "queued", "pollAfterSeconds": 5 }A finished run carries the answer and what it cost:
{
"runId": "64f0a1b2c3d4e5f6a7b8c9d1",
"threadId": "64f0a1b2c3d4e5f6a7b8c9d2",
"status": "completed",
"stopReason": "answered",
"answer": "Instagram could not download the image: its URL answered 403 to Meta's servers. Host it on a public URL and retry the post.",
"usage": { "inputTokens": 12, "outputTokens": 3111, "cacheReadTokens": 82793, "cacheWriteTokens": 24625 },
"costUsd": 0.327766,
"maxCostUsd": 3,
"createdAt": "2026-10-08T13:20:12.477Z",
"startedAt": "2026-10-08T13:20:13.102Z",
"finishedAt": "2026-10-08T13:21:27.514Z",
"supportTicket": null
}Pricing
You pay per question, once it finishes. There is no subscription and no fee for reading answers. What a question costs depends on how much looking into it takes, and the exact amount charged is the run's costUsd: the question above cost $0.33.
| Question | You pay |
|---|---|
| A typical question | $0.10 to $0.50 |
| The most one question can cost | Its maxCostUsd: from $0.50 to $3, $3 by default |
Handed to the Zernio team (needs_human) | Charged like an answered question |
Failed or expired (failed) | $0 |
Reading answers (GET calls and webhooks) | $0 |
| Everything in one UTC month | At most $100 per account |
maxCostUsdcaps each question. Near the cap the run stops investigating and answers with what it found so far (stopReason: cost_cap), and it never charges more than the cap. If it has nothing to answer yet, it ends asfailedand costs nothing. Lower it for simple questions.- The monthly limit counts questions still running at their cap. A question is accepted only if its
maxCostUsdfits in what is left of the $100 for the month; otherwise it gets429 support_monthly_cap_exceeded. - Charges appear as "Support API" on your invoice, billed with the rest of your usage (how billing works).
Integrate it
An integration that never loses an answer and never pays twice for one question takes five steps.
1. Subscribe a webhook
Subscribe an endpoint to support.run.completed and support.run.failed with POST /v1/webhooks/settings (Support Assistant webhooks). Use an endpoint with no profileIds or accountIds filter: an answer can cover your whole team, so scoped endpoints never receive these events. Deduplicate deliveries on the event id.
2. Ask with an Idempotency-Key
Send one Idempotency-Key per question and reuse it when you retry. A retry with the same key and body returns the first response instead of starting, and billing, a second run. Point Ana at what the question is about with context (postId, accountId or profileId); each id must belong to your workspace.
3. Handle the answer by status
status | What happened | What to do |
|---|---|---|
completed | Ana answered. answer holds it. | Show it to your user. |
needs_human | Ana passed the question to the Zernio team. answer holds a short notice for your user. When supportTicket is set, a teammate follows up by email with the user whose API key asked; when it is null, the notice asks your user to email support@zernio.com. | Show the notice as is. Do not ask the same question again. |
failed | The run errored, timed out or expired before it had an answer (stopReason is error, deadline, max_iterations, cost_cap or expired). It is not billed. | Ask again with a new Idempotency-Key. |
4. Poll only as a fallback
If a delivery is missed, read the run with Get a support answer, waiting pollAfterSeconds between calls. It returns the same object the webhook carries.
5. Ask follow-ups in the same thread
Send the threadId back with the next question to continue the conversation with the same context. A thread answers one question at a time: asking while one is queued or running returns 409 support_run_in_progress. List a thread's support answers returns every run in a thread, oldest first. Runs are kept for 90 days.
Limits
| Limit | Value | When you reach it |
|---|---|---|
| Questions running at once | 3 per account | 429 support_active_runs_limit. Retry when one finishes. |
| Spend | $100 per account per UTC month | 429 support_monthly_cap_exceeded. Retry-After points at the start of next month. |
| Question length | 10,000 characters | 400 |
| Cost per question | maxCostUsd, $0.50 to $3 | The run answers with what it found so far and charges the cap at most. |
If it fails
| Status | Code | Meaning | Fix |
|---|---|---|---|
402 | payment_method_required | No card on file. | Add a card in Billing. |
402 | payment_required | The last payment failed. | Pay the open invoice or update the card. |
403 | insufficient_permissions | Not an unrestricted API key (restricted, profile-scoped and OAuth credentials are refused), or the user is read-only, restricted or profile-scoped. | Use an unrestricted key from a user with full team access. |
404 | support_thread_not_found, post_not_found, account_not_found, profile_not_found | The threadId or a context id is not in your workspace. | Check the id. |
409 | support_run_in_progress | The thread already has a question queued or running. | Wait for its answer, then ask. |
409 | billing_setup_incomplete | There is no billing customer to attach a card to. | Contact support. |
409 | idempotency_conflict | A request with the same Idempotency-Key is still being processed. | Retry the same request shortly. |
422 | usage_billing_required | The workspace is not on a usage-based plan. | Switch to usage-based billing. |
422 | idempotency_key_reused | The Idempotency-Key was already used with a different question. | Use a new key for a new question. |
429 | support_active_runs_limit, support_monthly_cap_exceeded | A limit was reached. | Wait for Retry-After. |
503 | temporarily_unavailable | The question could not be accepted in time. Nothing was started or charged. | Retry after Retry-After. |
Related
- Ask a support question: every request field and response.
- Get a support answer: read one run.
- List a thread's support answers: every run in a thread.
- Support Assistant webhooks: the
support.run.*payloads. - Pricing: every usage meter on your invoice.
Workflows
Create and activate a workflow with POST /v1/workflows so DMs, ref links, comments, story mentions and reactions on one account run a graph of messages, waits, conditions and handoffs.
Profiles
Create a profile, connect accounts into it (several of the same platform if you like), move accounts between profiles, and rename or delete it later.