Skip to content

Accounts and roles ​

A panel account is an owner, an admin, a reseller, or an account on a custom role. A role is a set of permission scopes and default limits. These endpoints list and change accounts, set a password or reset a second factor, read an account's usage, apply plan actions, and manage roles.

Times are Unix seconds and traffic is bytes. All endpoints here are owner-only. A full token made by the owner can call the token-enabled endpoints; password and second-factor changes require a browser session. A custom token cannot call owner-only endpoints, even when it carries every permission.

List accounts ​

GET/api/adminspermissionowner

Returns every account, the owner included, with its role, state, client count and effective limits.

bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" "$BASE/admins"
json
[
  {
    "id": 7,
    "username": "shop",
    "role": "reseller",
    "roleId": 2,
    "roleName": "Reseller",
    "state": "active",
    "disabled": false,
    "totpEnabled": false,
    "expireAt": 1796000000,
    "trafficLimit": 1099511627776,
    "usedBytes": 82463372083,
    "clients": 24,
    "online": 3,
    "maxClients": 100,
    "note": "",
    "createdAt": 1793000000,
    "lastLoginAt": 1795915000
  }
]

Create an account ​

POST/api/adminspermissionowner
FieldTypeRequiredMeaning
usernamestringyes3-32 characters without spaces or quotes. Unique.
passwordstringon createInitial password. Ignored on update.
rolestringnoowner, admin or reseller. Used when roleId is 0.
roleIdintegernoAny role, built-in or custom. 0 with role: owner makes an owner.
overridesobjectnoLimits that replace the role's defaults for this account.
disabledbooleannoBlock sign-in.
expireAtintegernoAccount end in Unix seconds. 0 means never.
trafficLimitintegernoTraffic pool in bytes. 0 means unlimited.
notestringnoFree text, at most 500 characters.
bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  -H "Content-Type: application/json" -X POST "$BASE/admins" \
  -d '{
    "username": "shop",
    "password": "a-long-password",
    "role": "reseller",
    "trafficLimit": 1099511627776,
    "expireAt": 1796000000,
    "overrides": { "maxClients": 100, "maxDevices": 2 }
  }'
json
{
  "id": 7,
  "username": "shop",
  "role": "reseller",
  "roleId": 2,
  "roleName": "Reseller",
  "state": "active",
  "disabled": false,
  "expireAt": 1796000000,
  "trafficLimit": 1099511627776,
  "usedBytes": 0,
  "clients": 0,
  "maxClients": 100
}

400 means a bad field or a taken username. 402 means the licence does not allow another account.

Get one account ​

GET/api/admins/{id}permissionowner

Returns one account. Path parameter id is the account id.

bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" "$BASE/admins/7"

404 means no such account.

Change an account ​

PUT/api/admins/{id}permissionowner

Sends the same fields as create. password is ignored here; use the password endpoint. The last owner cannot be removed or turned into another role.

bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  -H "Content-Type: application/json" -X PUT "$BASE/admins/7" \
  -d '{"username":"shop","roleId":2,"trafficLimit":2199023255552,"expireAt":1798592000,"disabled":false}'

The answer is the changed account. 400 means a bad field, a taken username, or a change that would remove the last owner.

Remove an account ​

DELETE/api/admins/{id}permissionowner

Removes an account. Its clients are moved to another account by default, or deleted.

ParameterInTypeMeaning
idpathintegerAccount id.
clientsquerystringdelete deletes the account's clients instead of moving them.
toqueryintegerAccount that receives the clients. Default is the caller.
bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  -X DELETE "$BASE/admins/7?to=1"
json
{ "ok": true, "clients": 24 }

clients is how many clients were moved or deleted. 400 means the account cannot be deleted or the target is not valid.

Set another account's password ​

POST/api/admins/{id}/passwordpermissionownersession only

Session only. Sets a new password for an account and signs out its other sessions.

FieldTypeRequiredMeaning
passwordstringyesThe new password, checked for strength.
bash
curl -sS -b cookies.txt -X POST "$BASE/admins/7/password" \
  -H "Content-Type: application/json" -H "X-CSRF-Token: $CSRF" \
  -d '{"password":"a-new-long-password"}'
json
{ "ok": true }

400 means the password is too weak.

Reset another account's second factor ​

POST/api/admins/{id}/reset-2fapermissionownersession only

Session only. Turns off two-factor sign-in for an account, for example when its phone is lost.

bash
curl -sS -b cookies.txt -X POST "$BASE/admins/7/reset-2fa" \
  -H "X-CSRF-Token: $CSRF"
json
{ "ok": true }

404 means no such account.

Read an account's traffic ​

GET/api/admins/{id}/usagepermissionowner
ParameterInTypeMeaning
idpathintegerAccount id.
rangequerystring24h, 7d, 30d or 90d. Default 30d.
tzqueryintegerViewer's offset from UTC in minutes, -840 to 840. Default 0.
bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  "$BASE/admins/7/usage?range=30d"

The answer is a usage series with points, from, to, bucket and offset. 404 means no such account.

Apply a plan action ​

POST/api/admins/{id}/{action}permissionowner

Changes an account's traffic pool, end date or state. The action in the path wins over body.action.

ActionWhat it does
add-trafficAdds bytes to the pool.
extendAdds days from the later of now and the current end. A bytes value above 0 replaces the pool. resetUsage also zeroes used traffic.
reset-usageSets the account's used traffic to zero.
disable or enableBlocks or restores sign-in.
disable-clients or enable-clientsBlocks or restores all clients the account owns.
FieldTypeMeaning
actionstringThe same action. Ignored when the path already names one.
bytesintegerBytes to add, or a new pool for extend when above 0.
daysintegerDays to add for extend, 0-3650.
resetUsagebooleanFor extend: also zero the used traffic.
bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  -H "Content-Type: application/json" -X POST "$BASE/admins/7/add-traffic" \
  -d '{"bytes":1099511627776}'

The answer is the account after the action. 400 means the action is not valid or the last owner cannot be disabled.

List roles ​

GET/api/admin-rolespermissionowner

Returns every role, built-in first, and the permission keys a role may grant.

bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" "$BASE/admin-roles"
json
{
  "items": [
    {
      "id": 2,
      "name": "Reseller",
      "builtin": true,
      "perms": { "clients.view": "own", "clients.create": "own", "connections.view": "own" },
      "limits": { "maxClients": 0, "maxDevices": 0, "allowUnlimited": true },
      "createdAt": 0,
      "admins": 4
    }
  ],
  "perms": [
    { "key": "clients.view", "scoped": true },
    { "key": "groups.manage", "scoped": false }
  ]
}

A scope is none, own or all. For groups.view and inbounds.view, own means only the granted groups or inbounds.

Create a role ​

POST/api/admin-rolespermissionowner
FieldTypeRequiredMeaning
namestringyes1-40 characters. Unique.
permsobjectnoPermission key to scope. Missing keys are none.
limitsobjectnoDefaults for accounts on this role.
bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  -H "Content-Type: application/json" -X POST "$BASE/admin-roles" \
  -d '{
    "name": "Support",
    "perms": {
      "clients.view": "all",
      "clients.edit": "all",
      "connections.view": "all",
      "connections.kick": "all"
    },
    "limits": { "maxClients": 0, "allowUnlimited": true }
  }'

The answer is the new role. 400 means a bad field or a taken name.

Change a role ​

PUT/api/admin-roles/{id}permissionowner

Sends the same fields as create. Built-in roles cannot be changed.

bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" \
  -H "Content-Type: application/json" -X PUT "$BASE/admin-roles/5" \
  -d '{"name":"Support","perms":{"clients.view":"all","clients.edit":"all"}}'

400 means a bad field, a built-in role, or a taken name.

Remove a role ​

DELETE/api/admin-roles/{id}permissionowner

Removes a custom role. A role that accounts still use cannot be removed.

bash
curl -sS -H "Authorization: Bearer $OVIRA_TOKEN" -X DELETE "$BASE/admin-roles/5"
json
{ "ok": true }

400 means the role is built-in. 409 means accounts still use it.

Limits object ​

limits and overrides use these fields. In overrides, only the fields you send replace the role's value; 0 means no cap.

FieldTypeMeaning
maxClientsintegerClient cap; 0 means no cap.
allowedGroupsinteger[]Group ids the account may use.
allowedInboundsinteger[]Inbound ids the account may use.
requireGroupbooleanClients must join an allowed group instead of single inbounds.
maxClientTrafficintegerPer-client traffic cap in bytes; 0 means no cap.
maxClientDaysintegerPer-client lifetime in days; 0 means no cap.
maxDevicesintegerPer-client device cap; 0 means no cap.
allowUnlimitedbooleanThe account may create clients without a traffic cap.
trafficLimitintegerDefault pool for new accounts on the role, in bytes.

Proprietary software · documentation free to share