Documentation

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 caseExample routesAuth
End-user sign-in from your productGET /oauth/authorize, POST /oauth/token, GET /api/userBrowser redirect for authorize; Bearer access token for /api/user
Your backend talks to Bookmer LoginSign as the appGET /api/applications/:appId/users, GET /api/applications/:appId/licenses, POST /api/applications/:appId/marketplace/events, PATCH /api/applications/:appId/users/:globalId/statusHTTP 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/api/user

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://..."
}
GET/api/developer/applications/:appId/users

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.

PATCH/api/developer/applications/:appId/users/:connectionId

Update user connection

Body: optional isForwarding (boolean) and/or appEmail (string email). At least one field is required.

PATCH/api/developer/applications/:appId/users/:connectionId/email

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/api/developer/applications/:appId/users/:connectionId

Delete user connection (account closure)

Permanently removes the connection. Webhook user_account_deleted is sent. See Account closure.

POST/oauth/token

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).