Authentication

The OpenBoxes API uses session-based authentication with JSESSIONID cookies. You authenticate once via the login endpoint, receive a session cookie, and include that cookie in all subsequent requests.

Login

Authenticate by sending a POST request to the login endpoint with your credentials and a location ID:

curl -X POST \
  https://acme.openboxes.cloud/openboxes/api/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "username": "admin@acme.com",
    "password": "your-password",
    "location": "ff808181648b61df01648b6f43210001"
  }'

Request Body

Field Type Required Description
username string Yes Your OpenBoxes username or email
password string Yes Your account password
location string Yes ID of the warehouse/location to log into

Successful Response

{
  "status": 200,
  "data": {
    "user": {
      "id": "ff808181648b61df01648b6f43210002",
      "username": "admin@acme.com",
      "firstName": "Admin",
      "lastName": "User"
    },
    "location": {
      "id": "ff808181648b61df01648b6f43210001",
      "name": "Main Warehouse"
    }
  }
}

The response sets a JSESSIONID cookie. When using curl, the -c cookies.txt flag saves it to a file for reuse.

Failed Response

{
  "errorCode": 401,
  "errorMessage": "Invalid username or password"
}

Include the session cookie in all subsequent API requests using the -b flag:

# List products using the saved session cookie
curl -b cookies.txt \
  https://acme.openboxes.cloud/openboxes/api/products

# Create a new product
curl -X POST \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  https://acme.openboxes.cloud/openboxes/api/products \
  -d '{"name": "Amoxicillin 250mg", "category": {"id": "cat-123"}}'

Session Timeout

Sessions expire after a period of inactivity (default: 30 minutes). When a session expires, the API may respond in one of two ways:

  1. HTTP 302 redirect to the login page (most common)
  2. HTTP 401 Unauthorized with an error message

Always handle both cases in your integration code:

# Check the HTTP status code
response=$(curl -s -o /dev/null -w "%{http_code}" \
  -b cookies.txt \
  https://acme.openboxes.cloud/openboxes/api/products)

if [ "$response" = "302" ] || [ "$response" = "401" ]; then
  echo "Session expired, re-authenticating..."
  # Re-authenticate and retry
fi

Logout

End a session explicitly by calling the logout endpoint:

curl -X POST \
  -b cookies.txt \
  https://acme.openboxes.cloud/openboxes/api/logout

After logout, the JSESSIONID cookie is invalidated and cannot be reused.

Best Practices

Re-use Sessions

Do not call the login endpoint before every request. Authenticate once, store the cookie, and re-authenticate only when the session expires.

# Bad: authenticating on every request
curl -X POST .../api/login -d '...' -c cookies.txt
curl -b cookies.txt .../api/products

# Good: authenticate once, reuse the session
# (re-authenticate only on 302/401)
curl -b cookies.txt .../api/products

Secure Credential Storage

Never hardcode credentials in source code. Use environment variables or a secrets manager:

export OB_USERNAME="admin@acme.com"
export OB_PASSWORD="$(vault read -field=password secret/openboxes)"

curl -X POST \
  https://acme.openboxes.cloud/openboxes/api/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d "{\"username\": \"$OB_USERNAME\", \"password\": \"$OB_PASSWORD\", \"location\": \"$OB_LOCATION\"}"

Handle Redirects

By default, curl follows redirects automatically. To detect session expiry, disable redirect following with -L omitted or use --max-redirs 0:

curl -s --max-redirs 0 \
  -b cookies.txt \
  -o /dev/null -w "%{http_code}" \
  https://acme.openboxes.cloud/openboxes/api/products
# Returns 302 if session expired, 200 if valid

Limitations

  • No API keys or tokens: Authentication is session-based only. OAuth2 and API key support are planned Lift platform features.
  • Email + aliases: Usernames containing + characters (e.g., user+tag@example.com) may fail during form-based login due to URL encoding. Use the JSON API login endpoint shown above to avoid this issue.
  • Single location per session: Each session is bound to one location. To work with a different location, log in again with the new location ID.