MATIH Platform is in active MVP development. Documentation reflects current implementation status.
7. Tenant Lifecycle
Branding & Customization
Custom Domains

Custom Domains

The CustomDomainController at /api/v1/tenants/{tenantId}/domains provides a full domain lifecycle: registration, DNS verification, SSL provisioning, routing configuration, and lifecycle management.


Domain Lifecycle

ADD --> PENDING_VERIFICATION --> DNS_VERIFIED --> DNS_CONFIRMED --> SSL_PROVISIONING --> ACTIVE
  |                                                                                       |
  v                                                                                       v
FAILED                                                                              SUSPENDED
                                                                                          |
                                                                                          v
                                                                                       DELETED

Adding a Domain

@Data
public static class AddDomainRequest {
    @NotBlank
    @Pattern(regexp = "^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\\.[a-zA-Z]{2,}$",
             message = "Invalid domain name format")
    private String domainName;
 
    private String subdomain;
 
    private VerificationMethod verificationMethod;  // DNS_TXT (default), CNAME, HTTP
}
curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "domainName": "analytics.acmecorp.com",
    "verificationMethod": "DNS_TXT"
  }'

Response (201 Created):

{
  "id": "d1e2f3a4-...",
  "tenantId": "e5f6a7b8-...",
  "domainName": "analytics.acmecorp.com",
  "status": "PENDING_VERIFICATION",
  "verificationMethod": "DNS_TXT",
  "verificationRecordName": "_matih-verify.analytics.acmecorp.com",
  "verificationRecordValue": "matih-verify=a1b2c3d4e5f6",
  "createdAt": "2026-02-12T10:00:00Z"
}

DNS Verification

After adding a domain, the tenant must configure the required DNS records. Retrieve the records with:

curl http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/dns-records \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "domainName": "analytics.acmecorp.com",
  "verificationMethod": "DNS_TXT",
  "verificationRecordName": "_matih-verify.analytics.acmecorp.com",
  "verificationRecordValue": "matih-verify=a1b2c3d4e5f6",
  "cnameTarget": "acme.matih.ai",
  "aRecordIp": "20.10.30.40",
  "dnsConfigured": false
}

Once DNS records are configured, trigger verification:

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/verify \
  -H "Authorization: Bearer $TOKEN"

Returns a VerificationResult indicating success or failure with details.


Confirming DNS Configuration

After verification passes, confirm DNS configuration:

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/dns-confirm \
  -H "Authorization: Bearer $TOKEN"

SSL Certificate Provisioning

Provision an SSL certificate for the verified domain:

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/ssl/provision \
  -H "Authorization: Bearer $TOKEN"

Returns an SslProvisioningResult with the certificate status. Certificates are provisioned via cert-manager with DNS01 challenge using the platform's Azure DNS integration.

SSL Renewal

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/ssl/renew \
  -H "Authorization: Bearer $TOKEN"

Routing Configuration

Configure how traffic is routed for the custom domain:

@Data
public static class RoutingUpdateRequest {
    private RoutingMode routingMode;   // PROXY, REDIRECT, CNAME
    private String originServer;
    private Boolean forceHttps;
    private Boolean hstsEnabled;
}
curl -X PUT http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/routing \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "routingMode": "PROXY",
    "forceHttps": true,
    "hstsEnabled": true
  }'

Setting Primary Domain

Designate a domain as the tenant's primary domain:

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/primary \
  -H "Authorization: Bearer $TOKEN"

Only active domains can be set as primary.

Get Primary Domain

curl http://localhost:8082/api/v1/tenants/{tenantId}/domains/primary \
  -H "Authorization: Bearer $TOKEN"

Domain Lifecycle Management

Suspend Domain

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/suspend \
  -H "Authorization: Bearer $TOKEN"

Activate Domain

curl -X POST http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId}/activate \
  -H "Authorization: Bearer $TOKEN"

Delete Domain

curl -X DELETE http://localhost:8082/api/v1/tenants/{tenantId}/domains/{domainId} \
  -H "Authorization: Bearer $TOKEN"

Returns 204 No Content.


Domain Statistics

curl http://localhost:8082/api/v1/tenants/{tenantId}/domains/stats \
  -H "Authorization: Bearer $TOKEN"

Returns a DomainStatsResponse with counts by status and SSL certificate expiration data.


Source Files

FilePath
Controllercontrol-plane/tenant-service/src/main/java/com/matih/tenant/controller/CustomDomainController.java
Servicecontrol-plane/tenant-service/src/main/java/com/matih/tenant/service/CustomDomainService.java
Entitycontrol-plane/tenant-service/src/main/java/com/matih/tenant/entity/CustomDomain.java