Examples¶
This page provides links to complete code examples demonstrating common use cases.
Available Examples¶
All examples are located in the examples/ directory.
Basic Usage¶
File: examples/basic_usage.py
Demonstrates fundamental SDK operations:
- Client initialization with JWT authentication
- Listing folders and resources
- Creating and updating folders
- Proper client cleanup
from foxnose_sdk.management import ManagementClient
from foxnose_sdk.auth import JWTAuth
client = ManagementClient(
base_url="https://api.foxnose.net",
environment_key="your-environment-key",
auth=JWTAuth.from_static_token("YOUR_ACCESS_TOKEN"),
)
# List all folders
folders = client.list_folders()
for folder in folders.results:
print(f"{folder.name} ({folder.key})")
client.close()
Async Client¶
File: examples/async_client.py
Shows how to use the async client for concurrent operations:
- AsyncManagementClient setup
- Concurrent API calls with
asyncio.gather() - Proper async context management
import asyncio
from foxnose_sdk.management import AsyncManagementClient
async def main():
client = AsyncManagementClient(...)
# Fetch multiple resources concurrently
results = await asyncio.gather(
client.get_folder("folder-1"),
client.get_folder("folder-2"),
client.list_resources("folder-3"),
)
await client.close()
asyncio.run(main())
Using Model Objects as Identifiers¶
Instead of extracting .key from every returned object, pass objects directly into subsequent calls:
# Get a folder object and use it directly
folder = client.get_folder("blog-posts")
# Pass the folder object — no need for folder.key
resources = client.list_resources(folder)
# Chain objects through a full workflow
resource = client.create_resource(folder, {"data": {"title": "New Article"}})
revision = client.create_revision(folder, resource, {
"data": {"title": "Draft Content", "body": "..."},
})
client.publish_revision(folder, resource, revision)
# Works with all entity types
org = client.get_organization("org-key")
projects = client.list_projects(org)
project = projects.results[0]
envs = client.list_environments(org, project)
Resources and Revisions¶
File: examples/resources_and_revisions.py
Complete resource lifecycle management:
- Creating resources
- Managing revisions
- Publishing content
- Updating and deleting resources
# Create a resource
resource = client.create_resource("blog-posts", {
"data": {"title": "My First Post", "content": "Hello, world!"},
})
# Create a new revision
revision = client.create_revision(
"blog-posts",
resource.key,
{"data": {"title": "Updated Title", "content": "Updated content"}},
)
# Publish the revision
client.publish_revision("blog-posts", resource.key, revision.key)
Upsert (Create or Update by External ID)¶
Use upsert_resource to sync content from an external system. The SDK creates the resource on the first call and updates it on subsequent calls, matched by external_id.
articles = [
{"id": "ext-1", "title": "First Article", "body": "..."},
{"id": "ext-2", "title": "Second Article", "body": "..."},
]
for article in articles:
resource = client.upsert_resource(
"blog-posts",
{"title": article["title"], "body": article["body"]},
external_id=article["id"],
)
print(f"{resource.key} (external_id={resource.external_id})")
You can also set an external_id when creating resources via create_resource:
resource = client.create_resource(
"blog-posts",
{"title": "Imported Post"},
external_id="legacy-post-99",
)
Batch Upsert¶
Use batch_upsert_resources to upsert many resources in parallel. This is much faster than calling upsert_resource in a loop:
from foxnose_sdk import ManagementClient, BatchUpsertItem
items = [
BatchUpsertItem(
external_id=f"article-{i}",
payload={"title": f"Article {i}", "body": "..."},
)
for i in range(1000)
]
result = client.batch_upsert_resources(
"blog-posts",
items,
max_concurrency=10,
on_progress=lambda done, total: print(f"\r{done}/{total}", end=""),
)
print(f"\nSucceeded: {result.success_count}, Failed: {result.failure_count}")
for error in result.failed:
print(f" Item {error.index} ({error.external_id}): {error.exception}")
Folder Schema¶
File: examples/folder_schema.py
Schema and field management:
- Creating schema versions
- Adding and configuring fields
- Publishing schema versions
- Field type options
# Create a new schema version
version = client.create_folder_version("blog-posts", {"name": "v2.0"})
# Add fields
client.create_folder_field("blog-posts", version.key, {
"key": "author",
"name": "Author",
"type": "text",
"required": True,
})
# Publish the version
client.publish_folder_version("blog-posts", version.key)
Roles and Permissions¶
File: examples/roles_and_permissions.py
Access control configuration:
- Creating management roles
- Creating Flux roles
- Setting permissions
- Generating API keys
# Create a role
role = client.create_management_role({
"name": "Content Editor",
"description": "Can edit content but not delete",
})
# Add permissions
client.upsert_management_role_permission(role.key, {
"content_type": "resources",
"actions": ["read", "create", "update"],
"all_objects": True,
})
# Create an API key with this role
api_key = client.create_management_api_key({
"description": "Editor Key",
"role": role.key,
})
Flux Client¶
File: examples/flux_client.py
Content delivery:
- FluxClient initialization
- Fetching published content
- Search capabilities
- Pagination and filtering
from foxnose_sdk.flux import FluxClient
from foxnose_sdk.auth import SimpleKeyAuth
client = FluxClient(
base_url="https://<env_key>.fxns.io",
api_prefix="v1",
auth=SimpleKeyAuth("YOUR_PUBLIC_KEY", "YOUR_SECRET_KEY"),
)
# Get published content
resource = client.get_resource("blog-posts", "my-article")
print(resource["data"]["title"])
# Search for content
results = client.search("blog-posts", body={"find_text": {"query": "python"}})
Vector Search¶
File: examples/vector_search.py
Vector search modes and configuration:
- Semantic search with auto-generated embeddings
- Custom embedding search
- Hybrid text + vector search
- Boosted search with vector similarity
from foxnose_sdk.flux import FluxClient
# Semantic search
results = client.vector_search("blog-posts", query="machine learning")
# Hybrid search
results = client.hybrid_search(
"blog-posts",
query="ML applications",
find_text={"query": "machine learning"},
vector_weight=0.7,
text_weight=0.3,
)
Running Examples¶
- Clone the repository:
- Install dependencies:
- Set environment variables:
export FOXNOSE_API_URL="https://api.foxnose.net"
export FOXNOSE_ENVIRONMENT_KEY="your-environment-key"
export FOXNOSE_ACCESS_TOKEN="your-access-token"
- Run an example:
Real-World Patterns¶
Environment-Based Configuration¶
import os
from foxnose_sdk.management import ManagementClient
from foxnose_sdk.auth import JWTAuth
def get_client():
return ManagementClient(
base_url=os.environ.get("FOXNOSE_API_URL", "https://api.foxnose.net"),
environment_key=os.environ["FOXNOSE_ENVIRONMENT_KEY"],
auth=JWTAuth.from_static_token(os.environ["FOXNOSE_ACCESS_TOKEN"]),
)
Context Manager Pattern¶
from contextlib import contextmanager
@contextmanager
def foxnose_client():
client = ManagementClient(...)
try:
yield client
finally:
client.close()
# Usage
with foxnose_client() as client:
folders = client.list_folders()
Pagination Helper¶
def iter_all_resources(client, folder_key, page_size=50):
"""Iterate through all resources with automatic pagination."""
offset = 0
while True:
page = client.list_resources(
folder_key,
params={"limit": page_size, "offset": offset},
)
yield from page.results
if len(page.results) < page_size:
break
offset += page_size
# Usage
for resource in iter_all_resources(client, "blog-posts"):
print(resource.title)