MiniApps
MiniApp SDK
The small, stable contract every MiniApp imports. You don't write this yourself, Kai does. But knowing what's available helps you describe what your app can do.
The manifest
Every MiniApp has a kaiday.app.yaml at the root. It declares the entry point, the secrets the app needs, and which scopes it's allowed to use.
kaiday.app.yamlname: client-portal entry: app:application sdk: 1 secrets: - STRIPE_SECRET_KEY scopes: - db.read - db.write - storage.read - storage.write - email.send - kai.invoke
The runtime refuses to mount apps that request scopes you haven't approved, and refuses to mount apps targeting an SDK version newer than what it ships.
The SDK surface
kaiday.db
Per-app namespaced Mongo. Read and write your own collections; you cannot read another app's data unless an admin grants a cross-app view.
pythonfrom kaiday import db # Each app gets its own namespace db.bookings.insert_one({"client_id": user.id, "package": "premium"}) recent = db.bookings.find({"client_id": user.id}).limit(10)
kaiday.current_user
The authenticated caller. Either a team member (your Kaiday user) or a client (a person you've invited into a portal).
pythonfrom kaiday import current_user if current_user.is_client: show_client_view(current_user) else: show_admin_view()
kaiday.secrets
Per-company secrets, scoped to the app's manifest declarations. The raw secret never appears in your code.
pythonfrom kaiday import secrets stripe_client = stripe.Client(api_key=secrets.STRIPE_SECRET_KEY)
kaiday.storage
Object storage backed by MinIO. Use it for user uploads, generated PDFs, gallery images. Files can be private (signed URL access) or public (CDN URL).
pythonfrom kaiday import storage key = storage.put("uploads/intake-{user_id}.pdf", file_bytes) url = storage.signed_url(key, ttl=3600)
kaiday.email
Send mail from your verified domain. Subject to the same SPF/DKIM that Email uses.
pythonfrom kaiday import email email.send( to="client@example.com", subject="Your wedding shot list", template="shot-list-confirmation", vars={"name": user.name}, )
kaiday.kai
Call Kai from inside your app. Kai acts on the calling user's behalf and produces drafts the app can render or send.
pythonfrom kaiday import kai quote = kai.draft( intent="generate a quote", package="premium", client_id=user.id, ) return render("quote.html", quote=quote)
How an app runs
kaiday.dbkaiday.current_userkaiday.secretskaiday.storagekaiday.emailkaiday.kaiThe runtime architecture, in plain language:
- Every workspace gets one long-lived runtime container.
- The supervisor pulls every MiniApp repo this workspace owns.
- Each app is mounted under
/dyn/<workspace-slug>/<app-slug>. - A reverse proxy routes inbound requests to the right workspace's runtime.
- Inside the runtime, the SDK provides the contracts above.
What the SDK does not expose
The contract is deliberately small. There is no kaiday.calendar, no kaiday.crm. Those domains are accessible via db views, not dedicated module surfaces. Keeping the SDK minimal lets us evolve the platform without breaking your apps.