Skip to content

Releases: FoxNoseTech/foxnose-python

v0.4.1 — Flux Permission Objects Reliability

05 Mar 15:01

Choose a tag to compare

Patch release focused on Flux role permission object stability and SDK/docs consistency.

Fixed

  • Normalized Flux role permission object responses across legacy list and paginated payload shapes.
  • Improved handling of empty/variant permission-object create responses.
  • Aligned Flux permission-object behavior with production Management API contract.

Quality

  • Added targeted tests for payload coercion helpers to close patch coverage gaps in client.py

Docs

  • Added documentation badge in README for faster docs discovery.

Version

  • Python SDK bumped to 0.4.1 and tagged as v0.4.1.

v0.4.0 — Flux Introspection & API Route Descriptions

25 Feb 13:11

Choose a tag to compare

What's New

get_router() — discover all available routes for a Flux API prefix at runtime via GET /{api_prefix}/_router.

router = client.get_router()
print(router["api"])
print(len(router["routes"]))

get_schema(folder_path) — fetch live schema metadata for a connected folder route via GET /{api_prefix}/{folder_path}/_schema.

schema = client.get_schema("articles")
print(schema["json_schema"])
print(schema["searchable_fields"])
print(schema["non_searchable_fields"])

Route descriptions for API folder connectionsadd_api_folder() and update_api_folder() now support per-route descriptions used by Flux introspection:

  • description_get_one
  • description_get_many
  • description_search
  • description_schema
connection = client.add_api_folder(
    api_key="blog-api",
    folder_key="articles",
    allowed_methods=["get_many", "get_one"],
    description_get_one="Get one article by key",
    description_get_many="List published articles",
    description_search="Search published articles",
    description_schema="Read article schema",
)

APIFolderSummary now includes route description fields — all description_* values are exposed on returned models.

Highlights

  • Added Flux introspection support in both sync and async clients.
  • Added Management API support for route-level descriptions on connected folders.
  • Fully backward compatible: all new parameters are optional.

Full Changelog:
v0.3.0...v0.4.0

v0.3.0 — Upsert & Batch Upsert

10 Feb 22:25

Choose a tag to compare

What's New

upsert_resource() — create or update a resource by external_id in a single call. If no resource with the given external_id exists, a new one is created; otherwise a new revision is added.

resource = client.upsert_resource(
    "blog-posts",
    {"title": "My Article"},
    external_id="cms-article-42",
)

batch_upsert_resources() — upsert many resources concurrently. Uses threads (sync) or asyncio tasks (async) under the hood, with configurable parallelism.

from foxnose_sdk import BatchUpsertItem

items = [
    BatchUpsertItem(external_id=f"article-{i}", payload={"title": f"Article {i}"})
    for i in range(1000)
]

result = client.batch_upsert_resources("blog-posts", items, max_concurrency=10)
# result.success_count, result.failure_count, result.succeeded, result.failed
  • max_concurrency — limit parallel workers (default 5)
  • fail_fast=True — stop and raise on first error; False (default) — collect all results
  • on_progress — optional callback (completed, total) for progress tracking

external_id on create_resource() — optionally assign an external identifier when creating a resource via POST:

resource = client.create_resource("blog-posts", payload, external_id="legacy-post-99")

external_id on ResourceSummary — now exposed in all API responses.

New models: BatchUpsertItem, BatchItemError, BatchUpsertResult

v0.2.0 — Model Objects as Identifiers

26 Jan 23:23

Choose a tag to compare

What's New

Pass model objects directly as identifiers to any Management API client method — no need to extract .key manually.

# Before
folder = client.get_folder("blog-posts")
resources = client.list_resources(folder.key)
resource = client.get_resource(folder.key, resources.results[0].key)

# After
folder = client.get_folder("blog-posts")
resources = client.list_resources(folder)
resource = client.get_resource(folder, resources.results[0])

Highlights

  • Flexible identifiers — all ManagementClient and AsyncManagementClient methods accept either a string key or the corresponding model object (FolderSummary, ResourceSummary, etc.).

  • 13 type aliases — available for use in your own type annotations:

  • FolderRef, ResourceRef, RevisionRef, ComponentRef, SchemaVersionRef, OrgRef, ProjectRef, EnvironmentRef, ManagementRoleRef, FluxRoleRef, ManagementAPIKeyRef, FluxAPIKeyRef, APIRef.

  • Fully backward compatible — string keys continue to work everywhere.

Other

  • Improved async client test coverage (60% → 77%).
  • Overall test coverage increased to 84%.

Full Changelog:
v0.1.0...v0.2.0

Initial release

14 Jan 15:09

Choose a tag to compare

Initial release of the FoxNose Python SDK.

  • ManagementClient and FluxClient (sync + async)
  • JWT and API key authentication
  • Python 3.9+