Together AI API 400 Bad Request

Together AI is a marketplace, which means the model id is a namespaced path matched exactly — and a string that looks right is the single most common 400 on the platform.

11 min read
Staff Pick

📡 Monitor your APIs — know when they go down before your users do

Better Stack checks uptime every 30 seconds with instant Slack, email & SMS alerts. Free tier available.

Start Free →

Affiliate link — we may earn a commission at no extra cost to you

Live Together AI status right now

Check this first only to close it off. A 400 is never an outage — a service that is down cannot read your payload well enough to object to it — but ruling the platform out in thirty seconds is cheaper than arguing about it for an hour.

A 400 is the only refusal that is genuinely about what you sent. The connection succeeded, TLS completed, the credential was accepted, your quota was never in question — and then Together AI read the body and could not use it. No tokens were generated. Nothing was billed. Nothing half-happened, which is the one mercy this error offers compared with a 500.

That makes it the most tractable error in the catalogue and the one most often debugged in the wrong place. Teams open the status page, check the billing dashboard and re-read the retry policy, when the entire fault surface is a few hundred bytes of JSON that are sitting in a variable one stack frame away. The response body names the offending field. Almost nobody reads it, because the SDK threw an exception before anyone got the chance.

30-second triage: serialise the exact body your client was about to send, write it to a file, and replay it with curl. The raw response will name the field Together AI objected to. If curl reproduces the 400, the bug is in how you built the request and no amount of retrying, failing over or checking live Together AI status will change it. If curl succeeds with the same bytes, your client is not sending what you think it is sending — look at middleware, a proxy, or a serialiser that drops or adds fields.

400, 401, 404, 422 and 429 are five different problems

These get collapsed into “the API rejected us” and handled by one branch, which is how a malformed body ends up in a retry loop and a validation bug ends up being escalated as an incident. The distinction is how far the request got before it stopped.

 400 Bad Request401 Unauthorized404 Not Found422 Unprocessable429 Too Many Requests
What was refusedThe shape of what you sentWho you areThe thing you namedThe values you sentHow much you asked for
Was the body parsed?Attempted, then rejectedNever looked atRouted before parsingParsed successfullyUsually not reached
Does retrying help?Never — deterministicNeverNeverNeverYes, after a backoff
Who fixes itWhoever builds the requestSecret-store ownerWhoever pins model idsWhoever owns the input dataWhoever controls pacing
Counts as Together AI downtime?NeverNeverNeverNeverNever

The row that costs the most time is the third. A client that applies one retry policy to every non-2xx response will hammer a deterministic refusal until its deadline expires, converting an error you could have shown in milliseconds into a request that hangs for the full retry budget and then times out — and a timeout is the one symptom that genuinely does look like an outage. That is how a malformed body gets escalated to an on-call engineer. The full map is in the Together AI API error codes reference.

📡
Recommended

Separate Your Bad Requests From Their Bad Days

External checks run from outside your infrastructure with their own known-good payload, so a 400 in your application is never debugged as a possible provider incident — you can see the provider answering a valid request perfectly well at the same moment.

Try Better Stack Free →

Read the response body, not the SDK exception

A 400 is the error where the provider actually tells you the answer, and the SDK is the thing most likely to throw it away. Most clients collapse a validation failure into a generic exception with a message that has been through two layers of wrapping: the status code survives, and the JSON body naming the offending field frequently does not. Replay the call at the wire level before forming a theory:

# Write the exact body your client builds to a file, then replay it verbatim:
curl -i -s -X POST https://api.together.xyz/v1/chat/completions \
  -H "Authorization: Bearer $TOGETHER_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @body.json

# Prove the bytes are valid JSON before blaming the schema:
python3 -m json.tool < body.json > /dev/null && echo "parses"

Those two commands split the category in half. If the file does not parse, you have a serialisation bug and the schema is irrelevant. If it parses and Together AI still objects, the response body names the field, and you are done. The structural fix is to log the outgoing body — redacted, and only on a 400 — so the next occurrence is diagnosed from a log line instead of a reproduction. See the Together AI API testing guide for wiring that into a contract test rather than discovering it in production.

The Together AI trap: the model id is a path, and the string is the request

Together AI is a marketplace rather than a first-party model provider, and the model field reflects that: it is a full namespaced path such as meta-llama/Llama-3.3-70B-Instruct-Turbo, matched exactly. A bare llama-3.3-70b is a 400. So is the correct model with the wrong casing, a missing organisation prefix, or a dropped -Turbo suffix — a variant that exists, is spelled almost identically, and is a different listing. There is no fuzzy resolution, and there should not be, because two neighbouring strings are genuinely two different products with different prices.

The second shape is a bound rather than a name. max_tokens is validated against the specific model's context window at request time, so a body that is entirely valid on a 128k-context model is rejected on an 8k one. That matters more than it sounds, because the shorter, cheaper model is usually the one sitting in your fallback branch — which means the rejection first appears while you are already failing over, at the exact moment a second error is least welcome. The fallback path is the least-tested code you own and the most likely to carry a max_tokens copied from the primary.

Both are solved by the same discipline. Pin every model id in one constant module rather than scattering literals through call sites, store the context window alongside each id, and add a CI check that resolves every pinned id against the models endpoint. That turns a marketplace listing change — a deprecation, a rename, a new suffix — into a red build on a Tuesday instead of a 400 during an incident.

The six causes, in the order worth checking

Work down this list rather than across it. Each check is cheap, and the ordering reflects which answers turn out to be correct most often rather than which are most interesting.

  • The model id is not an exact match. Missing organisation prefix, wrong casing, or a dropped -Turbo suffix. The marketplace does not resolve near-misses.
  • The JSON never parsed. A trailing comma, a NaN, or an unescaped control character that arrived inside user-supplied text. The body looks fine in a log because the log printed the object, not the bytes.
  • A field has the right name and the wrong type. max_tokens as a string, temperature as a string, a boolean as "true". Anything that has been through a form, a query string or an environment variable is a suspect.
  • A content bound was exceeded. max_tokens above the model’s window, too many messages, an attachment over the size cap. These are input-dependent, so they fire for one request in a thousand and look intermittent.
  • A tool or function schema is not valid JSON Schema. Hand-written parameter definitions with a missing type or a malformed required array are rejected as part of the request, not at call time.
  • A null was sent where the field should have been omitted. Serialisers that emit every key make optional parameters explicit nulls, and an explicit null is a value the validator has to reject.

Notice the split running through that list. The first two are deploy-shaped: they appear at a release, affect a clean fraction of traffic, and are identical every time. The last three are input-shaped: they fire on one request in a thousand, look intermittent, and are usually triggered by something a user typed. Which of those two patterns your error rate shows is worth more than any individual hypothesis, and it is visible before you have read a single response body. If tool schemas are involved, the Together AI tool calling guide and the structured output guide cover the shapes that are accepted.

Make the next one impossible instead of fast

A 400 is a ten-minute fix that recurs forever unless the conditions that produced it change. Four structural changes remove most of the category permanently:

  • Validate the body against a schema before it leaves your process. A local validator rejects the same request in microseconds, with a stack trace pointing at the line that built it, instead of a round trip and a field name. This is the single highest-leverage change and almost nobody makes it.
  • Build requests in one place, per provider. Most deploy-shaped 400s come from a request-builder shared across providers whose parameter sets have quietly diverged. One builder per provider makes the divergence a compile-time fact rather than a runtime discovery.
  • Log the outgoing body on a 400 only, redacted. The information needed to fix this error exists at the moment it happens and is discarded microseconds later. Capturing it turns every future occurrence from a reproduction exercise into a log lookup.
  • Alert on 4xx separately from 5xx. A 400 rolled into a general error-rate alert either pages the wrong person or hides in noise. It has a different owner, a different runbook and a different urgency — and unlike a 5xx, it will not resolve itself. The setup is in the Together AI status alerts guide.
  • Pin the SDK, and read the changelog on majors. Parameter sets and request shapes change between major versions, and a 400 arriving the day after a dependency bump is not a coincidence. The Together AI SDK version guide covers what moves.

Frequently Asked Questions

What does a 400 from the Together AI API actually mean?

It means the request reached Together AI, was parsed, and was found unusable on its contents. That is a narrower statement than it sounds, and the narrowness is the useful part: a 400 is decided after the credential was accepted and before any model work began, so it says nothing about your key, nothing about your quota, and nothing about capacity. Everything you would normally check when a call fails — the status page, the billing dashboard, your rate limiter — is on the wrong side of the point at which this one stopped. The entire fault surface is the bytes you sent.

Is a Together AI 400 ever caused by Together AI being down?

No, and the reasoning is worth keeping because it inverts the usual instinct. A 400 is a considered answer: something on the far end read your payload, understood it well enough to judge it, and refused. A service that is down cannot do that. So a 400 should never be counted against Together AI availability in your own metrics, and a monitor that treats every non-2xx response as downtime will page you for your own malformed request. The one edge case is a proxy, gateway or WAF in front of the API returning its own 400 — a header too large, a URL too long — which you can distinguish immediately because the body will not be Together AI's JSON error shape.

Should I retry a 400?

Not with the same body, ever. A 400 is deterministic: the identical request will be refused identically every time, so a backoff loop converts one instant refusal into dozens of them plus the full retry budget in latency, and delivers a timeout to your user instead of an error you could have shown them in milliseconds. If your client applies one policy to all non-2xx responses, this is the error that proves 4xx and 5xx need splitting. Fail fast, log the response body — which names the offending field — and surface it to an engineer rather than to a customer. A 400 is only retryable after the body has actually changed.

How do I tell a Together AI 400 from a 422?

By asking how far the request got before it was rejected. A 400 means the request could not be understood as a valid request at all: unparseable JSON, an unknown parameter, a field of the wrong type, a model id that is not a model id. A 422 means the request was understood perfectly and the values in it are not acceptable — well-formed, correctly typed, semantically wrong. The distinction matters because it tells you where to look. A 400 is usually a code or configuration bug you find by diffing your body against the schema; a 422 is usually a data bug you find by looking at the specific values that arrived. Providers are not always rigorous about which they return, so treat the response body as authoritative over the code.

Why does Together AI 400 on a model name that clearly exists?

Because the model field is a namespaced path matched exactly, and 'clearly exists' usually means a neighbouring listing exists. meta-llama/Llama-3.3-70B-Instruct-Turbo and a bare llama-3.3-70b are not the same string, and neither are two spellings that differ only in casing or in a -Turbo suffix. A marketplace cannot safely guess which listing you meant, because the near-miss is a real product with a different price and different throughput. Resolve ids from the models endpoint rather than from documentation or memory, pin them in one module, and check them in CI so a rename lands as a failing build.

Why did my Together AI fallback path start returning 400s during an outage?

Almost certainly because max_tokens is validated against the specific model's context window, and your fallback model has a smaller one than your primary. The value was copied from the primary path, it is legal there, and the fallback branch has probably never been exercised under load since it was written — so the first real failover is also the first execution of that combination. Store the context window next to each pinned model id and clamp max_tokens to it at request time rather than trusting a constant, and exercise the fallback path on a schedule so it is not being run for the first time during an incident.

Related Together AI Guides

Stop Escalating Your Own Payload as a Together AI Outage

API Status Check watches Together AI and the rest of your stack from outside your infrastructure with its own known-good request — so a malformed body never gets escalated as an incident, and a real incident never gets dismissed as somebody’s bad JSON.

Start Your Free Trial →

Alert Pro

14-day free trial

Stop checking — get alerted instantly

Alert Pro checks the 60+ APIs we monitor every hour and emails you within the hour of a detected change.

  • Email alerts for up to 10 of the APIs we monitor
  • $0 charged today — card required to start
  • Cancel anytime — $9/mo after trial

🌐 Can't Access Together AI?

If Together AI is working for others but not for you, it might be an ISP or regional issue. A VPN can help bypass network-level blocks and routing problems.

🔒

Troubleshoot with a VPN

Connect from a different region to test if the issue is local to your network. Also protects your connection on public Wi-Fi.

Try NordVPN — 30-Day Money-Back Guarantee
🔑

Secure Your Together AI Account

Service outages are a common time for phishing attacks. Use a password manager to keep unique, strong passwords for every account.

Try NordPass — Free Password Manager
Quick ISP test: Try accessing Together AI on mobile data (Wi-Fi off). If it works, the issue is with your ISP or local network.

⏳ While You Wait — Try These Alternatives

🛠 Tools We Use & Recommend

Tested across our own infrastructure monitoring 200+ APIs daily

SEMrushBest for SEO

SEO & Site Performance Monitoring

Used by 10M+ marketers

Track your site health, uptime, search rankings, and competitor movements from one dashboard.

We use SEMrush to track how our API status pages rank and catch site health issues early.

From $129.95/moTry SEMrush Free
View full comparison & more tools →Affiliate links — we earn a commission at no extra cost to you