Changelog
Track changes to the Zyphr API, SDKs, and platform.
October 2026
2026-10-06 (magic link, gaming, anonymous, org switch)
The remaining sign-in paths complete the same way
- Game Center and Google Play Games sign-in now store a session. ⚠️ Before this, their refresh tokens could never be used, so players had to sign in again whenever an access token expired. These sign-ins now also apply stored claims,
claims_version, the session limit and suspension. They count toward MAU (test environments excluded) and fireuser.login(returning players) oruser.created(new players), withmethodset to the provider. As before, gaming tokens carry no organization context. - Magic-link sign-in now refuses suspended users and applies stored claims,
claims_versionand organization context. It now fires webhooks:user.login(method: 'magic_link') for returning users anduser.createdfor new ones. Before this it fired neither. - Switching organization now gives stored claims precedence over the refresh token's claims and embeds
claims_version, as refresh does. - Anonymous sign-in refuses a returning anonymous user who has been suspended, and applies stored claims and
claims_version. The session limit still doesn't apply to anonymous sign-ins. - Converting an anonymous account issues its new session with stored claims,
claims_versionand organization context.
2026-10-06 — session revocation
Logging out now revokes the access token too
- Access and refresh tokens carry a new
sidclaim naming the login session. It stays the same across refreshes. - Logout, revoking a single session, and
revoke_oldesteviction now reject every access token of that session immediately in Zyphr's own verification, including ones issued before its last refresh. Before this, they stayed valid until expiry (24 hours by default). The user's other sessions are unaffected. - Suspending a user (
PATCH /v1/auth/users/:idwithstatus: "suspended", or from the admin portal) now revokes all of their sessions at once. Before this, a suspended user's access tokens kept working until they expired. - Refreshing a token does not revoke the previous access token.
- Offline JWKS verifiers can't see revocations. See Revocation and the access-token lifetime.
2026-10-06
Every login method now completes the same way
Phone OTP, email OTP, passkey and OAuth logins now finish the same way password login does (the MFA hand-off is unchanged; OAuth still doesn't prompt for MFA, see #1678):
- Stored claims take precedence over
custom_claimssent at login. ⚠️ Before this, those four methods let the caller's claims override the claims you set with your secret key, for the life of that access token. - Suspended users are refused at completion. Phone and email OTP answer
400 user_inactive, the same as requesting a code. Passkey and OAuth answer403 account_inactive. ⚠️ Passkey and OAuth previously ignored suspension. - Tokens carry
claims_versionand org context (org_id/orgs), and sessions are stored under the user's environment. max_concurrent_sessionsapplies to all four (403 session_limit_exceeded).- Usage and MAU: phone OTP, email OTP and passkey logins now count toward auth usage and MAU (test environments excluded). OAuth already did. ⚠️ An account at its MAU limit will now refuse those logins for users not yet counted this month, with
402 mau_quota_exceeded, as password and OAuth logins already do. - Webhooks: OAuth now fires
user.login(method: 'oauth',provider) for returning users anduser.createdfor first sign-ins. An MFA-completed login'suser.logincarries the first-factormethodwhen it wasn't a password. - An MFA login now counts as one auth request, not two.
2026-10-05
MFA logins now behave exactly like password logins
- Tokens from a login completed with MFA (
/v1/auth/mfa/verify,/v1/auth/mfa/verify-backup) now carryenvironment_id,org_id/orgsandclaims_version, like every password login. Sessions are stored under the user's environment. MFA sessions created before this change pick upclaims_versionon their next refresh, but keep noenvironment_idororg_iduntil the user logs in again. - Stored claims set with your secret key now take precedence over
custom_claimssent at login, for MFA logins too. max_concurrent_sessionsnow applies to MFA logins. Withdeny_new, a user already at the limit gets403 session_limit_exceededat the first step (password, phone OTP, email OTP or passkey), before an MFA challenge is issued, so no TOTP or backup code is spent. Withrevoke_oldest, completing MFA evicts the oldest session.user.loginnow fires for MFA logins, withmetadata.mfa_used: true.- A user suspended between the first step and MFA completion now gets
403 account_inactiveinstead of a session. - MFA logins in a test environment no longer count toward auth usage or MAU.
August 2026
2026-08-14
Per-application and per-environment push provider configs
- Push provider configurations (APNs, FCM, Web Push) can now be scoped to a specific application and environment, not just to the project. Ship several apps from one project, each delivering through its own credentials.
- Resolution picks the most specific configuration available for the device: environment → application → project. Existing project-level configs are unchanged and remain the fallback.
- Devices are scoped at registration by the credential presented: an environment-scoped application key (
za_test_pub_*/za_live_pub_*) binds the device to that application and environment; a project secret key (zy_live_*/zy_test_*) leaves it project-scoped exactly as before. - The application is never read from the request body — there is no
application_idparameter. Scope is derived from the credential so that registering against the wrong application is unrepresentable rather than merely validated. - ⚠️ Ordering matters. The device→environment binding is set at registration and is not retroactive. A device registered with a legacy application-level key (
za_pub_*) carries no environment and falls back to the application-level config regardless of later setup — the only fix is re-registration. Create environment-scoped keys before registering devices. - ⚠️ Applications scope credentials, not isolation. Subscribers are unique per project, and push delivery targets every device under a
user_idin the project across all applications. For genuinely isolated apps, use a separate project per app. - Dashboard: configure under Applications → [App] → Push.
- Docs: see Scoping devices to an application and Core Concepts.
July 2026
2026-07-29
Native Gaming Identity (New) — Apple Game Center + Google Play Games
- Released native gaming identity providers: players sign in with their platform account (Game Center on iOS, Google Play Games on Android) — no email, no password, no OAuth redirect. Zyphr verifies the platform-signed identity server-side and issues a normal end-user session.
- New endpoints:
POST /v1/auth/game-centerandPOST /v1/auth/google-play-games. Both are public-key (X-Application-Key) only and return the standard auth result (201for a new player,200for a returning one). - Apple Game Center: the app relays GameKit's
fetchItemsoutput; Zyphr validates Apple's certificate chain, the RSA-SHA256 signature, timestamp freshness (single-use replay guard), and the bundle-id allow-list. Players are keyed on the scopedteamPlayerID. - Google Play Games: the app relays a single-use server auth code from
requestServerSideAccess; Zyphr exchanges it server-to-server with Google and reads the trusted player id from the Play Games API. The player id is never taken from the client. - Model: one Zyphr application per game (players isolated per game; no org-scoping on the gaming path). Configure providers under Applications → [App] → OAuth → Native gaming identity (Game Center bundle-id allow-list; Google Play Games web client id + write-only client secret).
- SDK methods added to all generated SDKs:
signInWithGameCenter(...)andsignInWithGooglePlayGames(...). - Docs: see Native Gaming Identity for the integration flow, dashboard configuration, and SDK usage.
Auth enhancements
- Anonymous sign-in can now be organization-scoped for multi-tenant auth apps.
- Client-safe
ZyphrClientfor public-key browser/mobile use, custom end-user claims with revocation, and configurable email-OTP were rolled out across the auth surface.
June 2026
2026-06-20
Zyphr Muse (New) — Starter / Pro / Scale / Enterprise
- Released Zyphr Muse — AI-powered authoring baked into the dashboard, grounded in your project's real data. Subject suggestions, template drafting, block rewriting, full workflow generation from a sentence, and pre-send broadcast analysis.
- Five surfaces, three model tiers: Subject suggestions (Haiku 4.5) · Template drafts + Block rewrites (Sonnet 4.6) · Workflow generation + Broadcast analysis (Opus 4.7). Per-call cost is shown in the dashboard for transparency, but customers pay for calls, not Bedrock dollars — we absorb the model cost.
- Per-action monthly quotas sized for ~90% margin at full utilization. Starter: 200 subjects / 25 drafts / 50 rewrites / 5 workflows / 4 analyses. Pro: 1,000 / 150 / 300 / 25 / 30. Scale: 5,000 / 750 / 1,500 / 100 / 150. Enterprise: unlimited, sized to a negotiated monthly volume.
- Quotas reset on the first of each calendar month UTC. Running out of one action's quota does NOT stop the others. The dashboard's Usage tab shows real-time progress against every quota.
- Per-project overrides (Pro+): project owners can lower the budget ceiling, restrict allowed roles, or block specific model tiers (e.g. disable Opus on staging projects).
- Grounding is project-scoped. Subject suggestions read your project's open-rate history. Template drafts read your template library and Handlebars variables. Workflow generation reads your configured channels and event types. Broadcast analysis reads your reputation metrics, suppression list, and scheduled-overlap window. There is no cross-project leakage.
- Privacy: AWS Bedrock as model gateway, runs Claude models in your AWS region. Anthropic does not retain prompts or completions submitted via Bedrock. Audit log records scrubbed request shapes (counts, sizes) but not raw content.
- New endpoints under
/v1/muse/*(entitlement, usage, subjects/suggest, draft, rewrite, workflows/generate, broadcasts/analyze). New dashboard tabs for Usage, Audit, and per-project Settings. - Plan packaging: Free sees the entry points with an upgrade prompt; Starter and above get progressively wider quotas; Enterprise is unlimited.
- Docs: see Zyphr Muse for the full surface area, model tiers, grounding details, and privacy model.
MCP Server v0.2.0 — Auth Organizations tools
- Released
@zyphr-dev/mcp-server@0.2.0— adds 9 Auth Organizations tools:list_organizations,get_organization,create_organization,update_organization,list_organization_members,add_organization_member,update_organization_member_role,remove_organization_member,list_organizations_for_user. - AI clients (Claude Code, Cursor, Cline, Claude Desktop, etc.) can now manage tenants inside an Auth-as-a-Service application directly from the chat surface — list orgs, add/remove members, update role labels, walk past the 50-org JWT cap.
- Read-only and ALLOWED_TOOLS guards apply as before. No
delete_organizationtool by policy — destructive ops stay in the dashboard. - Full surface: SDKs → MCP Server
Auth Organizations (New) — Pro / Scale / Enterprise
- Released Organizations — multi-tenant your auth. One end-user identity, many workspaces. The Slack model, built in.
- Each Auth application now has organizations scoped to live + test environments; end users can belong to many organizations within an environment.
- Tokens carry the active
org_idplus anorgs[]list (capped at 50; calllistOrganizationsForUserto enumerate beyond). - New
POST /v1/auth/sessions/switch-organizationmints a new token pair for the target org and rotates the refreshjti(membership verified at mint time —org_idis Zyphr-attested, no server-side re-check needed). - New SDK namespace:
zyphr.auth.organizations.{create,list,get,update,delete,addMember,removeMember,listMembers,updateMemberRole,listForUser,isMember}pluszyphr.auth.switchOrganization(...). - Dashboard: new Organizations tab on every Auth application (env-scoped Test/Live toggle, full CRUD, member management).
- Audit log: every org CRUD, member action, and
switchedevent records a row queryable by org/user via the new dashboard endpoint. - Backward compatible: every existing environment gets a backfilled Default organization; existing flat-app integrators see no change. Tokens for environments that don't adopt orgs are byte-identical to today.
- Plan packaging: Free / Starter see the Default org and can keep operating it;
organizations.createreturns403 plan_upgrade_required. Pro / Scale / Enterprise get unlimited organizations and unlimited members per org. Free customers downgraded from Pro keep read access to existing orgs (frozen mode — no new writes). - Docs: see Auth Organizations for the full primitive, the JWT shape changes, and the switch-organization flow.
2026-06-16
MCP Server (New)
- Released
@zyphr-dev/mcp-server@0.1.2— a Model Context Protocol server for AI coding clients (Claude Code, Cursor, Cline, Claude Desktop, etc.) - One-line install via
npx -y @zyphr-dev/mcp-serverplus aZYPHR_API_KEYenvironment variable - 18 tools total: 16 runtime tools (send_email, send_push, send_sms, send_inbox_message, list/get/render/create templates, find/list/create/update subscribers + set_subscriber_preferences, list/create webhooks + get_webhook_deliveries) and 2 integration tools (get_sdk_install_for_language, get_quickstart_for_channel) that help an AI wire Zyphr into a new project from scratch
- Safety guards:
ZYPHR_READ_ONLY=truesuppresses every mutating tool;ZYPHR_ALLOWED_TOOLS="a,b,c"is an explicit whitelist that overrides read-only - No
delete_*tools shipped — destructive operations stay in the dashboard - Webhook handler snippets always include HMAC-SHA256 signature verification with a 5-minute replay window
- Errors surface verbatim with HTTP status, error code, request ID, and structured details so the AI can act on them
- Full guide: SDKs → MCP Server
API
- Fixed
GET /v1/templates/:idreturning 500 instead of 404 when the ID is not a valid UUID (sc-5321)
March 2026
2026-03-19
Multi-Project Accounts
- Renamed workspaces to accounts — accounts are now the top-level billing and organizational unit
- Added projects as isolated resource environments within accounts
- Each account can have multiple projects (plan-dependent: Free=1, Starter=3, Pro=10, Scale=50, Enterprise=Unlimited)
- Two-level role system: account roles (Owner, Admin, Billing Admin, Member) + project roles (Admin, Developer, Viewer)
- Role cascade: account Owners/Admins automatically get Admin access to all projects
- Project-scoped API keys, domains, messages, subscribers, webhooks, and templates
- Per-project usage tracking with account-level billing rollup
- Account and project avatars with 24 built-in icons
Account Abuse Prevention
- Added per-user free account limit: each user can own a maximum of 2 free accounts
- Added cross-account usage aggregation: usage across all accounts a user owns is summed and enforced against free-tier limits
- Prevents abuse where users create multiple free accounts to circumvent plan limits
- Enforcement applied to all channels: email, push, SMS, in-app, and MAU
- Dashboard shows upgrade prompt when free account limit is reached
API
- Added
POST /v1/accounts— create new accounts (with free account limit enforcement) - Added
GET /v1/accounts/me— get current account with plan and limits - Added
PATCH /v1/accounts/me,DELETE /v1/accounts/me— update/delete account - Added account member management: list, invite, update role, remove
- Added account invitation management: list, resend, revoke
- Added
GET /v1/accounts/me/projects— list projects for account - Added
GET /v1/accounts/me/project-breakdown— per-project usage and resource breakdown - Added
GET /v1/accounts/me/resource-counts— account-wide resource counts - Added project CRUD: create, list, get, update, delete
- Added project member management: list, add, update role, remove
- Added
GET /v1/usage/user-aggregate— cross-account usage aggregation - Added
POST /v1/usage/reconcile— manual usage reconciliation - Removed legacy
/v1/workspacesendpoints
Documentation
- Updated Postman collection: replaced Workspaces with Accounts, added Projects and Usage folders
- Added Accounts & Projects guide with free account limits documentation
- Updated Usage & Analytics guide with cross-account usage aggregation
February 2026
2026-02-06
Documentation
- Added auto-generated API reference from OpenAPI spec
- Added Go and PHP integration guides
- Added cURL examples for all API endpoints
- Added Error Codes reference page
- Added FAQ and troubleshooting guide
- Fixed Python SDK docs (now a
requests-based integration guide) - Added Postman collection documentation
January 2026
2026-01-31
Auth-as-a-Service
- Launched Auth-as-a-Service feature set
- Added auth applications management
- Added end user management
- Added magic link authentication
- Added OAuth provider integration (Google, GitHub, Microsoft, Apple)
- Added MFA support (TOTP, SMS, email, recovery codes)
- Added security features (rate limiting, IP allowlists, session management)
API
- Added 67 new auth endpoints under
/v1/auth/ - Added comprehensive webhook events for auth actions
Documentation
- Added Auth-as-a-Service guide and feature documentation
2026-01-15
Platform Launch
- Launched Zyphr v1 API
- Email channel (AWS SES)
- Push notification channel (APNs, FCM, Web Push)
- SMS channel (Twilio)
- In-App Inbox with real-time WebSocket support
- Template engine with Handlebars
- Subscriber management with preferences
- Topic-based pub/sub notifications
- Webhook delivery with signature verification
- Node.js SDK (
@zyphr-dev/node-sdk) - React Inbox component (
@zyphr-dev/inbox-react) - Dashboard for account and project management
Versioning Policy
The Zyphr API uses URL-based versioning (/v1/). We maintain backwards compatibility within a major version:
- Additive changes (new endpoints, new optional fields) are made without version bumps
- Breaking changes will be introduced in new versions (
/v2/) with migration guides and a deprecation period - SDKs follow semantic versioning
Subscribe to the Status Page for uptime and incident notifications.