What's New
Release notes for the Amba API, SDKs, and CLI — new features, improvements, and breaking changes with migration notes.
Breaking changes follow semver and ship with migration notes here. Pin your SDK versions and check this page before upgrading.
2026-06-12
New
-
Byte-range requests on the CDN. Asset responses from
{projectId}.cdn.amba.hostnow advertiseAccept-Ranges: bytes, and a singleRange: bytes=...request on an original asset returns206 Partial Contentwith a correctContent-Range— audio and video players can seek into large files without re-downloading the whole object. Suffix (bytes=-500) and open-ended (bytes=1024-) forms are supported; a range starting past the end of the file returns416withContent-Range: bytes */<size>; multi-range requests are answered with the full200body. Range headers on transformed image URLs are ignored (full response). The new Media Serving & CDN page documents the serving domain, cache lifetimes, image transform parameters, range behavior, and the cache-freshness model. -
Integrations promote with your project. Promotion bundles now include an
integrationssection: each active integration's non-secret config (push bundle id, team/key ids, environment) exports with credential material stripped and an explicitcredentials: "stripped"marker — bundles stay safe to commit and diff. On import, integrations land in a clearly signalledpending_credentialsstate (inactive, with per-provider guidance on exactly which call uploads the credentials), or — when the source and target projects belong to the same developer — passinclude_integration_credentials: trueand the stored credentials are copied directly between the projects' credential stores, entirely server-side, activating push on the target as part of the same import call. No more hand-reconfiguring APNs/FCM after every dev → prod promotion. See the promotion API reference for the new request field, response statuses, and error codes. -
Generated SDK platform-parity matrix. The SDK platform parity page is now generated directly from the SDK method catalog and the SDK sources — one method-level matrix (136 methods × 34 namespaces × 9 platforms) showing exactly which methods ship on Web, Node, React, React Native, Expo, iOS, Android, Flutter, and Unity. Because the page is generated from the same source of truth the SDKs are built from, it can't drift from what the SDKs actually ship.
Improved
- Push payload contract, documented field by field. The new
payload contract page shows the literal
on-device payload for both platforms — the APNs envelope (your
datakeys top-level alongsideaps,alerttitle/body,mutable-content: 1) and the FCM message (notificationtitle/body, high delivery priority, and thedatamap where every value arrives as a string — numbers, booleans, and objects are JSON-stringified, so parse them in typed Android handlers). It also states the stability guarantee explicitly: Amba injects nothing into yourdata— no campaign or segment identifiers (attribution is recorded server-side per delivery) — so tap handlers can rely on your own keys exclusively. No more reverse-engineering test pushes with console logs. - INSERT vs PATCH body shapes, stated as a contract. The
admin rows reference
now documents the deliberate shape split side by side: insert takes a flat
column → value map; single-row PATCH canonically takes
{ "set": { … } }(with the flat body accepted as an alias); bulk PATCH requires thesetwrapper because it disambiguates the update payload from the siblingwherefilter — and a wrong-shape body returns a pointed400naming the top-level keys you sent. Also corrected: bulk update rejects an emptywhere: {}(WHERE_REQUIRED) rather than matching every row, and the admin single-row PATCH'sexpectedcompare-and-set is now documented. return=minimalresponse shapes. The insert reference now shows the id-only response vs the full-row default for both the single insert androws:batch— pass?return=minimal(orPrefer: return=minimal) on agent-driven bulk migrations so large JSONB rows don't blow the token budget on echo.- Content library delete. The
library DELETE reference
now spells out the safety contract: deleting a non-empty library is refused
with
409 LIBRARY_NOT_EMPTYunless you pass?cascade=true, which atomically deletes the library and all its items, schedules, and deliveries — irreversibly. - Catalog-data docs: collections vs content libraries, search, and array
columns. The Content Libraries and
Collections pages now open with reciprocal
guidance on the global-catalog vs per-user decision — including the trap
where admin-seeded rows in a default (
read_policy: "owner") collection are invisible to end users, and theread_policy: "public"fix. The collections feature guide and client API reference now fully document typo-tolerant text search (search: { q, columns, fuzzy, threshold }— word-similarity ranking, default threshold0.3), thelike/ilikeoperators, when to reach for search vs find-nearest, native array column types (text[],integer[],uuid[], …) with thecontains/containedBy/overlapsset operators, and arrays-vs-jsonbguidance. The Migrating from Postgres cookbook gained explicit mappings forILIKE/full-text habits → thesearchparameter, array columns → native array types (notjsonb), and triggers → event-webhook-driven functions.
2026-06-10
New
- Filtered, projected, and nested eager-loading on
find. Anincludeclause can now carry its ownwhere(filter the related rows),select(project their columns), andinclude(load relations OF the related rows — novels → chapters → comments, up to 3 levels, one batched query per relation). The included collection's read policy and soft-delete filter still apply independently. Works on the client find (auto-scoped) and the admin row reads. See Eager-loading. having,order_by, andlimiton group-by aggregation. Filter the grouped result post-aggregation (having: [{ fn: "count", op: "gte", value: 3 }]), order groups by any group column or select alias, and cap the number of groups — "top 5 statuses by revenue" is now one call on both the client and admin aggregate endpoints.- Tail function logs from a request id.
amba functions logs <name> --since-request-id r_...starts the log range at the oldest event mentioning that request id and shows everything from there onward — the "show me what happened after this request" debugging flow. Composes with--request-id(filter) and--tail(anchor the backfill, then stream). Also available on the logs API (?since_request_id=) and theamba_functions_get_logsMCP tool.
Improved
-
Monetization & payments docs, zero to paid. New Monetization Quickstart walks the whole journey: declare entitlements / products / offerings in
amba.config.json, review the plan (including the human-floor checklist of store-side steps no API performs, with exact console locations), confirm and apply the durable operation, provision the store products, wire the RevenueCat webhook, gate features withAmba.entitlements.has(), and cascade subscribers into segments, push, XP, and currency rewards. The Environment Promotion page now documents themonetizationbundle section, the RevenueCat integration page documents the canonicalsecret_api_key/secret_api_key_writeconfig fields, and the Entitlements page's SDK snippets were corrected to the real method names (entitlements.has()/entitlements.list()). -
Storage bucket
bucket_pathfield. Bucket admin responses (/admin/projects/:projectId/storage/buckets) now returnbucket_path— the URL path segment assets are served under. The oldr2_bucket_pathfield is deprecated: it's still accepted on create and still emitted in responses, but it's an alias ofbucket_pathand will be removed in a future major. Switch reads and writes tobucket_path.
Fixed
includenow reaches the wire from every SDK. The shared engine dropped thefindoption'sincludeclauses before sending the request, so eager-loading silently returned bare rows on Web, Node, and React Native. The option now passes through verbatim, andFindOptionsgained the matchingincludefield on iOS, Android, and React Native — parity with Web/Node. Ships in the next SDK patch release.
2026-06-09
New
- Store-product provisioning through the monetization apply. Declared
products that don't exist upstream are now created by apply: each is
registered with RevenueCat (attached to the right app automatically), and App
Store products that declare
store_metadata.push_to_store(plusduration+subscription_group_namefor subscriptions) are created in App Store Connect through RevenueCat's store connection — one apply provisions entitlements, offerings, packages, paywall drafts, AND the store products they sell. Store catalog writes are held to a stricter gate than other gated ops: they never run off an up-frontconfirm— the apply waits until you explicitly approve the started run (re-call apply withconfirm, oramba monetization apply --confirm). The plan now returns ahuman_floorchecklist for what no API can do — pricing, agreements/banking/tax, app review, and store SKUs outside the App Store — each with the exact console location (your declaredstore_metadata.priceis echoed into the checklist). Store products join the three-way diff like every managed object: display-name updates apply automatically, removals archive (soft — the store product is untouched), and out-of-band edits surface as drift. Blocking gaps (a product referenced but never declared, or a store with no connected RevenueCat app) still fail fast with422 MONETIZATION_STORE_FLOORand the exact fix. - Your app's MCP: exposure allowlist, function tools, and surface config.
The per-app agent surface (Your app's MCP) now exposes
collections and deployed functions behind an explicit allowlist —
nothing is exposed by default; opt collections/functions in via
PUT /admin/projects/:id/app-mcp/exposure(or theamba_app_mcp_set_exposureMCP tool). Exposed deployed functions become callable tools (<app>_fn_<name>) that invoke through the same execution path as every other caller — and they're fully typed when the function declaresmcp: { description, input_schema }in its deploy metadata (supported schema subset validated at deploy time; promote restores the annotation that shipped with a version). New per-app surface config (GET/PATCH .../app-mcp/config,amba_app_mcp_get_config/amba_app_mcp_update_config): anenabledkill switch, anauth_moderestriction (all/client_only/developer_only), and a hostnameslugthat reserveshttps://<slug>.mcp.amba.host/mcpfor your app — hostname availability is rolling out, and the path-addressed endpoint keeps working unchanged either way. - Spend ceilings now enforce, and usage is fully visible. The ceiling you
set with
amba_billing_set_ceiling(orPUT …/billing/ceiling) is no longer advisory: when the current period's overage cost reaches it, the project degrades to read-only mode — metered writes (event tracking, collection inserts/updates, media uploads, push sends, new signups) return402with a machine-readable payload (code, current usage, ceiling, reset date) while reads and deletes keep working. Tier quotas enforce through the same path onthrottlemode (402 TIER_QUOTA_EXCEEDED). Two control-plane webhook events —billing.ceiling_warning(80%) andbilling.ceiling_reached(100%) — fire once per billing period so you can alert before the flip.GET …/billing/status(andamba_billing_status,amba billing status) now returns current-period usage and cost by meter, the billing period and reset date, percent of ceiling consumed, a projected end-of-period overage, and the live enforcement state; the console gains a per-project Usage page showing the same. See Billing & Usage. - Web subscriptions. Sell on the web through your own Stripe Billing
account — the path RevenueCat documents for web checkout — and web purchases
grant the same Amba entitlements as mobile ones: same
has()check, same auto-reward cascade, same segments and webhooks. Connect withamba_integrations_configure({ provider: "stripe_billing", … }), map your Stripe price to an Amba product (store_product_refs.web), and passamba_user_idin the checkout metadata. Ingest is signature-verified, idempotent, and order-safe. See Web Subscriptions. - Durable monetization apply.
POST /admin/projects/:id/monetization/apply(andamba monetization apply/amba_monetization_apply) now starts a durable, pollable apply instead of writing in-request: the response carries anoperation_idto poll viaGET /operations/:operationId(the CLI polls for you). Writes are paced against RevenueCat's API rate limits and carry per-step idempotency keys, so a large plan applies safely over several minutes and an interrupted apply resumes without double-creating anything. Destructive changes now wait for confirmation: apply withoutconfirmreportsconfirm_required: trueand holds the gated ops (up to 24h) until you re-call apply withconfirm=plan_hash; a confirmation that no longer matches the plan is rejected with nothing written. One apply runs at a time per project (409 MONETIZATION_APPLY_IN_PROGRESScarries the in-flightoperation_id). Migration note: the apply endpoint now returns202with{ operation_id, status, confirm_required, gated, refused }— poll the operation for the finalapplied/skipped_existing/gated_appliedcounts that previously came back inline, and confirm-required / invariant outcomes now settle the operation instead of failing the request. - Your app's MCP: end-user scope, vector search, faster connects, metering.
The per-app agent surface (Your app's MCP) now serves two
credential modes: the existing developer scope, and a new end-user
scope (
X-Api-Key+ the user's session token) whose tools run through the same enforcement path as the client SDK — collection access policies hold with no bypass, so an in-app assistant only ever sees the signed-in user's data. Collections with a vector column automatically gain a<collection>_find_nearestsimilarity-search tool. The tool surface is now built from a per-app manifest cached with explicit invalidation on schema changes (connects are faster; a schema change still shows on the nexttools/list). Usage is metered: tool calls appear as the new agent tool calls axis inamba_billing_status,amba billing status, and the console billing page. - Cursor pagination from page one. Collection list/find responses (REST
and the app-MCP tools) now return
next_cursoron the first page whenever the query has a single-columnorder— previously only continuation pages carried it, so there was no way to start a cursor chain. The app-MCPlist/findtools default tocreated_at descso agents paginate out of the box. - Agent build reference. An agent builds an app walks the entire journey — account, project, data model, SDK install, identity, XP + streaks, push, live updates, ship checklist — with every MCP tool call and SDK method taken from the live surface. Executable top to bottom by a coding agent.
- Capability Index. /capabilities maps every shipped surface — identity, engagement, gamification, economy & monetization, social, analytics, infrastructure, and the agent/developer surface — on one scannable page with one-liners and links.
- Generated OpenAPI reference. The full API surface is now published as a
machine-readable OpenAPI 3.1 document, generated directly from the live route
registrations — fetch it at
https://api.amba.dev/openapi.json(no auth, CORS-open) or browse the new endpoint index with per-endpoint auth requirements. - Live updates are generally available for shipped apps. Long-lived
subscriptions now connect to a dedicated realtime host
(
realtime.amba.host) with no request-duration ceiling, soAmba.collection().subscribe(), conversation subscriptions, andAmba.gamification.subscribe()stay open as long as your app does. The SDK routes there automatically when pointed at the default production API; a customapiUrlkeeps live updates on that same origin. Ships in@layers/amba-web4.0.6,@layers/amba-node4.0.7, and@layers/amba-react-native4.0.5 (Expo inherits via React Native). See Live Updates.
Improved
- React Native: offerings + Restore Purchases on npm.
Amba.offerings()andAmba.entitlements.restore()(with theOffering*/RestoreResulttypes) are now published in@layers/amba-react-native4.0.5 — parity with Web and Node. - SDK + tooling patch wave.
@layers/ambaCLI 4.0.4 (monetization plan/apply/adopt, payments setup/balance/payouts —amba --versionnow reports the real version),@layers/amba-mcp4.0.6 (monetization, payments, auto-MCP collection tools, AI transcription + vision, media catalogs, translations),@layers/amba-shared4.0.4, and@layers/amba-core4.0.6 pick up everything shipped on the platform since their last publish.
Fixed
- Collection row updates now merge JSON object columns (merge-patch).
PATCHon a collection row used to replace ajsonbcolumn wholesale, so two devices each updating their own key clobbered each other. Object values targetingjsonbcolumns now merge into the stored object — shallow, atomic, on every update path (single-row, bulk,update_many, and transactionupdateops, client and admin alike). Arrays, scalars andnullstill replace the column value. Need the old overwrite behavior? Pass?objects=replace(orobjects: "replace"on a transaction op / theamba_*_update_rowMCP tools). Matches the merge semantics userpropertiesalready had. See the client API reference.
2026-06-07
New
-
Monetization gated destructive apply.
amba monetization applycan now make destructive changes — detaching a product, archiving an entitlement or offering, and removing a package — behind an explicit confirmation. They run only when you re-apply with--confirm(orconfirmset to theplan_hash); without it they're reported but not executed. Confirmed applies enforce an ordering invariant before any write: Amba never archives the offering customers currently see (RevenueCat has no API to move the default pointer — do it in the dashboard) and never detaches the last product a live customer resolves unless you pass--allow-detach-live. New--reconcile amba|adoptcontrols how out-of-band drift is reconciled. If you configure a sandbox RevenueCat project, destructive changes are tried there first (with a synthetic purchase→entitlement-resolve check) before production. Setting the default offering and publishing a paywall live remain dashboard steps (no RevenueCat API) and are surfaced with the exact instructions. -
Subscription products, offerings & a paywall read. Declare a provider-neutral product catalog Amba owns: define an entitlement, declare the products that unlock it (with per-store identifiers), and group them into an offering your paywall renders. New client read
Amba.offerings()returns the offering + packages + the product behind each, in a neutral shape. Configure it agentically (amba_entitlements_define,amba_products_create,amba_entitlements_map_product,amba_offerings_create/amba_offerings_list) or via/admin/projects/:projectId/subscriptions/*. Any grant carrying aproduct_id— a store webhook or a server grant — now resolves to the mapped entitlement automatically, so every purchase path lands on the same entitlement set. -
Restore Purchases. New
Amba.entitlements.restore()(web / node / RN / Expo; iOS + Android in SDK 4.1.0) andPOST /client/entitlements/restorere-sync the user's owned entitlements from the configured subscription service and return the active set — the App Store 3.1.1 requirement. Fail-closed: a transport failure leaves access exactly as it was, never a silent unlock or revoke. -
Reward bundles on subscribe. Entitlement grants now emit neutral
entitlement.granted/subscription.started/subscription.renewedevents. Bind a currency/XP grant rule (or any event rule) to them to auto-reward new subscribers — grant currency, move to a segment, fire a push — with no glue. Idempotent: a redelivered webhook or repeat grant rewards at most once per billing period. -
Amba Payments — accept payments in your app. Your app can now collect payments from its users with Amba as the rail: your app is the seller, Amba takes a configurable platform fee, and the money settles to your own connected account. Onboard in one flow —
amba payments setup(or theamba_payments_account_create+amba_payments_create_onboarding_linkMCP tools) creates your account and returns a hosted setup link you complete once. Then create charges server-side withapplication_fee_amount, and read your balance and payouts withamba payments balance/payouts. The charge returns aclient_secretyour app completes on-device with the platform's standard payment sheet (any Stripe-compatible client SDK). See Payments. Availability is enabled per platform; checkamba payments statusif a call reports payments aren't enabled yet. -
Metered overage collection. When a project's spend mode is
overage_bill, usage past your included quotas is now tallied into a per-period usage ledger and reconciled daily onto your upcoming invoice — so overage genuinely rolls into your next invoice instead of being served for free.GET .../billing/statusgained three honest figures:recorded_overage_usd_this_period(tallied),billed_overage_usd_this_period(actually added to Stripe), andmetered_billing_live(whether charging is enabled yet). Set a spend ceiling for hard429throttling instead of accruing charges. Metered charging is rolling out behind a flag — until it's switched on, usage is tracked and visible but nothing is billed. -
Monetization apply (write to RevenueCat).
amba monetization apply(andamba_monetization_apply,POST /admin/projects/:id/monetization/apply) now pushes your declared subscription config to RevenueCat. Additive ops (create entitlements, offerings, packages, and paywall drafts; attach products) apply automatically. Pass theplan_hashfrom a freshplan; apply refuses if RevenueCat drifted since then, hard-fails if a referenced store product isn't registered yet, reads back every write to confirm it landed, and stops on the first failure without rolling back (the additive half-state still resolves your current offering).plannow returns aplan_hash. Apply needs a read-write RevenueCat key — set it assecret_api_key_writeon the integration, or use one full-access key for both read and write.
Changed
storevalue"stripe"→"web". The entitlementstorefield's vendor-named"stripe"value is now the neutral"web"(covering any non-native checkout). Existing rows are migrated automatically and the server still accepts"stripe"on write (folding it to"web"), so no client change is required — but new code and SDK types use"web".
2026-06-06
New
- Your app's MCP (preview). Every collection in your app is now automatically
a set of typed agent tools at your app's own MCP endpoint —
https://mcp.amba.dev/app/<project-id>/mcp. Create arecipescollection and the endpoint immediately exposesrecipes_list / get / find / insert / update / delete / aggregate, with a typed, per-columnwhereschema so an agent queries your data without writing query strings by hand. Tools are generated live from your schema at connect time — add a collection and the nexttools/listreflects it. Admin-scoped today; end-user scope, per-collection access policies, and typed tools for deployed functions are coming. See Your app's MCP. - Live updates on React Native & Expo.
Amba.collection(name).subscribe(),Amba.messaging.conversation(id).subscribe(), andAmba.gamification.subscribe()now ship in@layers/amba-react-nativeand@layers/amba-expowith the exact same surface and change shape as Web and Node. On mobile the live connection rides the platform's native networking, so it works in release builds with no extra setup or peer dependency, and reconnects with backoff just like Web. See Live Updates. - Audio transcription via the managed AI proxy. The AI surface now proxies speech-to-text alongside image generation and text-to-speech: upload an audio file and get a transcript back, with your provider key kept server-side and per-call usage metered per audio minute. Same managed pattern as the other media endpoints.
- Google Gemini in named prompts. Register a prompt against
geminiand invoke it by name like any other provider — amba builds Gemini's distinct request shape for you (system instruction + multi-turn content + variables), including multimodal image input, and parses the response back to the common result. Previously Gemini was reachable only through the raw passthrough. - Monetization control plane (preview). Manage your subscription config —
entitlements, products, offerings, packages, paywalls — as Infrastructure-as-Code
on top of RevenueCat.
amba monetization planpreviews the three-way diff (declared vs adopted baseline vs live) with a store-floor preflight and drift;driftsurfaces out-of-band dashboard edits (a daily background sweep records them automatically);exportsnapshots the live config to a declarative bundle;adoptrecords the live config as your managed baseline. Also wired into the promotion bundle and exposed as MCP tools (amba_monetization_*). Phase 1 is read-only against RevenueCat — plan/drift/export/adopt never write to RevenueCat (adopt writes only Amba's own state). Pushing declared changes back to RevenueCat ("apply") is coming in a later phase. - Automatic offline queue. Turn on
Amba.offline.enable()and a collection write ortrack()that fails because the device is offline is buffered to a durable on-device outbox instead of throwing — then replayed in order on reconnect. Replays are idempotent, so a write that reached the server before the connection dropped is never applied twice. Web auto-flushes on the browseronlineevent; React Native drivesflush()from your connectivity listener. Opt-in and additive. Web + React Native + Expo + Node SDKs. - Optimistic update helpers. New framework-agnostic
withOptimistic({ apply, mutate, rollback })applies a local change immediately, fires the real write, and rolls the local change back automatically if it fails — plusAmba.collections.optimisticInsert / optimisticUpdate / optimisticDeleteconvenience helpers for the common single-write case. - Push-token auto-rotation. Re-register the device push token whenever the
OS rotates it (reinstall, restore, key roll) so notifications keep arriving.
Web listens for the service-worker
pushsubscriptionchange; React Native wraps your token-refresh listener; Expo's one-callAmba.enablePushAutoRotation()wiresexpo-notificationsfor you. Re-registration is idempotent.
See the Offline & resilience guide.
- Realtime gamification. Subscribe to a user's live XP, level, achievement,
and streak changes over one stream — no polling.
Amba.gamification.subscribe((change) => { … })on the web and Node SDKs delivers each change (with itskindand new state) the moment it happens, and only ever surfaces the signed-in user's own updates. Backed byGET /v1/client/realtime/gamification. See Realtime. - Multi-collection transactions. Commit writes across several collections as
one atomic batch — the whole set applies, or none of it does.
Amba.collections.transaction([ … ])(web + Node) andPOST /v1/client/collections/transactiontake an ordered list of insert / update / delete ops, each with optional compare-and-set and upsert. See Collections (SDK). - Related rows in one query. Add
includeto a collection read to eager-load related rows in a single round-trip instead of an N+1 fan-out. See Collections (Client API). - Per-language content. Attach translations to a content item and Amba
serves the reader's language automatically from
Accept-Language(BCP-47), falling back to the base item when there's no match. See Content (Client API). - Admin collection-row tools. The MCP toolset gained
amba_admin_update_row,amba_admin_delete_row,amba_admin_bulk_update, andamba_admin_bulk_delete, so an agent can manage row data end-to-end — not just insert and read.
Fixed
- Subscription webhooks are now idempotent and order-safe. Subscription events are delivered at-least-once and can arrive out of order; ingest now deduplicates each event and refuses to let an older event overwrite newer entitlement state. A redelivered or late event can no longer silently revoke an active subscriber.
- Refunds revoke access. A refund now marks the entitlement inactive
immediately (previously a refunded subscription could stay active). A
cancellation correctly keeps access until the period's
expiration_daterather than revoking on the spot. - Expiry-aware reads.
GET /client/entitlementsnow derivesis_activefrom the expiration date, so a lapsed subscription never reads as active even before its expiry event lands.?active_only=truefilters to currently-active grants server-side.
Changed
- Paywall engagement events are now recorded with neutral
paywall_<event>names (previouslysuperwall_<event>), and subscription user properties use neutralsubscription_*keys (previouslyrc_*). Existing segment/rule references to the old names keep working on data written before this change; update rules to the neutral names going forward.
2026-06-05
New
- AI vision (image input). Send images to a registered prompt running on a
vision-capable model. Pass
images(each{ url }or{ data, mime }) on the web + Node SDKai.*.createcall — or supplymessageswith content blocks ({ type: 'image', url | data, mime? }) directly — and Amba maps each image to the model's native format. Sending an image to a text-only model returns a clearai_model_not_multimodalerror instead of silently dropping it. Works for Anthropic, OpenAI, and Gemini vision models; theamba_ai_prompts_invokeMCP tool gained animagesparameter for testing. See AI proxy → Vision. - On-device local notifications. Schedule reminders that fire on the
device itself — no server round-trip — with
Amba.notifications.scheduleLocal({ title, body, trigger }), thencancelLocal(id)andlistScheduledLocal(). Triggers can be an absolute time ({ at: Date }) or a delay ({ inSeconds, repeats? }). Available on the React Native, Expo, and web SDKs; iOS and Android schedule fully (even while the app is closed), and the web SDK schedules within the browser's capabilities and reports its mode (scheduledVia). Distinct from remote push — use local for device-owned timing (streaks, focus timers), push for server-owned timing. See Local notifications. - Event dry-run / explain. Preview what an event would trigger before you
fire it.
Amba.events.explain(event, properties, { userId })(web + Node) evaluates the rule engine — XP rules, currency grants, feed rules, streaks, and webhook subscriptions — against a candidate event and returns the would-be effects without committing any side effect. Matched rules that a per-user daily limit, cooldown, or balance cap would suppress carry a note. Backed byPOST /v1/client/events/explain(and the admin equivalent) and the read-onlyamba_events_explainMCP tool. See Events → Explain. - AI cost visibility. Every buffered AI response now carries a
cost_usdfield — the dollar cost of the call, computed from token usage — so you can show per-call spend or sum it per user without a separate metrics call. Surfaced on the web + Node SDKAiMessageResponsetype. See AI proxy. - Per-prompt AI budgets. Cap a registered prompt's spend with a per-period
USD ceiling (
monthly,daily, or lifetimetotal). Once the period's spend reaches the budget, invocations are denied with a clearai_budget_exceedederror until the period resets — so a prompt you expose to your app can't run away with spend. Off by default (unlimited). Manage it via the new budget endpoints or theamba_ai_prompts_set_budget/amba_ai_prompts_get_spendMCP tools. - Media catalogs. Group media assets into a named, slug-addressable
catalog your app fetches in one call — instead of hard-coding asset URLs in
client code. Items stay in the order you set; each resolves to a stable,
long-cacheable public URL. Curate with the
amba_media_catalogs_*tools and read from your app withAmba.media.catalog(slug)(GET /v1/client/media/catalogs/:slug). See Media → Catalogs.
2026-06-04
New
- AI — structured JSON output & streaming. Force a registered prompt to
return parseable JSON with
response_format(json_objectorjson_schema), and opt into a Server-Sent Events stream withstream: true— usage stays metered server-side. See AI proxy and the new client AI reference. - Async operation handles. Side-effecting actions (starting with domain
purchase) hand back an
operation_idyou poll tosucceeded/failedinstead of guessing. See Operations. - Configurable XP level curve. Set
xp_per_levelor explicitlevel_thresholdsper project, and read the effective curve from the client. See XP and Levels. - Collection access policies (public catalogs).
read_policy: "public"lets every signed-in user read a collection;write_policy: "authenticated"opens writes. The default stays strict per-user. See Collections (Admin API). - Idempotent collection writes. Pass an
Idempotency-Keyheader (oridempotency_keybody field) on a collection insert and a retry can never create a duplicate — the replay returns the original row. - Scoped reset. Reset one user's state to zero
(
DELETE …/users/:id/reset, optionally?delete=true), or empty a single collection's rows (DELETE …/collections/:name/data) — instead of the all-or-nothing sandbox wipe. See Users (Admin API) and Collections (Admin API). - Seed a cohort.
POST …/users/cohortmints N anonymous users sharing properties (and optional segments) in one call. - Daily content batches. Set
batch_sizeon a content schedule to deliver N distinct items per tick (delivered as an array). See Content scheduling. - Message read receipts.
GET …/messages/:id/receiptsreturns who has seen a message for a "seen by N of M" UI. See Messaging (Client API). - SDK — collection upsert, deleteWhere, restore. The web and Node SDKs
gained typed
Amba.collections.upsert(),deleteWhere(), andrestore(). See Collections (SDK). - CLI — infrastructure as code.
amba export/amba diff/amba applymanage your project's reusable configuration declaratively (amba.config.json), andamba functions deploynow accepts a directory (with--entry). See the CLI reference.
2026-05-30
Fixes
- Expo Go.
Amba.configure()now initializes cleanly on first call across Expo Go, development, and standalone builds. If you're on an earlier@layers/amba-expo4.0.x, upgrade withnpx expo install @layers/amba-expo— no code changes required on your side.
New
- Experiments — A/B testing with significance. Define weighted variants, get sticky per-user assignment, log exposures, and read per-variant conversion rates with a built-in two-proportion z-test. See Experiments.
- Environment promotion. Export a project's declarative configuration bundle and import it into another project (dev → prod) in one call — currencies, achievements, collection schemas, content libraries, flags, and more. See Environment Promotion.
- Messaging — threads, attachments, typing, reactions. Reply in threads with
parent_message_id, attach files, broadcast a typing signal, and add emoji reactions. See Messaging. - Auth — email + password account linking.
Amba.auth.linkEmailPassword(email, password)upgrades an anonymous session to an email-identified account in place, preserving the guest's data. See Account linking. - Collections —
return=minimal. Pass?return=minimal(orPrefer: return=minimal) on single or batch inserts to trim the response to row ids — keeps large-row migrations inside an agent's token budget. See Collections (Admin API). - Users — admin create.
POST /admin/projects/:projectId/users(MCP:amba_users_create) mints a seed / system user to attribute migrated rows to. See Users (Admin API).
2026-05-29
Breaking change — Admin collections: includeDeleted now defaults to false. The Admin
list rows and count rows endpoints used to return soft-deleted rows by default; they now
exclude them. If you relied on seeing soft-deleted rows from an admin call, pass
includeDeleted: true explicitly. The client (SDK-facing) surface has always defaulted to false
and is unchanged.
New
- Collections — atomic upsert. Insert with
on_conflict(ignoreorupdate) and aconflict_targetto insert-or-update in a single call. See Collections (Admin API). - Collections — compare-and-set. Conditional updates that only apply when
the row still matches an
expectedsnapshot, so concurrent writers don't clobber each other. See Collections (Admin API). - Collections — group-by aggregation. Roll rows up with
count,sum,avg,min, andmaxover a group-by key. - Collections — client-side bulk insert. Insert many rows at once via
/batch. Both single-row and batch insert return a clear 409 on a unique-key clash, so a duplicate always surfaces immediately. - Economy — exactly-once grants & spends. Pass an
idempotency_keyon a currency grant or spend and a retry can never double-apply. See Idempotent grants and spends. - Economy — spendable initial balance. A currency's
initial_balanceis now spendable: it's credited to the ledger the first time a balance is touched. See Spendable starting balances. - Functions — filter logs by request.
amba functions logs <name> --request-id <id>narrows a function's logs to a single request (r_...), and works with--tail. See the CLI reference.