workos-domain-verification
npx skills add https://github.com/workos/skills --skill workos-domain-verification
Agent 安装分布
Skill 文档
WorkOS Domain Verification
Step 1: Fetch Documentation (BLOCKING)
STOP. Do not proceed until complete.
WebFetch these URLs for source of truth:
If this skill conflicts with the documentation, follow the documentation.
Step 2: Pre-Flight Validation
Environment Variables
Check for required WorkOS credentials:
WORKOS_API_KEY– starts withsk_WORKOS_CLIENT_ID– starts withclient_
Verify: Both variables are set in .env or .env.local
SDK Installation
Confirm WorkOS SDK is installed:
# Check package.json contains @workos-inc/node
grep "@workos-inc/node" package.json || npm install @workos-inc/node
CRITICAL: SDK must be installed before writing any import statements.
Step 3: Organization Exists (REQUIRED)
All domains must belong to an Organization. You cannot create or verify a domain without an Organization.
Check if organization already exists:
# If you have organization ID
curl https://api.workos.com/organizations/org_123 \
-H "Authorization: Bearer $WORKOS_API_KEY"
If no organization exists, create one first using the Organizations API (see workos-organizations skill).
Do NOT proceed to Step 4 until you have a valid Organization ID.
Step 4: Implementation Path (Decision Tree)
Choose based on your use case:
Domain verification flow?
|
+-- Self-serve (IT admin verifies) --> Admin Portal flow (Step 5A)
|
+-- Programmatic (you verify) --> API flow (Step 5B)
Self-serve = Your customer’s IT admin proves ownership via DNS TXT records through the Admin Portal UI
Programmatic = You integrate domain creation/verification directly into your application code
Step 5A: Admin Portal Flow (Self-Serve)
Create Portal Link
Generate a temporary Admin Portal session link (valid 5 minutes):
import { WorkOS } from '@workos-inc/node';
const workos = new WorkOS(process.env.WORKOS_API_KEY);
const portalLink = await workos.portal.generateLink({
organization: 'org_123',
intent: 'domain_verification',
return_url: 'https://yourapp.com/settings/domains'
});
// portalLink.link - redirect user here
Check documentation for exact method signature – may be createLink or generateLink depending on SDK version.
User Flow
- Redirect user to
portalLink.link - User adds domain in Admin Portal
- User adds DNS TXT record to their domain’s DNS
- WorkOS verifies TXT record automatically
- User returns to
return_urlwhen complete
Verification
Listen for webhook to know when domain is verified, or poll the domain status:
# Get domain status
curl https://api.workos.com/organization_domains/org_domain_123 \
-H "Authorization: Bearer $WORKOS_API_KEY"
Check documentation for webhook event name – likely domain.verified or similar.
Step 5B: API Flow (Programmatic)
Create Domain
import { WorkOS } from '@workos-inc/node';
const workos = new WorkOS(process.env.WORKOS_API_KEY);
const domain = await workos.organizationDomains.create({
organization_id: 'org_123',
domain: 'example.com'
});
// domain.id - save this
// domain.verification_token - share this with domain owner
Check documentation for exact method path – may be workos.domains.create() or similar.
Share Verification Instructions
The domain owner must add this DNS TXT record:
Type: TXT
Host: _workos-challenge (or @ for root)
Value: [domain.verification_token from response]
Check documentation for exact TXT record format – host name may vary.
Trigger Verification
After DNS TXT record is added, trigger verification check:
await workos.organizationDomains.verify({
domain_id: domain.id
});
Check documentation for exact method name – may be verify(), checkVerification(), or automatic.
Poll for Status
Check if verification succeeded:
const updatedDomain = await workos.organizationDomains.get(domain.id);
if (updatedDomain.state === 'verified') {
// Domain verified successfully
} else if (updatedDomain.state === 'pending') {
// Still waiting for DNS propagation
} else if (updatedDomain.state === 'failed') {
// Verification failed - check TXT record
}
Check documentation for exact state values – may be status instead of state, may use different enum values.
Step 6: List Domains for Organization
Retrieve all domains (verified and unverified) for an organization:
const domains = await workos.organizationDomains.list({
organization_id: 'org_123'
});
domains.data.forEach(domain => {
console.log(`${domain.domain}: ${domain.state}`);
});
Verification Checklist (ALL MUST PASS)
Run these commands to confirm integration:
# 1. Check environment variables exist
env | grep WORKOS_API_KEY && env | grep WORKOS_CLIENT_ID
# 2. Check SDK is installed
npm list @workos-inc/node 2>/dev/null || echo "FAIL: SDK not installed"
# 3. Verify organization exists (replace org_123 with your ID)
curl -s https://api.workos.com/organizations/org_123 \
-H "Authorization: Bearer $WORKOS_API_KEY" | grep '"id"'
# 4. Test domain creation (replace with test domain)
curl -X POST https://api.workos.com/organization_domains \
-H "Authorization: Bearer $WORKOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organization_id":"org_123","domain":"test.example.com"}'
# 5. Build succeeds
npm run build
If check #3 fails: Create organization first (see Step 3) If check #4 fails: Check API key permissions or organization ID
Error Recovery
“Organization not found”
Root cause: No organization exists or wrong ID
Fix:
- List organizations:
curl https://api.workos.com/organizations -H "Authorization: Bearer $WORKOS_API_KEY" - If empty, create organization first
- Use correct organization ID in domain creation
“Invalid domain format”
Root cause: Domain contains invalid characters or format
Fix:
- Use bare domain:
example.comnothttps://example.com - No subdomains for verification (unless docs explicitly allow)
- Check documentation for allowed domain formats
“Domain already exists”
Root cause: Domain already registered to this or another organization
Fix:
- List domains:
workos.organizationDomains.list() - If domain belongs to current org, use existing domain ID
- If domain belongs to different org, cannot claim (security feature)
“Verification failed” / “TXT record not found”
Root cause: DNS TXT record not added correctly or DNS not propagated
Fix:
- Check TXT record exists:
dig TXT _workos-challenge.example.comornslookup -type=TXT _workos-challenge.example.com - Verify token matches exactly (no extra quotes or spaces)
- Wait for DNS propagation (can take up to 48 hours, usually <15 minutes)
- Check documentation for exact TXT record host format
“API key does not have permission”
Root cause: API key lacks domain verification scope
Fix:
- Go to WorkOS Dashboard â API Keys
- Check key has required permissions
- Generate new key if needed
SDK method not found
Root cause: SDK version mismatch with documentation
Fix:
- Check SDK version:
npm list @workos-inc/node - Check documentation for method names matching your SDK version
- Update SDK:
npm install @workos-inc/node@latest
Portal link expired
Root cause: Portal links are valid for 5 minutes only
Fix:
- Generate new portal link immediately before redirecting user
- Do not cache or reuse portal links
Related Skills
- workos-organizations: Creating organizations (required before domain verification)
- workos-sso: SSO connections require verified domains
- workos-directory-sync: Directory Sync requires verified domains
- workos-admin-portal: General Admin Portal integration patterns