Skip to content

Releases: FoxNoseTech/foxnose-python

v0.7.0 — Flux Writes & Typed Write Errors

Choose a tag to compare

@loookashow loookashow released this 22 Jul 18:08

Release notes:

This release adds write support to the Flux client and aligns the error and usage types with the current delivery API.

Highlights

Flux writes

  • FluxClient.create_resource(folder_path, data, *, key=None) and the async AsyncFluxClient.create_resource(...) — create and publish a resource immediately. key is an optional external identifier for deduplication.
  • update_resource(folder_path, resource_key, data) (sync + async) — a full-document replace that publishes a new revision (not a partial merge).
  • Both accept nested collection paths, e.g. users/usr_1/memories.
  • Returns resource_key, revision_key, write_units, published.
created = client.create_resource("articles", {"title": "Hello"}, key="my-id")
client.update_resource("articles", created["resource_key"], {"title": "Hello (edited)"})

Typed errors

New subclasses of FoxnoseAPIError (exported from the package root, still caught by except FoxnoseAPIError):

  • CollectionNotWritable (403)
  • ExternalIdConflict (409)
  • ContentValidationFailed (422) — exposes .errors (each with a json_path) and .errors_truncated
  • UpstreamError (502) — the write outcome is unknown

Reliability

  • Writes are never retried automatically. A failed write's outcome is unknown, so on failure re-read with a GET before retrying. (Backed by a new per-request allow_retries flag on the transport, defaulting to True for reads.)

Misc

The default User-Agent now reports the real package version.

Breaking changes

  • UsageBreakdown now exposes projects, resources, and users (previously also environments, folders, and components). Parsing stays forward-compatible with additional server fields.

Install

pip install --upgrade foxnose-sdk

v0.6.0

Choose a tag to compare

@loookashow loookashow released this 21 Jul 09:11
9fed6dc

foxnose-sdk 0.6.0

Warning

Breaking changes. This release renames the Folder API to Collection and
removes composite folder support. The old *_folder* methods still work as
deprecated aliases (removed in 1.0) — see Migration below.

Added

  • Typed billing exceptions in foxnose_sdk.errors, all subclasses of FoxnoseAPIError
    and exported from the package root (caught by except FoxnoseAPIError):
    • SpendCapExceeded (402 spend_cap_reached) — cap_usd, cycle_resets_at, raise_cap_url
    • PlanExhausted (402 plan_exhausted) — axis, window_resets_at, upgrade_url
    • PlanLimitExceeded (403 plan_limit_exceeded) — entity, limit, current, upgrade_url
    • RateLimitExceeded (429 rate_limited) — retry_after (from the Retry-After header)
  • Components on CollectionsNestedFieldMeta helper for building nested-field meta
    (component, component_version, auto_update), and sync_collection_component() on
    ManagementClient / AsyncManagementClient to advance pinned nested fields to a target
    Component version. New models SyncComponentResponse, SyncComponentSkippedItem,
    ComponentSyncConflictDetail.

Changed

  • Renamed Folder → Collection across the Management API surface. New *_collection*
    methods (list_collections, create_collection, list_collection_versions,
    list_collection_fields, …) and models (CollectionSummary, CollectionList,
    APICollectionSummary, APICollectionList) are the preferred names. The old *_folder*
    methods and FolderSummary / FolderList remain as deprecated aliases that emit a
    one-shot DeprecationWarning on first use and will be removed in 1.0.

Removed

  • Composite folder support.

Fixed

  • RolePermission.all_objects is now optional (bool | None), so permissions for
    non-object-based content types (returned by the API as all_objects: null) parse
    without error.
  • Corrected the roles_and_permissions example and docs to the real permission wire-shape
    (content_type + actions list, all_objects only on object-based content types), the
    renamed content-type keys (collection-structure / collection-items in place of
    folder-*), and the real API-key create shape (description + a single role).

Migration

  • Replace *_folder* calls with their *_collection* equivalents; old names still work but
    emit a DeprecationWarning and are removed in 1.0.
  • Content-type keys folder-structure / folder-itemscollection-structure / collection-items.
  • Remove any usage of composite folders.

Full changelog: v0.5.0...v0.6.0

v0.5.0 — Vector Search

Choose a tag to compare

@loookashow loookashow released this 19 Mar 16:06
f9b66f1

What's New

Vector Search Support

The SDK now provides typed models and convenience methods for the Flux vector search API.

4 search modes:

  • vector_search() — semantic search with auto-generated embeddings
  • vector_field_search() — search with custom pre-computed embedding vectors
  • hybrid_search() — blended text + vector search with configurable weights
  • boosted_search() — keyword search boosted by vector similarity

Typed models with validation:

  • SearchMode, VectorSearch, VectorFieldSearch, VectorBoostConfig, HybridConfig, SearchRequest
  • Cross-field validation catches invalid configurations before the API call
  • SearchRequest forwards extra fields (where, sort) via extra="allow"

All methods available on both FluxClient and AsyncFluxClient.

Other Changes

  • Fixed examples/flux_client.py search body to use correct find_text/results keys

Links

v0.4.2 - Fix SecureKeyAuth

Choose a tag to compare

@loookashow loookashow released this 18 Mar 12:01
d80b03a

Fixed

  • Secure Management/Flux signing with query parameters:
  • SecureKeyAuth now signs only the URL path (without query string)
  • aligns SDK signatures with server-side verification and Management auth docs - prevents 401 authentication_failed / Invalid signature on requests with query params

v0.4.1 — Flux Permission Objects Reliability

Choose a tag to compare

@loookashow loookashow released this 05 Mar 15:01

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

Choose a tag to compare

@loookashow loookashow released this 25 Feb 13:11

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

Choose a tag to compare

@loookashow loookashow released this 10 Feb 22:25

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

Choose a tag to compare

@loookashow loookashow released this 26 Jan 23:23

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

Choose a tag to compare

@loookashow loookashow released this 14 Jan 15:09

Initial release of the FoxNose Python SDK.

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