OAuth Flow
Copy this flow exactly for a reliable 2-minute integration. Most integration failures come from small deviations in start URL, redirect URI, or token exchange.
Use Exactly These Endpoints
Bookmer LoginSign uses the canonical OAuth base URL https://id.bookmer.com. Use this host unchanged for every production integration.
| Endpoint | URL |
|---|---|
| Authorization | https://id.bookmer.com/oauth/authorize |
| Token | https://id.bookmer.com/oauth/token |
Quickstart (Copy/Paste)
- Start login only via
/oauth/authorize. - Receive
?code=...&state=...at your callback URL. - Exchange code on your backend via
POST /oauth/token. - Use access token to fetch
/api/user.
1) Authorization Request (Frontend Redirect)
Recommended scope for documentation and new integrations: openid email profile (single string, space-separated). Bookmer LoginSign forwards scope through the flow; use the same convention everywhere you copy examples.
GET https://id.bookmer.com/oauth/authorize? client_id=YOUR_CLIENT_ID& redirect_uri=https://yourapp.com/callback& response_type=code& scope=openid%20email%20profile& state=random_state_string
Do not start with /login or /api/auth/*. Always start with /oauth/authorize.
Optional license_code auto-redeems that license after the user consents (or when a connection already exists). Use this on your own landing page. Marketplace buyers who already completed /activate/:appId should not send license_code again. Full contract: Marketplace licenses.
GET https://id.bookmer.com/oauth/authorize? client_id=YOUR_CLIENT_ID& redirect_uri=https://yourapp.com/callback& response_type=code& license_code=LS-NRS97-RPPEX-SSCZF-Z7HMB
2) Token Exchange (Backend)
Exchange the received code on your server. The redirect_uri must be exactly the same value you used in step 1.
POST https://id.bookmer.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& code=AUTHORIZATION_CODE& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRET& redirect_uri=https://yourapp.com/callback
Recommended ENV Setup
Don't hardcode OAuth values in frontend code. Keep environment values for local and production.
# Frontend (.env.local) LOGINSIGN_CLIENT_ID=YOUR_CLIENT_ID LOGINSIGN_REDIRECT_URI=http://localhost:3000/oauth/loginsign/callback # Backend (.env) LOGINSIGN_CLIENT_ID=YOUR_CLIENT_ID LOGINSIGN_CLIENT_SECRET=YOUR_CLIENT_SECRET LOGINSIGN_REDIRECT_URI=http://localhost:3000/oauth/loginsign/callback
Redirect URIs
The Redirect URI is the URL in your app to which Bookmer LoginSign sends the user after they allow or deny access. You must register one or more Redirect URIs in the Console when creating or editing your application.
- Match rule: Use the same
redirect_urivalue in authorize + token exchange. Keep it byte-identical to avoid edge-case failures. - HTTPS in production: Use
https://for production.http://localhostis allowed for local development. - Callback path: Typically something like
https://yourapp.com/oauth/callbackorhttps://yourapp.com/auth/callback. Your app must handle this route: read thecodeandstatequery parameters, exchange the code for a token, and verifystate.
Add all Redirect URIs that your app will use (e.g. production and staging). You can add or remove URIs later in the application settings.
Quick Validation
Validate your setup before go-live and after each redirect URI change:
GET https://id.bookmer.com/api/oauth/healthcheck? client_id=YOUR_CLIENT_ID& redirect_uri=https://yourapp.com/oauth/loginsign/callback
You can also run this check directly inside the Console under Settings → Redirect URIs → OAuth config check.
Troubleshooting (Symptom → Fix)
- Redirect URI not allowed: Add exact callback URL in Console and run OAuth config check.
- Lands on the Bookmer LoginSign dashboard: Ensure your app starts with
/oauth/authorize, not/login. - Consent fails / “valid email required”: The signing-in user needs a valid primary email on their Bookmer LoginSign profile before a new app connection can be created.
- invalid_client: Check client ID/secret pair and environment mix-ups (staging vs production).
- invalid_grant: Code expired, already used, or
redirect_urimismatch in token exchange. - Sign-in failed in callback: Log the raw response from
/oauth/token(status + JSON) before generic UI errors. - License did not apply: Confirm
license_codeis unused and belongs to thisclient_id. A failed redeem does not block OAuth — pull inventory or listen forlicense_activated. See Marketplace.
Related docs
- Integration — end-to-end callback and token exchange
- Marketplace licenses — hosted
/activateand when to omitlicense_code - Licenses — variants, redeem, assign
- API Reference — route index