Ir al contenido
Developers

Authentication

How to request a token, how long it lasts, which role your user needs, and how to survive expiry without a refresh

Updated on 2026-08-16For: Beginners · Developers

This page is about the Transactions API v1, which authenticates with BistroWeb credentials. It covers how to get the token, how to send it, and how to live with a two-day lifetime and no refresh endpoint.

Información:

The Catalog API and Transactions API v2 do not use this scheme: they authenticate with an API key and secret against the Authorization API, and their token carries no shops. Everything below is about v1.

The flow

BistroWeb username + password
        │
        ▼
POST /api/v1.0/Token
        │
        ▼
JWT valid for 48 hours
        │
        ▼
Authorization: Bearer <token>   on every request

Requesting the token

curl -X POST "https://$BISTRO_HOST/api/v1.0/Token" \
  -H "Content-Type: application/json" \
  -d '{"username": "integrations@company.com", "password": "..."}'
{
  "token": "eyJ...",
  "expiration": "2026-08-18T13:04:22Z"
}

expiration is UTC. Store it next to the token so you can renew before the integration breaks rather than after.

Sending the token

GET /api/v1.0/sales?ShopCode=1001&From=2026-08-01T00:00:00&To=2026-08-02T00:00:00
Authorization: Bearer eyJ...
Atención: The Bearer prefix is mandatory

The OpenAPI document declares the scheme as an API key in the Authorization header rather than as HTTP Bearer authentication. In practice some generated clients emit the header without the prefix and the server answers 401 without explaining why. The header value must be exactly Bearer, a space, and the token.

The ApiUser role

Credentials are shared with BistroWeb, permissions are not. A user who signs into BistroWeb perfectly well can still get 403 because they lack the ApiUser role. A BistroWeb administrator assigns it.

Información: Use a dedicated user

Create a user for the integration instead of reusing a person's account. When that person leaves the company and their account is disabled, the integration does not go down with them.

Which shops your token can see

The v1 JWT carries shop_code claims. Two consequences:

  • Requesting a shop outside your claims returns empty, never someone else's data.
  • Granting a new shop in BistroWeb does not update tokens already issued. You need a fresh token for the new shop to appear.

The Authorization API access token works the other way around: it carries no shops, only the client_id and the scopes, and every API resolves which shops the credential may operate on each request. There, granting a shop takes effect without issuing a new token.

Expiry without refresh

import time
import requests

_token = None
_expires_at = 0.0

def get_token(host: str, username: str, password: str) -> str:
    global _token, _expires_at
    # Renew 5 minutes early so a long batch never expires mid-run.
    if _token and time.time() < _expires_at - 300:
        return _token

    response = requests.post(
        f"https://{host}/api/v1.0/Token",
        json={"username": username, "password": password},
        timeout=30,
    )
    response.raise_for_status()
    _token = response.json()["token"]
    _expires_at = time.time() + 2 * 24 * 60 * 60
    return _token

Three rules follow:

  1. Do not request a token per call. It is the most expensive endpoint.
  2. Do not cache it forever. After 48 hours the nightly job fails silently.
  3. Retry a 401 once with a fresh token. If the second attempt fails too, the problem is credentials or roles, and retrying again only locks the account.

Where not to put the token

  • Not in the URL as a query parameter: it ends up in every proxy log.
  • Not in a web or mobile app bundle: it reads sales for every shop of the user.
  • Not shared across customers: each company integrates with its own user.