This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
sbxpy is a Python SDK for the SBXCloud BaaS (Backend as a Service) platform. It provides async HTTP clients (via aiohttp) for CRUD operations, querying, event handling, workflow management, and optional Redis caching. Published to PyPI as sbxpy.
- Package manager: uv
- Python: >= 3.12 (pyproject.toml) / >= 3.13 (README target)
- Install dependencies:
uv sync - Add dependency:
uv add <package> - Run a script:
uv run <script.py> - Build package:
python setup.py sdist bdist_wheel - No test suite exists — test manually via scripts with env vars configured
Required for SBXCloud connection:
SBX_DOMAIN— domain IDSBX_APP_KEY— application keySBX_TOKEN— auth tokenSBX_HOST— base URL (e.g.,https://sbxcloud.com/api)
Optional for Redis caching:
REDIS_HOST,REDIS_PORT,REDIS_USER,REDIS_PASSWORD
All library code lives in sbxpy/. The build/ directory contains stale build artifacts.
Contains multiple client classes, each following the same pattern: initialize with domain/credentials, build queries, execute async HTTP requests via aiohttp.
SbxCore— Main SBXCloud client. Handles auth, CRUD (upsert,login), cloudscript management (run,create_cloudscript,list_cloudscripts,get_cloudscript,update_cloudscript), model/field management (create_model,create_field,list_domain), and createsFindquery objects viawith_model().Find— Fluent query builder for find/delete operations. Supportsand_where_*/or_where_*conditions,fetch_models(JOINs), pagination,find_all()with concurrent page fetching via semaphore-limitedasyncio.gather. Also supports the additive find features (all opt-in — see below):select(*fields)(field projection),column_oriented()/object_array()/set_array_type(),sort_by(field, order)(newsortarray, needed for_METAsorting),set_timezone(tz),_METAWHERE helpers (and_where_created_after/before/between,and_where_updated_after/before/between), andfind_old()(legacy/data/v1/row/find/old).SbxEvent/EventQuery— Client for the SBXCloud event service (separate base URL, usessbx-secretheader).SbxWorkflow/WorkflowQuery— Client for workflow/process execution API.SbxCRMUser/UserQuery— Client for CRM user management API.ReferenceJoin/FilterJoin— Reference join query helpers.
Low-level query JSON builder. Constructs the where, rows, fetch, order_by, and page/size parameters sent to the SBXCloud API. Additive find keys (select, array_type, timezone, sort) are emitted only when their setters are called; compile() strips them from insert/update (rows) payloads.
Step— Builders for the STEP date DSL (docs/DATES-QUERY-DSL.md). Produce${...}expression strings (Step.last("7d"),Step.this("week"),Step.start_of("day", tz="America/New_York"),Step.now("-7d"),Step.expr("last 7 days")). Pass the result as a WHERE value. Re-exported assbxpy.Step.
SBXModel— Pydantic BaseModel base class for all domain models. Maps_KEYtokeyfield and_METAto themetafield (aMetaModel). Hashable by key.@sbx(model="name")— Decorator that binds a model class to an SBXCloud model name (stored ascls._model).MetaModel— Timestamps sub-model (created_time,updated_time).
SBX— Singleton accessor forSbxCore, reads credentials from env vars.SBXService— Abstract base withfind(),get_by_key(),list_all()convenience methods.SBXResponse— Pydantic model wrapping API responses. Key methods:all(Type),first(Type),get_ref(model, key, Type),merge(),has_results(),to_objects().resultsis kept raw — it is either a legacy object array or the column-oriented{headers, data}dict.to_objects()(and the module-levelcolumn_to_objects()) reconstruct rows (nesting_META.*headers back under_META);all()/first()/has_results()route through it, so they work with either layout.
RedisService— Async Redis client (viaredis.asyncio) for caching Pydantic objects as JSON. Supports get/set/mget/mset with optional TTL, plus key index management.
SBXCachedService— ExtendsSBXServicewith Redis cache-through pattern forget()andlist()operations.
POST /data/v1/row— insert recordsPOST /data/v1/row/update— update recordsPOST /data/v1/row/find— query records (find())POST /data/v1/row/find/old— legacy query endpoint (find_old())POST /data/v1/row/delete— delete records
These map to new server capabilities (docs/FIND-SELECT-AND-ARRAY-TYPE.md, docs/DATES-QUERY-DSL.md). They are emitted only when explicitly requested, so a default query compiles byte-identically to before and works against old servers, which ignore unknown request keys and always return legacy object-array results:
select/fields— field projection viaFind.select(*fields)(_KEY/_METAalways returned).array_type: "column_oriented"—Find.column_oriented(); the responseresultsbecomes{headers, data}(smaller wire payload). The library never converts implicitly:find_all()/merge_results()keep a column-oriented merge column-oriented (oneheaders+ all pages'dataconcatenated, witharray_typeechoed); object-array pages stay a list. Convert explicitly viaSBXResponse.to_objects()/all()/first()or the standalonecolumn_to_objects()(insbxpy.columns, re-exported fromsbxpy.sbx).delete()extracts keys internally regardless of layout._META.created/_META.updated— usable in WHERE (constantsMETA_CREATED/META_UPDATEDor theand_where_*_METAhelpers) and insort_by(field, order)(newsortarray; legacyorder_byis unchanged).- STEP date DSL +
timezone— wrap date values withStep.*(${...}) and optionallyset_timezone(tz). STEP/_META.*against an old server is a caller choice (old server treats${...}literally / may reject_META.*); the library never injects them implicitly.
GET /data/v1/row/model/list?domain={id}— list models (list_domain())POST /data/v1/row/model?domain={id}&name={name}— create model (create_model())POST /data/v1/field/model?domain={id}&name={name}&row_model_id={id}&type={type}— create field (create_field()). Field types:STRING,INT,FLOAT,BOOLEAN,TEXT,REFERENCE. ForREFERENCE, passreference_type=target_model_id.
POST /cloudscript/v1/run— execute a cloudscript (run())POST /cloudscript/v1.5/{domain_id}— create cloudscript (create_cloudscript())GET /cloudscript/v1.5/{domain_id}?page=N— list cloudscripts (list_cloudscripts())GET /cloudscript/v1.5/{domain_id}/{key}— get cloudscript (get_cloudscript())PUT /cloudscript/v1.5/{domain_id}/{key}/script— update cloudscript (update_cloudscript())
- All API calls are async (use
await). The library usesaiohttp.ClientSessionper request. upsert()separates items with_KEY(updates) from those without (inserts) and sends them to different endpoints (/data/v1/row/updatevs/data/v1/row).- Maximum 1000 records per upsert call.
find_all()fetches the first page, readstotal_pages, then fetches remaining pages concurrently with semaphore-limited parallelism (default 2).- Dates in SBXCloud are often stored as
intinYYYYMMDDformat. - Domain models use Pydantic v2 with
populate_by_name=Trueto handle the_KEYalias.