Skip to main content

Quick start

Every Nium Embed component uses the same Proof Key for Code Exchange (PKCE) authorization setup. Set it up once. Then change only the scopes array for each component. Each component guide gives its scope string.

Step 1: Install the packages​

@nium/nium-sdk works with any frontend framework and includes TypeScript types. It runs in the browser only, so don't import it in server-side code.

Nium Embed supports these minimum browser versions:

BrowserMinimum version
Chrome and Edge111
Firefox113
Safari, including iOS16.4
Terminal
npm install @nium/nium-sdk js-base64

Step 2: Generate the PKCE values​

Run this code in your client.

pkce.ts
import { Base64 } from 'js-base64'

export const generateCodeVerifier = () => {
const randomBytes = new Uint8Array(32)
crypto.getRandomValues(randomBytes)
return Base64.fromUint8Array(randomBytes, true)
}

const sha256 = async (plain: string) => {
const data = new TextEncoder().encode(plain)
return crypto.subtle.digest('SHA-256', data)
}

export const generateCodeChallenge = async (codeVerifier: string) => {
const hashed = await sha256(codeVerifier)
return Base64.fromUint8Array(new Uint8Array(hashed), true)
}

Step 3: Get an authorization code​

Send the code challenge to your server. Your server, written in any language, calls the Nium auth endpoint and returns the authorization code.

Call the auth endpoint from your server only

Never call the Nium auth endpoint from the browser, because it exposes your x-api-key and clientSecret.

server.js
// server endpoint — never expose this in the browser
// sandbox shown — use https://api.nium.com in production
const response = await fetch(
`https://gateway.nium.com/client/${clientHashId}/oauth/authcode`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_SECRET_TOKEN',
'X-Request-ID': crypto.randomUUID(), // required — unique per request, used for tracing and support
},
body: JSON.stringify({
clientHashId,
clientSecret: 'YOUR_CLIENT_SECRET',
codeChallenge,
scopes: ['SCOPE_FOR_THIS_FORM'], // changes per component — see each guide
}),
}
)
const { authorizationCode, expiresInSecs } = await response.json()
EnvironmentBase URLenv value in init()
Sandboxhttps://gateway.nium.comsandbox
Productionhttps://api.nium.comproduction

Use the base URL that matches the env you pass to init() in Step 4. This applies to every component.

Authorization codes expire

The response includes the authorizationCode and expiresInSecs, the number of seconds until the code expires (typically 300). Pass the code to init() before it expires, and request a new one if it does.

Step 4: Initialize the SDK and mount the component​

Run this code in your client.

client.ts
import { init, createElement } from '@nium/nium-sdk'
import { generateCodeVerifier, generateCodeChallenge } from './pkce'

// 1. Generate PKCE pair on the client
const codeVerifier = generateCodeVerifier()
const codeChallenge = await generateCodeChallenge(codeVerifier)

// 2. Send codeChallenge to your server — receive authorizationCode
const { authorizationCode } = await yourServerEndpoint({ codeChallenge })

// 3. Initialize the SDK
await init({
env: 'production', // or 'sandbox'
authCode: authorizationCode, // from your server
codeVerifier,
clientId: 'YOUR_CLIENT_HASH_ID',
})

// 4. Create and mount the component
const element = await createElement('<type>', { /* component-specific options, such as customerHashId */ })
element.mount('#container') // the id of the div where you want the iFrame

The SDK doesn't keep its session across a page reload. After a reload, or after an AUTH_EXPIRED error, repeat Steps 2 to 4 with a new authorization code.

Allowlist your domains

Ask Nium support during onboarding to allowlist every domain that hosts a component, such as production and staging. This is a setup step, not an init() parameter. localhost works for development, and the component also runs in a WebView.

Step 5: Listen to events​

Subscribe to the events that the component fires.

events.ts
element.on('ready', () => { /* the component has loaded */ })

element.on('submit', (e) => {
// not every component emits submit, and the payload varies — see each guide
console.log(e.result)
})

element.on('error', (e) => { /* surface e.error.message to the user */ })

Every component fires ready and error. Only some components fire submit, and only Convert currencies fires cancel. Check each guide for the events it emits.

Best practices​

These practices apply to all Nium Embed integrations.

  • Generate the auth code on your server. Never call the Nium auth endpoint from the browser, because it exposes your API key. Your frontend generates the PKCE codeVerifier and codeChallenge. Send only the codeChallenge to your server to get the auth code. Keep the codeVerifier in your frontend and pass it to init().
  • Use element.submit() only where it's supported. If one Next button in your UI advances across steps, programmatic submit lets your outer flow control the iFrame. Only the Beneficiary Management (payment) form supports it today. Other components reject with SUBMIT_UNSUPPORTED.
  • Apply brandColor for brand alignment. brandColor applies your brand color to buttons, links, selected cards, focus rings, and tints in the iFrame. You inject no custom CSS. Add preset: 'dark' if your platform uses a dark UI.
  • Handle error events. Always wire the error handler and show your users clear feedback. Some failures, such as a failed quote or a validation error, appear only inside the iFrame, so your handler covers setup and session failures.

Next steps​

LLM-ready documentation:: llms.txt and llms-full.txt
Was this page helpful?