Trace Developers

Errors & limits

The error shape

Every failure is JSON with the same two keys. Validation failures add errors, keyed by field, in Laravel's standard shape.

{
  "message": "The given data was invalid.",
  "errors": {
    "local_capture_id": ["This field is required."]
  }
}

Status codes

Code Meaning
200 Success. On an upload, also means the capture was already stored โ€” check `duplicate`.
201 Created. On an upload, a genuinely new photo.
401 No token, an expired token, or a revoked one.
403 The token is valid but lacks the scope, or the user's role does not permit it.
404 No such resource โ€” including anything belonging to another team. Trace does not distinguish the two, because doing so confirms the row exists.
422 Validation failed, or a rule refused: a checklist item that requires a photo, for instance.
429 Rate limited. Retry after the seconds in `Retry-After`.
503 The install is in demo mode, which blocks writes.

404 rather than 403, across tenants

Asking for a project that belongs to another company returns a 404, not a 403. A 403 would confirm the id exists, which is a slow enumeration of somebody else's data. The tenant scope fails closed at the query layer, so this is the natural outcome rather than a special case anyone has to remember to write.

Rate limits

Bucket Limit Applies to
api240 / minEverything on /api/v1
uploads120 / minPhoto upload only
login20 / minSign-in, by IP
share90 / minPublic share and portfolio pages

Uploads have their own bucket deliberately. A phone that has been offline for two days draining a large queue must not be able to lock the office out of the API it is using at the same time.

Every limit is a config value the buyer owns โ€” this is their server. See config/trace.php.

Idempotency

Photo upload is idempotent on local_capture_id, generated on the device at the moment of capture and sent unchanged on every retry. A repeat returns 200 with duplicate: true and the existing photo. Both 200 and 201 are success; a client that treats only 201 as success will re-upload forever.