@clink-ai/clink-elements is currently published at 0.0.1 and the API may still change. Pin the version in package.json.What the full chain looks like
Elements only replaces the frontend segment. Creating the Session still has to happen on your server, because that call uses the Secret Key. Step 1 submits a product identifier, not a final amount computed in the browser. The amount is recalculated server-side in step 2.Who owns what
1. Server: write your own Session endpoint
This layer is not an optional optimization. It is three boundaries at once: the Secret Key security boundary, the amount validation boundary, and the local order association boundary. TheclinkRequest helper below is the authenticated helper from Hosted Checkout; it returns the data field of the response.
uiModeiselementsandreturnUrlis required. Put{ELEMENTS_SESSION_ID}in the URL and Clink substitutes the real Session ID- The field is
returnUrl. Older material calls itredirectUrl, which is wrong —redirectUrlis a response field used inrequires_actionflows merchantReferenceIdis for reconciliation only. It is not an idempotency key; the same value twice gives you two Sessions
What Clink returns
Thedata that clinkRequest hands back looks like this:
- The response contains no Publishable Key and no
environment. Both come from your own application config — see the next section - The response does contain
url, the hosted checkout address. An Elements integration does not use it
2. Frontend: call your own endpoint, then initialize
The browser does two things: ask your backend for asessionId, then initialize the SDK with it.
PUBLIC_CLINK_PUBLISHABLE_KEY and environment are your application’s deployment config, taken from the Publishable Key under Developers > API Keys (it starts with pk_uat_). They are safe to expose in the browser, but they do not come from the Create Session response.
- Vite
- Next.js
The SDK parameter is named
publishKey. When this page says Publishable Key, that is the field it means — write publishKey in code.3. Mounting, submitting, and third-party buttons
Two kinds of button can appear on a checkout page, and they behave differently: Your own pay button — for cards and anything else where the host triggers submission. Callclink.submit() on click.
SDK built-in third-party buttons — Apple Pay, Google Pay, PayPal, and similar. The paymentMethod element renders these internally and handles the click itself. When one takes over, the SDK emits submit-visible: false and you hide your own button.
submit-enabled reports whether submission is allowed. Write disabled = !enabled rather than passing the event value straight into disabled, which inverts the logic.
4. Events
Two groups, by what you do with them. Update host UI
Flow signals
5. Promo codes
Optional. Creating Coupons and Promotion Codes server-side is covered in Discounts and promotion codes. This section is frontend only.{ amount }, with the fields nested under amount. Writing (info) => info.enablePromotionCode yields undefined, and the promo code entry never appears.
Discounts and the final amount due come from amount. Do not compute them yourself.
6. Error handling
SessionNotSupportedError is the most common one early on, and almost always means the backend is still sending uiMode: "hostedPage".
7. Implementation constraints
Get these wrong and the integration breaks. Everything else about layout is your own design decision.Before you ship
- No Secret Key and no webhook signing key in browser Network traffic or the build output
- The browser only calls your own Session wrapper endpoint, never Clink’s Create Session directly
- The backend does not trust a final amount from the browser; it recalculates from the product or cart
- The local order,
merchantReferenceId, andsessionIdmapping is stored - The Publishable Key and
environmentcome from application config, and are not described as Create Session response fields -
submit-visiblehides your own button when Apple Pay, Google Pay, PayPal, or similar appear -
session-successdoes not trigger fulfillment; the final state comes from verified webhooks and backend queries - Old instances are destroyed when the Session changes or the page unmounts
Next
Hosted Checkout
The backend and webhook halves are identical to Hosted Checkout.
Go live
The checklist before switching to production.