Skip to main content
Customer email links let your customers interact with their bookings directly from email. When Opencals sends an appointment confirmation, feedback request, or password reset, the link in the email takes them directly to the right page — signed in automatically. This guide is for merchants building custom frontends with the Opencals Storefront SDK. If you use the multi-tenant Opencals storefront (salon.opencals.com), no setup is needed.

Overview

All customer email links follow the same pattern:
  • Every link is {storefrontBaseUrl}/link/{token}
  • Your app implements one route: GET /link/{token}
  • The route calls Auth.resolveLink(token) to get the customer’s action and redirect target
  • You sign the customer in (if tokens are provided) and redirect them

Setup

Step 1: Set the storefrontBaseUrl Setting

In the Opencals dashboard, go to Settings → API → Storefront Base URL and enter your app’s base URL:
This tells Opencals where to send customer email links. If you don’t set it, Opencals will fall back to the store’s domain, and links may not reach your custom frontend.

Step 2: Implement the /link/{token} Route

Your app must handle GET /link/{token}. Here’s an example with Next.js:
app/link/[token]/page.tsx
For production, store the tokens securely (httpOnly cookies) and redirect via a handler:
app/api/auth/link/route.ts

Purpose → Redirect Table

This table shows what each link type does and where the customer is redirected:

Special Case: Password Reset

Password reset links do not return customer tokens. Instead, the token is passed as a query parameter so your app can verify it when the customer submits a new password.

Example: Password Reset Handler

app/auth/reset-password/page.tsx

Passwordless Email Login (Optional)

In addition to email links, you can offer passwordless login with 6-digit codes:
The code expires in 5 minutes and allows 5 failed attempts before a new code must be requested.

SDK Methods

The following SDK methods are used for email links and passwordless auth: See the API reference for full request and response schemas.

Security Checklist

  • Store API keys in environment variables — never in client code.
  • Call resolveLink on the server, not the client.
  • Store customer tokens in httpOnly cookies (not localStorage) when possible.
  • Redirect after storing tokens to avoid exposing them in the URL.
  • For password reset, store the token as a query parameter only (it does not grant authentication).
  • Tokens expire according to their purpose (1 hour for verify-email/reset-password, 7 days for leave-feedback, 24 hours default).

Troubleshooting

“Invalid or expired link”
  • The token may have been used already (one-time use only).
  • The token may have expired (check the purpose expiry in the earlier table).
  • The store context may not match the API key’s store.
Customer not signed in after clicking the link
  • Verify tokens were stored (httpOnly cookies, session, etc.).
  • Check that AuthService.resolveLink returned accessToken and refreshToken.
  • For reset-password links, no sign-in occurs — the customer must reset their password and sign in manually.
Password reset token not working
  • The token is included in the URL query string only, not in the API call.
  • Pass it to AuthService.resetPassword({ body: { token, newPassword } }) exactly as received.
Last modified on June 21, 2026