Skip to content

Deactivate Device

Release (revoke) a device activation so its seat is freed. There are two ways to do this, for two different callers:

  1. App self-service release (Integration API) — the licensed application releases the seat it activated (e.g. on uninstall / deregister / hardware change). This is the recommended, automated path and the one that lets a activations.max: 1 license move to a new device without manual help.
  2. Administrative revoke (Tenant / Admin API) — the account owner (or a ValidonX admin) force-revokes a specific activation by id from the dashboard.

Revocation is non-destructive: the activation record is preserved (status = "revoked", deactivated_at set) for audit purposes, and the seat it held no longer counts against the license's activations.max.


1. App self-service release (Integration API)

The application releases the activation it created, identified by the same license_key + instance_id it activated with — no activation id required.

Endpoint

POST /api/v1/integration/activations/deactivate

Headers

HeaderRequiredValue
X-API-KeyYesYour API key
Content-TypeYesapplication/json

Request Body

json
{
  "license_key": "VX-ACME-abc123def456",
  "instance_id": "server-prod-01",
  "device_fingerprint": "sha256-hash-of-device-info"
}
FieldRequiredTypeDescription
license_keyYesstringThe license key the seat was activated against
instance_idYesstringThe instance identifier used at activation
device_fingerprintNostringIf supplied, further narrows the match to a specific device

Response (200 OK)

json
{
  "data": {
    "activation": {
      "id": "9a1b7c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d",
      "license_key_id": "1f2e3d4c-5b6a-7988-a0b1-c2d3e4f5a6b7",
      "instance_id": "server-prod-01",
      "device_fingerprint": "sha256-hash...",
      "status": "revoked",
      "deactivated_at": "2026-07-06T10:00:00.000000Z"
    }
  },
  "meta": { "request_id": "uuid", "api_version": "1" }
}

Idempotency

Releasing a seat that is already released returns 200 with the same revoked activation — safe to retry, and safe to call on every uninstall even if a previous attempt already succeeded.

Freeing a single-seat license

For a license with activations.max: 1, a second device is refused with ACTIVATION.LIMIT_EXCEEDED while the first seat is active. Releasing the first activation frees the seat, and the next device can then activate — the intended device-transfer flow.

Error Responses

CodeHTTPDescription
LICENSE.NOT_FOUND404License key not found for your tenant
ACTIVATION.INVALID400No activation exists for that license_key + instance_id
VALIDATION.FAILED422license_key or instance_id missing
AUTH.INVALID_API_KEY401Invalid API key

2. Administrative revoke (Tenant / Admin API)

The account owner force-revokes a specific activation by id — e.g. to reclaim a lost, stolen, or stuck seat. Activation ids come from GET /api/v1/tenant/activations (see the Activation Lifecycle guide).

Endpoint

DELETE /api/v1/tenant/activations/{activationId}

Platform admins can revoke on behalf of a tenant at:

DELETE /api/v1/admin/tenants/{tenantId}/activations/{activationId}

Headers

HeaderRequiredValue
AuthorizationYesBearer {token} (token needs the tenant ability)

This path uses a tenant Bearer token, not an API key — it is an account-management action, not something the distributed application performs.

Response (200 OK)

json
{
  "data": {
    "id": "9a1b7c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d",
    "status": "revoked",
    "deactivated_at": "2026-07-06T10:00:00.000000Z"
  },
  "meta": { "request_id": "uuid", "api_version": "1" }
}

Idempotent — revoking an already-revoked activation still returns 200. An activation that belongs to another tenant is reported as not found (ACTIVATION.INVALID), never revealed or revoked.

Error Responses

CodeHTTPDescription
ACTIVATION.INVALID400Activation not found (or not owned by your tenant)
AUTH.TOKEN.REQUIRED401Missing / invalid Bearer token

Activation States

StatusDescription
activeCurrently active, counts against activations.max
suspendedTemporarily suspended
revokedDeactivated — deactivated_at set; no longer counts against the limit