Skip to main content

Applications

An application is the top-level unit of isolation in Obsidian. Every license key, end user, log line, blacklist entry, webhook and API credential lives under exactly one app, so shipping two products means registering two apps and giving a reseller access to one never leaks the other.

This page walks the Applications listing and the per-app detail view: creation, credentials, tabs and toggles. The SDK download flow and per-language integration live on C# SDK, C++ SDK and Python SDK.

Creating an application

Open Applications from the sidebar and click New Application. The dialog asks for a name (required, shown on cards and headers), a version (defaults to 1.0, and clients calling /init must match it), and an optional description that stays on the dashboard and is never returned to clients.

Submitting posts to POST /apps, the dashboard drops you straight into the new app, and the listing page renders each app as a card with its enabled/disabled badge, current version, key count and user count pulled from the stats object.

Resellers

The New Application button is hidden for resellers. Only owners, admins and developers can create apps.

The detail view

Opening an app renders AppDetail. The header shows the app name, the v{version} label under it, and a status badge that reads active when enabled is true and disabled otherwise.

If Pause All Keys is on, a yellow banner sits above the tabs telling you every key is paused and clients cannot authenticate until you resume in Security settings. The banner disappears the moment you flip the toggle back.

Directly below the header is the Application Credentials card.

Application Credentials card

Five fields, always visible at the top of the detail page:

FieldCopyRevealReseller visibility
Application Nameyesplaintextyes
Application Versionyesplaintextyes
Account Owner IDyesplaintextyes
API Keyyesblurred, click the eye to revealyes
API Secretyesblurred, click the eye to revealhidden, replaced by a "Restricted, visible to owner and admins only" message

The API Key is safe to embed in client code. The API Secret signs requests and must stay on trusted machines; see Request Signing for the HMAC-SHA256 canonical form.

Tabs

Which tabs render depends on the caller's role and, for resellers, per-permission flags:

TabGatePurpose
Licensesview_keysGenerate, extend, ban, reset HWID, delete keys.
Usersview_keysEnd users registered against this app.
Securityview_blocked_ipsIP and HWID blacklist plus the feature toggles.
Logsview_auth_logsRecent auth events for this app.
IntegrationalwaysClient snippet, API key, base URL, SDK downloads.
Settingsowners, admins, developersVersion, webhook, reseller pricing, secret rotation, delete.

The default tab is Licenses when the caller can see keys, otherwise Integration.

Licenses

The table columns are Key, Status, Duration, Time Left, Level, Used By, Used From (geo), Screen (activation screenshot thumbnail), and Actions.

Time-left rendering follows a small set of rules. Lifetime keys (or any key with duration_days == 0) render as , a key that has not been activated yet renders as a dash placeholder, and an expired key renders red with the label expired. An active key renders as Nd Nh, Nh Nm, Nm, or < 1m, colored gray at three or more days out, yellow at one day out, and orange when less than a day remains.

Each row exposes four actions, gated as follows:

  • Clock (owners, admins, developers only) opens the per-key edit dialog. It posts to POST /licenses/{id}/extend with value, unit and a subtract flag, so the same call adds or removes time.
  • Counter-clockwise arrow (reset_hwid) posts to POST /licenses/{id}/reset-hwid and unbinds the device the key was locked to.
  • Prohibit (ban_unban_keys) toggles the key's ban state via PATCH /licenses/{id}/ban.
  • Trash (delete_keys) permanently removes the key with DELETE /licenses/{id}.

Above the table sit two buttons. Extend Active (owners, admins, developers) opens a bulk dialog that bumps every currently-active key, skips unused inventory and lifetime keys, and returns {extended, skipped} from POST /apps/{id}/licenses/extend-all. Generate Keys (gated by generate_keys) opens the generation dialog with fields for amount, level, duration and unit; the unit picker offers hours, days, weeks, months and lifetime, and choosing lifetime disables the duration input.

For a cross-app inventory view with filters and bulk operations, see Manage Keys.

Users

End users are accounts registered through /api/client/register. The columns are Username, Created, Last Login, IP (gated by view_ip), HWID (gated by view_hwid), Level, Location, Screen, Expires, Status and Actions.

Click-to-copy is enabled on the username, IP and HWID cells. Row actions mirror the license actions but target users:

  • Counter-clockwise arrow (reset_hwid) posts to POST /users/{id}/reset-hwid.
  • Prohibit (freeze_unfreeze) toggles the user's ban state via PATCH /users/{id}/ban.
  • Trash (delete_keys) removes the user with DELETE /users/{id}.

The empty state reads "No users have registered via the client API yet." For the difference between registration and login on the wire, see Client Endpoints.

Security

The tab splits into two columns.

The left column is the IP / HWID Blacklist. Owners, admins and developers get a small form with a type picker (ip or hwid), a value input and an Add button, which posts to POST /apps/{id}/bans. Entries render as chips with a delete icon that calls DELETE /bans/{id}; resellers see the list but cannot mutate it.

The right column is a stack of feature toggles. Each toggle patches a single field on the app:

ToggleFieldEffect when on
Pause All Keyskeys_pausedBlocks key validation and logins for this app. Yellow banner appears above the tabs.
HWID Lockhwid_lockBinds each license to the first device that activates it. See HWID Lock.
Request Signingrequire_signatureRejects unsigned client calls, enforcing HMAC-SHA256. See Request Signing.
Injection Detectioninjection_detection (default on)Kills the session on heartbeat when the client reports a debugger or probe. Turn off if your loader legitimately trips debugger checks.
Application EnabledenabledMaster kill switch. When off, all client access is blocked.

Every toggle hits PATCH /apps/{id} with only the field that changed.

Logs

A read-only feed of recent auth events for this app. Columns: Time, Action, Detail, IP (gated by view_ip), Location, Screen.

Integration

The left column renders a live Python client snippet with the real API key and base URL baked in, ready to paste:

import requests, hashlib, platform

BASE = "https://your-obsidian-host/api/client"
API_KEY = "<this app's api key>"

def get_hwid():
return hashlib.sha256(platform.node().encode()).hexdigest()[:32]

r = requests.post(f"{BASE}/init", json={"api_key": API_KEY, "version": "1.0"})
session = r.json()["session"]

r = requests.post(f"{BASE}/login", json={
"session": session,
"username": "user1",
"password": "pass",
"hwid": get_hwid(),
})
print(r.json())

r = requests.post(f"{BASE}/license", json={
"session": session,
"license": "XXXX-XXXX-XXXX-XXXX",
"hwid": get_hwid(),
})
print(r.json())

The right column exposes the API Key (reveal and copy), the API Secret (reveal and copy, hidden for resellers), the Base URL (copy), and for non-resellers a Download Client SDK card with three buttons. The buttons hit GET /apps/{id}/sdk/{lang} and stream back obsidian_sdk_python.zip, obsidian_sdk_csharp.zip or obsidian_sdk_cpp.zip depending on which language you pick.

Settings

Owner, admin and developer only. Four cards, top to bottom.

Version and Forced Update. Sets the version string clients must send to /init, toggles force_update to hard-block outdated clients with a 426 response, and sets the update_url plus update_message returned to those clients. The message defaults to A new version is required. if left blank.

Alert Webhook (this app). A per-app override of the global webhook. It fires with a screenshot and location when a key is used from a new device or a new location; leaving the input blank falls back to the global webhook.

Reseller Credit Costs. Sets how many credits a reseller spends per generated key, broken down by duration tier:

TierKey
1 daydays:1
7 daysdays:7
30 daysdays:30
90 daysdays:90
180 daysdays:180
365 daysdays:365
lifetimelifetime

Leave a tier blank to fall back to the 30-day price prorated by days. All tiers blank means one credit per key.

API Secret. A single Rotate Secret button calls POST /apps/{id}/rotate-secret.

Rotation is destructive

Rotating invalidates any signature hardcoded into an older client build. Plan the rollout before clicking, or all in-field clients start failing signed calls immediately.

Danger Zone. Delete Application removes the app, every key, every user and every log. A confirmation dialog is required, and the operation is not reversible.

Reseller view

Resellers get a strict subset of the detail view. They do not see the New Application button, the Settings tab, or the API Secret anywhere on the page, and Extend Active is hidden because bulk mutations are owner-side only.

Per-tab and per-action gates then apply on top. A reseller with view_keys but not delete_keys sees the Licenses table without the trash icon; blacklist entries are visible but read-only. For the full permission matrix, see Team and Resellers.