Open the panel

Errors PRO ​

When something goes wrong, the status code says what kind of problem it is, and the body explains it:

json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Product not found.",
    "request_id": "req_ftth2xt814314w"
  }
}
FieldWhat it's for
codeStable and made for code. It never changes, so write your if against this.
messageFor people, in English. It can get better over time, so don't compare it.
retry_afterOnly on 429: how many seconds to wait.
request_idSend it to support if something looks wrong.

All the codes ​

StatuscodeWhat happenedWhat to do
400BAD_REQUESTSomething in the request is wrong. The message says what.Fix the request. Trying again won't help.
401UNAUTHORIZEDNo key, a wrong key, or a revoked key.Check the Authorization header.
403MISSING_SCOPEThe key isn't allowed to do this.Add the scope in Store settings → API.
403PRO_REQUIREDThe store has no Pro, or it expired (for changes).Renew Pro. Reading keeps working when it expired.
403STORE_SUSPENDEDThe store is suspended: read-only.Contact support.
404NOT_FOUNDThat route or thing doesn't exist in this store.Check the id.
409CONFLICTIt clashes with the current state, like redelivering a refunded sale.Read the message. Trying again won't help.
409IDEMPOTENCY_MISMATCHThe same Idempotency-Key came with a different body.Use a new key for a new action.
429RATE_LIMITEDA limit was reached.Wait retry_after seconds. See Limits.
500INTERNALOur fault.Try again. If it keeps happening, send the request_id to support.

Examples ​

A wrong value names the field:

json
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "body.price: Too small: expected number to be >=0",
    "request_id": "req_vz899gn85hnvdb"
  }
}

So does a field the route doesn't know, which usually means a typo:

json
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "body: Unrecognized key: \"color\"; body: send at least one field",
    "request_id": "req_yvnwhzcph0spxs"
  }
}

Handling errors ​

Two questions cover almost everything: should I try again? and should a person look at this?

js
async function fasty(path, options = {}) {
  const res = await fetch(`https://api.fastyvendor.com/api/v1${path}`, {
    ...options,
    headers: { Authorization: `Bearer ${process.env.FASTY_KEY}`, ...options.headers },
  })
  const data = await res.json()
  if (res.ok) return data
  const { code, message, request_id } = data.error
  throw Object.assign(new Error(`${code}: ${message} (${request_id})`), { code, status: res.status })
}

try {
  const product = await fasty('/products/prd_nothing')
} catch (e) {
  if (e.code === 'NOT_FOUND') console.log('No such product')
  else throw e
}
python
import os, requests

class FastyError(Exception):
    def __init__(self, status, error):
        super().__init__(f"{error['code']}: {error['message']} ({error['request_id']})")
        self.status, self.code = status, error["code"]

def fasty(method, path, **kwargs):
    res = requests.request(
        method,
        f"https://api.fastyvendor.com/api/v1{path}",
        headers={"Authorization": f"Bearer {os.environ['FASTY_KEY']}"},
        **kwargs,
    )
    data = res.json()
    if res.ok:
        return data
    raise FastyError(res.status_code, data["error"])

try:
    product = fasty("GET", "/products/prd_nothing")
except FastyError as e:
    if e.code == "NOT_FOUND":
        print("No such product")
    else:
        raise
lsl
http_response(key id, integer status, list meta, string body)
{
    if (status == 200 || status == 201) return;     // all good: read the body here

    string code = llJsonGetValue(body, ["error", "code"]);
    if (code == "RATE_LIMITED")
        llSetTimerEvent((float)llJsonGetValue(body, ["error", "retry_after"]));
    else
        llOwnerSay("Fasty: " + llJsonGetValue(body, ["error", "message"]));
}

Timeouts are not errors

If the connection drops, you don't know if Fasty got your request. Retry with the same Idempotency-Key and nothing happens twice.