Quick Start Guide#
This guide is to help get you up and running with FolioClient quickly.
Making Your First Request#
Fetch some data from FOLIO using the context manager:
with FolioClient(gateway_url="...", tenant_id="...", username="...", password="...") as client:
# Get all users
users = client.folio_get("/users", "users")
print(f"Found {len(users)} users")
# Get first user details
if users:
first_user = users[0]
print(f"First user: {first_user['username']}")
Basic Setup#
First, import FolioClient and create a client instance. Note: Using context managers is recommended for automatic cleanup:
from folioclient import FolioClient
# Recommended: Use context manager for automatic cleanup
with FolioClient(
gateway_url="https://your-folio-instance.com",
tenant_id="your_tenant",
username="your_username",
password="your_password"
) as client:
# Your code here - client automatically closed when done
users = client.folio_get("/users", "users")
print(f"Found {len(users)} users")
# Alternative: Manual cleanup (not recommended)
client = FolioClient(
gateway_url="https://your-folio-instance.com",
tenant_id="your_tenant",
username="your_username",
password="your_password"
)
# Remember to call client.close() when done!
Filtering with Queries#
Use CQL queries to filter results:
with FolioClient(gateway_url="...", tenant_id="...", username="...", password="...") as client:
# Get active users only
active_users = client.folio_get(
"/users",
"users",
query="active==true"
)
# Get users by username pattern
admin_users = client.folio_get(
"/users",
"users",
query="username=admin*"
)
# Complex query with sorting
recent_users = client.folio_get(
"/users",
"users",
query="metadata.createdDate>2024-01-01 sortBy metadata.createdDate/sort.descending"
)
Note
Some APIs in FOLIO do not support CQL queries. For these endpoints, you will need to specify the query parameters used to perform a query/filter manually using the query_params keyword argument to folio_get() or passing them as extra keyword arguments to the folio_get_all() methods. For folio_get_all* methods, these APIs may also require specifying a keyword argument no_cql=True, to prevent default CQL queries from being used.
Working with Large Datasets#
For large datasets, use the pagination methods:
with FolioClient(gateway_url="...", tenant_id="...", username="...", password="...") as client:
# Process all users one by one
for user in client.folio_get_all("/users", "users"):
print(f"Processing: {user['username']}")
# Process with query filtering
for active_user in client.folio_get_all("/users", "users", query="active==true"):
print(f"Active user: {active_user['username']}")
Attention
The folio_get_all* methods do not currently support APIs that do not utilize a limit/offset argument pairing for paging, unless you are able to sort your query by ID, which will utilize the offset by ID approach to retrie the requested records. For more information about working with paged results, visit the pagination docs.
Creating and Updating Data#
Create new records:
# Create a new user group
new_group = {
"group": "students",
"desc": "Student user group"
}
result = client.folio_post("/groups", new_group)
print(f"Created group with ID: {result['id']}")
Update existing records:
import uuid
# Update a user group
group_id = result['id'] # Previously created group object
updated_group = {
"id": group_id,
"group": "graduate_students",
"desc": "Graduate student user group"
}
client.folio_put(f"/groups/{group_id}", updated_group)
Deleting Records#
# Delete a record
record_id = record['id'] # Previously created group object
client.folio_delete(f"/users/{record_id}")
Error Handling#
FolioClient includes automatic retry logic for common error conditions. Always handle potential errors:
import httpx
from folioclient.exceptions import FolioClientClosed
try:
users = client.folio_get("/users", "users")
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
print("Endpoint not found")
elif e.response.status_code == 401:
print("Authentication failed")
else:
print(f"HTTP error: {e.response.status_code}")
except FolioClientClosed:
print("Client has been closed")
Automatic Retry Behavior#
FolioClient automatically retries certain error conditions when configured:
import os
# Enable automatic retries for server errors
os.environ['FOLIOCLIENT_MAX_SERVER_ERROR_RETRIES'] = '3'
# Enable automatic retries for auth errors (with re-authentication)
os.environ['FOLIOCLIENT_MAX_AUTH_ERROR_RETRIES'] = '2'
# Client methods now automatically retry on transient errors
users = client.folio_get("/users", "users")
The retry system handles:
Server errors (502, 503, 504) with exponential backoff
Connection errors with automatic reconnection
Authorization (permission) errors (403) with automatic re-authentication
Note
401 errors (authentication) are handled by the httpx auth flow process that manages your FOLIO access token. If a 401 error is returned by FOLIO after your have previously authenticated, FolioClient will attempt to re-authenticate you and re-submit the original request. For more information, see the authentication docs.
For detailed retry configuration, see the Retry Configuration Guide.
Cleaning Up#
Always close the client when done:
# Synchronous cleanup
client.close()
# Async cleanup
await client.async_close
# Or use context manager (recommended)
with FolioClient(gateway_url="...", tenant_id="...", username="...", password="...") as client:
users = client.folio_get("/users", "users")
# Client automatically closed when exiting the block
# Async context manager
async with FolioClient(gateway_url="...", tenant_id="...", username="...", password="...") as client:
users = await client.folio_get_async("/users", "users")
...
Environment Variables#
For security, use environment variables for credentials:
import os
from folioclient import FolioClient
client = FolioClient(
gateway_url=os.getenv("FOLIO_URL"),
tenant_id=os.getenv("FOLIO_TENANT"),
username=os.getenv("FOLIO_USERNAME"),
password=os.getenv("FOLIO_PASSWORD")
)
Common Patterns#
Here are some common usage patterns:
Batch Processing#
with FolioClient(gateway_url="...", tenant_id="...", username="...", password="...") as client:
# Process all users one by one (recommended approach)
for user in client.folio_get_all("/users", "users"):
process_user(user)
# Process users with filtering
for active_user in client.folio_get_all("/users", "users", query="active==true"):
process_user(active_user)
# Process in larger chunks for better performance
for user in client.folio_get_all("/users", "users", limit=1000):
process_user(user)
Note
folio_get_all automatically handles pagination for you, so you don’t need to manually manage offsets and batching. However, you can experiment with limit values to tune the number of records retrieved per request. For more information, see the pagination docs.
Finding Specific Records#
# Find user by exact username
users = client.folio_get("/users", "users", query="username==johndoe")
if users:
user = users[0]
print(f"Found user: {user['id']}")
Sync vs Async Usage#
FolioClient supports both synchronous and asynchronous APIs. Here’s a side-by-side example:
Synchronous:
from folioclient import FolioClient
client = FolioClient(...)
users = client.folio_get("/users", "users")
print(f"Found {len(users)} users")
client.close()
Asynchronous:
import asyncio
from folioclient import FolioClient
async def main():
client = FolioClient(...)
users = await client.folio_get_async("/users", "users")
print(f"Found {len(users)} users")
await client.close()
asyncio.run(main())
See Async Usage for more advanced patterns.
Troubleshooting#
Common issues:
Authentication errors: Double-check your username, password, and tenant. Use environment variables for credentials when possible.
Endpoint not found: Make sure your FOLIO instance URL and endpoint paths are correct.
Connection errors: Check network connectivity and firewall settings.
Client closed: Always use context managers or remember to call
client.close()/await client.close().
See Authentication and Retry Configuration for more help.
Next Steps#
Learn about async_usage for high-performance applications
Understand authentication options and security
Explore pagination strategies for large datasets
Check the API Reference for all available methods