Skip to content

Changelog

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 a verification_method (member_otp, loyalty_session, or enrollment) 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. Returns 201 {"linked": true, "program_code": "..."}.
  • DELETE /v1/identity/loyalty-link — remove an association; idempotent, returns 200 {"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.

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 at POST /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.

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; feeds create_booking’s bag_selections) and update_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-button examples now carry the isProd callout: since v0.3.0 the package defaults to Movmo’s e2e environment, so production integrations must pass isProd.
  • SDK pages updated to current package versions: @movmo_app/payments 0.6.0 (new onEvent action callback, useUpdatePaymentMethod hook) and @movmo/express-checkout-button 1.10.1 (booking-complete now replaceStates the checkout history entry so back-navigation after “Return to airline” lands on your real pre-checkout page; onExit gains the "booking_confirmed" reason).

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.

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.

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.

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.

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.

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.

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_supported on both discovery documents — RFC 8414 /.well-known/oauth-authorization-server and 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 their scope request 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 scope no 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.

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 scope parameter drawn from a ten-scope catalog (profile / preferences / passengers / payments / bookings, each split .read / .write; write does not imply read). Unknown values are rejected with 400 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_uri with error=access_denied and your state.
  • 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 with 400 invalid_scope.
  • Enforcement: requests made with a scoped token outside its grants return 403 {"error":"insufficient_scope", "scope":"<required>"} with an RFC 6750 WWW-Authenticate challenge (delivered as x-amzn-remapped-www-authenticate through API Gateway). See Errors.
  • No breaking change: tokens issued without a scope request 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 to scopes_supported in 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.

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).

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.

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.

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.

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.

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.

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.