Service for the storefront buyer-authentication surface: register, log in, read the current buyer and their bookings, manage their address book, reset a forgotten password, and manage marketing consent. Accessible via lynkow.customers.

Requires a publishable key: pass publishableKey to createClient(...) so every request carries it (customer routes reject calls without a valid key). The customer session token is a SEPARATE identity track: activation.confirm and login return it and write it to shared in-memory client state. Authenticated customer methods attach it as Authorization: Bearer <token> ALONGSIDE the publishable key, and signed-in reservation creation reads the same state so a new booking appears in me() right away. logout clears the shared value. Persist the token in your own storage (for example a cookie) and seed it back via createClient({ customerToken }) to keep the buyer signed in across a reload or SSR. The SDK never persists or logs it.

Signing up is TWO steps and no session exists between them: register only asks for an activation link to be sent, and activation.confirm (called from the page that link lands on) sets the password and returns the session.

Access via: lynkow.customers

Methods

6 methods

login

TypeScript
login(input: CustomerLoginInput): Promise<CustomerAuthResult>

Authenticates a buyer by email plus password. On success the returned token is STORED and attached on later authenticated calls, and { customer, token } is returned. Any failure (wrong password, unknown email) surfaces as one uniform LynkowError with no field that reveals whether the email exists. Login is not spam-gated (it is rate-limited server-side), so no honeypot fields are sent.

Parameter

Type

Description

input

CustomerLoginInput

CustomerLoginInput: email and password.

Returns: Promise<CustomerAuthResult>

TypeScript
const { customer, token } = await lynkow.customers.login({
  email: '[email protected]',
  password: 'a-strong-passphrase',
})
saveToken(token)

logout

TypeScript
logout(options?: CustomerLogoutOptions): Promise<void>

Logs the buyer out. By default this is a local token discard with no network round-trip: the shared token is cleared so later customer and reservation calls go out without a Bearer header. With { everywhere: true } it requires a stored token, first revokes EVERY session token issued to this buyer server-side, then clears the local token. Resolves to void.

Parameter

Type

Description

options

CustomerLogoutOptions

Optional CustomerLogoutOptions: everywhere to also revoke all server-side sessions.

Returns: Promise<void>

TypeScript
await lynkow.customers.logout() // discard the token on this client only
await lynkow.customers.logout({ everywhere: true }) // also revoke all sessions server-side

me

TypeScript
me(): Promise<CustomerSession>

Returns the current buyer plus at most their 100 most recent bookings. Retro-linked guest bookings are withheld until customer.emailVerified is true. Not cached: the booking list changes as the buyer books. Requires a stored session token.

Returns: Promise<CustomerSession>

TypeScript
const { customer, bookings } = await lynkow.customers.me()
for (const booking of bookings) {
  console.log(`${booking.reference}: ${booking.status} at ${booking.startsAt}`)
}

register

TypeScript
register(input: CustomerRegisterInput, options?: CustomerSpamOptions): Promise<void>

Step 1 of signing up: asks for an activation link to be sent to email. It takes the address and nothing else, creates no session, and does NOT sign the buyer in. Step 2 is CustomersService.activation.confirm, called from the page the emailed link lands on, where the password is set and the session is issued.

ALWAYS resolves the same way whether or not the address already has an account, so it reveals nothing about who is registered. Do NOT branch your UI on the outcome: show one message either way, or you re-create client-side the account-enumeration signal the API removed.

Honeypot and timestamp anti-spam fields are injected automatically; on a reCAPTCHA-protected storefront pass options.recaptchaToken. Passing a password, acceptsTerms, a profile or marketingOptIn here has NO effect: the server SILENTLY STRIPS them and still returns the same success, so do not write a catch expecting a rejection. They are simply discarded, never stored and never replayed. Collect them at activation.confirm instead.

Parameter

Type

Description

input

CustomerRegisterInput

CustomerRegisterInput: email, and nothing else.<br>The anti-spam _ts uses options.formStartedAt when supplied. Otherwise it uses<br>client creation time clamped to at most 55 minutes before this request: a freshly<br>created server client can still hit the API's minimum fill-time rejection, while a<br>long-lived browser client does not become permanently expired.

options

CustomerSpamOptions

Optional CustomerSpamOptions: formStartedAt, recaptchaToken (required on reCAPTCHA-protected storefronts), a locale override selecting the activation-mail language, and fetchOptions (e.g. an AbortSignal).

Returns: Promise<void>

TypeScript
await lynkow.customers.register({ email: '[email protected]' })
// Same message on every outcome: never branch on whether the email is known.
show('Check your inbox. If this address can be registered, a link is on its way.')

resendVerification

TypeScript
resendVerification(options?: BaseRequestOptions): Promise<void>

Re-sends the verification mail for the signed-in buyer. The API returns no content both when it dispatches a fresh link and when the email is already verified, so this method does not expose verification state. Requires a stored session token.

Parameter

Type

Description

options

BaseRequestOptions

Optional request options. locale selects the buyer-mail language; fetchOptions can carry an AbortSignal.

Returns: Promise<void>

TypeScript
await lynkow.customers.resendVerification({ locale: 'fr' })

verifyEmail

TypeScript
verifyEmail(token: string): Promise<CustomerEmailVerificationResult>

Confirms a buyer's email with the single-use token from the verification mail, flipping emailVerified (and, for a claimed guest row, hasAccount) to true. This is what makes retro-linked guest bookings, placed with the same email before registration, appear in me().bookings. An invalid, expired, or already-used token surfaces as one uniform LynkowError (no oracle). No session token is required, and confirming does NOT sign the buyer in (they log in normally afterward). Not spam-gated (the token is unguessable; the endpoint is rate-limited server-side).

Parameter

Type

Description

token

string

The single-use, short-lived email-verification token from the emailed link.

Returns: Promise<CustomerEmailVerificationResult>

TypeScript
await lynkow.customers.verifyEmail(tokenFromEmailLink)
const { bookings } = await lynkow.customers.me() // retro-linked guest bookings now visible