Custom Domains
Manage custom domains for your projects via the REST API. Each project supports up to 5 custom domains with automatic HTTPS.
Add Domain
POST /v1/projects/:id/domains
curl -X POST https://api.sota.io/v1/projects/550e8400-.../domains \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"domain": "app.example.com"}'
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | The custom domain to add (e.g., app.example.com or example.com) |
Response (201 Created):
{
"data": {
"domain": {
"id": "d47e8f9a-1234-5678-9abc-def012345678",
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "app.example.com",
"status": "pending",
"dns_type": "CNAME",
"last_checked_at": null,
"verified_at": null,
"error_message": null,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:00:00Z"
},
"dns_instructions": {
"type": "CNAME",
"name": "app",
"value": "my-app.sota.io"
}
}
}
The dns_instructions object tells you exactly which DNS record to add at your registrar.
List Domains
GET /v1/projects/:id/domains
curl https://api.sota.io/v1/projects/550e8400-.../domains \
-H "Authorization: Bearer <token>"
Response (200 OK):
{
"data": [
{
"id": "d47e8f9a-1234-5678-9abc-def012345678",
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "app.example.com",
"status": "active",
"dns_type": "CNAME",
"last_checked_at": "2026-03-01T10:05:00Z",
"verified_at": "2026-03-01T10:02:00Z",
"error_message": null,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:05:00Z"
}
]
}
Get Domain
GET /v1/projects/:id/domains/:domainId
curl https://api.sota.io/v1/projects/550e8400-.../domains/d47e8f9a-... \
-H "Authorization: Bearer <token>"
Response (200 OK):
{
"data": {
"domain": {
"id": "d47e8f9a-1234-5678-9abc-def012345678",
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "app.example.com",
"status": "active",
"dns_type": "CNAME",
"last_checked_at": "2026-03-01T10:05:00Z",
"verified_at": "2026-03-01T10:02:00Z",
"error_message": null,
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-01T10:05:00Z"
},
"dns_instructions": {
"type": "CNAME",
"name": "app",
"value": "my-app.sota.io"
}
}
}
Remove Domain
DELETE /v1/projects/:id/domains/:domainId
curl -X DELETE https://api.sota.io/v1/projects/550e8400-.../domains/d47e8f9a-... \
-H "Authorization: Bearer <token>"
Returns 204 No Content. This removes the custom domain and its SSL certificate. Traffic will no longer be routed to this domain.
Domain Object
| Field | Type | Description |
|---|---|---|
id | string | Domain UUID |
project_id | string | Parent project UUID |
domain | string | The custom domain (e.g., app.example.com) |
status | string | One of: pending, verified, active, error |
dns_type | string | DNS record type: A (apex) or CNAME (subdomain) |
last_checked_at | string | Last DNS verification check (ISO 8601) |
verified_at | string | When DNS was verified (ISO 8601) |
error_message | string | Error details if status is error |
created_at | string | Creation timestamp (ISO 8601) |
updated_at | string | Last update timestamp (ISO 8601) |
DNS Instructions Object
Returned when adding or getting a single domain:
| Field | Type | Description |
|---|---|---|
type | string | A for apex domains, CNAME for subdomains |
name | string | @ for apex domains, subdomain part for subdomains |
value | string | 23.88.45.28 for A records, {slug}.sota.io for CNAME records |
DNS Examples
Apex domain (example.com):
| Type | Name | Value |
|---|---|---|
| A | @ | 23.88.45.28 |
Subdomain (app.example.com):
| Type | Name | Value |
|---|---|---|
| CNAME | app | my-app.sota.io |
Error Responses
| Status | Error | Description |
|---|---|---|
404 | Project not found | The project ID does not exist or you do not have access |
404 | Domain not found | The domain ID does not exist on this project |
409 | Domain already exists | This domain is already added to a project |
422 | Domain limit reached | Maximum 5 custom domains per project |
422 | Validation error | Invalid domain format or platform domain blocked |