Custom Domains
Set up custom domains with automatic SSL via the OrbitKit API.
Custom domains let you serve your app’s privacy policy and other pages from your own domain (e.g., privacy.myapp.com) instead of the default sites.orbitkit.io subdirectory.
OrbitKit automatically provisions SSL certificates via Google Certificate Manager. After setting a domain, you’ll receive DNS instructions to point your domain to OrbitKit’s servers.
Endpoints
| Method | Path | Description |
|---|---|---|
| PUT | /api/apps/:appId/site/domain |
Set custom domain |
| DELETE | /api/apps/:appId/site/domain |
Remove custom domain |
| GET | /api/apps/:appId/site/domain/status |
Check domain status |
Rate limit: 5/hour per user for domain operations.
Set custom domain
PUT /api/apps/:appId/site/domain
Assigns a custom domain to the app, provisions an SSL certificate, and returns DNS instructions.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | Yes | Domain name (max 253 chars, must contain a dot) |
Full example
curl -X PUT https://api.orbitkit.io/api/apps/-NtestApp123/site/domain \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"domain": "privacy.myapp.com"}'
var request = URLRequest(url: URL(string: "https://api.orbitkit.io/api/apps/\(appId)/site/domain")!)
request.httpMethod = "PUT"
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(["domain": "privacy.myapp.com"])
let (data, _) = try await URLSession.shared.data(for: request)
let result = try JSONDecoder().decode(DnsInstructionsResponse.self, from: data)
// Show DNS records to user
const res = await fetch(`https://api.orbitkit.io/api/apps/${appId}/site/domain`, {
method: "PUT",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ domain: "privacy.myapp.com" }),
});
const { dnsInstructions } = await res.json();
Response
{
"dnsInstructions": [
{
"type": "A",
"name": "privacy.myapp.com",
"value": "34.120.1.2"
},
{
"type": "CNAME",
"name": "_acme-challenge.privacy.myapp.com",
"value": "abc123.acme.goog."
}
]
}
The user must configure both DNS records at their registrar:
- A record — points the domain to OrbitKit’s load balancer
- CNAME record — proves domain ownership for SSL certificate provisioning
Errors
| Code | Status | When |
|---|---|---|
VALIDATION_FAILED |
400 | Invalid domain format or blocked domain |
DOMAIN_IN_USE |
409 | Domain is mapped to another account |
CERT_CREATION_FAILED |
500 | SSL certificate provisioning failed |
Remove custom domain
DELETE /api/apps/:appId/site/domain
Removes the custom domain and its SSL certificate. The site remains accessible via the default sites.orbitkit.io URL.
Response 204 No Content
No response body.
Check domain status
GET /api/apps/:appId/site/domain/status
Returns DNS verification and SSL provisioning status for the custom domain.
Response
{
"domain": "privacy.myapp.com",
"dnsVerified": true,
"sslProvisioned": true,
"status": "active"
}
Status values
| Status | Meaning |
|---|---|
pending_dns |
DNS records not yet detected |
pending_ssl |
DNS verified, SSL certificate being provisioned |
active |
Domain is fully configured and serving traffic |
error |
Something went wrong — check DNS records |
Errors
| Code | Status | When |
|---|---|---|
NOT_FOUND |
404 | No custom domain configured for this app |