Changelog
2026-10-26 — v2.7.3
Section titled “2026-10-26 — v2.7.3”Dynamic Client Registration caps. POST /v1/oauth/register accepts at most 10 redirect_uris (512 bytes each) in a 16 KB body, and is limited to 30 registrations per hour per source IP and 500 per hour overall (429 rate_limited, Retry-After: 3600). Registered clients live 30 days: register once per installation. See Rate limits.
2026-10-26 — v2.7.2
Section titled “2026-10-26 — v2.7.2”Token endpoint hardening.
- Rate limit:
POST /v1/oauth/tokenis limited to 100 requests per 5 minutes per source IP;/v1/oauth/registerand/v1/oauth/revokeare 20 (the page said 10). WAF429s carryRetry-After: 300. See Rate limits. - Authorization codes are single-use, whatever the outcome: a token request that presents a valid authorization code consumes it, so a mismatched
redirect_uri,code_verifier,client_id,resourceorclient_secretrequires a new authorization. Do not retry the same code after an error.
2026-10-23 — v2.7.1
Section titled “2026-10-23 — v2.7.1”Account deletion: resolve answers 404 from the moment a traveler requests deletion; data deleted 14 days later. See Operations and compliance.
2026-10-23 — v2.7.0
Section titled “2026-10-23 — v2.7.0”@movmo/connect-button 3.0.0: “Not you?” is in-page, the FedCM client path is gone. See Migrating from 2.x.
| Change | Effect for you |
|---|---|
| ”Not you?” | Device-scoped and in-page: no redirect, no movmo_signed_out, onSignedOut fires once, the Movmo session stays signed in. The next click asks “Continue as {email}? / Use another account”. |
| FedCM | fedcmConfigUrl removed; mechanism is always 'rt', isAutoSelected always true. |
| Device key | Deleted when a sign-in ends without a handle (declined, or an ?error= redirect). |
| Authorize URL | rt_request and dpop_jwk travel in the URL fragment. |
POST /v1/oauth/consent: a remember-only request now returns400unless the traveler has a standing consent for your client.- Recognition limit:
recognizeandforgetare limited to 120 requests per minute per IP.
2026-10-23 — v2.6.3
Section titled “2026-10-23 — v2.6.3”Identity integration guide, Remembered devices (§4): four partner notes. Recognition never signs in, unlocks payments or opens a PNR (rule M10); “Not you?” and “Forget this device” call preventSilentAccess() for your whole origin; a silently minted code carries only the scopes already granted; the chip renders the traveler’s first name in your DOM. The storage table now lists every key the SDK writes, and Operations and compliance adds the storage-notice duty.
2026-10-20 — v2.6.2
Section titled “2026-10-20 — v2.6.2”@movmo_app/payments 0.8.0: R1 403s (recovery_cooldown, reauth_required, movmo_session_required, first_party_only) no longer trigger a session refresh; API helpers throw PaymentsApiError with status/code/until; onError payloads carry code/until; the recovery cool-down is shown with its end time.
- Details: Payments SDK.
2026-10-20 — v2.6.1
Section titled “2026-10-20 — v2.6.1”PUT /v1/users/{userId} profile contract. email and phone_number in the body are now ignored (previously email was required, so a profile-only body returned 400); the update is a full replacement of the profile fields; date_of_birth is documented as RFC3339 date-time (it always was).
2026-10-17 — v2.6.0
Section titled “2026-10-17 — v2.6.0”Access tokens are now resource-bound (RFC 8707). aud is a JSON array with the API URL first, and each surface requires its own resource in it.
{ "aud": ["https://e2e.api.movmo.io", "https://e2e.api.movmo.io/v1/mcp"] }| Surface | Requires aud to contain |
|---|---|
REST (/v1/*) | https://e2e.api.movmo.io |
MCP (/v1/mcp) | https://e2e.api.movmo.io/v1/mcp |
| Client type | Default aud |
|---|---|
| Onboarded partner | API URL only. Ask Movmo to add the MCP resource. |
| Self-registered (DCR) | API URL and MCP |
resourceparameter: accepted on the authorize and token requests. Omitted atPOST /v1/oauth/token, it inherits the authorize value; matching is exact.invalid_target: returned for aresourceoutside your client’s allowed set.- Upgrade: verify
audas an array membership check, not a string comparison. Details: Token audience.
2026-10-08 — v2.5.0
Section titled “2026-10-08 — v2.5.0”@movmo/connect-button 2.0.0: the chip recognizes a remembered device. No REST change for existing integrations; redirect_uri is simply not sent when redeeming a recognition code.
onRecognized({ code, codeVerifier, firstName, isAutoSelected, mechanism }): exchange the code atPOST /v1/oauth/tokenwithcode_verifierand your client secret, withoutredirect_uri.travelerbecomes an optional first-paint hint. Opt-in is per device on Movmo’s screen, unticked by default;recognition: 'off'restores 1.3.0 behavior.- “Forget this device” and
onForgotten(drop yourtravelerhint there); “Not you?” and Forget callnavigator.credentials.preventSilentAccess()for your origin. - Script tag:
connect/v2/connect.js(or pinnedconnect/2.0.0/connect.jswith its.srihash);v1keeps 1.x. - Upgrade: the chip now always claims the sign-out return; if you call
consumeMovmoSignOutyourself, move the handler toonSignedOutor call it before mounting. HeadlessuseMovmoOAuth/startMovmoOAuthdefault torecognition: 'off'. - Storage on your origin, limits and browser support: Remembered devices and Migrating from 1.x.
2026-10-05 — v2.4.0
Section titled “2026-10-05 — v2.4.0”@movmo/connect-button 1.3.0 places the chip for you; @movmo/express-checkout-button 2.0.2 shows a pending state. No API change in either.
- Connect chip: new
chipPositionoption ('bottom-left'default,'bottom-right','inline'). The fixed positions render into a package-owned slot ondocument.body(40px from the side, 28px from the bottom), so you write no CSS and add no wrapper. Script tag:MovmoConnect.mountButton(options)with no target;mountButton(target, options)still works, and'inline'requires the target. Upgrade by bumping the version, then delete your own chip wrapper and positioning CSS. See Add the chip. - Express Checkout button: on click it is disabled,
aria-busy, and shows “Opening Movmo…” until Movmo’s page replaces yours; it resets if the offer save fails and when the page returns from the back/forward cache. See What your users see. - Pinned script tags: update the URL and hash together (
connect/1.3.0,express-checkout/2.0.2; the.srisidecars hold the hashes).
2026-10-05 — v2.3.0
Section titled “2026-10-05 — v2.3.0”One self-switching chip: @movmo/connect-button 1.2.0. ConnectMovmoButton (React) and MovmoConnect.mountButton (script tag) now show both states: pass traveler={ firstName } from your own session for the recognized chip, null or nothing for “Checkout faster with Movmo”. No conditional logic on your side.
- Upgrade: replace
MovmoRecognizedChip/MovmoConnect.mountRecognized(1.1.0, now deprecated aliases) with the one chip and addtraveler. Script-tag handles gainupdate({ traveler }). onSignedOut: return a promise that resolves once your session is cleared; after a confirmed “Not you?” the chip stays anonymous until then. SSR: rendertraveler={null}when the URL carriesmovmo_signed_out.- Sign-out contract, return params and “Manage” are unchanged. See Not you? and sign-out.
2026-10-05 — v2.2.0
Section titled “2026-10-05 — v2.2.0”Recognized chip and “Not you?”: @movmo/connect-button 1.1.0. Once you hold a traveler’s GUID, render MovmoRecognizedChip (React) or MovmoConnect.mountRecognized(target, options) (script tag) in place of the connect chip: “Welcome back, {firstName}”, “Not you?” and “Manage”. Options: firstName, clientId (required), onSignedOut, isProd, postLogoutRedirectUri, manageUrl, collapseAfterMs.
- “Not you?” ends the Movmo session through Movmo’s own sign-out page and returns the traveler to your page; the SDK verifies the return, removes only
movmo_signed_outandmovmo_logout_state, and callsonSignedOutonce. There is no endpoint for you to call. InonSignedOut, clear your own session, greeting, pre-fill and GUID cookie. Sign-out is not consent revocation; the GUID keeps resolving until the traveler revokes in Connected apps. - No chip on the page?
consumeMovmoSignOut/MovmoConnect.consumeSignOutclaims the return; both chips also acceptonSignedOut. @movmo/express-checkout-button2.0.1 scrubs only its own return params (movmo_exit,movmo_state,movmo_booking_id,movmo_pnr), so both SDKs can share a page.- See the recognized chip.
2026-10-04 — v2.1.0
Section titled “2026-10-04 — v2.1.0”Identity is now a one-click chip: @movmo/connect-button 1.0.0 (breaking). The recognition iframe and the recognition token are retired. The traveler clicks “Checkout faster with Movmo” on your landing page; Movmo returns a code to your callback with no screen when they have a session and a standing consent, and otherwise signs them in and asks for one consent. Your backend exchanges the code and calls POST /v1/identity/resolve with the guid.
- Upgrade:
npm install @movmo/connect-button@^1.0.0, or load thev1script tag (https://cdn.e2e.movmo.io/sdk/connect/v1/connect.js; pin an exact version with SRI for production)./v0/on the CDN stays on 0.x. Replace<MovmoRecognition />/MovmoConnect.mountRecognitionwith<ConnectMovmoButton />/MovmoConnect.mountButton(target, options)on the landing page, never next to the Express Checkout button. - Callback page: check
errorfirst (a denied consent returns?error=access_deniedand no code), then callcompleteMovmoOAuth/MovmoConnect.completeOAuth. It now throwsMovmoOAuthErrorwithcode === "missing_code"whencodeis empty; show the same retry state as forMissingVerifierErrorandStateMismatchError. See the callback page. - Remove: the
onToken,onState,onSignedOut,transparency,chipPosition,readyTimeoutMs,extraOriginsoptions, the/v1/identity/recognition-tokencall from your page, your backend’srecognition_tokenresolve, and theframe-srcCSP entry. Yourlink-completeendpoint andresolve {guid}are unchanged. Clear your own session on sign-out; a GUID you stored keeps resolving until the traveler revokes your airline. - Removal date:
POST /v1/identity/recognition-tokenandrecognition_tokenonPOST /v1/identity/resolveare removed from Movmo’s API in the week of 2026-10-05. After that, resolve accepts onlyguid, and arecognition_tokenbody returns400. - Origins: your registered origins now cover CORS for the Express Checkout offer save and the Express Checkout return URL; nothing embeds in your page. Sign-in is always on Movmo’s page, with an email code or a passkey.
2026-10-04 — v2.0.0
Section titled “2026-10-04 — v2.0.0”Express Checkout is now a top-level redirect: @movmo/express-checkout-button 2.0.0 (breaking). Clicking the button navigates the whole tab to Movmo’s checkout page, and Movmo sends the traveler back to your page. The in-page overlay, the iframe, the /movmo/checkout route and the MOVMO_BOOKING_COMPLETE / postMessage events are gone.
- Upgrade:
npm install @movmo/express-checkout-button@^2.0.0, or load thev2script tag. Props are unchanged, plus an optionalreturnUrl;/v1/on the CDN stays on 1.x. - Return page: the traveler comes back by a full page load. Mount the button on the return page, or call
consumeMovmoCheckoutReturn/MovmoExpressCheckout.consumeReturnthere; SPA router state is empty. See The return. - Callbacks:
onBookingCompletethenonExitfire on that load, verified by a one-time state nonce; the airline PNR arrives only in the URL fragment. They are unauthenticated browser signals: confirm the booking server-side before fulfilling. - Remove: the
/movmo/checkout*route, anymessagelistener and theframe-srcCSP entry. Your registered origins now also gate thereturnUrl; an unregistered one gets no return link. - Sign-in: travelers sign in on Movmo’s page with an email code or a passkey, with no pop-ups or storage prompts.
2026-10-03 — v1.18.0
Section titled “2026-10-03 — v1.18.0”In-checkout passkey sign-in for Express Checkout; identity SDK improvements. @movmo/express-checkout-button 1.14.0+ and @movmo/connect-button 0.7.0+ are on npm:
- Express Checkout passkey sign-in. A returning traveler with a Movmo passkey can now sign in inside the Express Checkout iframe with one biometric, instead of the separate popup, when the browser lets the checkout use Movmo cookies (Chrome by default; others after the traveler allows it). Requires
@movmo/express-checkout-button1.14.0+; travelers without a passkey, and browsers that do not report the embedding page to the authenticator (Safari today), continue in the existing sign-in popup. The SDK grantspublickey-credentials-getto the iframe when it’s embedded on a registered origin. See What your users see and Where it can run. - Iframe permissions. From 1.14.0,
@movmo/express-checkout-buttonsets the iframe’sallowattribute tostorage-access; publickey-credentials-get. Partners who embed the checkout in a raw iframe must set the same attribute. See@movmo/express-checkout-button. - Identity SDK allow attribute.
@movmo/connect-button0.7.0 addspublickey-credentials-getto the recognition iframe’sallowattribute in preparation for identity-scoped passkey features (no behaviour change yet). See Connect button.
2026-09-24 — v1.17.1
Section titled “2026-09-24 — v1.17.1”Express Checkout guide fixes from the fourth pilot-kit validation run (a server-rendered stack, script-tag build).
- The script-tag mount no longer sets a fixed container size (the old
240×44wrapped the label); the button’s natural size is about 303×68 px, and Styling is now size and width only, matching the prompt. onExitsays your page is visible while it runs, recommends an interim state before navigating, and shows how to chain an asynconBookingComplete(the button does not await it).- Routing: a reload re-opens the overlay with the URL’s
offerId,mvsis an analytics session id, a reloaded overlay calls no callbacks, and a server-rendered site keeps the selection in its session. - Pre-saved offer ID shows the
201 { offer_id }and400 { error: { message } }bodies; theonErrorstages400row points aterror.message. - After the click:
airlineRefis your company code as registered, uppercase;search_againcomes only from “Search again” after a non-retryable failure, and a browser-back close calls noonExit. - The sandbox example now says what the checkout displays: the airline behind your
iataCode, notowner. TheproviderIDprop row lists the sandbox provider id, and the AI-assistant prompt covers rendering the API key on a server-rendered stack.
2026-09-24 — v1.17.0
Section titled “2026-09-24 — v1.17.0”Express Checkout for airlines: a product section mirroring the identity guides.
- Three new pages: Overview & onboarding, the integration guide (with the AI-assistant prompt) and Operations & compliance.
- Booking hand-off:
MOVMO_BOOKING_COMPLETEnow carriesairlinePnr, the record locator in your own reservation system, and the button takes anonBookingCompletecallback (@movmo/express-checkout-button1.13.0+). See After the click. - What your users see lists the traveler-facing states in order, with the three common symptoms.
- The
@movmo/express-checkout-buttonpage is now a package reference (install, SRI, props, styling); the build moved to the guide.
2026-09-24 — v1.16.0
Section titled “2026-09-24 — v1.16.0”Identity guide fixes from the third pilot-kit validation run (a server-rendered, no-React stack against a live e2e integration):
- The script-tag callback sample now guards a declined consent / malformed callback the same way the React sample already does, and defines the
showRetryPrompthelper it calls. - The return path: both callback samples now restore the page the traveler started from instead of always redirecting to
/, and the retry copy no longer tells a traveler to “tap the chip” on a page that has none. - Flow B defines “server-sealed cookie” (encrypted + authenticated, key from your secret store, or HMAC-derived from
client_secretwith no key store) with a Python and a Node example; What your users see coversonSignedOutfor a site with no accounts. - “Where it can run” says the origin-keyed allowlist reads the callback POST’s
Originheader, and that a CDN or gateway in front of your backend must forward it. - Uniform 404 discipline notes there’s no test GUID — revoking your airline in Connected apps is the test — and that on a server-rendered page the next
resolvecall is the retry. - The onboarding checklist now mentions the script-tag install option alongside
npm install.
2026-09-24 — v1.15.0
Section titled “2026-09-24 — v1.15.0”Script-tag build of the recognition surface (no React). @movmo/connect-button 0.6.0 is on npm:
- Any stack can now mount the recognition surface with one
<script>tag and no bundler:https://cdn.e2e.movmo.io/sdk/connect/v0/connect.jsdefineswindow.MovmoConnect, withMovmoConnect.mountRecognition(...)andMovmoConnect.completeOAuth(...)mirroring the React component andcompleteMovmoOAuth. See No React? One script tag. - Pin an exact version with Subresource Integrity for production —
https://cdn.e2e.movmo.io/sdk/connect/0.6.0/connect.jswithintegrity="sha384-Kqf/2NZVts5g/2grV+djlJl9T9bG8smNHQ4bbx6ALd88GxJ2VwjqgZXn0wgJb3hF"— or fetch the published.srisidecar for any version. - Props reference documents three new
MovmoRecognition/mountRecognitionoptions:extraOrigins(non-prod origin trust),authorizeUrl(auth UI base URL override) andstorage(a customStorageAdapterfor SSR/route-handler callbacks). - The AI-assistant prompt is now stack-aware: it tells the assistant to use the script tag for a non-React site and the React component otherwise, instead of assuming React everywhere.
2026-09-24 — v1.14.2
Section titled “2026-09-24 — v1.14.2”readyTimeoutMs default raised 10 s → 15 s; frame_timeout is a signal, not a teardown. Use @movmo/connect-button 0.5.3 or later (earlier versions still default to 10 s):
- Fixes a cold-load false negative: a slower boot handshake — a cold CloudFront edge container, a slow connection — could fire
frame_timeoutbefore the surface had a real chance to recognize the traveler, making the recognition chip intermittently absent even though it would have appeared moments later. - Props reference and What your users see are clearer that
frame_timeoutis a telemetry signal, not a teardown: the iframe keeps listening after it fires, and the chip can still appear once the network catches up. Keep your page fully usable without it — log the event, with elapsed time, for your own monitoring rather than hiding UI or treating it as permanent.
2026-09-24 — v1.14.1
Section titled “2026-09-24 — v1.14.1”A Flow A must return to the origin it started on. A site served on more than one origin (www vs. apex, a staging alias, …) needs one registered redirect_uri per origin — the fix below turned out to be a workaround for eviction, not the root cause of the incident that prompted it:
- New rule in Where it can run: build
redirect_urifromwindow.location.originplus your callback path at runtime, and have your backend send the token exchange the same value, chosen from its own allowlist keyed by the request’s origin, never taken from the browser. PKCE state is per-origin storage; a callback on a different origin cannot complete the flow. - Mobile Safari and the one-time code and What your users see each get a pointer:
MissingVerifierError/StateMismatchErrorfrom an origin mismatch fails every time on that origin, not just occasionally like tab eviction (v1.14.0) does — “works the second time, not the first” or “greeting missing on one hostname” is the tell. - The AI-assistant prompt block now tells the assistant to build
redirect_urifromwindow.location.origin, have the backend pick it from an origin-keyed allowlist, and ask for every origin the site is served on.
2026-09-24 — v1.14.0
Section titled “2026-09-24 — v1.14.0”The callback example no longer treats a failed connection as success. Use @movmo/connect-button 0.5.2 or later:
- Fixes a live defect where the callback example on this page (
MovmoCallback) treatedMissingVerifierError/StateMismatchErrorthe same as success — a silentreplace("/")with no greeting and no way to tell what happened. Causes include e.g. iOS Safari evicting a tab’ssessionStoragewhile the traveler switches to Mail to read a one-time code (see the origin-mismatch cause added in v1.14.1). The example now shows a visible “tap the Movmo chip to try again” state and logs the error name; success is judged only by a 2xx from your ownlink-completeendpoint, never assumed on redirect. See Add one thin OAuth callback page. @movmo/connect-button0.5.2 mirrors PKCE state tolocalStoragewith a 10-minute TTL alongsidesessionStorage, so the lost-tab case above self-heals with no code change on your side; a customstorageadapter is still available. See Mobile Safari and the one-time code.- The AI-assistant prompt block states the same rule explicitly, and What your users see gets a troubleshooting bullet for a missing greeting after the first sign-in on a phone.
2026-09-23 — v1.13.0
Section titled “2026-09-23 — v1.13.0”The recognition surface reports sign-out: onSignedOut. @movmo/connect-button 0.5.1 is on npm:
<MovmoRecognition onSignedOut={() => …}>fires once after the traveler’s “Not you?” inside the surface — after Movmo’s own session is already cleared in this browser (other devices unaffected). Clear your own session for this traveler (greeting, pre-fill, any cookie carrying the GUID), but keep a consented GUID: logging out and removing consent are two different actions, and revocation still shows up as the 404 you already handle on resolve. See Props reference and What your users see.- Supersedes the earlier “a dedicated sign-out callback is on the roadmap” note and the do-it-yourself “Not you?” advice for Flow B sites — wire the callback, build nothing.
2026-09-23 — v1.12.0
Section titled “2026-09-23 — v1.12.0”Express Checkout button ships an exports map; the button reports save failures via onError. @movmo/express-checkout-button 1.12.0, @movmo/connect-button 0.5.0 and @movmo_app/react-common 0.13.0 are on npm (PR #183):
@movmo/express-checkout-buttonnow ships proper ESM/CommonJS builds behind anexportsmap (import,require,./dist/index.css), so it loads in plain Node, Vitest/Jest and SSR frameworks without the bundler workarounds the Install (React) section previously documented; in SSR the component itself still renders client-side.- The button’s offer-save failure is no longer silent to your code: it always logs
console.warn('[movmo] express checkout: offer save failed', { status, message })and now calls anonError({ stage, status?, message })callback —stage: 'save_offer'for a failedcreateProviderOffercall,stage: 'missing_offer'when neitherflightOffernorflightOfferIDwas passed. The script-tagmount()accepts the same option. See Handling save failures. @movmo/connect-button0.5.0 and@movmo_app/react-common0.13.0 carry the same README/exports-map fix; no behavior change for the identity guide beyond the version bump.
2026-09-23 — v1.11.1
Section titled “2026-09-23 — v1.11.1”Sandbox provider offers are now validated at save time (MOVMO-672). createProviderOffer for the sandbox provider used to accept any shape with 201 and only fail when the checkout read the offer back (undefined fields, a stuck click). It now rejects a bad offer immediately with 400 and a message naming the field; nothing is stored. Slice, segment and layover duration also now accepts ISO 8601 ("PT1H25M") in addition to "N hr M min" ("1 hr 25 min") — read-back is always "N hr M min". See the updated rules in “The offer object” and OfferSlice/OfferSegment in openapi.yaml.
2026-09-23 — v1.11.0
Section titled “2026-09-23 — v1.11.0”Express Checkout page rebuilt from the second validation run (an engineer following only that page on a Vite app against the e2e sandbox provider), plus one platform fix:
- Registered origins now get CORS as well as iframe trust. The button’s offer save and analytics beacon are cross-origin calls from your page; until now the response headers came from a static list, so a registered partner’s click did nothing. Identity partners’ embed origins now pass both the API Gateway preflight and the API’s CORS check automatically. The new Where the button can run section says what an unregistered origin looks like and how to detect it.
- The offer object: per-provider shape (PSS JSON or provider offer id — the adapter does the unwrapping; Duffel is id-only), a complete sandbox-provider example, and the rules that were previously discoverable only by trial — decimal-string amounts, the empty
passengers[].id(the checkout fills it; a non-empty value breaks passenger entry),provider_passenger_idback-references, the"1 hr 25 min"duration format, zone-less local times — and the offer lifecycle (30-minute expiry, bound to the first account that opens it).openapi.yamlgainedOfferSlice,OfferSegment,OfferPassengerSlot,OfferCarrierandOfferPlaceschemas. - Server-side save example for the pre-saved offer ID mode; routing rule for
/movmo/checkout/*; the sign-in popup; a plainmessagelistener instead of “intercept it”; the1.11.1package’s Node-loading gap with the Vitest and Next.js workarounds; version header, label wording and SRI example updated to1.11.1. - The AI-assistant prompt now names the sandbox-provider shape, the passenger-id rule, the router rule and what a dead click means.
2026-09-23 — v1.10.1
Section titled “2026-09-23 — v1.10.1”Identity guide fixes from the first end-to-end validation run (an engineer following only these pages on a Vite app):
@movmo/connect-button0.4.1 (and@movmo/express-checkout-button1.11.1) no longer read a Create-React-Appprocess.envoverride without a guard; 0.4.0 threwReferenceError: process is not definedat mount under Vite and similar bundlers. The mount step now says 0.4.1+ and gives the stopgap for older pins.- One backend path everywhere (
/api/movmo/link-complete); the callback example checks the response status and no longer lets the browser supplyredirect_uri. - The 404 rule is stated one way on every page: delete the stored GUID, never retry it; recover with the next recognition token.
- Flow B for sites without customer accounts (a server-sealed HttpOnly cookie is an acceptable store), what “Not you?” does and doesn’t tell your page, both anonymous chip texts, the expected console 403 from the iframe’s session probe, and a note for stacks without React.
2026-09-23 — v1.10.0
Section titled “2026-09-23 — v1.10.0”Registered origins are embed origins; identity endpoints in the OpenAPI spec.
- The origins of an identity partner’s registered redirect URIs (plus its airline domain) are now the origins allowed to embed Movmo’s recognition surface and the Express Checkout iframe — automatically, within minutes of registration, with no deploy on either side. Register every host you embed from; see Where it can run. The public directory backing this is
GET /v1/identity/embed-origins. POST /v1/identity/resolve,POST/DELETE /v1/identity/loyalty-linkandGET /v1/identity/embed-originsare now inopenapi.yamlunder theIdentitytag (53 operations), matching the prose contract that was previously the only reference. The AI-assistant prompt is checked against the spec in CI on every docs change.- The Express Checkout button page gained its own AI-assistant prompt.
- Effort framing removed from the identity pages: the build is described by its parts (What you build), not by a day count.
2026-09-04 — Amadeus provider removed
Section titled “2026-09-04 — Amadeus provider removed”The amadeus provider id is no longer accepted. Amadeus shut its developer/test environment in June 2026, so the adapter could not be exercised anywhere and has been removed from the platform. Partner-observable changes:
providerpath parameters and the Express Checkout button’sproviderIDacceptdarwin,duffel,dohoponly;amadeusreturns404.GET /v1/flights/providersno longer listsamadeus; the MCP resourcemovmo://providers/amadeusno longer resolves.- The provider coverage matrix now has three rows. Also corrected: Dohop does require the separate pricing step (
requires_pricing: true), matching its runtime capabilities. - The
@movmo/express-checkout-buttonpackage still ships its Amadeus- and Sabre-shapedflightOfferTypeScript types (they describe an airline PSS payload, not the Amadeus API), but no live adapter consumes the Amadeus shape. Submit the payload shape the adapter you name inproviderIDexpects — seecreateProviderOffer.
2026-09-03 — v1.9.0
Section titled “2026-09-03 — v1.9.0”Loyalty claim scoped to your own program; revocation and scope hygiene. Three partner-observable changes on the identity surface:
- The
loyaltyclaim group on/v1/identity/resolvenow returns only the programs your airline linked for the traveler. Previously every membership saved on the traveler’s Movmo profile was returned with a per-carrierverifiedflag; memberships with other airlines are no longer disclosed, andverifiedis alwaystruefor a returned program. - When a traveler turns off recognition for your airline entirely, your loyalty links are now revoked and the member data you supplied is deleted — the same effect as your own
DELETE /v1/identity/loyalty-link. See the updated loyalty revocation matrix. Turning offloyalty.readalone still keeps the association. - Scopes outside the set registered for your
client_idare dropped before the consent screen (defaultprofile.read+preferences.read, plus scopes enabled for you at onboarding). Read thescopefield of the token response rather than assuming you received what you requested — see Flow A.
2026-08-28 — v1.8.0
Section titled “2026-08-28 — v1.8.0”Loyalty account linking is now available, in early access — extends the loyalty single login with a public API contract. Two new endpoints on the identity surface:
POST /v1/identity/loyalty-link— associate a consenting traveler’s pairwise GUID with their membership in your loyalty program. You supply the member number, your loyalty account reference, your airline name/IATA code, and averification_method(member_otp,loyalty_session, orenrollment) recording how you verified ownership through your own channel, plus optionally the tier/points you want reflected back through resolve — Movmo never fabricates member data. Returns201 {"linked": true, "program_code": "..."}.DELETE /v1/identity/loyalty-link— remove an association; idempotent, returns200 {"linked": false, "program_code": "..."}whether or not a link existed.
Both authenticate with the same client_secret_basic credentials as resolve and share its anti-enumeration property: an unknown, revoked, or not-yours GUID is a uniform 404 {"error":"unknown_guid"}. Linking is independent of disclosure consent — a traveler can be linked without ever granting loyalty.read, and revoking loyalty.read alone stops disclosure without dropping the association. See the new loyalty claim group, the Loyalty account link section of the integration guide, and the loyalty revocation matrix.
2026-08-24 — v1.7.0
Section titled “2026-08-24 — v1.7.0”New: Identity for airlines — a full onboarding and integration guide for the Movmo identity layer, live on the e2e environment for integrating partners. Three new pages:
- Overview & onboarding — recognize consented travelers on your own site with no PSS change: the two-layer architecture (browser recognition vs. server-to-server consent + data), the pairwise per-airline GUID, what you build vs. what Movmo provides, and a concrete onboarding checklist.
- Integration guide — the build with copy-paste examples: the
<MovmoRecognition />embed and props reference, the OAuth callback page, the three backend flows (first connection, stored-GUID resolve, anonymous recognition-token resolve atPOST /v1/identity/resolve), and the scope-gated claim set. - Operations & compliance — security checklist, day-2 operating responsibilities, and your GDPR duties as an independent controller.
The identity surface uses the same confidential-client credentials and consent machinery documented on the Authentication page; recognition tokens and pairwise GUIDs are the new, identity-specific concepts the guide introduces.
2026-08-09 — v1.6.5
Section titled “2026-08-09 — v1.6.5”Documentation reconciliation pass — no runtime behavior changes, but several pages had fallen behind what is already shipped:
- The MCP tool catalog now lists two tools that have been live for a while but were missing from the docs:
get_bags(checked-bag options for an offer; feedscreate_booking’sbag_selections) andupdate_payment_method(edit cardholder name / billing ZIP on saved cards — card addition remains deliberately unexposed over MCP). - Under review no longer claims scopes are unenforced — scope enforcement shipped (see the v1.3.0–v1.6.4 entries below) and the stale section pointed at a heading that no longer exists.
- The
@movmo/connect-buttonexamples now carry theisProdcallout: since v0.3.0 the package defaults to Movmo’s e2e environment, so production integrations must passisProd. - SDK pages updated to current package versions:
@movmo_app/payments0.6.0 (newonEventaction callback,useUpdatePaymentMethodhook) and@movmo/express-checkout-button1.10.1 (booking-complete nowreplaceStates the checkout history entry so back-navigation after “Return to airline” lands on your real pre-checkout page;onExitgains the"booking_confirmed"reason).
2026-07-27 — v1.6.4
Section titled “2026-07-27 — v1.6.4”Consent is now granular per scope (MOVMO-455, monolith-api #279). On the consent screen, users can untick individual permissions before approving — the resulting authorization code, and the token it exchanges for, are bound to the intersection of what you requested and what the user left checked (requested ∩ granted). Always read the token response’s scope field rather than assuming you received everything you asked for; see the new Granular consent section.
Two related behavior changes:
- A scope the user has previously declined for your client is not re-offered on later authorizations — the code is simply issued without it, and only never-yet-decided scopes trigger the consent screen. If the user declines every requested scope, the code request fails
400 invalid_scope. - Users can now toggle individual permissions off or back on for a connected client from Connected apps, without disconnecting the client entirely. See the updated Revocation section.
Calls needing a scope the user withheld still fail 403 insufficient_scope exactly as documented in Enforcement — that contract is unchanged, only how the underlying grant is negotiated. The MCP reference is updated with guidance for agents that may now receive a real subset of their requested scopes: degrade gracefully per tool rather than failing the whole session.
2026-07-16 — v1.6.3
Section titled “2026-07-16 — v1.6.3”The Security & data handling analytics disclosure now covers the post-booking satisfaction rating — a one-click, 1–5 booking-experience score collected on the confirmation page (numeric only; the card has no free-text field), with a screenshot of the card as travelers see it. Documentation only; the rating itself has always been part of the checkout.
2026-07-15 — v1.6.2
Section titled “2026-07-15 — v1.6.2”The Security & data handling page’s Analytics section is now a categorized breakdown (MOVMO-519) — funnel/interaction events, product-quality signals captured inside Movmo’s checkout only, technical context, and the per-tab session identifier — plus an explicit “what’s never captured” list. No behavior change; documentation only.
2026-07-15 — v1.6.1
Section titled “2026-07-15 — v1.6.1”New Security & data handling page (MOVMO-519), written for partner security and data-protection reviewers. Covers the PCI boundary for payment card data (hosted fields, vault token, forwarding to the airline’s own PSP, “PCI-descoped by architecture”), traveler PII handling (field-level KMS encryption, passwordless accounts, consent and deletion), the Express Checkout button’s footprint on a partner page (no cookies, no page observation, iframe isolation, CSP frame-src guidance), first-party analytics, platform controls, sub-processors, and Movmo’s current compliance posture. Linked from Authentication and the @movmo/express-checkout-button page. No API or SDK behavior changes — documentation only.
2026-07-13 — v1.6.0
Section titled “2026-07-13 — v1.6.0”Express Checkout is now embeddable with a single script tag — no React, no build step (MOVMO-513/514). @movmo/express-checkout-button@1.9.0 ships a self-contained browser bundle hosted on the Movmo CDN:
- Auto-updating:
https://cdn.e2e.movmo.io/sdk/express-checkout/v1/express-checkout.js - Version-pinned + SRI (immutable, sha384 hash published per release):
/sdk/express-checkout/1.9.0/express-checkout.js
The bundle exposes window.MovmoExpressCheckout.mount(target, options) taking the same options as the React component’s props, carries React internally, and injects its own styles — the default Movmo-branded button needs zero CSS from the host page. This unlocks Express Checkout for non-React stacks (Vue, Angular, server-rendered templates, plain HTML). The React package surface is unchanged; 1.9.0 also adds a fix so overlay restore-on-refresh works when the script loads after DOMContentLoaded. See the updated @movmo/express-checkout-button page.
2026-07-03 — v1.5.0
Section titled “2026-07-03 — v1.5.0”Users can now self-revoke a connected app’s access (MOVMO-408). A new Connected apps page in Movmo account settings lists every application/agent holding an OAuth grant and lets the user revoke it. Revocation takes effect within minutes — the user’s session tokens are invalidated immediately and the underlying consent is deleted. For partners this surfaces on the token endpoint: a refresh attempt after revocation returns 400 invalid_grant (session invalidated) or 400 invalid_scope (consent gone); either means re-authorize from scratch. See the new Revocation section. No new partner-facing endpoint — the management surface is first-party.
2026-07-03 — v1.4.0
Section titled “2026-07-03 — v1.4.0”Movmo scopes are now advertised in discovery, and consent is the default for dynamically-registered clients (MOVMO-409, completing the epic’s discovery story):
scopes_supportedon both discovery documents — RFC 8414/.well-known/oauth-authorization-serverand the MCP server’s RFC 9728/.well-known/oauth-protected-resource— now lists the OIDC identity scopes plus the full ten-scope Movmo catalog. MCP clients and OAuth libraries that derive theirscoperequest from discovery route through the consent screen automatically.- Scope-less requests from dynamically-registered clients (RFC 7591) are now defaulted to the full ten-scope catalog: the consent screen is always shown and the issued token is narrowed and enforced. Omitting
scopeno longer bypasses consent for agents. Pre-registered partner clients keep the legacy un-narrowed scope-less behavior. See the updated Tokens without scopes. - Rollout is graceful: grants issued before this change continue to refresh without narrowing; the new behavior applies from each client’s next full authorization.
- The MCP reference Scopes section and the OpenAPI spec’s discovery-metadata schema are updated to match.
2026-07-03 — v1.3.0
Section titled “2026-07-03 — v1.3.0”Partner-level OAuth scopes and user consent are live (epic MOVMO-346). The Authentication page replaces the “Scopes (planned)” stub with the full model:
- The authorization redirect accepts a space-delimited
scopeparameter drawn from a ten-scope catalog (profile / preferences / passengers / payments / bookings, each split.read/.write; write does not imply read). Unknown values are rejected with400 invalid_scope. - A Movmo-hosted consent screen appears after sign-in whenever the requested scopes exceed the user’s prior grants to your client — first-time users see the full list, returning users only the delta. Consent is per-client and incremental (new approvals merge with prior grants). Denial redirects to your
redirect_uriwitherror=access_deniedand yourstate. - The token response now echoes the effective
scope(RFC 6749 §5.1) on both grants — always the intersection of your request and the user’s current consent. Refresh preserves the original grant’s scopes and never escalates; after a consent revocation the refresh grant fails with400 invalid_scope. - Enforcement: requests made with a scoped token outside its grants return
403 {"error":"insufficient_scope", "scope":"<required>"}with an RFC 6750WWW-Authenticatechallenge (delivered asx-amzn-remapped-www-authenticatethrough API Gateway). See Errors. - No breaking change: tokens issued without a
scoperequest are not narrowed and keep the user’s full permissions — the pre-scopes behavior, still the default for autonomous MCP agents until the Movmo scopes are added toscopes_supportedin discovery (upcoming). A new Scopes section on the MCP reference covers the agent perspective.
The OpenAPI spec adds the scope field to OAuthTokenResponse and rewrites the top-level scopes note to the shipped behavior.
2026-06-01 — v1.2.1
Section titled “2026-06-01 — v1.2.1”The @movmo_app/payments reference is updated for 0.5.0. <PaymentMethodsManager> now accepts an optional onError callback that fires for every user-facing failure with a discriminated source (list, tokenization-session, spreedly-script, card-tokenize, save-from-token, set-default, update, delete) — partners wire it to telemetry (e.g. Sentry) and/or UI gates. The callback is additive: errors are still rendered in-component. A new Error handling section documents the PaymentManagerError shape and the source values, and <MovmoCardForm> gains a matching onErrorDetail prop. The page also now documents the edit-card row action (cardholder name + billing ZIP on Spreedly-vaulted cards).
2026-05-26 — v1.2.0
Section titled “2026-05-26 — v1.2.0”New JavaScript / React SDKs sidebar section documents the two publicly-published partner-facing React packages. @movmo_app/payments wraps Spreedly Hosted Fields and the createPaymentMethodFromToken exchange into drop-in components — partners who want to embed Movmo card capture in their own UI now have a documented on-ramp without needing to redirect users to the Movmo accounts UI. @movmo/express-checkout-button — already published on npm but previously undocumented — gets its own reference page covering both raw-offer and pre-saved-offer-ID modes, props, and the iframe postMessage lifecycle.
The Payments domain page now cross-links to the SDK page for partners who want to embed capture directly.
No changes to the REST or MCP surface — this release is documentation only.
2026-05-26 — v1.1.2
Section titled “2026-05-26 — v1.1.2”The Payments domain page and the matching OpenAPI sections have been rewritten to describe the vault + Receiver-forwarding model. Movmo is documented as never being the merchant of record — at booking time Movmo forwards the vaulted card to the airline’s PSP, which authorizes the charge and owns 3DS / SCA.
The PaymentMethod response shape is leaner: id, userId, methodType, last4, brand, expMonth, expYear, isDefault, createdAt, updatedAt. Legacy customerId, paymentMethodId, and token fields are no longer documented and should be ignored if present in transitional responses.
The CreateBookingRequest shape drops customer_id. Partners pass only payment_method_id (the Movmo UUID read from GET /v1/users/{userid}/payment-methods) at booking time. Existing integrations that already pass payment_method_id need no changes; those still sending customer_id should remove the field — it is ignored server-side.
Card capture is documented under a new operation: POST /v1/users/{userid}/payment-methods/from-token. It exchanges a vault token (produced in the Movmo accounts UI by Hosted Fields against the PCI vault) for a Movmo payment method UUID. The previously documented bare POST /v1/users/{userid}/payment-methods is removed from the partner-facing surface. Partners do not call the capture endpoint directly — they read existing methods and pass id on bookings.
DELETE /v1/users/{userid}/payment-methods/{methodid} is documented as best-effort against the vault: the server attempts to redact the vault token, then deletes the local row regardless of the vault result so the UI removes the card immediately. A 204 means the card is gone from the partner-visible surface; orphaned vault tokens are reconciled out-of-band.
2026-05-03 — v1.1.1
Section titled “2026-05-03 — v1.1.1”DELETE /v1/flights/providers/{provider}/bookings/{booking_id} now returns 403 Forbidden when the calling user is not the booking owner (and not an admin). Previously the handler authorized on the bookings:delete permission only — any authenticated caller holding that permission could cancel another user’s booking by guessing the booking ID. The handler now mirrors the ownership check already applied to the matching GET operation: it fetches the booking, verifies booking.user_id against the caller, and rejects cross-user cancellations.
The cancelProviderBooking operation in the OpenAPI spec now lists 403 and the temporary authorization caveat in the operation description has been removed.
2026-05-02 — v1.1.0
Section titled “2026-05-02 — v1.1.0”The Authentication page now leads with @movmo/connect-button — a published React component that bundles PKCE generation, state issuance, sessionStorage round-trip, and the redirect to auth.movmo.io. Drop the button onto your sign-in page; pair completeMovmoOAuth() on your callback page to validate state and forward code + code_verifier to your backend. Headless useMovmoOAuth() is exported for partners with their own CTA component.
The seven-step manual walkthrough remains for non-React partners (Vue, Svelte, plain JS, native mobile) under a Building your own subsection.
The token exchange itself is unchanged — client_secret still cannot reach a browser, your backend still calls POST /v1/oauth/token. This release only changes the recommended frontend on-ramp.
2026-05-02 — v1.0.1
Section titled “2026-05-02 — v1.0.1”POST /v1/oauth/token now accepts Authorization: Basic credentials on the refresh_token grant for confidential clients registered with token_endpoint_auth_method: "client_secret_basic". Previously the refresh grant rejected Basic with 400 invalid_client and required client_secret in the form body. The authorization_code grant has always accepted Basic; the bug was specific to refresh.
Both client_secret_basic (header) and client_secret_post (body) now work on both grants. Partners who worked around the issue by sending client_secret in the form body can switch to Basic — the spec-preferred method per RFC 6749 §2.3.1 — or keep using body credentials.
2026-05-02 — v1.0.0
Section titled “2026-05-02 — v1.0.0”Initial public release of the partner API surface.
- 49 REST operations across Authentication, Profile, Passengers, Payments, and Flights — see the OpenAPI spec.
- MCP server with tool and resource parity for the Aviare-scoped surface — see the MCP reference.
- Provider coverage: Amadeus, Duffel, Dohop, Darwin — see Provider coverage.