> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vellaro.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Core concepts

> Store, envelope, errors, pagination, i18n, and images.

## Base URL & store identification

```
https://<store-domain>/api/v1
```

When you call the API through the store domain, you receive **only** that store's data —
no identifier to send. From a client without a domain (mobile/server), use the
[publishable key](/en/authentication).

## Envelope

Every JSON response uses the same envelope:

```json theme={null}
{ "data": null, "meta": null, "error": null, "error_code": null }
```

## Errors

On errors, `data` is `null` and `error_code` carries a stable machine-readable code. The frontend
should **switch on `error_code`**, not display `error` (English, for debugging only).

```json theme={null}
{
  "data": null,
  "error": "Invalid credentials",
  "error_code": "auth.invalid_credentials"
}
```

HTTP statuses follow standard semantics (200, 201, 400, 401, 403, 404, 409, 422, 502).

## Pagination

Lists accept `page` and `page_size` and return `meta`:

```json theme={null}
{ "meta": { "page": 1, "page_size": 24, "total": 190, "total_pages": 8 } }
```

## Internationalization

Many content endpoints accept `?lang=it|en|sq` (or the `Accept-Language` header) and
return fields already resolved in the requested language, falling back to the store's
default language.

## Images

Image paths are relative (`/uploads/products/xyz.webp`): prepend the store's origin
→ `https://<domain>/uploads/...`. In production they are served via a CDN/signed
redirect, so use the URL exactly as returned.

## Multi-tenancy in brief

Each store is an isolated **tenant**. The publishable key and domain determine the
tenant for storefront calls; the staff token's `tenant_id` claim determines it for the
Admin API. There is no way, with one store's credentials, to see another store's data.
