# Connect your app to Mementom For a first integration, follow the [company walkthrough](/developers/api/#first-integration). It includes downloadable Node route wiring and a check after each step. Start with the [three cumulative integration recipes](/developers/guides/integration-tiers.md): Tier 1 connects sessions and permitted insights; Tier 2 adds rights and challenges; Tier 3 adds account-specific sign-in. Use one consolidated server SDK and the shared browser controller. Complete framework adapters are planned; the current SDK helpers and reference examples are described separately in that guide. Keep two secrets on your server: your company server credential and this app's private RSA key. Setup registers its public key and retrieves the configuration through the API. You do not paste public-key JSON or copy challenge/key IDs. ## Backend choices and SDK coverage This guide uses the JavaScript server SDK. Mementom itself uses a language-neutral HTTPS/JSON contract: Python, .NET, Java, PHP and Go do not need a Node backend. See [backend integration and current adapter coverage](/developers/guides/backend-contract.md). The same [browser window controller](/developers/guides/browser-window.md) works with every backend. The single server download now includes authentication, company API methods, insights, optional session cookies and the separately authenticated Marketing API. Existing imports and download names remain compatible. ```js const { api, configuration } = await mementom.forAttempt(); // client remains an alias. const catalog = await mementom.insights.getCatalog(); const session = mementom.forSession(currentSessionId); await session.insights.ingest({ expectedRevision: catalog.revision, datasetId, eventId, sample }); const permitted = await session.insights.read(); ``` These calls require the setup/connection shown below and a current backend session. An insight write also requires an approved dataset and holder permission. For a custom installation, set both `baseUrl` for authorization and `apiBaseUrl` for public insight calls. General company API methods remain available on `api`. ## First setup 1. In your app's Integration page, enter its website and the return route your server actually handles. Choose account sign-in if your app has accounts. 2. Download the server SDK and the generated setup file. Keep both files together in your server project. The setup file already contains this app's public ID and addresses. The SDK is Node.js server code; do not load it in a browser. 3. Set `MEMENTOM_VENDOR_CREDENTIAL` and `MEMENTOM_RESPONSE_PRIVATE_KEY` in your server's secret store, then run `node mementom-setup.mjs` on your server. The company credential is shown once at company registration. Reuse it for the company's apps. If it is lost, use the console's credential replacement flow; replacement affects every app using the old credential. For a new app without an RSA key, generate one **on your server** using its key management tools. For example, this Node script creates a 2048-bit PKCS#8 PEM file with owner-only permissions and refuses to overwrite an existing file: ```js import { generateKeyPairSync } from 'node:crypto'; import { writeFileSync } from 'node:fs'; const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 }); writeFileSync('mementom-private.pem', privateKey.export({ type: 'pkcs8', format: 'pem' }), { mode: 0o600, flag: 'wx' }); ``` Store that PEM value as `MEMENTOM_RESPONSE_PRIVATE_KEY` using your server's secret store. Exclude the temporary PEM file from Git. If this app already has a registered key, use its existing matching private key; do not generate a replacement. Setup is an explicit installation operation. It safely reuses the same public-key registration and completed setup on a repeat run. It does not overwrite custom policies, change a saved callback, rotate an existing key, grant account access, or rewrite settings on ordinary server startup. Resolve any reported conflict in the relevant existing setting before retrying. ## Connect after setup Your server needs only these Mementom inputs: | Input | Where it belongs | | --- | --- | | Application ID | Server configuration; not a secret | | Company server credential | Server secret store | | Private RSA response key | Server secret store; never sent to Mementom | ```js import { Mementom } from './mementom-sdk.mjs'; const mementom = await Mementom.connect({ applicationId: 'APP_ID_FROM_YOUR_GENERATED_CODE', // Already filled in by the console. credential: process.env.MEMENTOM_VENDOR_CREDENTIAL, privateKey: process.env.MEMENTOM_RESPONSE_PRIVATE_KEY, }); // At the beginning of each flow: const { client, configuration } = await mementom.forAttempt(); const { applicationId, origin, responseDestinationId, challenges } = configuration; const loginActionId = challenges.login.actionId; const callbackUrl = challenges.login.returnUri; // Account rights: challenges.accountAccess.actionId (no account challenge created). // Explicit challengeRequired:false uses client.useAccountAccess with no extra prompt. ``` The SDK retrieves configuration from the authenticated Developer API, matches the private key locally to this app's active public keys, and loads Mementom's decision-signing keys. Origin, callbacks, company ID, challenge IDs, and response key IDs are not separate deployment variables. Production service discovery is anchored to `https://auth.mementom.app`; an explicit trusted `baseUrl` override is available for local development. Never take it from a browser request. ## Retain a snapshot for each attempt `forAttempt()` shares a server-memory cache for at most 60 seconds. Concurrent loads are combined. On expiration, the next call retrieves fresh configuration; there is no background timer or persistent settings file. `refresh()` refreshes immediately. A failed refresh prevents new attempts from using the old cache. Keep the returned `configuration` with that attempt's server-side state. It is immutable. Later refreshes cannot change it. Across a restart or load-balanced callback, retrieve a current SDK client for decryption but verify the response against the original stored state, app, session, request, action, resource and callback bindings. Do not substitute freshly retrieved bindings for the pending attempt. The API still enforces live rights, revocation and one-use results. ```js import { randomBytes } from 'node:crypto'; const state = randomBytes(32).toString('base64url'); const issued = await client.createConnectionRequest({ applicationId, challengeActionId: loginActionId, state, ...(responseDestinationId ? { responseDestinationId } : {}), }); // Persist state + requestId + configuration, bound to this browser's session. // Pass issued.consumerUrl to the browser window component through your start endpoint. // On return: check the saved state and callback before exchanging its code. // Exchange using the saved applicationId and responseDestinationId. // Verify the resulting request/session bindings before signing into your app. ``` Use the [browser window component](/developers/guides/browser-window.md) to manage opening, returning, cancellation, timeouts and cleanup. Setup does not create app accounts or grant account rights. After Login and your own account verification, call `client.linkAccountAccess` under that same server-side session to associate the account with its current keyring. Invitation APIs remain available to grant new rights. Follow the [account-access guide](/developers/guides/vendor-account-access.md) for both flows. Your application still owns session storage and cookie/security policy. Use your framework’s session support. If it requires a session secret, create and store that on your server; it is not another Mementom credential. ## Changes, failures and key rotation `MementomSetupError.code` identifies the problem without including credentials or private key content. Common codes include `vendor_credential_rejected`, `application_not_found`, `integration_setup_required`, `integration_challenge_required`, `response_key_not_registered`, and `challenge_response_key_mismatch`. Correct the setting in Integration or the server's secret store, then retry. Never treat a setup error as successful login. An existing challenge may still reference an older active response key. The SDK checks the actual challenge binding; it does not assume the newest key wins. Coordinate key rotation with pending attempts. The advanced `MementomVendorClient` remains available for multiple retained private keys or KMS/HSM `decryptKey` providers; it is not required for ordinary setup. ## Migrating an existing integration Keep your existing explicit challenge bindings, replace manual client construction with `Mementom.connect`, and obtain the values above from each attempt's snapshot. Remove separate origin, return-URI, login-action, account-action, company-ID and response-key-ID deployment settings only after the adapter uses discovery. Preserve existing cookies, durable state, account mapping, rights checks and callback validation. Installing the SDK alone does not migrate an older adapter. Harbor and Aster use the shared server adapter and this discovery path, while retaining their individual action challenges. Aster also retains its demonstration builder. Harbor's [marketplace contract](harbor-marketplace.md) separates public shopping, optional Mementom connection, private-auction access and bid approval. The exact registered Harbor Connect action verifies one personal key without a Harbor invitation or prior login right. It does not alter other companies' policies, shared/delegated owner restrictions or insight-sharing permission. The active action ID is `connect`; `login` is a separate legacy definition with a two-key source default, not a one-key alias. The single server SDK download does not contain Harbor's storefront, commerce backend or shared reference adapter. The [Harbor module guide](harbor-marketplace.md) explains those layers. Their reference-app registration is automated through the authenticated API; ordinary integrations use the explicit server setup operation. Custom integrations can retain their own published challenge bindings. ## Diagnose a failed setup or login The three-input SDK writes structured JSON diagnostics to your server's standard output by default. Mementom writes matching API diagnostics to its own server logs. No extra environment variable or debug mode is required. Each received API response carries an `x-mementom-request-id` support reference. The SDK preserves it as `error.diagnosticId`; network failures have a local reference because no Mementom response was received. These references cannot authorize an operation. The logs name the operation, stage, HTTP status, outcome, safe error code and elapsed milliseconds. Setup success includes the application configuration version. They omit headers, credentials, keys, images, captions, session/account identifiers, request/response bodies and callback URLs. Do not log the full error, its `response`, the SDK client or the configuration snapshot yourself. You can direct those same safe events to your existing server logger: ```js const mementom = await Mementom.connect({ applicationId, credential, privateKey, onDiagnostic: event => logger.info(event), // optional; defaults to JSON stdout }); ``` A logging failure cannot turn a failed authentication into success, or prevent a valid request from completing. There is no background settings refresh; the existing 60-second cache and `forAttempt()` behavior still apply. | Error code | What to check | | --- | --- | | `application_id_required` | Set this app's Application ID. | | `vendor_credential_required` / `vendor_credential_rejected` | Check the complete company credential in the running server's secret store. | | `response_private_key_invalid` | Check PEM formatting and that it is a private RSA key of at least 2048 bits. | | `configuration_endpoint_unavailable` | The service has no configuration endpoint. Confirm the new Mementom release is deployed and the SDK uses the authorization service. | | `application_not_found` | Confirm the app belongs to the company represented by that credential. | | `integration_setup_required` | Run the downloaded server setup, or bind your existing custom challenges in Integration. | | `integration_challenge_required` | Publish Login and enable the selected account scope. No account challenge is needed. | | `integration_origin_changed` / `integration_callback_required` / `response_destination_not_found` | Reconcile the selected origin and callback with Connection settings. | | `integration_response_key_required` / `response_key_not_registered` | Run server setup to register the matching public key automatically. | | `integration_response_key_unavailable` / `challenge_response_key_mismatch` | The account challenge points to a retired or different response key. Reconcile its binding before retrying. | | `configuration_timeout` / `request_timed_out` | Mementom did not finish responding within the request timeout. Check service health and retry without reusing a consumed result. | | `configuration_network_error` / `transport_unavailable` | Check the server's DNS, TLS trust and outbound access to the authorization service. | | `configuration_response_invalid` / `response_invalid` | Inspect service/proxy health using the reference; do not log the response body. | | `configuration_unavailable` | Use the support reference to inspect the corresponding Mementom error. A 500/503 may require service/database repair. | | `decision_verification_failed` | Stop authorization. Check the original attempt bindings, response-key rotation and expiry; never skip verification. | For a support report, retain only `code`, `stage`, `diagnosticId`, HTTP `status` and the UTC time. Display a plain failure message and that support reference to the user. Keep the detailed diagnosis in server logs. SHUI must also log its own callback/state validation, database and account-mapping failures with a local support reference; the SDK cannot observe failures that occur outside it. On Mementom AWS, API diagnostics use the existing CloudWatch log group `/mementom/pilot/application`. Search the reference in Logs Insights: ```text fields @timestamp, event, operation, status, code, failureCode, durationMs, diagnosticId | filter diagnosticId = "mdiag_REPLACE_WITH_SUPPORT_REFERENCE" | sort @timestamp asc ``` An internal database error can include a safe SQLSTATE `failureCode`, never SQL text or data. No matching server record is expected for an SDK input error, network failure, or local decision verification failure. Use the vendor's SDK log in those cases. Before publishing a migrated vendor, verify that Mementom's matching API/SDK release is online, that discovery succeeds with the vendor's real server secrets, and that any required account-access role is selected. A successful setup check does not prove the user's keyring/account grant or complete a sign-in. Test the real standalone ceremony, returning account access, denied access and sign-out with the user; never generate a keyring or fabricate an account grant to pass it.