Skip to content
Oclavex is in private preview, available to selected users. Public signup is blocked. Request access at [email protected].

Using the REST API

Every endpoint follows the same conventions, so learning them once covers the whole surface. Per-endpoint request and response schemas are in the generated REST API reference; this page is the contract around them.

Routes are api/v1/provision/... and split by audience:

Area Audience Credential
admin/* Back-office: catalog authoring, entitlement management, reporting Admin-scoped client credentials
operational/* Your backend automating lifecycle operations — issue codes, renew, top up Operational-scoped client credentials
unmarked The runtime surface your shipped application calls Anonymous (activation) or license session token

The split is deliberate: runtime endpoints never require an API secret, so nothing secret ships inside your application.

What a shipped application (or the .NET SDK on its behalf) calls:

Activation & sessions

  • POST /activations/jwt — activate, returns the license token only.
  • POST /activations/license — activate, returns token plus metadata (the entitlement description and license terms link, the licensed products and their Public custom properties, feature names and descriptions).
  • POST /activations/{sessionId}/renew — extend the lease without re-activating.
  • POST /activations/{sessionId}/check-in / /release — heartbeat and seat release for floating and inactivity-based licenses.

Session calls present the session’s license token. A token the server no longer accepts, because its signing key, audience or lifetime doesn’t validate, is refused with 401 license.session_token_rejected. A session that no longer exists, deleted or revoked, is refused with 409 license.no_active_session on every session call; a usage upload under it is answered entitlementResolved: false and records nothing. Either way, activate again. The .NET SDK does this once on its own.

Usage & metering

  • POST /usage/sessions/{sessionId}/transactions — batch usage upload.
  • POST /usage/preview-consume/{sessionId}/{metric} and /usage/consume/{sessionId}/{metric}?amount= — ask, then charge metered consumption where overuse must be blocked. The first changes nothing and reserves nothing; the second is the decision that binds. A metric the entitlement doesn’t track is refused with 404 license.metric_not_tracked, and a session that no longer exists is refused with 409 license.no_active_session; nothing is charged either way.
  • GET /usage/{sessionId}/{metric}/usage and /consumption — current usage snapshot and remaining balance; 204 for a metric the entitlement doesn’t track.
  • GET /usage/sessions/{sessionId}/rating-prompt — the next feature-rating prompt to show, if any.

Signed-in user self-service (/consumer/me/..., user token)

  • GET /consumer/me/sessions — the user’s active license sessions.
  • GET /consumer/me/activation-codes — codes issued to the user.
  • GET /consumer/me/entitlements/{entitlementId}/plans and /sessions/{sessionId}/plans — the plans behind a license, for in-app display.

Collection endpoints return a shared envelope:

{
"items": [ … ],
"pageNumber": 1,
"pageSize": 25,
"totalCount": 112,
"totalPages": 5,
"hasNextPage": true,
"hasPreviousPage": false
}

Page with pageNumber (1-based) and pageSize (max 100). A pageSize above the maximum is silently clamped to it, not rejected.

filter and sortOrder take Sieve expressions:

  • filter — Field==Value for equality, Field@=text for contains; comma-separate terms and they are ANDed (name@=acme,status==Active).
  • sortOrder — Field ascending, -Field descending, comma-separated (-createdAt,name).

Filterable and sortable fields are whitelisted per endpoint — see the REST API reference. An expression that doesn’t parse or names a non-whitelisted field returns 400 license.validation_error.

  • PATCH <collection>/{id} is a merge: send only the fields you’re changing; absent or null fields stay untouched. Where a field must be explicitly cleared, the DTO documents a sentinel (e.g. clearExpirationDate).
  • PUT replaces the full editable representation — send everything.
  • Toggles and anything needing a payload on delete are POST .../{id}/<action> (e.g. enable-activations / disable-activations).

A request that returns something answers 200 with it. A request that changes something and has nothing to return answers either 200 or 204 No Content with an empty body; the REST API reference names which for each endpoint. Treat any 2xx as success.

  • Activation is retry-safe: re-activating with the same code and fingerprint returns the existing session, never a duplicate seat.
  • Idempotency-Key header (up to 200 characters) — send one on any mutating request you might retry. On the activation endpoints the key is durable: it persists on the session, a replay of an identical request returns the same session, and reusing the key with different parameters is rejected with 409. On the operational balance mutations and the consumer credit grant the key is honored for 24 hours — a retry returns the original response.
  • Usage transactions carry their own ids and timestamps; upload batches can be retried after a network failure, under the same session or another session of the same license. A record already uploaded is acknowledged and not counted again. A record captured more than 90 days before it is uploaded is acknowledged but not counted.
  • Metered consumption (consume) accepts an idempotencyKey query parameter — a retried consume with the same key returns the original decision instead of consuming twice. A key is remembered for 24 hours. Once it is older than that, it is forgotten within the hour, and a consume that sends it again counts as a new consume.
  • Pass X-Correlation-Id on any request to correlate it across your logs and Oclavex’s — echo one id through a whole business operation.
  • When consuming webhooks, dedupe on the webhook-id header — delivery is at-least-once.

Failures return application/problem+json with a stable numeric code and dotted codeName:

{
"status": 404,
"title": "Not Found",
"detail": "The activation code does not map to an entitlement.",
"code": 2004,
"codeName": "license.not_found"
}

Branch on code or codeName — never on detail, which is human-facing prose and may change. The full catalog is in Error codes.