{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Embedded Components"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"embedded-components","__idx":0},"children":["Embedded Components"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Resolve embedded components let a partner display a narrowly scoped Resolve experience for one of its sub-merchants without exposing the partner's OAuth credentials in the browser. Your backend mints a short-lived embed token; the published component uses that token only for its approved merchant API routes."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"before-you-begin","__idx":1},"children":["Before you begin"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You need:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["a Resolve partner merchant account and at least one active sub-merchant"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["OAuth enabled for the partner in Merchant Dashboard"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["a standard REST API OAuth access key whose scopes include the permissions required by the component"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]}," stored only in your server-side secret manager"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the published component package and the merchant API version that its release supports"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Do not use an MCP access key for this flow. The partner OAuth credentials and the embed token are different credentials with different purposes."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-the-flow-works","__idx":2},"children":["How the flow works"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Your backend exchanges the partner OAuth access key for a partner bearer token."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Your backend calls ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /api/embed-sessions"]}," for a specified sub-merchant and component."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Resolve validates the partner, sub-merchant relationship, OAuth/API access, and the partner permissions required for that component."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Resolve returns a short-lived embed token scoped to that sub-merchant and component."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Your application provides the embed token to the published component in memory."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The component calls only its allowed merchant API routes using the embed token."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Resolve persists the session behind the token. A token is rejected if the session expires or is revoked, the issuing OAuth access key is no longer active, or the sub-merchant is no longer associated with the partner."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"1-set-up-partner-oauth-credentials","__idx":3},"children":["1. Set up partner OAuth credentials"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In Merchant Dashboard, open ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Settings > Integrations > Direct API"]}," for the partner merchant."]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Enable OAuth."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Create a standard REST API access key with the scopes appropriate for the component."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Copy the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]}," when shown, then place them in your backend secret manager."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/mint-an-access-token"},"children":["OAuth access-token guide"]}," to exchange these credentials for a bearer token. Never ship the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_secret"]}," to the browser, a mobile application, component configuration, source control, or logs."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"2-create-an-embed-session-on-your-backend","__idx":4},"children":["2. Create an embed session on your backend"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST https://app.resolvepay.com/api/embed-sessions"]}," from your backend. Send the partner OAuth bearer token and the partner API version header:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"http","header":{"controls":{"copy":{}}},"source":"POST /api/embed-sessions\nAuthorization: Bearer <partner_oauth_access_token>\nContent-Type: application/json\nresolve-api-version: partner-v1\n\n{\n  \"partner_merchant_ref\": \"child-merchant-external-id\",\n  \"component\": \"payments\"\n}\n","lang":"http"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["partner_merchant_ref"]}," can be the Resolve ID or external ID of a sub-merchant that currently belongs to your partner account."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["component"]}," is a Resolve-managed identifier. Use the identifier documented by the embedded-components package version you are installing. Component identifiers and the routes they authorize are versioned with the published package."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A successful response is similar to:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"session_id\": \"es_123\",\n  \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  \"expires_at\": \"2026-08-27T15:30:00.000Z\",\n  \"merchant_id\": \"merchant_123\",\n  \"component\": \"payments\",\n  \"capabilities\": [\"payments:read\"]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["expires_at"]}," as the source of truth. When the component needs a new token, have your backend mint another session. A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["503"]}," response means embed sessions are not configured for that Resolve environment."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"3-supply-the-token-to-the-component","__idx":5},"children":["3. Supply the token to the component"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Pass the returned ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["token"]}," to the published component using its documented token option. Keep it in memory only."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Do not place the token in a URL, local storage, session storage, cookies, analytics events, error reports, fixtures, or logs."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Do not expose the partner OAuth access token or OAuth client credentials to the component."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Do not let browser input choose the sub-merchant independently of your server-side authorization. Your backend should determine which sub-merchant session to mint for the signed-in partner user."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Treat a component authentication error as a signal to request a fresh embed token from your backend."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The component identifier used to mint the session is a server authorization choice; it does not need to match an npm export name. Follow the documentation for the exact component package release you install."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"token-lifetime-and-revocation","__idx":6},"children":["Token lifetime and revocation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Embed tokens are intentionally short-lived and are not a general-purpose API credential. Resolve rejects a token when any of the following occurs:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the token or persisted embed session expires"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the persisted session is revoked or inactive"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the source OAuth access key is revoked, disabled, deleted, or expires"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the target sub-merchant is detached from or reassigned outside the issuing partner"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the requested route or HTTP method is not allowed for the component"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The route allowlist is deliberate: possessing a permission does not automatically grant access to every API route that shares that permission. A new merchant API endpoint is unavailable to an embedded component until Resolve explicitly approves it for that component."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"api-reference","__idx":7},"children":["API reference"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/partners-api/openapi#tag/Embed-Sessions"},"children":["Embed Sessions endpoint"]}," for the full request and response contract."]}]},"headings":[{"value":"Embedded Components","id":"embedded-components","depth":1},{"value":"Before you begin","id":"before-you-begin","depth":2},{"value":"How the flow works","id":"how-the-flow-works","depth":2},{"value":"1. Set up partner OAuth credentials","id":"1-set-up-partner-oauth-credentials","depth":2},{"value":"2. Create an embed session on your backend","id":"2-create-an-embed-session-on-your-backend","depth":2},{"value":"3. Supply the token to the component","id":"3-supply-the-token-to-the-component","depth":2},{"value":"Token lifetime and revocation","id":"token-lifetime-and-revocation","depth":2},{"value":"API reference","id":"api-reference","depth":2}],"frontmatter":{"seo":{"title":"Embedded Components"}},"lastModified":"2026-09-02T20:31:30.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/embedded-components","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}