TEST offer emails
View .mdA TEST welcome offer can award a configured perk and send one real email with
[STAGING] at the start of its normal subject. This is an early-access operation:
use a matching API deployment and immutable SDK release that includes these helpers.
Source tests alone do not establish deployed availability or inbox delivery.
Configure the offer
Section titled “Configure the offer”The collection must have a canonical welcome perk with authored email copy and an
immediate lead.captured → DIRECT_ISSUE award rule. DRAFT perks can be rehearsed
in TEST without enabling a production offer. The award-email renderer consumes
an already-issued code, its expiry, approved redemption URL and terms. It does
not invent a booking, join a membership, or issue another code while rendering.
The installation needs offers.read and offers.write, a TEST server key, the
exact registered collection-owned STAGING origin, and registered TEST recipients.
Publishable browser keys and LIVE credentials cannot call these operations.
Keep the server key in the server environment; the browser uses your same-origin
BFF. Never add a provider key to application code or use a private capture API.
Add the server and Next handlers
Section titled “Add the server and Next handlers”import { createKismetClient } from '@kismet-tech/sdk/server';import { createKismetGuestAuthNextHandlers } from '@kismet-tech/sdk/next';
const server = createKismetClient({ apiKey: process.env.KISMET_SERVER_KEY, collection: 'your-collection', baseUrl: 'https://api.ksmt.app/v1',});const offerId = process.env.KISMET_OFFER_ID!; // configured canonical perk UUIDconst handlers = createKismetGuestAuthNextHandlers({ ...yourExistingGuestHandlerConfig, offers: { client: server.offers, offerIds: [offerId] },});Map GET /api/kismet/guest/offers/[offerId] to handlers.offer(request, offerId)
and POST /api/kismet/guest/offers/[offerId]/captures to
handlers.captureOffer(request, offerId). The existing auth CSRF route remains
required. The handlers enforce configured offer IDs and exact site origins,
validate CSRF on POST, and derive origin from the authorized request URL.
Caller-supplied origin, environment, code and extra fields are rejected.
For direct server integrations, use server.offers.get(offerId, { origin })
and server.offers.capture(offerId, { ...input, origin }). Both operations send
the exact Origin header; capture also sends the matching body origin.
Display the disclosure before submission
Section titled “Display the disclosure before submission”import { createKismetGuestBrowserClient } from '@kismet-tech/sdk/react';const guest = createKismetGuestBrowserClient();const offer = await guest.offers.get(offerId);// Render offer.headline, offer.promise, offer.terms and offer.disclosure.text.// Only the explicit submit handler below may capture the offer.const result = await guest.offers.capture(offerId, { email, idempotencyKey: stableSubmissionKey, consent: { accepted: true, disclosureHash: offer.disclosure.hash },});Typing an email or signing in with Google does not submit the offer. The canonical TEST disclosure explains that this sends one real staging email without LIVE marketing enrollment or membership. Render that exact disclosure and send its hash only after the guest chooses the submit action. A changed disclosure must be displayed again before a fresh explicit submission.
Keep the same 16–200 character alphanumeric, hyphen or underscore idempotency key and identical payload for retries, including after a timeout. Do not generate a new key just because the response is uncertain. The API also deduplicates by recipient, offer and installation, so changing keys cannot produce another send.
Report the actual result
Section titled “Report the actual result”email.status: 'accepted' means the provider accepted the email. It does not prove
inbox delivery or redemption. not_sent, pending, unknown and failed are
separate outcomes; never present them as sent. Preserve the submission key when
checking again. The response includes replayed and the durable captureId.
The API records the canonical award event and capture/send state. Engagement clicks and Google login are not award, delivery, redemption or marketing-consent proof. Do not infer dashboard fulfillment counts from those events.
See read the offer and capture the offer for the REST contract.