Super Admin API
Platform-wide operations that cross tenant boundaries: creating tenants, defining the base domain they sit under, and imposing one sign-in or sharing policy on all of them. For operations inside a single tenant, see Admin. Issuing and managing API Keys for any tenant, including on the super admin surface, is covered in Authentication.
Base URL and authorization
/api/external/v1/super-admin
These endpoints require an API Key issued to an account holding the SUPER_ADMIN role. An ordinary administrator's key
does not pass.
Like the admin endpoints, authorization is by role alone. A key holding only api:read can create tenants, change the
base domain, and enforce policy across every tenant. A super administrator key is the most privileged credential in the
system regardless of the scope it was issued with.
Tenant entry-key issuance is not available through the external API.
Failures use the common envelope. Each section below lists the codes its endpoints return.
{
"result": false,
"code": 404,
"errorCode": "TENANT_001",
"message": "..."
}
Base domain
Tenants are addressed as a subdomain of one shared base domain.
GET /api/external/v1/super-admin/base-domain
PUT /api/external/v1/super-admin/base-domain
Read the base domain
curl "https://drive.example.com/api/external/v1/super-admin/base-domain" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY"
| Field | Type | Meaning |
|---|---|---|
baseDomainSeq | integer | Always 1 once configured; null when not configured |
baseDomain | string | The base domain; null when not configured |
Reading before a base domain is configured is not an error. It returns 200 with both fields null.
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"baseDomainSeq": 1,
"baseDomain": "drive.example.com"
}
}
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"baseDomainSeq": null,
"baseDomain": null
}
}
Set the base domain
| Parameter | Type | Required | Description |
|---|---|---|---|
bd | string | Yes | Base domain as a full domain name, up to 253 characters |
bd accepts lowercase letters, digits, and hyphens only - uppercase is rejected. Each dot-separated label is 1-63
characters and starts and ends with a lowercase letter or digit, and the last label (the TLD) is at least two letters.
Anything else returns BASE_DOMAIN_002.
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/base-domain" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"bd": "drive.example.com"}'
The call registers the base domain if none exists and changes it otherwise. It returns 200 OK with no data.
Sending the current value again also succeeds and repeats the recalculation below.
Setting the base domain recalculates tenant domains:
- First setting - organization tenants that already have a domain are rewritten. The first label of the existing
domain becomes the subdomain, giving
{subdomain}.{new base domain}. A domain with no dot becomes the base domain itself. - Change - only tenants linked to this base domain are rewritten, each keeping its own subdomain.
Tenants with no domain, or not linked to the base domain, are unchanged. If any recalculation fails, nothing is applied. Rewritten tenant URLs stop resolving at their old addresses, so plan for DNS, certificates, and any hard-coded client URLs before changing it.
| Code | Status | Meaning |
|---|---|---|
REQUEST_001 | 400 | bd is missing or longer than 253 characters |
BASE_DOMAIN_002 | 400 | bd is not a valid domain |
RESPONSE_001 | 500 | Unexpected server error |
BASE_DOMAIN_001 is not returned here. It is returned by tenant create and update when bs names a base domain that
does not exist.
Tenants
List tenants
GET /api/external/v1/super-admin/tenants
| Parameter | Type | Required | Description |
|---|---|---|---|
ps | integer | Yes | Page size, minimum 1 |
ci | long | No | Cursor - the last tenantSeq of the previous page |
curl "https://drive.example.com/api/external/v1/super-admin/tenants?ps=20" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY"
Results are ordered by tenantSeq descending. When the page comes back full, the response carries hasNext: true and
nextCursor, the last tenantSeq; pass it as ci for the next page.
| Field | Type | Meaning |
|---|---|---|
tenantSeq | long | Tenant identifier |
tenantName | string | Tenant name |
domain | string | {subdomain}.{base domain}, or null when there is none |
clientUrl | string | https:// followed by domain |
registerDate | string | YYYY-MM-DD HH:mm:ss.SSS |
license | object | Licence summary, or null |
license is null for a tenant with no licence and also when its licence fails verification. Otherwise it carries
state, expiresOn (YYYY-MM-DD), and seat. seat holds current and max only for a seat-limited licence and
is null for any other, so you can spot over-subscribed tenants only among seat-limited licences.
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"list": [
{
"tenantSeq": 12,
"tenantName": "Example",
"domain": "example.drive.example.com",
"clientUrl": "https://example.drive.example.com",
"registerDate": "2026-09-01 10:15:30.123",
"license": null
}
],
"pageSize": 20,
"hasNext": false
}
}
Read a tenant
GET /api/external/v1/super-admin/tenants/{tenantSeq}
curl "https://drive.example.com/api/external/v1/super-admin/tenants/12" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY"
Returns tenantSeq, tenantName, subdomain, baseDomainSeq, and allowedIps. allowedIps is always in
{IP}/{prefix} form - a single address is reported as /32. An unknown tenant returns TENANT_001.
Note that the listing returns the assembled domain while this endpoint returns the subdomain it was built from.
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"tenantSeq": 12,
"tenantName": "Example",
"subdomain": "example",
"baseDomainSeq": 1,
"allowedIps": ["192.168.0.12/32", "192.168.0.0/24"]
}
}
Create a tenant
POST /api/external/v1/super-admin/tenants
Creates the tenant, its first administrator, and its IP allowlist in one call.
| Parameter | Type | Required | Description |
|---|---|---|---|
tn | string | Yes | Tenant name |
sd | string | Yes | Subdomain, up to 253 characters |
bs | integer | Yes | Base domain seq |
e | string | Yes | Administrator account id, an email address; unique across all tenants |
n | string | Yes | Administrator display name |
p | string | Yes | Administrator password |
ips | array | No | IPv4 addresses or CIDR ranges allowed to reach the administrator |
sdaccepts lowercase letters, digits, and hyphens only; uppercase returnsTENANT_007. Each dot-separated label is 1-63 characters and starts and ends with a lowercase letter or digit. The full domain is{sd}.{base domain}.emust not match an account id already used in any tenant, or it returnsUSER_004.pis 8-64 characters and contains at least one uppercase letter, lowercase letter, digit, and special character, or it returnsUSER_001.ipssupports IPv4 only, and a single address is stored as/32. A CIDR range must be a network address -192.168.0.0/24is accepted,192.168.0.12/24returnsACCESS_004.
curl -X POST "https://drive.example.com/api/external/v1/super-admin/tenants" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"tn": "Example", "sd": "example", "bs": 1, "e": "admin@example.com", "n": "Administrator", "p": "Test1234!", "ips": ["192.168.0.12", "192.168.0.0/24"]}'
A successful call returns 201 Created with no data. Find the new tenantSeq through the listing.
The administrator is created with the ADMIN role and zero storage quota, and the tenant's login type is local. If any
part - tenant, administrator, allowlist, or default settings - fails, nothing is created.
The new tenant starts with a default configuration. The office domain and adapter name are empty and must be set
before the tenant can open documents. Default share settings are created as well: per-tenant, external sharing off,
SPECIFIC_USERS on, ORG_LINK on, and PUBLIC_LINK off. Change these through the tenant's own Admin
endpoints.
Update a tenant
PATCH /api/external/v1/super-admin/tenants/{tenantSeq}
| Parameter | Type | Required | Description |
|---|---|---|---|
tn | string | Yes | Tenant name |
sd | string | Yes | Subdomain, up to 253 characters |
bs | integer | Yes | Base domain seq |
ips | array | No | Allowed IPv4 addresses or CIDR ranges; replaces the whole list |
sd and ips follow the same format rules as create. The tenant's own current domain does not count as a duplicate.
Changing sd changes the tenant's address.
ips replaces the allowlistThe list you send replaces the existing allowed IPs, and an empty array removes them all. All three of tn, sd, and
bs are required too, so read the tenant first and resend its current values - including allowedIps - for anything
you are not changing.
curl -X PATCH "https://drive.example.com/api/external/v1/super-admin/tenants/12" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"tn": "Example Inc.", "sd": "example", "bs": 1, "ips": ["192.168.0.12/32", "192.168.0.0/24"]}'
Search a tenant's accounts
GET /api/external/v1/super-admin/tenants/{tenantSeq}/users/search
Finds accounts in a tenant, for choosing the target of an API Key on the super admin surface.
| Parameter | Type | Required | Description |
|---|---|---|---|
sk | string | Yes | Partial match on account id or name |
rt | string | No | ADMIN or USER; both when omitted. Any other role returns USER_028 |
curl "https://drive.example.com/api/external/v1/super-admin/tenants/12/users/search?sk=admin&rt=ADMIN" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY"
Only active accounts are returned, ordered by name ascending, with no paging. Each entry has userSeq, userId,
userName, status, and roleType. An unknown tenant returns TENANT_001.
Tenant errors
| Code | Status | Meaning |
|---|---|---|
REQUEST_001 | 400 | A required value is missing or too long |
TENANT_001 | 404 | The tenant was not found |
TENANT_006 | 409 | The domain is already in use |
TENANT_007 | 400 | The subdomain is not valid |
BASE_DOMAIN_001 | 404 | bs names a base domain that does not exist |
USER_001 | 400 | The administrator password does not meet the rules |
USER_002 | 400 | The administrator id is not a valid email address |
USER_004 | 409 | The administrator id is already in use |
USER_013 | 500 | The administrator account could not be saved |
USER_028 | 400 | Account search rt is not ADMIN or USER |
ACCESS_004 | 400 | An IP address or CIDR range is not valid |
RESPONSE_001 | 500 | Unexpected server error |
Sign-in policy
The same sign-in configuration as the tenant-level endpoint, with the addition that a super administrator can impose it on every tenant at once.
GET /api/external/v1/super-admin/login-settings
PUT /api/external/v1/super-admin/login-settings
Read the sign-in policy
| Parameter | Type | Required | Description |
|---|---|---|---|
s | string | No | Scope to build the response for - tenant or global |
l | string | No | Login type to build the response for - local, oidc, or jwt |
s and l do not filter stored values; they choose which view of the setting is returned. Precedence is s, then
l, then the stored enforcement flag:
s=tenantreturns the per-tenant view:loginTypenull,isEnforcedfalse, and an emptyconfigs.s=global, orlgiven, returns the providers for that login type.ltakes the place of the stored login type.- With neither, the response follows the stored enforcement flag.
curl "https://drive.example.com/api/external/v1/super-admin/login-settings?s=global&l=oidc" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY"
The response carries superAdminLoginSettingSeq, loginType, isEnforced, and configs. configs holds only
providers registered for global enforcement. For OIDC, scopes is always null and allowIdpInitiated is always
false; registerDate appears only on OIDC providers. With no setting saved, every value is null and configs is
empty, whatever the parameters.
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"superAdminLoginSettingSeq": 1,
"loginType": "jwt",
"isEnforced": true,
"configs": [
{
"ssoProviderSeq": 3,
"displayName": "Example SSO",
"status": "ACTIVE",
"config": {
"type": "jwt",
"issuer": "https://sso.example.com",
"keySourceType": "public_key",
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
}
}
]
}
}
As at tenant level, clientSecret and publicKey come back unmasked. Keep the response server-side.
Set the sign-in policy
| Parameter | Type | Required | Description |
|---|---|---|---|
ie | boolean | Yes | true applies this setting to every tenant; false leaves each tenant to its own |
l | string | Conditional | Login type - local, oidc, or jwt; required when ie is true |
ps | array | Conditional | Identity providers; required when ie is true and l is oidc or jwt |
Providers and their config objects take the same fields as the tenant-level endpoint described in
Admin. A config.type that differs from l returns REQUEST_001, and an l value that is not defined,
such as saml, returns RESPONSE_001. SSO_PROTOCOL_001 and SSO_PROTOCOL_002 are not returned by this endpoint.
With ie=false, l and ps are ignored and the stored global providers are kept, not deleted.
- OIDC - saving with
l=oidcreplaces the provider list withps. Existing providers missing from the request are deleted; to keep one, send it back with itsssoProviderSeq. Exactly one provider must havestatusACTIVE, or the call returnsREQUEST_001. - JWT - one provider only. If an active JWT provider already exists, send its
ssoProviderSeqto update it; sending none returnsSSO_PROVIDER_005.statusis always saved asACTIVE. Anissueralready used by another JWT provider returnsSSO_PROTOCOL_JWT_002. displayNamemust be unique within the request after trimming, or the call returnsREQUEST_001. AnssoProviderSeqthat does not exist or is not a global provider returnsSSO_PROVIDER_001.publicKeyis stored with the PEM header and footer and all whitespace removed, and is read back in that form.
A successful call returns 200 OK with no data. While ie is true, a tenant administrator who tries to change the
tenant's sign-in settings gets SSO_PROVIDER_006.
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/login-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ie": true, "l": "local"}'
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/login-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ie": true, "l": "oidc", "ps": [{"displayName": "Example SSO", "status": "ACTIVE", "config": {"type": "oidc", "issuerUrl": "https://sso.example.com", "clientId": "example-client", "clientSecret": "replace-with-your-client-secret"}}]}'
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/login-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ie": true, "l": "jwt", "ps": [{"ssoProviderSeq": 3, "displayName": "Example SSO", "config": {"type": "jwt", "issuer": "https://sso.example.com", "keySourceType": "public_key", "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."}}]}'
This endpoint uses l and ps where the tenant endpoint uses loginType and providers, and adds ie. The read
response reports isEnforced rather than superAdminEnforced. The config objects are identical.
Sign-in policy errors
| Code | Status | Meaning |
|---|---|---|
REQUEST_001 | 400 | A required value is missing or a rule is broken; also an invalid s or l on read |
SSO_PROVIDER_001 | 404 | The ssoProviderSeq does not exist or is not a global provider |
SSO_PROVIDER_005 | 409 | An active JWT provider exists and no ssoProviderSeq was sent |
SSO_PROTOCOL_JWT_002 | 409 | The JWT issuer is already used by another provider |
RESPONSE_001 | 500 | Unexpected server error, including an undefined l on save |
Sharing policy
GET /api/external/v1/super-admin/share-settings
PUT /api/external/v1/super-admin/share-settings
Read the sharing policy
curl "https://drive.example.com/api/external/v1/super-admin/share-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY"
| Field | Type | Meaning |
|---|---|---|
shareSettingSeq | long | Setting identifier |
isEnforced | boolean | Whether the policy is applied to every tenant |
shareEnabled | boolean | Whether sharing is available |
externalShareAllowed | boolean | Sharing outside the organization |
allowSpecificUsers | boolean | SPECIFIC_USERS share type |
allowOrgLink | boolean | ORG_LINK share type |
allowPublic | boolean | PUBLIC_LINK share type |
Even when isEnforced is false, the stored values are returned - the values last enforced. With no setting saved,
every field is null.
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"shareSettingSeq": 1,
"isEnforced": true,
"shareEnabled": true,
"externalShareAllowed": false,
"allowSpecificUsers": true,
"allowOrgLink": true,
"allowPublic": false
}
}
Set the sharing policy
| Parameter | Type | Required | Description |
|---|---|---|---|
e | boolean | Yes | true applies this setting to every tenant; false leaves each tenant to its own |
se | boolean | Conditional | Whether sharing is available; required when e is true |
esa | boolean | Conditional | Allow sharing outside the organization; required when e and se are true |
sua | boolean | Conditional | Allow the SPECIFIC_USERS share type; required when e and se are true |
ola | boolean | Conditional | Allow the ORG_LINK share type; required when e and se are true |
pa | boolean | Conditional | Allow the PUBLIC_LINK share type; required when e and se are true |
When enforcing with sharing on, at least one of sua, ola, and pa must be true, and enabling pa requires esa
to be true as well - the same rules as the tenant endpoint.
Values that do not apply are ignored and the stored ones kept. With e=false, se, esa, sua, ola, and pa are
ignored and no shares are cleaned up. With e=true and se=false, esa, sua, ola, and pa are ignored.
A successful call returns 200 OK with no data. While e is true, every tenant's own share settings endpoint
reports isEnforced and returns these global values instead of its own.
Saving with e=true compares each organization tenant's previous settings with the new ones, and deletes existing
shares for every item that narrows from allowed to not allowed:
- Sharing turned off - every share in the tenant.
SPECIFIC_USERS,ORG_LINK, orPUBLIC_LINKdisallowed - shares of that type, with their targets and the recent, starred, and pinned-folder entries that depend on them.- External sharing disallowed - share targets in other tenants, and those users' recent, starred, and pinned-folder entries.
Setting e back to false returns each tenant to its own settings, but the deleted shares are not recovered.
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/share-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"e": false}'
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/share-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"e": true, "se": false}'
curl -X PUT "https://drive.example.com/api/external/v1/super-admin/share-settings" \
-H "Authorization: Bearer replace-with-your-SUPERADMIN-API-KEY" \
-H "Content-Type: application/json" \
-d '{"e": true, "se": true, "esa": false, "sua": true, "ola": true, "pa": false}'
Sharing policy errors
| Code | Status | Meaning |
|---|---|---|
REQUEST_001 | 400 | e missing; se missing when enforcing; esa, sua, ola, or pa missing when enforcing with sharing on; sua, ola, and pa all false; or pa true with esa false |
RESPONSE_001 | 500 | Unexpected server error |
Errors
See Errors for the full list of codes across the API.