Control costs
Your plan includes a token allowance, and requests beyond it are paid from usage credits at per-token rates. This guide collects the practical ways to get more work out of the allowance, spend less once you are on credits, and make sure spending never surprises you. Each technique says what it saves and what it costs you in effort or quality.
Know where the tokens go
You cannot reduce what you do not measure. Every response reports its usage:
"usage": { "prompt_tokens": 8412, "completion_tokens": 356, "total_tokens": 8768, "cached_tokens": 7680 }With streaming, the same object arrives in the last chunk before [DONE]. Log it per request together with:
- the feature or endpoint in your product that made the request,
- the model,
- the
x-syntic-billing-sourceheader (subscriptionorapi_credit), - the
x-syntic-request-idheader.
A week of these logs usually shows that one or two features account for most tokens, and that prompts (not replies) are the bulk. That tells you where to start.
Techniques, roughly in order of payoff
| Technique | Typical saving | Effort |
|---|---|---|
| Order prompts for caching | Large on repeated prompts | Low |
| Trim conversation history | Large for long chats | Medium |
| Choose a lighter model where it is good enough | About a third per token | Medium (needs evaluation) |
Set max_tokens and ask for shorter output | Moderate | Low |
| Keep tool definitions and tool results small | Moderate in tool loops | Low |
| Don’t re-ask: store results | Varies | Low |
1. Order prompts for caching
Prompt tokens that repeat the beginning of a recent request are billed at the cached-input rate, which is about one-sixth to one-tenth of the normal input rate (for example $0.40 instead of $2.50 per million on Amara S1.2). Caching is automatic; you only need to arrange the prompt so it can match:
- System message first, and keep it identical between requests. Do not put the current time, a user’s name or a request ID in it.
- Tool definitions next, in a fixed order.
- Long reference material (documents, product catalogs) next.
- The conversation, appended to, never rewritten.
- The newest user message last.
Check it is working by watching the cached count in usage: on the second and later requests of a conversation it should cover most of the prompt.
2. Trim conversation history
Every request re-sends the whole conversation. In a long chat, old turns can make up most of the prompt while contributing little. Options, from simplest:
- Keep the last N turns plus the system message.
- Summarize older turns into one short message once the conversation passes a size you choose, then keep appending after the summary.
- Drop tool results once used. After the model has answered from a large tool result, replace that result with a one-line note in your stored history.
Trimming changes the prompt’s beginning only once, when you trim; after that, caching resumes from the new shape. Trim in larger steps (for example every 20 turns) rather than one message at a time, or each trim will defeat the cache.
3. Use a lighter model where it is good enough
Rates differ between models (see Pricing). Amara Quick costs $1.50 per million input tokens and $8.00 per million output tokens, against $2.50 and $12.00 for Amara S1.2. For labelling, routing, extraction and short replies it is often accurate enough. Measure on your own data before switching; Choosing a model has a method.
Mixing models in one feature (a light model for triage, a stronger one only when needed) often costs less than either model alone would.
4. Bound the output
Output tokens are the most expensive kind on every model. Two controls:
max_tokensis a hard ceiling. Set it to what the feature really needs. It also lowers the pre-request cost estimate used when paying from credits, so a small balance can still serve short requests (see Pricing).- Ask for brevity in the instructions: “Answer in at most three sentences”, “Return only the JSON object”. This shortens replies without cutting them off mid-sentence the way a low
max_tokenscan.
5. Keep tools lean
In a tool loop, tool definitions and every earlier tool result are sent on every round.
- Include only the tools a task can use. A feature that only reads orders does not need the refund tool.
- Write descriptions that are clear but short.
- Return only the fields the model needs from each tool; truncate long text results.
6. Store answers you will need again
If many users ask the same thing (a product description, a summary of a fixed document), generate the answer once and store it. The cheapest request is the one you do not send.
Keep spending predictable
Saving tokens is half the job; the other half is making sure costs cannot run away. These are set by an administrator in the Console (see Billing & credits):
| Control | What it does |
|---|---|
| Usage credits on or off | When off, requests stop with 402 once the plan allowance is used; nothing is charged per token. |
| Organization monthly spend limit | Caps credit spending per calendar month. New organizations start at $20. |
| Group and member spend limits | Cap individual members or groups, so one script cannot use the whole budget. |
| Auto-reload trigger and target | Keeps the balance from running dry, within the spend limit. |
And in your own code:
- Alert when
x-syntic-billing-sourcebecomesapi_credit. That means a plan window is full and you are now paying per token. - Cap loops. Tool loops and retry loops should have a maximum number of rounds.
- Budget batch jobs. Before running a job over thousands of items, run it on 50, multiply, and decide whether the total is acceptable.
A bug that sends requests in a tight loop can use a lot of tokens quickly. The 600-requests-per-minute rate limit slows it down but does not stop it. A member spend limit on the key owner of each automated system is a cheap safety net.
Automate spend controls
Every control in the table above will also be readable and settable with the Admin API, so finance and platform teams can manage budgets from scripts, infrastructure-as-code or their own dashboards:
| Task | Endpoint |
|---|---|
| Read or change the organization’s monthly spend limit, and per-workspace and per-member limits | GET/PUT /v1/organizations/spend_limits |
| See spend by day, workspace and line item | GET /v1/organizations/cost_report |
| See tokens by model, key and workspace | GET /v1/organizations/usage_report/messages |
| Be told when spend passes 50%, 80% and 100% of a limit | spend.threshold_reached webhook |
A nightly job that checks yesterday’s cost per workspace and lowers a runaway workspace’s limit:
curl -sS -G https://app.syntic.ai/v1/organizations/cost_report \
-H "Authorization: Bearer $SYNTIC_ADMIN_KEY" \
-H "syntic-beta: admin-2026-11-01" \
--data-urlencode "starting_at=$(date -u -d yesterday +%Y-%m-%dT00:00:00Z)" \
--data-urlencode "group_by[]=workspace_id"Estimate before you build
A quick estimate for a feature, using your expected traffic:
RATES = { # $ per 1M: input, cached input, output
"Amara S1.2": (2.50, 0.40, 12.00),
"Amara Quick": (1.50, 0.25, 8.00),
}
def monthly_credit_cost(model, requests_per_month, prompt_tokens, cached_share, output_tokens):
rin, rcache, rout = RATES[model]
cached = prompt_tokens * cached_share
fresh = prompt_tokens - cached
per_request = (fresh * rin + cached * rcache + output_tokens * rout) / 1_000_000
return per_request * requests_per_month
# A help widget: 40,000 requests a month, 3,000-token prompts (80% cached), 250-token replies.
print(round(monthly_credit_cost("Amara S1.2", 40_000, 3_000, 0.8, 250), 2)) # ~ 218.4
print(round(monthly_credit_cost("Amara Quick", 40_000, 3_000, 0.8, 250), 2)) # ~ 140.0This is the cost if every request were paid from credits. Requests inside your plan’s token allowance cost nothing extra, so compare total monthly tokens with your plan’s allowance on Pricing as well.
Related pages
- Pricing: rates, caching and worked examples.
- Usage & cost: what the Console shows about consumption.
- Handle usage limits: what to do when a limit is reached.
- Spend limits API and Cost report (preview).