Documentation

License Sync

Pull the full license-code inventory from LoginSign into your backend. One Basic Auth request returns every code for your app — including marketplace keys — so you can sync without extra portal steps. Partner write APIs (generate, import, redeem, revoke, events) are documented in Marketplace licenses.

1. Endpoint

GET /api/applications/:appId/licenses
GET /api/applications/:appId/licenses?state=all|used|unused

Authentication is required via Basic Auth:

Authorization: Basic base64(client_id:client_secret)

client_id must be identical to appId.

2. Response shape

{
  "codes": [
    {
      "code": "LS-NRS97-RPPEX-SSCZF-Z7HMB",
      "state": "ACTIVE",
      "duration": "MONTH",
      "variant": { "id": "var_123", "name": "Premium" },
      "ownerGlobalId": "AB1234",
      "activatedAt": "2026-09-08T16:10:00.000Z",
      "expiresAt": "2026-10-08T16:10:00.000Z",
      "createdAt": "2026-09-08T16:10:00.000Z",
      "source": "MARKETPLACE",
      "marketplaceProvider": "APPSUMO",
      "marketplaceLicenseKey": "3794577C-3DBC-11EC-9BBC-0242AC130002",
      "marketplaceTier": 2
    }
  ],
  "total": 1,
  "summary": { "total": 1, "used": 1, "unused": 0 }
}

duration is the validation period after activation (MONTH, YEAR, or LIFETIME). Unused codes have activatedAt and expiresAt set to null.

3. Field reference

code           The license key
state          UNUSED | ACTIVE | EXPIRED
duration       Validation after activation: MONTH | YEAR | LIFETIME
variant        Plan type for this code
ownerGlobalId  LoginSign user when the code is assigned; otherwise null
activatedAt    When validation started
expiresAt      When validation ends (null for unused or lifetime)
createdAt      When the code was created
source         MANUAL | MARKETPLACE | STATUS_SYNC
marketplaceProvider     APPSUMO | GENERIC | null
marketplaceLicenseKey   Marketplace UUID or imported deal key (searchable)
marketplaceTier         AppSumo / partner tier number, or null
summary        Inventory counters for the whole app (not the current filter)

4. Example usage

const auth = Buffer.from(`${appId}:${clientSecret}`).toString('base64');
const res = await fetch(`${API_URL}/api/applications/${appId}/licenses`, {
  method: 'GET',
  headers: { Authorization: `Basic ${auth}` }
});
const data = await res.json(); // { codes, total, summary }

5. Recommended sync strategy

1) Pull GET /licenses periodically (or after generate/assign/redeem/marketplace events)
2) Upsert codes in your database by the code string or marketplaceLicenseKey
3) Map ownerGlobalId to your user records
4) Treat duration as validation that starts at activatedAt
5) Prefer license_activated / license_updated / license_deactivated webhooks for near real-time
6) Use GET /api/applications/:appId/users.activeLicenses for per-user checks

6. Related write APIs

  • User redeem: POST /api/user/licenses/redeem (user session).
  • Assign from a connected user: POST /api/developer/applications/:appId/users/:connectionId/licenses (developer session). A code can be assigned only once.
  • Grant/revoke by globalId: PATCH /api/applications/:appId/users/:globalId/status (Basic Auth). This creates or updates a status-license for that user; it does not replace the inventory pull.
  • Marketplace partner writes: generate, import, lookup, redeem, and revoke on the same Basic Auth surface. Full contract: Marketplace licenses.

Generate and import exist on both the Console session APIs and the Basic Auth partner APIs. Upload / import accept at most 5000 rows per request. Use the partner APIs when a marketplace or your backend writes codes without a browser session.

7. Error handling

  • 401 unauthorized: Basic Auth header missing.
  • 401 invalid_client: wrong client secret.
  • 403 forbidden: client_id does not match appId.

8. Integration test endpoint

POST /api/developer/applications/:appId/licenses-sync-api/test

Confirms your app exposes the license-sync endpoint metadata. Use Run API test in /console/synchronisation.

Related docs