Errors & Rate Limits
Every Miso endpoint reports failure the same way. This page is what to check when a call does not do what you expect.
Error shapes
Most errors carry a message:
{
"message": "invalid api key."
}
A failed upload adds errors, and puts one entry per bad record in data:
{
"errors": true,
"message": "None of the records were inserted because at least one of them contained schema errors. Please see the `data` field for details.",
"data": [
"data.1.published_at (not-a-date) is invalid. The attribute does not match any of the subschemas. (id: x)"
]
}
A malformed request body on a GenAI endpoint comes from the request validator, and names the field instead:
{
"detail": [
{
"loc": ["body", "__root__"],
"msg": "Either 'template' or 'instructions' or 'task_id' must be provided",
"type": "value_error"
}
]
}
Read detail when it is present, and message otherwise.
Status codes
| Code | Meaning | What to do |
|---|---|---|
200 |
Success. | On an upload, still read errors in the body. |
400 |
The request is malformed. | Read message. |
401 |
The key is missing or wrong. | Check the header name (X-API-KEY) and the key. |
403 |
A publishable key on a secret-key endpoint, or a blocked robot. | Use the secret key from your server. |
404 |
Unknown id. | A question_id from another app is also 404. So is a deleted product. |
422 |
Validation failed. | Read data or detail for the field. |
429 |
Over the rate limit. | Back off, then retry. |
500 |
A fault on Miso's side. | Retry, then contact Miso. |
The errors you will actually hit
403 on a product upload. You used the publishable key. It reaches
POST /v1/interactions and nothing else:
{
"message": "Publishable key is not allowed for this endpoint; use the secret key"
}
422 on a whole batch because of one record. Uploads are all-or-nothing.
Nothing is written. The data array names each problem by index, so
data.1.published_at is the second record in the batch you sent.
422 for a field Miso does not define. Any unknown top-level field is
rejected. Everything of your own belongs in custom_attributes. See
Product Schema.
404 from the status endpoint. The task id is unknown or it expired. Task
ids do not live forever. Read the status while the load runs, not the next day.
404 "engine is not found". Search and recommendation run on an engine
that Miso creates for your app. Answers and hybrid search do not. If those work
and /v1/search/* does not, ask Miso to create the engine.
404 "no such index" from /v1/users/*. The user index is created by your
first user upload. Before that, reading user ids or aggregations returns this.
404 "field is not found" from _aggregations. Miso aggregates fields it
holds in the schema, such as published_at. A field no record carries is not
there to aggregate, and not every custom attribute can be reached this way.
403 on interactions from a server. A publishable key is meant for a
browser, so Miso refuses it when the request looks automated:
{
"message": "Request is denied due to bot blocking. Please only access this API from a real browser or use Secret API Key instead."
}
Use the secret key from your back end, and keep the publishable key in the browser.
Rate limits
Miso limits requests per API key. Over the limit you get 429.
Three things to plan for:
- Bulk endpoints are stricter than the rest.
- Your limit depends on your plan and your region. Ask your Miso representative before you build a large backfill.
- Retry with an exponential backoff. Start at a few seconds and double it.
import time, requests
def post(url, headers, body, attempts=5):
delay = 2
for _ in range(attempts):
res = requests.post(url, headers=headers, json=body)
if res.status_code != 429:
return res
time.sleep(delay)
delay *= 2
return res
A steady upload of about 100 records per call runs inside the limit without a
backoff. A full load of 20,901 records in 210 calls hits no 429 at all.
When the call succeeds but nothing happens
An upload returns 200 when Miso accepts the batch, not when the records
are searchable. Poll the task, and expect it to take up to a minute. See
Integrating Your Data.
An answer that refuses is not an error either. finish_reason is success,
sources is empty, and the text explains that Miso found nothing. Check that
the catalog holds the article, and that the upload finished.
