Register Subname (Free Tier)
Register a new ENS subname. First registration per wallet/IP is FREE.
Endpoint​
POST /api/subnames/{parent}
Authentication​
None required for free tier registration (but ownership is tracked by wallet address).
Free Tier Rules​
Important
- ONE free registration per wallet address
- ONE free registration per IP address
- After using your free registration, use Purchase with x402 payment
Request Body​
{
"name": "alice",
"owner": "0x701B4937e6c943789ffA74CC8601813b2D87B454",
"records": {
"description": "My personal ENS subname",
"url": "https://alice.dev",
"com.twitter": "@alice"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | âś… | Subname label (alphanumeric + hyphens, max 63 chars) |
owner | string | âś… | Ethereum address that will own the subname |
records | object | ❌ | Optional ENS text records to set |
Response (Success)​
{
"success": true,
"parent": "aboutme.eth",
"name": "alice",
"fullName": "alice.aboutme.eth",
"owner": "0x701B4937e6c943789ffA74CC8601813b2D87B454",
"freeTier": true,
"note": "This was your free registration. Additional names require payment.",
"timestamp": "2024-02-10T14:30:00.000Z"
}
Response (Free Tier Exhausted - 402)​
When free tier is used up, you'll receive a 402 Payment Required:
{
"error": true,
"code": "FREE_TIER_EXHAUSTED",
"message": "Wallet 0x701B...B454 has already used its free registration",
"reason": "WALLET_USED",
"details": {
"usedAt": "2024-02-09T18:30:00.000Z",
"usedFor": "alice.aboutme.eth"
},
"pricing": {
"price": 0.97,
"priceFormatted": "$0.97",
"tier": "standard",
"currency": "USDC",
"network": "Base (Chain ID 8453)"
},
"nextStep": "Use POST /api/subnames/aboutme.eth/purchase with x402 payment"
}
Examples​
cURL​
curl -X POST "https://api.web3identity.com/api/subnames/aboutme.eth" \
-H "Content-Type: application/json" \
-d '{
"name": "alice",
"owner": "0x701B4937e6c943789ffA74CC8601813b2D87B454"
}'
JavaScript​
async function registerSubname(parent, name, owner, records = {}) {
const response = await fetch(
`https://api.web3identity.com/api/subnames/${parent}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, owner, records })
}
);
const data = await response.json();
if (response.status === 402) {
// Free tier exhausted - need to use /purchase with payment
console.log(`Free tier used. Price: ${data.pricing.priceFormatted}`);
console.log(`Next step: ${data.nextStep}`);
return { needsPayment: true, ...data };
}
if (response.status === 409) {
// Name already taken
console.log('Name is already registered');
return { taken: true, ...data };
}
return data;
}
// Register with optional records
const result = await registerSubname(
'aboutme.eth',
'alice',
'0x701B4937e6c943789ffA74CC8601813b2D87B454',
{
description: 'Web3 developer',
'com.twitter': '@alice'
}
);
Full Registration Flow​
async function registerWithFallback(parent, name, owner, records) {
// 1. Check availability first
const availability = await fetch(
`https://api.web3identity.com/api/subnames/${parent}/${name}/available`
).then(r => r.json());
if (!availability.available) {
throw new Error(`${name}.${parent} is already taken`);
}
// 2. Try free registration
const result = await registerSubname(parent, name, owner, records);
if (result.success) {
console.log(`âś… Registered ${result.fullName} for FREE!`);
return result;
}
if (result.needsPayment) {
// 3. Redirect to payment flow
console.log(`Free tier exhausted. Price: ${result.pricing.priceFormatted}`);
// Use /purchase endpoint with x402 payment header
return { requiresPayment: true, price: result.pricing };
}
throw new Error(result.message);
}
Name Validation​
| Rule | Valid | Invalid |
|---|---|---|
| Alphanumeric | alice, bob123 | alice!, bob@123 |
| Hyphens allowed | my-name, web-3 | -name, name- |
| Lowercase only | alice | Alice, ALICE |
| Max 63 chars | verylongname... | Names over 63 chars |
Error Responses​
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Missing name or owner |
| 400 | INVALID_ADDRESS | Owner is not valid Ethereum address |
| 400 | INVALID_NAME | Name format is invalid |
| 402 | FREE_TIER_EXHAUSTED | Free registration already used |
| 409 | NAME_TAKEN | Subname is already registered |
| 429 | RATE_LIMITED | Rate limit exceeded |
| 500 | SUBNAME_ERROR | Internal server error |
Related Endpoints​
- Check Availability — Check before registering
- Purchase — Register with x402 payment
- Get Price — Get pricing for a name