Endpoints
GET /api/user/custom-domain
POST /api/user/custom-domain
DELETE /api/user/custom-domain
Overview
Manages custom domain configuration for DROP service. Requires Enterprise tier. Custom domains are stored in service metadata.
GET /api/user/custom-domain
Retrieves custom domain configuration for the authenticated user’s DROP service.
Response
Custom domain (null if not set)
Whether domain is verified
Whether custom domain is configured
POST /api/user/custom-domain
Sets a custom domain for DROP service. Requires Enterprise tier.
Request
Domain name (1-255 characters). Must be valid domain format.
Response
“Domain connected successfully. Please configure your DNS settings.”
DELETE /api/user/custom-domain
Removes custom domain configuration.
Response
“Custom domain disconnected successfully”
Implementation Details
Code Reference
export async function POST(request: NextRequest) {
const corsResponse = handleCors(request)
if (corsResponse) return corsResponse
const blocked = await protectRoute(request)
if (blocked) return blocked
const auth = await requireAuth(request)
if ('error' in auth) return auth.error
try {
const body = await request.json()
const { domain } = domainSchema.parse(body)
const dropService = await prisma.userServiceEntitlement.findUnique({
where: {
userId_service: {
userId: auth.userId,
service: 'DROP',
},
},
})
if (!dropService || dropService.tier !== 'enterprise') {
return errorResponse('Enterprise plan required for custom domains', 403, request.headers.get('origin'))
}
const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9](?:\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*$/
if (!domainRegex.test(domain.trim())) {
return errorResponse('Invalid domain format', 400, request.headers.get('origin'))
}
const allEntitlements = await prisma.userServiceEntitlement.findMany({
where: {
service: 'DROP',
userId: {
not: auth.userId,
},
},
select: {
metadata: true,
},
})
const existingDomain = allEntitlements.find((entitlement: { metadata: any }) => {
const metadata = (entitlement.metadata as any) || {}
return metadata.customDomain === domain.trim()
})
if (existingDomain) {
return errorResponse('Domain is already in use', 409, request.headers.get('origin'))
}
const currentMetadata = (dropService.metadata as any) || {}
await prisma.userServiceEntitlement.update({
where: {
userId_service: {
userId: auth.userId,
service: 'DROP',
},
},
data: {
metadata: {
...currentMetadata,
customDomain: domain.trim(),
customDomainVerified: false,
},
},
})
await createAuditLog(auth.userId, 'USER_UPDATE', {
field: 'customDomain',
value: domain.trim(),
})
return jsonResponse({
success: true,
domain: domain.trim(),
message: 'Domain connected successfully. Please configure your DNS settings.',
}, 200, request.headers.get('origin'))
} catch (error: any) {
if (error.name === 'ZodError') {
return errorResponse(error.errors[0].message, 400, request.headers.get('origin'))
}
console.error('Custom domain error:', error)
return errorResponse('Internal server error', 500, request.headers.get('origin'))
}
}
Status Codes
Domain is already in use by another user
Missing or invalid authentication token
Requirements
- Tier: Enterprise plan required
- Service: DROP service only
- Domain Format: Valid domain name format (regex validated)
- Uniqueness: Domain must be unique across all users
Example Requests
Get Custom Domain
curl -X GET https://auth.nullpass.xyz/api/user/custom-domain \
-H "Authorization: Bearer YOUR_TOKEN"
Set Custom Domain
curl -X POST https://auth.nullpass.xyz/api/user/custom-domain \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com"
}'
Remove Custom Domain
curl -X DELETE https://auth.nullpass.xyz/api/user/custom-domain \
-H "Authorization: Bearer YOUR_TOKEN"
Example Response (GET)
{
"customDomain": "example.com",
"customDomainVerified": false,
"hasCustomDomain": true
}
Domain Storage
Custom domains are stored in the metadata field of the DROP service entitlement:
customDomain: Domain string
customDomainVerified: Verification status (boolean)
Audit Events
- USER_UPDATE: Custom domain set or removed (includes
field: 'customDomain')