API Reference
Complete API documentation for Bookmer LoginSign. Use the canonical API base URL https://id.bookmer.com. Sections below that show /api/user or OAuth typically require a Bearer access token; Console routes (/api/developer/…) use the logged-in Console session cookie instead.
Which API uses which credentials?
Pick the row that matches where your code runs. Do not call Portal session routes from your app backend, and do not expose your client secret to the browser.
| Use case | Example routes | Auth |
|---|---|---|
| End-user sign-in from your product | GET /oauth/authorize, POST /oauth/token, GET /api/user | Browser redirect for authorize; Bearer access token for /api/user |
| Your backend talks to Bookmer LoginSign as the app | GET /api/applications/:appId/users, GET /api/applications/:appId/licenses, POST /api/applications/:appId/marketplace/events, PATCH /api/applications/:appId/users/:globalId/status | HTTP Basic client_id:client_secret |
| You in the Console (browser) | /api/developer/… | Logged-in developer session cookie |
Authentication
Include the access token in the Authorization header:
Authorization: Bearer YOUR_ACCESS_TOKEN
User Identity
Every Bookmer LoginSign user has a Global User ID — a short identifier in the formatXX1234 (2 letters + 4 digits). This ID is stable, unique, and supports millions of users. Use it to reference users in your app instead of internal IDs.
Endpoints
Get current user
Returns the authenticated connection's profile for this app. The id field is the connection id (per app link), not the user's internal database id.
// Response
{
"id": "connection_id",
"globalId": "AB1234",
"name": "John Doe",
"email": "user@example.com",
"image": "https://..."
}List users (for developers)
Returns all users who have connected to your application. Requires developer session (cookie from Console).
// Response
{
"users": [
{
"id": "connection_id",
"globalId": "AB1234",
"name": "John Doe",
"email": "user@example.com",
"active": true,
"blocked": false,
"emailMuted": false,
"sessions": 23,
"lastSession": "2023-07-19T14:30:00Z",
"joined": "2023-07-19T10:00:00Z",
"region": "Germany"
}
],
"total": 312
}globalId — User identifier (2 letters + 4 digits). Use this to reference the user in your app.
email — The address the user shared with your app for this connection, or a dash if not shared.
Update user connection
Body: optional isForwarding (boolean) and/or appEmail (string email). At least one field is required.
Sync platform email to LoginSign
Body: { email: "new@example.com" }. Updates the LoginSign primary email for that connection's user and invalidates old magic-link tokens.
Delete user connection (account closure)
Permanently removes the connection. Webhook user_account_deleted is sent. See Account closure.
Exchange authorization code for access token
Content-Type: application/x-www-form-urlencoded
Client credentials are accepted either via form fields or Authorization header: Authorization: Basic base64(client_id:client_secret).
// Request body (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&
// Response
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "..."
}Critical: redirect_uri must match the authorize request value.
Licenses, marketplace & subscriptions
License inventory lives on Apps. Console generate/assign and user redeem are in Licenses. Inventory pull is in License Sync. AppSumo, generic partner write APIs, hosted activation, and outbound license webhooks are in Marketplace licenses. Common routes:
# End user (session cookie) GET /api/user/licenses/subscriptions POST /api/user/licenses/redeem # Console session GET /api/developer/applications/:appId/marketplace PATCH /api/developer/applications/:appId/marketplace POST /api/developer/applications/:appId/marketplace/appsumo/test GET /api/developer/applications/:appId/licenses/variants POST /api/developer/applications/:appId/licenses/variants PATCH /api/developer/applications/:appId/licenses/variants/:variantId DELETE /api/developer/applications/:appId/licenses/variants/:variantId POST /api/developer/applications/:appId/licenses/codes/generate POST /api/developer/applications/:appId/licenses/codes/upload GET /api/developer/applications/:appId/licenses/codes DELETE /api/developer/applications/:appId/licenses/codes/:codeId POST /api/developer/applications/:appId/users/:connectionId/licenses # Server-to-server (Basic Auth: client_id:client_secret) GET /api/applications/:appId/licenses GET /api/applications/:appId/licenses/:code POST /api/applications/:appId/licenses/codes/generate POST /api/applications/:appId/licenses/codes/import POST /api/applications/:appId/licenses/:code/redeem POST /api/applications/:appId/licenses/:code/revoke POST /api/applications/:appId/marketplace/events PATCH /api/applications/:appId/users/:globalId/status # Hosted marketplace POST /api/marketplace/appsumo/:appId/webhook GET /marketplace/appsumo/:appId/callback GET /activate/:appId?code= POST /api/marketplace/activate/:appId
GET /api/applications/:appId/licenses returns the full code inventory, including source and marketplace fields. A code can be assigned only once. Outbound webhook types license_activated, license_updated, and license_deactivated use the same webhookUrl as account deletion. See linkedConnectionId and validation-after-activation in the Licenses, License Sync, and Marketplace documentation.
Error Responses
All errors return JSON. Log status code and full body for troubleshooting:
{
"error": "invalid_grant",
"error_description": "The authorization code has expired"
}- invalid_client: wrong client_id/client_secret or unauthorized redirect URI for this app.
- invalid_grant: code invalid, expired, reused, or redirect URI mismatch between authorize and token requests.
- invalid_request: missing required parameters (grant_type, code, redirect_uri, credentials).