VisiDog EnterpriseIntegration API
← Back to Portal

Enterprise user provisioning API

Provision, update and deprovision enterprise users in batches. The integration token determines the tenant, so callers never supply an organization identifier.

1. Authenticate your integration

An enterprise administrator manages tokens through /api/enterprise/integration-tokens. Store the returned vdt_… secret in a secret manager: it is shown only once.

Authorization
Every request requires Authorization: Bearer vdt_your_secret_token. A disabled or expired token receives 401 Unauthorized. A token is valid only as long as the enterprise that issued it exists and is open: once that enterprise is deleted, purged after an expired licence, suspended or deactivated, its tokens stop working and receive the same 401 Unauthorized, so the status never tells a client whether an enterprise exists or what state it is in. Restoring the enterprise to an open state makes its existing secrets work again, with no new token to issue.

Activating or revoking a token is a PATCH on that same endpoint, carrying is_active. The field is required and accepts the JSON booleans true and false, the strings "true" and "false", and the integers 1 and 0. Any other value is refused with 400 invalid_is_active, and a request without is_active is refused too, so a malformed body can never revoke a token.

Replaying a state
Sending the state a token already has succeeds and changes nothing: the first revocation date is kept and no audit entry is written. A 404 therefore means the identifier belongs to no token of the tenant.

2. List users

GET/api/integration/users

Returns only users belonging to the tenant associated with the token. For linked members, email is the current global identity address and can be null. The display name, role and account status belong to the membership in this tenant.

Request
curl --request GET "https://visidog.com/api/integration/users" \
  --header "Authorization: Bearer vdt_your_secret_token"
200 response
{
  "users": [{
    "user_id": "user_01J…", "email": "[email protected]",
    "display_name": "Ada Lovelace", "role": "user", "status": "active",
    "is_active": 1, "config_id": "cfg_01J…", "access_role_id": 12,
    "valid_from": "2026-09-20 09:00:00", "valid_until": "2026-12-31 23:59:59"
  }]
}

3. Create users awaiting confirmation

POST/api/integration/users

Creation is batch-oriented. Each account receives a new global identity and waits for email confirmation. A valid email address is required. Existing accounts are never merged or attached by email; invite an existing identity through the portal. The integration sends an activation email after the account and its audit entry are committed. No password is issued by the provisioning API.

Request
curl --request POST "https://visidog.com/api/integration/users" \
  --header "Authorization: Bearer vdt_your_secret_token" \
  --header "Content-Type: application/json" \
  --data '{"users":[{"display_name":"Ada Lovelace","email":"[email protected]","config_id":"cfg_01J…","access_role_id":12,"role":"user"}]}'
200 response
{ "results": [{ "user_id": "user_01J…", "status": "created", "account_status": "pending", "is_active": false, "activation_sent": true, "activation_url": null }] }
Email confirmation
A pending account reserves a license seat. activation_url is null in ordinary responses: the link goes to the email recipient. If activation_sent is false, the account remains pending and an administrator can resend its link in the portal. The recipient confirms the address, then uses password recovery to choose a first password before signing in.
License enforcement
Creation is refused with 403 license_expired when the company license is expired. At quota, the corresponding item returns license_quota_exceeded.
Access role at creation
An omitted or null access_role_id takes the default role of your enterprise; an item that names a role of another enterprise, a role that does not exist or a value that is not a role identifier fails with invalid_access_role, and an enterprise without a default role fails with default_access_role_missing.

4. Update or delete users

PATCH/api/integration/users
Update request
curl --request PATCH "https://visidog.com/api/integration/users" \
  --header "Authorization: Bearer vdt_your_secret_token" \
  --header "Content-Type: application/json" \
  --data '{"users":[{"user_id":"user_01J…","display_name":"Ada L.","is_active":true}]}'
DELETE/api/integration/users
Delete request
curl --request DELETE "https://visidog.com/api/integration/users" \
  --header "Authorization: Bearer vdt_your_secret_token" \
  --header "Content-Type: application/json" \
  --data '{"users":[{"user_id":"user_01J…"}]}'
Role vocabulary and tenant administration
role only accepts user, admin and admin-light; any other value fails that item with invalid_role, and an omitted role means user. An item whose role or is_active would remove the tenant's last active administrator — including a delete of that account — fails with last_administrator_required. Promote or reactivate another account first, then retry.
Confirmation before reactivation
Setting is_active: true cannot activate a pending account or a global identity without a confirmed address. The item fails with account_not_verified, including after a prior deactivation. Confirm the address first. All fields of a refused item remain unchanged.
Access role is bound to your enterprise
access_role_id must designate a role of your own enterprise, on POST as on PATCH. Any other value fails that item with invalid_access_role, which covers a role that does not exist, a role of another enterprise, and a value that is not a role identifier at all. A creation that names no role takes your enterprise's default role, and a creation in an enterprise that has none fails with default_access_role_missing. On PATCH, null removes the explicit assignment: the account then follows the default role of your enterprise, as the enterprise portal does. The audit entry of a successful assignment records the role that was written, not the string that was sent.

5. Batch responses and audit

A mutation returns one result per submitted item. Successful operations are recorded individually and the complete batch is also written to the enterprise audit trail.

createdNew account awaiting email confirmation, with its delivery status.
updated / deletedOperation completed for the supplied user ID.
errorOnly that item failed; inspect its stable code and safely retry the remaining items.
Operational guidance
Never put tokens in URLs, browser code, logs or source control. Rotate a token by creating a replacement, updating your integration secret, then disabling the old token.

6. Error codes and support correlation

An item with status: error carries a stable code. Business refusals use an explicit vocabulary: invalid_role, missing_required_fields, email_already_exists, account_invitation_required, account_not_verified, license_expired, invalid_config_id, invalid_access_role, default_access_role_missing, license_quota_exceeded, user_id_required, no_mutable_field, not_found and last_administrator_required. An audit failure uses audit_trail_unavailable.

A technical failure uses integration_user_failed, a neutral error message and a request_id. Supply that identifier to support to locate the server diagnostic. SQL details, internal paths and exception messages are not returned. A successful created result never carries a personal code or its hash. account_status describes the pending account and activation_sent reports email delivery.