CoCart supports multiple authentication methods depending on the use case.
No authentication is needed for guest cart operations. The SDK automatically manages the cart session for you:
- First request — No cart key exists yet. The CoCart server creates a new guest session and returns a
Cart-Keyheader in the response. - SDK extracts it — The SDK reads the
Cart-Keyheader and stores it on the client instance automatically. - Subsequent requests — The stored cart key is sent as both a
Cart-Keyheader and acart_keyquery parameter, so the server knows which cart to use.
from cocart import CoCart
client = CoCart("https://your-store.com")
# Add item — cart key is extracted from the response automatically
client.cart().add_item(123, quantity=2)
print(client.get_cart_key()) # "guest_abc123..."
# Subsequent requests use the stored cart key
cart = client.cart().get() # Same cart as beforeBy default, the SDK stores the cart key in memory. For web applications, use a storage adapter to persist between requests:
from cocart import CoCart
from cocart.storage.file_storage import FileStorage
storage = FileStorage("/tmp/cocart-sessions")
client = CoCart("https://your-store.com", storage=storage)If you already have a cart key (e.g. stored in your own database), pass it directly:
client = CoCart("https://your-store.com", cart_key="existing_cart_key")For authenticated customers using WordPress username/password:
client = CoCart("https://your-store.com",
username="customer@email.com",
password="customer_password",
)
# Or set at runtime
client = CoCart("https://your-store.com")
client.set_auth("customer@email.com", "password")
# Check auth status
client.is_authenticated() # True
client.is_guest() # FalseIf the CoCart JWT Authentication plugin (v3.0+) is installed, login() acquires JWT tokens automatically. If the plugin is not installed, login() raises an AuthenticationException. For stores without JWT, use Basic Auth directly via set_auth().
client = CoCart("https://your-store.com")
# Login — acquires JWT tokens (requires CoCart JWT Authentication plugin)
response = client.login("customer@email.com", "password")
print(response.get("display_name")) # "john"
print(response.get("user_id")) # "123"
# Subsequent requests automatically use the acquired credentials
cart = client.cart().get()If the CoCart 2FA plugin is installed and the user
has 2FA enabled, login() raises TwoFactorRequiredException instead of
returning tokens. Catch it, prompt the user for a verification code, then
call verify_two_factor() to complete the login:
from cocart.exceptions import TwoFactorRequiredException
try:
response = client.login("customer@email.com", "password")
except TwoFactorRequiredException as e:
print(e.available_providers) # e.g. ["email", "totp"]
print(e.default_provider) # e.g. "email"
print(e.email_sent) # True if a code was emailed automatically
code = input("Enter your 2FA code: ")
response = client.verify_two_factor(
"customer@email.com", "password", code, provider=e.default_provider,
)
# Subsequent requests automatically use the acquired credentials
cart = client.cart().get()client.logout() # Calls server logout endpoint, then clears local JWT and refresh tokensclient.jwt().refresh()if client.jwt().validate():
print("Token is valid")
else:
print("Token is expired or invalid")Check if the token is expired locally without making an API call:
# Check if expired (with 30-second leeway by default)
if client.jwt().is_token_expired():
client.jwt().refresh()
# Custom leeway (e.g., refresh 5 minutes before expiry)
if client.jwt().is_token_expired(300):
client.jwt().refresh()
# Get the expiry timestamp
expiry = client.jwt().get_token_expiry()
if expiry is not None:
from datetime import datetime
print(f"Token expires at: {datetime.fromtimestamp(expiry)}")Expired tokens are automatically refreshed and retried. This is enabled by default when using client.login(). If you set a JWT token manually, you can enable it explicitly:
client.set_jwt_token("eyJ...")
client.set_refresh_token("refresh_hash_...")
client.jwt().set_auto_refresh(True)
# Expired tokens are refreshed and retried automatically
cart = client.cart().get()Pass a storage adapter to the JWT Manager for automatic persistence:
from cocart import CoCart
from cocart.jwt_manager import JwtManager
from cocart.storage.file_storage import FileStorage
storage = FileStorage("/tmp/cocart-tokens")
client = CoCart("https://your-store.com")
jwt = JwtManager(client, storage)
# Tokens are saved to storage after login/refresh
jwt.login("user@example.com", "password")
# On subsequent runs, restore tokens from storage
client2 = CoCart("https://your-store.com")
jwt2 = JwtManager(client2, storage)
jwt2.restore_tokens_from_storage()
# client2 now has the stored JWT token — no need to login againclient.jwt().has_tokens() # True if a JWT token is set
client.jwt().is_token_expired() # True if token is expired (local check)
client.jwt().get_token_expiry() # Unix timestamp of token expiry
client.jwt().is_auto_refresh_enabled() # Check auto-refresh status
client.jwt().set_auto_refresh(True) # Enable/disable at runtimeFor admin-only endpoints like Sessions API, use WooCommerce REST API credentials:
client = CoCart("https://your-store.com",
consumer_key="ck_xxxxx",
consumer_secret="cs_xxxxx",
)
sessions = client.sessions().all()When multiple auth credentials are configured, the SDK uses this priority:
- JWT Token (
jwt_token) — Bearer token - Basic Auth (
username/password) — Basic auth header - Consumer Keys (
consumer_key/consumer_secret) — Basic auth header
# Start with JWT
client = CoCart("https://your-store.com", jwt_token="eyJ...")
# Switch to Basic Auth (clears JWT)
client.set_auth("user", "pass")
# Switch to JWT (clears Basic Auth)
client.set_jwt_token("new.jwt.token")
# Clear everything
client.clear_session()If your WordPress site uses a custom REST URL prefix (via rest_url_prefix filter) or CoCart has been white-labelled with a different namespace:
# Custom REST prefix (site uses /api/ instead of /wp-json/)
client = CoCart("https://your-store.com", rest_prefix="api")
# Requests go to: https://your-store.com/api/cocart/v2/cart
# White-labelled namespace
client = CoCart("https://your-store.com", namespace="mystore")
# Requests go to: https://your-store.com/wp-json/mystore/v2/cart
# Both together
client = CoCart("https://your-store.com", rest_prefix="api", namespace="mystore")
# Requests go to: https://your-store.com/api/mystore/v2/cart
# Or set at runtime
client.set_rest_prefix("api").set_namespace("mystore")JWT endpoints also respect the namespace automatically:
# Refresh calls: {rest_prefix}/{namespace}/jwt/refresh-token
# Validate calls: {rest_prefix}/{namespace}/jwt/validate-tokenSome hosting providers or reverse proxies (Cloudflare, Nginx, Apache) strip or block the standard Authorization header. You can configure the SDK to use an alternative header name:
# Via constructor
client = CoCart("https://your-store.com",
username="customer@email.com",
password="password",
auth_header_name="X-Authorization",
)
# Or at runtime
client.set_auth_header_name("X-Authorization")The SDK will send credentials using the custom header instead:
X-Authorization: Basic dXNlcjpwYXNz
X-Authorization: Bearer eyJ...
Your WordPress server must be configured to read the custom header. For example, in .htaccess:
RewriteEngine On
RewriteCond %{HTTP:X-Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:X-Authorization}]Use the SDK's HttpAdapter Protocol for easy mocking in tests:
from cocart import CoCart
from tests.mock_http_adapter import MockHttpAdapter
mock = MockHttpAdapter()
mock.queue(200, body='{"items": [], "item_count": 0}')
client = CoCart("https://example.com")
client._http_adapter = mock
response = client.cart().get()
assert response.get_item_count() == 0