SDK
Schift provides first-party SDKs for Python and TypeScript, plus a Python CLI for terminal workflows. All three surfaces talk to the same REST API and use the same API key.
SDK packages
Section titled “SDK packages”| Package | Language | Install | Use case |
|---|---|---|---|
schift | Python | pip install schift | Python apps, notebooks, data pipelines |
@schift-io/sdk | TypeScript | npm install @schift-io/sdk | Node, browser, and dashboard integrations |
schift-cli | Python CLI | pip install schift-cli | Repeatable terminal workflows and ops |
Note: An older npm
@schift-io/clistill exists for compatibility with legacy deploy/provider/agent workflows. For maintained bucket, catalog, usage, benchmark, and migration workflows, use the Pythonschift-clipackage.
Authentication
Section titled “Authentication”Create an API key in the workspace dashboard, then configure it with an environment variable or explicit constructor argument.
export SCHIFT_API_KEY=sch_your_key_hereexport SCHIFT_API_URL=<your-api-url>/v1For this environment, set SCHIFT_API_URL to {apiUrl}/v1. The SDKs also read SCHIFT_BASE_URL as a fallback for the API origin. The CLI reads SCHIFT_API_KEY first, then falls back to ~/.schift/config.json written by schift auth login.
Environment variables
Section titled “Environment variables”| Variable | Used by | Purpose |
|---|---|---|
SCHIFT_API_KEY | Python SDK, TypeScript SDK, CLI | API key (sch_...) |
SCHIFT_API_URL | Python SDK, TypeScript SDK, CLI | Full API base URL, usually ending in /v1 |
SCHIFT_BASE_URL | Python SDK, TypeScript SDK | API origin without the /v1 path |
Note: When
SCHIFT_API_URLis missing, the SDKs and CLI do not assume a production origin. Set it explicitly for local, staging, or hosted workspaces.
Python SDK
Section titled “Python SDK”The Python SDK exposes two client styles:
WorkspaceClient: modular client for live API operations such as bucket ingest, search, embeddings, usage, and hosted workflows.Client: legacy projection client for fitting and downloadingProjectionobjects that run locally.
WorkspaceClient
Section titled “WorkspaceClient”from schift import WorkspaceClient
with WorkspaceClient() as client: bucket = client.buckets.create(name="finance-docs") upload = client.buckets.upload( bucket["id"], [("files", ("q1-report.pdf", open("q1-report.pdf", "rb").read(), "application/pdf"))], ) hits = client.buckets.search( bucket["id"], "revenue guidance", top_k=5, )WorkspaceClient holds a shared httpx.Client, so prefer a context manager for short-lived scripts. For long-running processes, keep one instance and call close() during shutdown.
Core modules
Section titled “Core modules”| Module | Example call | Purpose |
|---|---|---|
catalog | client.catalog.list() | List embedding models |
embed | client.embed(text, model=...) | Single-text embedding |
embed.batch | client.embed.batch(texts=[...]) | Batch embedding |
buckets | client.buckets.create(name=...) | Bucket ingest and search |
db | client.db.upsert(collection=...) | Raw vector and document upserts |
query | client.query("...", bucket=...) | Hosted bucket or passthrough search |
rerank | client.rerank(query, documents=[...]) | Rerank candidates |
providers | client.providers.set("openai", api_key=...) | BYOK provider keys |
routing | client.routing.set(primary=..., fallback=...) | Server-side model routing |
pii | client.redact_pii(text, types=[...]) | Mask Korean PII |
usage | client.usage.get(period="30d") | Usage summaries |
workflow | client.workflow.create_rag(name=...) | Workflow CRUD and runs |
bench | client.bench.run(source=..., target=...) | Migration quality benchmark |
Legacy projection client
Section titled “Legacy projection client”from schift import Client
legacy = Client(api_key="sch_your_key_here")projection = legacy.fit( source=source_pairs, target=target_pairs, source_model="openai/text-embedding-3-small", target_model="google/gemini-embedding-001", project_name="openai-to-gemini",)projection.save("./projection-openai-to-gemini")The saved Projection can be reloaded offline and applied with the local migration engine:
from schift import Projectionfrom schift.migrate import migratefrom schift.adapters.file import NpyAdapter
projection = Projection.load("./projection-openai-to-gemini")source = NpyAdapter("old_embeddings.npy")sink = NpyAdapter("new_embeddings.npy")
migrate(source=source, sink=sink, projection=projection, batch_size=2048)TypeScript SDK
Section titled “TypeScript SDK”The TypeScript SDK centers on WorkspaceClient.
import { WorkspaceClient } from "@schift-io/sdk";
const client = new WorkspaceClient({ apiKey: process.env.SCHIFT_API_KEY!, baseUrl: process.env.SCHIFT_API_URL!,});
await client.createBucket({ name: "company-docs" });const file = new File([await readFile("manual.pdf")], "manual.pdf", { type: "application/pdf",});await client.db.upload("company-docs", { files: [file] });
const results = await client.bucketSearch("company-docs", { query: "refund policy", topK: 5,});Core methods
Section titled “Core methods”| Method | Purpose |
|---|---|
embed(request) | Single-text embedding |
embedBatch(request) | Batch embedding |
search(request) | Vector search |
bucketSearch(nameOrId, request) | Search a bucket |
chat(request) | Bucket-backed RAG chat |
chatStream(request) | Streaming RAG chat |
webSearch(query, maxResults?) | Web search |
redactPii(request) | Mask Korean PII |
mask(text, options) | Convenience PII mask |
restorePii(request) | Restore PII tokens locally |
providers.set(provider, config) | Register BYOK provider key |
workflows.create(request) | Create workflow |
workflows.run(id, inputs) | Run workflow |
tools.openai() / tools.anthropic() / tools.vercelAI() | Tool definitions for provider SDKs |
Note: For a complete TypeScript class and type reference, see the SDK API Reference.
The Python schift-cli package installs a schift executable.
pip install schift-clischift auth loginschift auth statusCommand groups
Section titled “Command groups”| Command | Purpose |
|---|---|
schift auth ... | Manage local authentication state |
schift catalog ... | Browse supported embedding models |
schift embed ... | Generate embeddings from text |
schift bench ... | Evaluate migration quality between two models |
schift migrate ... | Fit projections and run database migrations |
schift db ... | Create, list, and inspect buckets |
schift upload ... | Upload files into a bucket |
schift jobs ... | Inspect, reprocess, and cancel ingest jobs |
schift search ... | Run bucket search |
schift query ... | Compatibility alias for bucket search |
schift usage ... | Show aggregated usage and billing summary |
Common workflow
Section titled “Common workflow”export SCHIFT_API_KEY=sch_your_key_hereexport SCHIFT_API_URL=<your-api-url>/v1
schift upload ./handbook.pdf --bucket company-docsschift jobs list --bucket company-docsschift search "revenue report" --bucket company-docs --top-k 5SchiftIndex
Section titled “SchiftIndex”SchiftIndex is the SDK-managed sync surface for repeatable source ingestion into workspace buckets. Use it when a team wants local manifests, text diffs, checkpointed sync, retry, and source-specific adapters such as Obsidian vault sync.
cd "/path/to/Obsidian Vault"schift-index init --manifest schift.index.json --template dot-vaultSCHIFT_API_KEY=... schift-index sync --manifest schift.index.json --cloudError handling
Section titled “Error handling”Python SDK errors:
from schift import WorkspaceClientfrom schift import AuthError, QuotaError, SDKError
try: with WorkspaceClient() as client: client.catalog.list()except AuthError: ...except QuotaError: ...except SDKError: ...TypeScript SDK error classes:
import { AuthError, QuotaError, PlatformError } from "@schift-io/sdk";
try { await client.embed({ text: "test" });} catch (err) { if (err instanceof AuthError) { // 401 } else if (err instanceof QuotaError) { // 402 } else if (err instanceof PlatformError) { // 403, 422, 429, 500, 502 }}