Amba

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-10-04

Security

  • A password sign-up no longer verifies the email. POST /client/auth/email/signup and linkEmailPassword store the address with email_verified: false (an address the user had already verified stays verified). The user is still signed in at once. Proving the inbox from that session (linkEmailOtp with the same address) keeps the password. When the inbox is proven by a sign-in from anywhere else (email OTP, magic link, or an Apple / Google email the provider verified) on an account that still holds an unverified password, Amba clears the password, revokes every earlier session and access token (they now answer 401 SESSION_REVOKED), and detaches the phone, Apple / Google links, and anonymous id attached before the inbox was proven; the account no longer resumes by anonymous id. This closes account pre-hijacking, where someone registers another person's address before they arrive. Accounts without an unverified password see no change. Password accounts created before this release keep their verified email unless the operator marks a project's legacy accounts unproven.
  • Password sign-in is budgeted. POST /client/auth/email/login answers 429 RATE_LIMIT_EXCEEDED with Retry-After past 20 attempts a minute or 200 an hour per IP, 10 per 15 minutes or 100 a day per account, or 60 a minute per free project (600 per paid project). The budgets run before the password check.
  • Free-tier cost limits fail closed. When a free project's limits or daily counters cannot be read for a moment, calls that send, charge, or start work answer 503 LIMITS_UNAVAILABLE with Retry-After, and free-project function invocations get the router's retryable 503. Paid and comped projects are unaffected, and sign-in email keeps working.
  • The CLI keeps your token in the OS keychain (@layers/amba 4.1.10). amba login and amba init store the access and refresh tokens in macOS Keychain, Windows Credential Manager, or the Linux Secret Service, under service amba and account developer:<api host>, so production and staging logins stay separate. A replaced token moves to the endpoint's :previous slot (the last three are kept). Non-secret details move to ~/.amba/config.json. The first command after the upgrade moves an existing ~/.amba/credentials.json into the keychain, reads it back to confirm, and then deletes the file; if the keychain write fails, the file stays and the CLI keeps using it. Where no keychain is usable (CI, containers, Linux without a Secret Service), the token goes to ~/.amba/credentials.json with mode 0600 and the CLI prints one line naming that file. A keychain that holds the token but is locked stops commands with an error naming the entry. --token and AMBA_PAT still take precedence over both. amba login signs in through app.amba.dev and stores a production session; for another endpoint use AMBA_PAT or amba init --sandbox. New commands: amba whoami shows the account and where its credential is stored, amba token prints the token for scripts (replacing jq -r .pat ~/.amba/credentials.json), and amba logout removes the keychain entries and any fallback file entries. See CLI authentication.

2026-10-03

Security

  • Client keys can no longer reset a project. POST /v1/client/dev/reset-sandbox is removed and answers 404, and the React Native SDK's Amba.dev.resetSandbox() is removed with it. A client key ships inside your app, so it must never be able to delete users. Reset a free project with the amba_users_reset_sandbox MCP tool or DELETE /v1/admin/projects/{projectId}/users/reset-sandbox?confirm={projectId} using an owner or admin developer token. Server keys and function tokens now get 403 OWNER_CREDENTIAL_REQUIRED on that route.
  • Webhook destinations must be public HTTPS endpoints. Creating, updating, or testing an app or control-plane webhook subscription refuses loopback, private-network, link-local, carrier-grade NAT, multicast, and cloud metadata destinations, including hostnames that resolve to them, with 400 TARGET_URL_NOT_ALLOWED. Every delivery checks the address it connects to again, treats a 3xx response as a failed attempt, and reads at most 64 KB of the response body. See Outbound webhooks.
  • Function storage accepts only string keys. Every env.STORAGE method takes primitive string keys and list options of their documented types; any other value throws TypeError before the request reaches storage. Listings return only objects under your project's storage scope.

Changed

  • Free-tier limits on the surfaces that run on Amba's domains, sending reputation, and compute. New free projects keep everything needed to build an app and gain free-tier limits: custom domains, domain purchase, email to arbitrary recipients, custom email templates, and the app builder are paid features; sign-in email is capped at 100 a day, sign-in SMS at 10 a day, push campaigns at 3 a day, direct pushes at 100 a day, function invocations at 10,000 a day with 50 ms of CPU each, function schedules at 2 (hourly or slower), queue messages at 1,000 a day, and new tracked links at 50 a day. Hosted sites serve with a "Built with Amba · preview" bar and noindex; HTML, SVG, XML, and scripts on the media CDN download as attachments; HTML documents from functions serve sandboxed. A refusal returns 402 FREE_TIER_LIMIT_REACHED with details.limit naming the surface and details.upgrade carrying the one-call upgrade. Projects created before this release keep their previous behaviour.
  • Sign-in email on new free projects is capped at 25 a day (was 100). Magic links and email OTP share one sending reputation across every project, so the daily sign-in email allowance per free project is now 25. A refusal is the same 402 FREE_TIER_LIMIT_REACHED with details.limit set to auth_emails_per_day; upgrading lifts the cap.
  • Unclaimed sandbox accounts follow a timeline. Accounts an agent created with amba_developer_signup and nobody has claimed get a claim notice on every admin response and MCP result once a free project reaches day 7 of its own clock. The project goes on hold on day 14 (reads work, writes return 403 SANDBOX_CLAIM_REQUIRED) and is archived on day 90, after a full 76-day hold. Archiving deletes nothing. Each project's clock starts when it was created or became subject to the timeline, so a new project in an old account gets the whole window. Claiming lifts all of it in one request. See Unclaimed accounts.
  • An account is unclaimed until its owner proves the inbox, whatever its address. The claim link, signing in with an emailed code, and GitHub sign-in with a verified primary email prove it; the verify_token that signup returns does not. Free projects of any unclaimed account follow the timeline above, and an account that already uses its owner's real address claims that same address with amba_developer_claim. Accounts that proved their inbox, sign in with an emailed code, or own a paid or comped project before this release count as proven.
  • New projects for unclaimed accounts draw on a small daily capacity slice. When it is spent, creating a project returns 503 PLATFORM_CAPACITY with details.pool: "unproven" and the claim call, and signup still creates the account, returning project_unavailable in place of project. Claiming moves the account to the main pool.
  • Free media storage is capped at 250 MB (was 100 MB, and not enforced). On new free projects every upload registration takes size_bytes, the upload URL accepts at most that many bytes, and an upload past the budget returns 402 FREE_TIER_LIMIT_REACHED with details.limit set to media_storage. GET .../billing/status reports real media usage on every tier. On a free project a raw-key PUT presign returns 400 PRESIGN_PUT_NOT_AVAILABLE (register the upload instead), and deleting an asset within about 11 minutes of registering it returns 409 UPLOAD_WINDOW_OPEN with Retry-After, because its upload URL could still recreate it. Deleting media removes the stored file before it frees space.
  • Hosted sites on new free projects hold 50 MB. One deploy carries at most 50 MB and 1,000 files, and every site plus its kept deployments share 50 MB; older deployments are dropped to make room. A refusal is 402 FREE_TIER_LIMIT_REACHED with details.limit set to site_storage or site_files.
  • The two-free-projects limit covers app-factory provisioning and needs a paid subscription to lift. POST /v1/admin/provision counts each new child against its owner's free projects unless the developer or the parent org pays or is comped, and an unpaid checkout no longer lifts the limit on any path.
  • Account emails run on daily budgets. Claim links, sign-in codes, and invites share durable daily budgets per account, per address, and platform-wide (429 EMAIL_BUDGET_EXCEEDED with Retry-After). An address gets at most one claim email per 10 minutes (429 CLAIM_EMAIL_RECENTLY_SENT; the earlier link keeps working), and a new claim link replaces the account's older ones.

New

  • amba_developer_claim MCP tool. Hands an agent-created account to its human owner in one call; the owner clicks the emailed link. A sandbox that already redeemed its signup verify_token can now be claimed too.

Fixed

  • An inline pat works on the hosted MCP server with no Authorization header. After amba_developer_signup, an agent passing the returned PAT as the pat argument now keeps working in the same session; the call previously answered 401 MISSING_AUTHORIZATION when the MCP client sent no Authorization header.
  • MCP tool errors carry the API's code and details. A failed call's result now ends with the JSON error { status, error: { code, message, details } } after the readable API error <status>: <message> line it always had, so a 402 FREE_TIER_LIMIT_REACHED reaches the agent with the limit, the reset date, the billing URL and the one-call upgrade. A call with no credential returns MISSING_PAT as an error result too. See MCP tool errors.
  • Tracked-link destinations and the deep-link fallback URL refuse script, data, and file URLs (400 INVALID_DESTINATION_URL / INVALID_FALLBACK_URL). http(s) URLs and your app's own URL scheme are accepted as before.
  • SDK errors expose details as a plain object. In @layers/amba-web 4.0.10, @layers/amba-node 4.1.2 and @layers/amba-react 4.0.4, err.details on an API error reads by property (err.details.limit, err.details.upgrade, err.details.opIndex) and JSON.stringify prints it. Earlier releases of those three SDKs returned undefined for those reads; err.code, err.status and err.message were always correct. The React Native, Expo and native SDKs already returned plain objects.

2026-10-02

New

  • Invite-only developer signups. Amba is reopening new-account signups in steps. While signups are invite-only, a new account needs an invite code (AMBA- followed by four groups of four letters and digits, such as AMBA-7KQ2-M9XD-4TNB-HR3W; case, spaces, and dashes are ignored). Pass it as invite_code on POST /v1/auth/developer/signup, as the invite_code argument on amba_developer_signup and amba_affiliate_signup, with npx @layers/amba init --invite <code> (or AMBA_INVITE_CODE), or in the console signup form, which the invite email's link fills in. Refusals are 403 INVITE_REQUIRED, 403 INVITE_INVALID, and 403 SIGNUPS_CLOSED, each with details.request_access_url. An account created with a code can create projects right away. Existing accounts are unaffected: login, refresh, PAT rotation, and existing projects keep working. See Getting access.
  • Request access. POST /v1/auth/developer/waitlist (email, optional note) and the console page at app.amba.dev/request-access put you on the list. When access is granted, the invite email carries the code, a prefilled signup link, and a one-line prompt to paste into your coding agent.
  • Redeem an invite on an existing account. POST /v1/auth/developer/redeem-invite lets an account that already exists use an invite code to create projects while access is limited.
  • Free-tier database limits. Free projects run on 0.25 compute units with 10 CU-hours of database compute per billing month (about 40 hours awake) and a 512 MB database. At the compute cap the database pauses until the period resets on the 1st (UTC); at the storage cap, writes that add data are refused while reads and deletes keep working. Both return 402 FREE_TIER_LIMIT_REACHED with the limit, the reset date, and an upgrade field carrying the one-call upgrade. The owner gets an email at 80% of the compute allowance. See Database limits. Paid projects and projects that existed before this release are unaffected.
  • Database usage in billing status. GET .../billing/status (and amba_billing_status) gains a database block with compute CU-hours and storage MB against the caps, the reset date, and limit_reached. amba billing status and the console billing page show the same numbers.
  • amba_billing_upgrade MCP tool. Starts a Pro or Scale checkout in one call and returns the link for the project owner to open.

Fixed

  • Sites serve directory-style links. A request to /start/ now serves start/index.html (it previously returned 400 invalid_path), and /start serves start.html or redirects (308, query string kept) to /start/ when the page lives at start/index.html (it previously rendered the home page). Static exports from Astro, Hugo, Next.js, and similar generators work with their default link styles, including dotted slugs (/blog/release-2.0). Exact file paths resolve as before. See Sites routing.
  • File names with spaces or non-ASCII characters work end to end. Site deploys that include a non-ASCII file name (café.html) previously failed with STORAGE_WRITE_FAILED; they now upload, and a request for /caf%C3%A9 serves café.html. /my%20report.pdf serves my report.pdf.
  • Custom 404 pages. A site that ships a top-level 404.html now serves it, with status 404, for every path that doesn't resolve. Sites without one keep the single-page-app fallback to index.html.
  • The single-page-app fallback is no longer cached for an hour. Deep links that fall back to index.html are sent with the same no-cache policy as every other HTML page, so a new deployment shows up on the next request.

Changed

  • Background evaluation runs when there is something to evaluate. XP rules, segments, and leaderboards still pick up new data on their usual cycle (XP within 2 minutes, segments and leaderboards within 15). An app with no new data is now left idle between cycles. Segment rules with a within / not_within window re-evaluate when the next user crosses the window's boundary: within 15 minutes for windows under a day, within the hour for longer ones. Daily, weekly, and monthly leaderboards roll over at UTC midnight as before. See Evaluation cadence.
  • Engagement events record when Amba received them. New events carry a received_at timestamp next to occurred_at (which can be the client's time). It appears in the user data bundle and in GET /users/:id/events. A daily XP pass uses it to find events no evaluation run picked up and grants their XP once, checked against the daily limit of the event's own day and the cooldown around its own time, and dated at the event. An event an evaluation run already held back on a daily limit or cooldown stays held. A grant healed after its period closed adds to the user's total XP and appears in their XP history at the event's time; daily, weekly, and monthly leaderboards for that closed period are not recomputed.
  • One developer account per mailbox. Developer signup, GitHub sign-up and amba claim now treat aliases of the same mailbox as one address: case is ignored, any +tag is removed, and for Gmail the dots in the local part are ignored (j.doe+work@gmail.com and jdoe@gmail.com are the same mailbox). Binding an alias of an address that already owns an account returns 409 EMAIL_EXISTS. The address you typed is still the one we email.
  • Disposable inboxes are refused. The same paths return 400 DISPOSABLE_EMAIL for addresses on temporary-inbox domains.
  • Failed password attempts are capped per account. After 20 failed password sign-ins in an hour (100 in a day) for one account, password sign-in for that account returns 429 RATE_LIMIT_EXCEEDED with Retry-After until the window passes. The count covers amba login, the console and the MCP connector consent page together, and only failed attempts count. Sign-in with an emailed code keeps working.

Improved

  • Clearer reserved secret names. Secret names starting with AMBA_ or EDGE_ stay reserved for values the platform injects into every function. The RESERVED_BINDING error, amba secrets set, and the amba_secrets_set MCP tool now list the injected values (AMBA_PROJECT_ID, AMBA_API_URL, AMBA_INTERNAL_TOKEN, AMBA_AI_GATEWAY_URL) and suggest a usable name, for example APP_CLIENT_KEY in place of AMBA_CLIENT_KEY. See Reserved names.

2026-09-07

Fixed

  • Vision prompts accept every common image spelling. The client AI surface now accepts { type: 'image', source: { type: 'base64', media_type, data } } (and the url source), { type: 'image_url', image_url: { url } }, the media_type / mime_type synonyms for mime, and data: URLs, alongside the vendor-neutral { type: 'image', url | data, mime } block. Previously the provider-native spellings were dropped before the model saw the image.
  • Rolling model aliases are recognised as vision-capable. Prompts registered on gemini-flash-latest, gemini-flash-lite-latest, or gemini-pro-latest no longer return 422 ai_model_not_multimodal for image input, and they are priced at the current generation's rate so per-prompt budgets bind.

New

  • Passwordless developer sign-in by emailed code. POST /auth/developer/otp/request emails a 6-digit code to an existing account and POST /auth/developer/otp/verify redeems it for the normal session, so an account that never set a password (for example one created by an agent and later bound to your address) can sign in on the console and with amba login. Codes expire in 10 minutes, are single-use, and lock after 5 wrong attempts; redeeming one marks the account verified. The console sign-in page gained an Email me a sign-in code option.
  • Per-call system on registered prompts. A caller may pass system alongside prompt_slug; it is merged after the prompt's saved system prompt (the saved text stays first). A non-string value is rejected with 400 instead of being ignored.
  • thinking_budget for reasoning models. Bound (or disable with 0) the reasoning tokens that would otherwise be spent out of max_tokens on models that think before answering.

2026-08-26

New

  • Gemini 3.5 Transcribe in the managed AI gateway. The OpenAI-compatible /audio/transcriptions route now accepts gemini-3.5-transcribe, uploads the file through Google's resumable Files API, waits for it to become ACTIVE, invokes the unary Interactions API, and cleans up the temporary file on every terminal path. Automatic language detection, language hints, custom vocabulary, smart/verbatim modes, and diarized word timestamps are supported where Google allows them. verbose_json normalizes WordInfo into backward-compatible speaker segments and words. Cost is non-null and calculated from Google's returned modality token usage at its published $2/M audio-input and $12/M text-output rates; no estimated per-minute charge is used. The live WebSocket model is not part of this release.
  • Gemini and Mistral key registration in the CLI. amba ai providers add accepts all four gateway providers, matching the admin API and internal key callback.

2026-08-25

New

  • Function deploy readiness and controlled credential forwarding. CLI 4.1.5 adds amba functions deploy-status and amba functions deploy --forward-authorization. The latter is an explicit, per-deployment opt-in: only a bearer from a verified client request can reach customer code; API keys and internal trigger credentials remain stripped.
  • OpenAI-compatible image edits and variations. The AI gateway now routes /images/edits and /images/variations, supports their multipart payloads, and meters gpt-image-2 including its dated snapshot.

Fixed

  • Deleted functions stop serving immediately. Function deletion now removes the deterministic schedule, disables the active deployment, and publishes a persistent edge tombstone before provider cleanup. Deploy, promote, and disable reconcile that edge state immediately, including safe cache invalidation when a direct write fails.
  • App-MCP group scope and errors. X-Group-Context reaches generated collection and function tools, and non-2xx upstream responses are returned as MCP tool errors instead of successful results.
  • Function log visibility. CLI 4.1.5 prints successful invocations with no console output as [outcome] ok; docs now state the provider's batched ingestion window.
  • Truthful custom-hostname status. Site and function-domain reads expose raw provider ownership/certificate state and refresh it during list operations; unknown non-empty certificate states fail visibly instead of collapsing to pending. A five-minute background reconciler also re-fetches pending hostnames and publishes newly issued or rotated certificate-validation TXT values for domains whose DNS Amba manages, so activation does not depend on a customer polling the API.

2026-06-20

New

  • Team-owned collections (group/org ownership). A collection can now be owned by a group instead of a single user. Create it with owner_scope: "group" plus read_policy: "member" / write_policy: "member:admin" (on amba_collections_create/_alter or the admin API): any member of the owning group reads, and members at the given role write — enforced server-side from the group's membership (owner > admin > member > viewer). Act within a group via amba.asUser(uid).asGroup(gid) (Node SDK) or the X-Group-Context header; a non-member is rejected with 403, and inserts must target a private group. Additive and backward-compatible — existing collections stay strictly per-user. See team-owned collections.

2026-06-13

New

  • Monetization apply creates Google Play products. amba monetization apply now creates one-time products directly in Google Play — not just App Store Connect. Declare store_metadata.push_to_store: true on a play_store one-time product (one_time | consumable | non_consumable) with play_price_micros (integer micros) and play_currency (ISO code), connect a google_play integration (a Play Console service account with the Android Publisher permission), and apply creates the managed product and sets its price in one step. The credential is validated when you connect it, store catalog writes still require an explicit confirm, and Play subscriptions stay on the human-floor checklist (create those in Play Console; apply registers them). See the monetization quickstart.

  • amba ship — take your Expo app live. The CLI (@layers/amba 4.1.0) now carries amba ship: one config (amba.ship.json) and one command take a code-complete Expo app from build to live on the App Store and Google Play. Six idempotent phases — preflight, monetization, build, submit, metadata, release — with per-app state so a re-run resumes where it stopped. Every step no API can do (creating the store app record, the Apple Paid Apps agreement, screenshots, store review) is detected and surfaced with the exact console action, never pretended-automated. amba ship init scaffolds the config; --dry-run prints the whole plan and changes nothing; --phase runs a single phase. When monetization.enabled is set, ship verifies your in-app purchase catalog against the monetization control plane before building.

2026-06-12

New

  • Byte-range requests on the CDN. Asset responses from {projectId}.cdn.amba.host now advertise Accept-Ranges: bytes, and a single Range: bytes=... request on an original asset returns 206 Partial Content with a correct Content-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 returns 416 with Content-Range: bytes */<size>; multi-range requests are answered with the full 200 body. 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 integrations section: each active integration's non-secret config (push bundle id, team/key ids, environment) exports with credential material stripped and an explicit credentials: "stripped" marker — bundles stay safe to commit and diff. On import, integrations land in a clearly signalled pending_credentials state (inactive, with per-provider guidance on exactly which call uploads the credentials), or — when the source and target projects belong to the same developer — pass include_integration_credentials: true and 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 data keys top-level alongside aps, alert title/body, mutable-content: 1) and the FCM message (notification title/body, high delivery priority, and the data map 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 your data — 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 the set wrapper because it disambiguates the update payload from the sibling where filter — and a wrong-shape body returns a pointed 400 naming the top-level keys you sent. Also corrected: bulk update rejects an empty where: {} (WHERE_REQUIRED) rather than matching every row, and the admin single-row PATCH's expected compare-and-set is now documented.
  • return=minimal response shapes. The insert reference now shows the id-only response vs the full-row default for both the single insert and rows:batch — pass ?return=minimal (or Prefer: 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_EMPTY unless 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 the read_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 threshold 0.3), the like/ilike operators, when to reach for search vs find-nearest, native array column types (text[], integer[], uuid[], …) with the contains / containedBy / overlaps set operators, and arrays-vs-jsonb guidance. The Migrating from Postgres cookbook gained explicit mappings for ILIKE/full-text habits → the search parameter, array columns → native array types (not jsonb), and triggers → event-webhook-driven functions.

2026-06-10

New

  • Filtered, projected, and nested eager-loading on find. An include clause can now carry its own where (filter the related rows), select (project their columns), and include (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, and limit on 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 the amba_functions_get_logs MCP 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 with Amba.entitlements.has(), and cascade subscribers into segments, push, XP, and currency rewards. The Environment Promotion page now documents the monetization bundle section, the RevenueCat integration page documents the canonical secret_api_key / secret_api_key_write config fields, and the Entitlements page's SDK snippets were corrected to the real method names (entitlements.has() / entitlements.list()).

  • Storage bucket bucket_path field. Bucket admin responses (/admin/projects/:projectId/storage/buckets) now return bucket_path — the URL path segment assets are served under. The old r2_bucket_path field is deprecated: it's still accepted on create and still emitted in responses, but it's an alias of bucket_path and will be removed in a future major. Switch reads and writes to bucket_path.

Fixed

  • include now reaches the wire from every SDK. The shared engine dropped the find option's include clauses before sending the request, so eager-loading silently returned bare rows on Web, Node, and React Native. The option now passes through verbatim, and FindOptions gained the matching include field 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 (plus duration + subscription_group_name for 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-front confirm — the apply waits until you explicitly approve the started run (re-call apply with confirm, or amba monetization apply --confirm). The plan now returns a human_floor checklist 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 declared store_metadata.price is 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 with 422 MONETIZATION_STORE_FLOOR and 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 the amba_app_mcp_set_exposure MCP 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 declares mcp: { 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): an enabled kill switch, an auth_mode restriction (all / client_only / developer_only), and a hostname slug that reserves https://<slug>.mcp.amba.host/mcp for 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 (or PUT …/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) return 402 with a machine-readable payload (code, current usage, ceiling, reset date) while reads and deletes keep working. Tier quotas enforce through the same path on throttle mode (402 TIER_QUOTA_EXCEEDED). Two control-plane webhook events — billing.ceiling_warning (80%) and billing.ceiling_reached (100%) — fire once per billing period so you can alert before the flip. GET …/billing/status (and amba_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 with amba_integrations_configure({ provider: "stripe_billing", … }), map your Stripe price to an Amba product (store_product_refs.web), and pass amba_user_id in the checkout metadata. Ingest is signature-verified, idempotent, and order-safe. See Web Subscriptions.
  • Durable monetization apply. POST /admin/projects/:id/monetization/apply (and amba monetization apply / amba_monetization_apply) now starts a durable, pollable apply instead of writing in-request: the response carries an operation_id to poll via GET /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 without confirm reports confirm_required: true and holds the gated ops (up to 24h) until you re-call apply with confirm = 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_PROGRESS carries the in-flight operation_id). Migration note: the apply endpoint now returns 202 with { operation_id, status, confirm_required, gated, refused } — poll the operation for the final applied / skipped_existing / gated_applied counts 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_nearest similarity-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 next tools/list). Usage is metered: tool calls appear as the new agent tool calls axis in amba_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_cursor on the first page whenever the query has a single-column order — previously only continuation pages carried it, so there was no way to start a cursor chain. The app-MCP list/find tools default to created_at desc so 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, so Amba.collection().subscribe(), conversation subscriptions, and Amba.gamification.subscribe() stay open as long as your app does. The SDK routes there automatically when pointed at the default production API; a custom apiUrl keeps live updates on that same origin. Ships in @layers/amba-web 4.0.6, @layers/amba-node 4.0.7, and @layers/amba-react-native 4.0.5 (Expo inherits via React Native). See Live Updates.

Improved

  • React Native: offerings + Restore Purchases on npm. Amba.offerings() and Amba.entitlements.restore() (with the Offering* / RestoreResult types) are now published in @layers/amba-react-native 4.0.5 — parity with Web and Node.
  • SDK + tooling patch wave. @layers/amba CLI 4.0.4 (monetization plan/apply/adopt, payments setup/balance/payouts — amba --version now reports the real version), @layers/amba-mcp 4.0.6 (monetization, payments, auto-MCP collection tools, AI transcription + vision, media catalogs, translations), @layers/amba-shared 4.0.4, and @layers/amba-core 4.0.6 pick up everything shipped on the platform since their last publish.

Fixed

  • Collection row updates now merge JSON object columns (merge-patch). PATCH on a collection row used to replace a jsonb column wholesale, so two devices each updating their own key clobbered each other. Object values targeting jsonb columns now merge into the stored object — shallow, atomic, on every update path (single-row, bulk, update_many, and transaction update ops, client and admin alike). Arrays, scalars and null still replace the column value. Need the old overwrite behavior? Pass ?objects=replace (or objects: "replace" on a transaction op / the amba_*_update_row MCP tools). Matches the merge semantics user properties already had. See the client API reference.

2026-06-07

New

  • Monetization gated destructive apply. amba monetization apply can 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 (or confirm set to the plan_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|adopt controls 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 a product_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) and POST /client/entitlements/restore re-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.renewed events. 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 the amba_payments_account_create + amba_payments_create_onboarding_link MCP tools) creates your account and returns a hosted setup link you complete once. Then create charges server-side with application_fee_amount, and read your balance and payouts with amba payments balance / payouts. The charge returns a client_secret your app completes on-device with the platform's standard payment sheet (any Stripe-compatible client SDK). See Payments. Availability is enabled per platform; check amba payments status if 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/status gained three honest figures: recorded_overage_usd_this_period (tallied), billed_overage_usd_this_period (actually added to Stripe), and metered_billing_live (whether charging is enabled yet). Set a spend ceiling for hard 429 throttling 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 (and amba_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 the plan_hash from a fresh plan; 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). plan now returns a plan_hash. Apply needs a read-write RevenueCat key — set it as secret_api_key_write on the integration, or use one full-access key for both read and write.

Changed

  • store value "stripe" → "web". The entitlement store field'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 a recipes collection and the endpoint immediately exposes recipes_list / get / find / insert / update / delete / aggregate, with a typed, per-column where schema 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 next tools/list reflects 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(), and Amba.gamification.subscribe() now ship in @layers/amba-react-native and @layers/amba-expo with 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 gemini and 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 plan previews the three-way diff (declared vs adopted baseline vs live) with a store-floor preflight and drift; drift surfaces out-of-band dashboard edits (a daily background sweep records them automatically); export snapshots the live config to a declarative bundle; adopt records 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 or track() 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 browser online event; React Native drives flush() 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 — plus Amba.collections.optimisticInsert / optimisticUpdate / optimisticDelete convenience 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-call Amba.enablePushAutoRotation() wires expo-notifications for 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 its kind and new state) the moment it happens, and only ever surfaces the signed-in user's own updates. Backed by GET /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) and POST /v1/client/collections/transaction take 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 include to 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, and amba_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_date rather than revoking on the spot.
  • Expiry-aware reads. GET /client/entitlements now derives is_active from the expiration date, so a lapsed subscription never reads as active even before its expiry event lands. ?active_only=true filters to currently-active grants server-side.

Changed

  • Paywall engagement events are now recorded with neutral paywall_<event> names (previously superwall_<event>), and subscription user properties use neutral subscription_* keys (previously rc_*). 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 SDK ai.*.create call — or supply messages with 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 clear ai_model_not_multimodal error instead of silently dropping it. Works for Anthropic, OpenAI, and Gemini vision models; the amba_ai_prompts_invoke MCP tool gained an images parameter 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 }), then cancelLocal(id) and listScheduledLocal(). 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 by POST /v1/client/events/explain (and the admin equivalent) and the read-only amba_events_explain MCP tool. See Events → Explain.
  • AI cost visibility. Every buffered AI response now carries a cost_usd field — 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 SDK AiMessageResponse type. See AI proxy.
  • Per-prompt AI budgets. Cap a registered prompt's spend with a per-period USD ceiling (monthly, daily, or lifetime total). Once the period's spend reaches the budget, invocations are denied with a clear ai_budget_exceeded error 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 the amba_ai_prompts_set_budget / amba_ai_prompts_get_spend MCP 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 with Amba.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_object or json_schema), and opt into a Server-Sent Events stream with stream: 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_id you poll to succeeded / failed instead of guessing. See Operations.
  • Configurable XP level curve. Set xp_per_level or explicit level_thresholds per 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-Key header (or idempotency_key body 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/cohort mints N anonymous users sharing properties (and optional segments) in one call.
  • Daily content batches. Set batch_size on a content schedule to deliver N distinct items per tick (delivered as an array). See Content scheduling.
  • Message read receipts. GET …/messages/:id/receipts returns 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(), and restore(). See Collections (SDK).
  • CLI — infrastructure as code. amba export / amba diff / amba apply manage your project's reusable configuration declaratively (amba.config.json), and amba functions deploy now 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-expo 4.0.x, upgrade with npx 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 (or Prefer: 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 (ignore or update) and a conflict_target to 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 expected snapshot, so concurrent writers don't clobber each other. See Collections (Admin API).
  • Collections — group-by aggregation. Roll rows up with count, sum, avg, min, and max over 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_key on 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_balance is 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.

On this page