Documentation Index
Fetch the complete documentation index at: https://docs.linkutm.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Custom domains let a workspace serve branded short links from its own hostname. Endpoints live under/api/v1/domains. All management endpoints require a JWT and the x-workspace-id header. One endpoint, GET /domains/check, is public and exists only for the Caddy on-demand TLS handshake.
x-workspace-id accepts a workspace UUID or its slug.How a domain becomes usable
Add the domain
POST /api/v1/domains creates the record with status: "pending" and verified: false, and returns the cnameTarget value you need.Verify
POST /api/v1/domains/:id/verify resolves the CNAME. On success the domain flips to verified: true and status: "active".null) are seeded automatically. They are pre-verified and active, cannot be updated or deleted, and appear in list results alongside workspace domains.
Add a custom domain
@UseGuards(JwtAuthGuard)).
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Content-Type: application/json | Yes |
Body
The hostname to add, e.g.
go.acme.com. Stored lowercased.Optional URL that the bare domain redirects to when no short code is present.
Example request
Example response
The
cnameTarget field tells you where to point the CNAME record. Use this value, not a hardcoded host - it is environment driven.Errors
| Code | When |
|---|---|
401 | Missing or invalid JWT |
403 | Domain limit for the workspace plan reached. Message includes used and limit counts. |
409 | A domain with that hostname already exists |
List domains
@UseGuards(JwtAuthGuard)). Returns the workspace’s domains plus any seeded system domains, paginated.
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Query parameters
Case-insensitive substring match on the domain hostname.
Page number. Defaults to
1.Results per page. Defaults to
10.Example request
Example response
Behavior notes
- Each entry carries
linksCount(number of links using the domain),isDefault(whether it is the workspace default), and aprimaryboolean stored on the domain record. - System domains (those with no workspace) are merged in. If a system domain shares a hostname with a workspace domain, the system entry is dropped to avoid duplicates.
- The default domain, if any, is moved to the front of
data. pagination.totalincludes the merged system domains.
Errors
| Code | When |
|---|---|
401 | Missing or invalid JWT |
Get a domain by ID
@UseGuards(JwtAuthGuard)). Looks up the domain scoped to the workspace.
This endpoint only resolves domains that belong to the workspace in
x-workspace-id. Seeded system domains appear in GET /domains but are not workspace-scoped, so requesting one by its ID here returns 404.Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Example request
Example response
Errors
| Code | When |
|---|---|
401 | Missing or invalid JWT |
404 | Domain not found in this workspace |
Update a domain
@UseGuards(JwtAuthGuard)).
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Content-Type: application/json | Yes |
Body
New hostname. Stored lowercased.
New default redirect URL for the bare domain.
Example request
Example response
Errors
| Code | When |
|---|---|
401 | Missing or invalid JWT |
403 | The domain has canUpdate: false (system domain) |
404 | Domain not found in this workspace |
409 | The new domain hostname is already taken by another record |
Delete a domain
@UseGuards(JwtAuthGuard)).
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Example request
Example response
Returns the deleted domain record.Errors
| Code | When |
|---|---|
400 | The domain still has links attached |
401 | Missing or invalid JWT |
403 | The domain has canDelete: false (system domain) |
404 | Domain not found in this workspace |
Verify DNS
@UseGuards(JwtAuthGuard)). Resolves the domain’s CNAME record and, if it points to a valid target, marks the domain verified and active.
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Example request
Example responses
Already verified:Behavior notes
- Verification reads the live CNAME record for the domain. If the lookup fails or no record matches a known target, the response is
verified: falsewith HTTP200(not an error). - A successful verification flips the record to
verified: trueandstatus: "active", and queues a notification email to the workspace owner.
Errors
| Code | When |
|---|---|
401 | Missing or invalid JWT |
404 | Domain not found in this workspace |
Set default domain
@UseGuards(JwtAuthGuard)). Sets the domain as the workspace default for new links. The domain may be a workspace domain or a system domain.
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <jwt> | Yes | |
x-workspace-id: <uuid_or_slug> | Yes | Target workspace |
Example request
Example response
Returns the domain that is now the default.Errors
| Code | When |
|---|---|
400 | The domain is not verified or not active |
401 | Missing or invalid JWT |
404 | Domain not found in this workspace or as a system domain |
Caddy TLS check (public)
x-workspace-id. This is the on-demand TLS authorization endpoint that the Caddy reverse proxy calls before issuing a certificate for a custom domain. It is not intended for client integrations.
Query parameters
The hostname Caddy is requesting a certificate for.
The shared internal token. Must match the server’s configured Caddy token.
Example request
Example response
Behavior notes
- Returns
{ "ok": true }only when the domain exists and isverifiedandstatus: "active". - An empty
domainor a token mismatch returns403. - A domain that is not found, not verified, or not active returns
404.
Errors
| Code | When |
|---|---|
403 | Missing domain or invalid token |
404 | Domain not found, not verified, or not active |