Tenants API

External integration

Tenants are the top-level organisational unit in Altafid. Every contact, household, organisation, and staff member is scoped to a tenant. This page documents tenant administration, branding management, custom domain mapping, and the public branding endpoints used for pre-login theming.

Role requirements vary: most tenant management operations require SYSTEM_ADMIN. Branding and domain configuration additionally allow TENANT_ADMIN. The public branding endpoints require no authentication.

Tenant CRUD

The following endpoints manage tenant records. Most require SYSTEM_ADMIN.

EndpointPurposeRoles
GET /api/tenantsPaginated list of all tenants. Sort default: name.SYSTEM_ADMIN
GET /api/tenants/{id}Get a single tenant by internal ID.SYSTEM_ADMIN
GET /api/tenants/name/{name}Get a tenant by name.Any authenticated
GET /api/tenants/code/{code}Get a tenant by code (e.g. CONPAT_UAT).SYSTEM_ADMIN
POST /api/tenantsCreate a new tenant.SYSTEM_ADMIN
PUT /api/tenants/{id}Update an existing tenant by internal ID.SYSTEM_ADMIN
DELETE /api/tenants/{id}Soft-delete a tenant by internal ID.SYSTEM_ADMIN

The tenant request and response body (TenantDTO):

{
  "tenantUuid": "T019A16FF372A70B5A9307B00CE85E4DA",
  "name": "Conpat Advisory",
  "code": "CONPAT_UAT",
  "isActive": true,
  "createdAt": "2025-01-10T09:00:00",
  "updatedAt": "2026-02-14T16:30:00"
}
FieldRequired on create/updateNotes
nameYesMax 255 characters.
codeYesMax 50 characters. Used as a human-readable identifier.
isActiveNoDefaults to true on creation.
tenantUuidNo (server-assigned)Read-only on creation.

The hard-delete with full data purge endpoint is a separate, sensitive operation:

POST/api/tenants/delete — permanently deletes a tenant and all associated data. This operation is irreversible and restricted to SYSTEM_ADMIN.

{
  "tenantUuid": "T019A16FF372A70B5A9307B00CE85E4DA"
}

V2 filtering

POST/api/v2/tenants — filter tenants with the standard v2 filter model. Requires SYSTEM_ADMIN.

{
  "filters": [
    { "field": "isActive", "operator": "equals", "value": "true" }
  ],
  "page": 0,
  "size": 20,
  "sort": ["name,asc"]
}

POST/api/v2/tenants/filter-values — retrieve distinct values for a filterable field within the tenant scope. See the Shared Conventions page for the full filter model.

Tenant statistics

GET/api/tenants/{tenantUuid}/stats

Returns aggregated counts for the tenant. No special role restriction beyond standard authentication.

curl "https://api.altafid.dev.altafid.net/api/tenants/T019A16FF372A70B5A9307B00CE85E4DA/stats" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "x-tenant-uuid: T019A16FF372A70B5A9307B00CE85E4DA" \
  -H "x-user-email: YOUR_EMAIL" \
  -H "x-user-id: YOUR_USER_ID" \
  -H "x-user-type: TENANT_STAFF"
{
  "tenantUuid": "T019A16FF372A70B5A9307B00CE85E4DA",
  "householdCount": 42,
  "contactCount": 815
}

Domain management

Tenants can be mapped to a custom public domain which is then used for branding resolution. Requires TENANT_ADMIN or SYSTEM_ADMIN.

EndpointPurpose
POST /api/tenants/{tenantUuid}/domainsCreate or update the domain mapping for the tenant.
GET /api/v1/tenant-domains/{tenantUuid}Retrieve the current domain mapping for the tenant.

Request body for domain upsert:

{
  "domain": "portal.conpat.com",
  "active": true
}

Response:

{
  "tenantUuid": "T019A16FF372A70B5A9307B00CE85E4DA",
  "domain": "portal.conpat.com",
  "active": true,
  "createdAt": "2026-01-10T09:00:00",
  "updatedAt": "2026-04-15T11:00:00"
}

Branding administration

Tenant admins can customise colours and image assets (logo and favicon) that appear in the Altafid client portal. The workflow is a three-step process: initialise uploads, upload files directly to the presigned S3 URLs, then confirm to publish.

GET /api/tenants/{tenantUuid}/branding

Returns the current stored overrides and the system defaults so the admin form can show what is active.

{
  "tenantUuid": "T019A16FF372A70B5A9307B00CE85E4DA",
  "tenantName": "Conpat Advisory",
  "stored": {
    "version": 5,
    "colors": {
      "neutral": "#f8f9fa",
      "primary": "#1a56db",
      "sidebar": "#1e3a5f"
    },
    "useDefault": {
      "neutral": false,
      "primary": false,
      "sidebar": false,
      "logo": false,
      "favicon": true
    },
    "assets": {
      "logo": "https://cdn.altafid.net/tenants/T019.../logo.svg",
      "faviconPng32": null,
      "faviconIco": null
    }
  },
  "defaults": {
    "colors": { "neutral": "#ffffff", "primary": "#4a90e2", "sidebar": "#2d3748" },
    "assets": {
      "logo": "https://cdn.altafid.net/defaults/logo.svg",
      "faviconPng32": "https://cdn.altafid.net/defaults/favicon-32.png",
      "faviconIco": "https://cdn.altafid.net/defaults/favicon.ico"
    }
  },
  "updatedAt": "2026-03-01T12:00:00",
  "updatedBy": "admin@conpat.com"
}

POST /api/tenants/{tenantUuid}/branding/assets/init

Request presigned S3 upload URLs for one or more branding assets. The response includes a versionHint that must be passed to the confirm step to detect stale sessions.

{
  "files": [
    { "type": "logo", "ext": "svg" },
    { "type": "favicon", "ext": "png" }
  ]
}
{
  "versionHint": 5,
  "uploads": [
    {
      "type": "logo",
      "uploadUrl": "https://s3.amazonaws.com/altafid-assets/upload?X-Amz-...",
      "finalUrl": "https://cdn.altafid.net/tenants/T019.../logo.svg",
      "maxBytes": 2097152,
      "contentType": "image/svg+xml",
      "expiresAt": "2026-04-22T11:30:00"
    }
  ]
}

Upload each file by sending a PUT request directly to the uploadUrl with the file content and the matching Content-Type header. The presigned URL is valid until expiresAt.

POST /api/tenants/{tenantUuid}/branding/assets/cancel

Cancels any pending upload session so a new init can be performed. Use if an upload was started but not completed.

POST /api/tenants/{tenantUuid}/branding/confirm

Saves (publishes) the branding configuration. This is the only step that updates the tenant's visible branding. Each field in useDefault controls whether the system default is shown instead of a stored override.

{
  "colors": {
    "neutral": "#f8f9fa",
    "primary": "#1a56db",
    "sidebar": "#1e3a5f"
  },
  "useDefault": {
    "neutral": false,
    "primary": false,
    "sidebar": false,
    "logo": false,
    "favicon": true
  },
  "assets": {
    "logo": "https://cdn.altafid.net/tenants/T019.../logo.svg",
    "faviconPng32": null,
    "faviconIco": null
  }
}
Validation errors on confirm: the server returns 400 if upload tickets are expired or already used, if the session version is stale (versionHint mismatch), or if asset URLs from different upload sessions are mixed in the same confirm request.

Public branding endpoints

These endpoints are unauthenticated and are used to load the tenant's colour scheme and assets before the user logs in. Responses are cached with a max-age of 300 seconds.

EndpointPurpose
GET /api/public/tenants/{tenantUuid}/brandingGet effective branding by tenant UUID.
GET /api/public/branding?domain={domain}Get effective branding by the tenant's custom domain.
curl "https://api.altafid.dev.altafid.net/api/public/branding?domain=portal.conpat.com"
{
  "tenantUuid": "T019A16FF372A70B5A9307B00CE85E4DA",
  "version": 5,
  "colors": {
    "neutral": "#f8f9fa",
    "primary": "#1a56db",
    "sidebar": "#1e3a5f"
  },
  "assets": {
    "logo": "https://cdn.altafid.net/tenants/T019.../logo.svg",
    "favicon": {
      "png32": "https://cdn.altafid.net/defaults/favicon-32.png",
      "ico": "https://cdn.altafid.net/defaults/favicon.ico"
    }
  },
  "cache": {
    "ttlSeconds": 300
  }
}

The public response always contains fully resolved URLs — if a field is set to use the default, the default URL is returned rather than null. Returns 404 when the tenant or domain is not found.