v0.3.0 — Upsert & Batch Upsert
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.failedmax_concurrency— limit parallel workers (default 5)fail_fast=True— stop and raise on first error;False(default) — collect all resultson_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