Public avatar and header infrastructure for ENS names and subnames

Public Avatar and Header Service for ENS Names and Subnames

TL;DR: Namespace has a public service for uploading, updating, deleting, and serving avatars and headers for ENS names and subnames.

It is live at metadata.namespace.ninja, is free for anyone to use, and includes a REST API, the @thenamespace/avatar TypeScript SDK, and an AI-agent skill. It supports Ethereum Mainnet and Sepolia, regular wallets and smart accounts, pre-registration uploads, and short deterministic media URLs.

We originally built this infrastructure for our own subname products. We have now completed the migration to SIWE v4 and want to properly introduce the service to the wider ENS community.

Why we built it

Avatars are a major part of using ENS as identity, but profile-media infrastructure is often skipped in registration, onboarding, and profile flows.

Most teams do not want to operate wallet authentication, signature verification, uploads, storage, caching, and address-record checks just to let a user choose a profile image. The result is that many names and subnames are issued without a complete profile experience.

This is particularly relevant for offchain and L2-backed subnames. They can resolve normally through ENS, but builders still need a simple way for users to upload and manage profile media.

Because we already operate this infrastructure for Namespace, we made it available as a public ENS service.

What is available

The public stack includes:

  1. Hosted media service for avatars and headers.
  2. REST API and OpenAPI documentation for custom integrations.
  3. @thenamespace/avatar SDK v2.0.1 for JavaScript and TypeScript applications.
  4. avatar-sdk AI-agent skill for implementing the SDK with coding agents.

The service is already used in production by the Namespace Web App and ENS Components.

It is free for anyone to use, and no API key is required. Write operations are authorized with a short-lived SIWE proof from the wallet whose address is set as the name’s ETH address record.

How authorization works

Authorization is based on the ENS name’s resolved ETH address record (coinType 60), not registry or NFT ownership. This matters for offchain subnames, where the user represented by the subname may not be an onchain owner.

The flow is:

  1. The client requests a short-lived nonce from POST /auth/nonce.
  2. The wallet signs a SIWE message for an avatar, header, or combined update.
  3. The service verifies the SIWE message and signature.
  4. The service resolves the name’s ETH address record (coinType 60) and compares it with the verified signer.
  5. If they match, the media update is accepted.
  6. If the name or address record does not exist yet, the upload enters a five-minute pending queue. This lets a user upload an avatar or header before the application creates the name. The file becomes active only if the ETH address record is set to the signer during that window; otherwise it is deleted.

The SIWE v4 integration supports EOAs, deployed smart-contract wallets, and counterfactual smart accounts through EIP-1271 and EIP-6492 verification.

Stable public URLs

Media is served from deterministic paths:

Network Avatar Header
Mainnet https://avtr.cc/{name} https://avtr.cc/{name}/h
Sepolia https://avtr.cc/sepolia/{name} https://avtr.cc/sepolia/{name}/h

For example:

https://avtr.cc/alice.eth
https://avtr.cc/alice.eth/h

The short URL can be placed in a profile once while the underlying image is replaced later. For onchain names, the initial avatar record may require a resolver transaction, but later image updates do not require changing that record again.

REST API

Base URL:

https://metadata.namespace.ninja
Method Endpoint Purpose
POST /auth/nonce Request a scoped SIWE nonce
POST /profile/{network}/{name}/avatar Upload or replace an avatar
DELETE /profile/{network}/{name}/avatar Delete an avatar
POST /profile/{network}/{name}/header Upload or replace a header
DELETE /profile/{network}/{name}/header Delete a header

Uploads use multipart/form-data with the image, SIWE message, signature, and signer address. Deletes send the authentication fields as JSON.

The full API is available through the Swagger documentation and OpenAPI specification.

TypeScript SDK

Install the SDK:

npm install @thenamespace/avatar

AI-agent skill

For developers building with an AI coding agent:

npx skills add thenamespace/skills -s avatar-sdk

The skill gives the agent the SDK integration patterns, types, authentication flow, and examples needed to add avatar and header management to an application.

SDK example

import { createAvatarClient } from "@thenamespace/avatar";

const client = createAvatarClient({
  domain: window.location.hostname,
  network: "mainnet",
  provider: walletClient,
});

const result = await client.uploadAvatar({
  subname: "alice.example.eth",
  file,
  onProgress: (progress) => console.log(`${progress.toFixed(0)}%`),
});

console.log(result.avatarUrl);

The SDK handles SIWE authentication, network checks, wallet signing, upload progress, file validation, and response normalization. It works with Viem, Ethers, wagmi wallet clients, or a custom wallet provider, and also exposes a manual signing flow.

Supported networks and files

Networks:

  • Ethereum Mainnet (chainId: 1)
  • Sepolia (chainId: 11155111)

File limits:

Media Maximum size
Avatar 2 MB
Header 5 MB

Accepted formats:

  • JPEG
  • PNG
  • GIF
  • WebP
  • SVG

Authorization safeguards

  • For an existing name, the ETH address record is resolved again before its media can be changed or deleted.
  • Pending uploads are confirmed only after the ETH address record matches the verified signer.

Links

Use it in your ENS App

If you are building an ENS marketplace, subname issuance flow, wallet, community app, or any product where users should be able to upload an avatar or header, please try the service.

We would be happy to help with the integration and hear what is missing for your use case. You can reach us in the Namespace Builders Telegram group.

We would also like feedback on the authorization model: should we add support for additional address records or coin types beyond the ETH address record?

If you use it—or run into anything while integrating it—please let us know.

9 Likes