Developer docs
MCP connection
Connect an AI client to ExpiredLocal domain tools.
https://api.expiredlocal.com/mcp
- Transport
- Streamable HTTP
- Authentication
- Bearer API key
- Tools
- 7 read · 1 reveal
Connect your client
Your client needs remote Streamable HTTP and custom headers. No download is needed.
Create a read-only key
Open Account → API keys, create a Read only key and save its full value.
Add the remote connection
Use the URL above with
Authorization: Bearer YOUR_API_KEY. Do not use the REST/v1URL.Connect and discover tools
Reconnect and call
list_business_types. It uses no credits; pass an inventory and optionally a country code.
OAuth-only, legacy SSE-only and browser-only clients are unsupported.
Choose your client configuration
Add the entry to your existing config. Never paste a real key into a prompt.
Use this pattern only if your client accepts an mcpServers object with HTTP servers and custom headers. Replace YOUR_API_KEY in your private configuration; field names are not universal.
{
"mcpServers": {
"expiredlocal": {
"type": "http",
"url": "https://api.expiredlocal.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Merge this entry into .mcp.json. Set EXPIREDLOCAL_API_KEY in the environment that launches Claude Code, then approve the project server if prompted. The placeholder references your environment; do not replace it with a real key in a shared file. Official setup guide ↗
{
"mcpServers": {
"expiredlocal": {
"type": "http",
"url": "https://api.expiredlocal.com/mcp",
"headers": {
"Authorization": "Bearer ${EXPIREDLOCAL_API_KEY}"
}
}
}
}Merge this entry into your personal Cursor MCP configuration and replace YOUR_API_KEY privately. Save and restart Cursor. Do not commit the key in a project-level .cursor/mcp.json file. Official setup guide ↗
{
"mcpServers": {
"expiredlocal": {
"url": "https://api.expiredlocal.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}Set EXPIREDLOCAL_API_KEY in the environment that launches Codex, then add this server to ~/.codex/config.toml. Codex CLI, the IDE extension and the desktop app share this configuration. Official setup guide ↗
[mcp_servers.expiredlocal]
url = "https://api.expiredlocal.com/mcp"
bearer_token_env_var = "EXPIREDLOCAL_API_KEY"If your client uses a form, enter the same URL and bearer header.
Make a first, read-only request
“List domain extensions, then find 20 expired US domains with at least 10 reviews. Do not reveal anything.”
You should see eight tools. Unrevealed expired results omit the domain name.
Read-only keys cannot call reveal_domains.
Tool reference
Tools follow Domain API access rules. There are no account or billing tools.
| Tool | Access | Returns |
|---|---|---|
search_expired_domains | Read | Filtered, paginated expired inventory. |
search_auction_domains | Read | Filtered, paginated auction inventory. |
search_pending_delete_domains | Read | Filtered, paginated pending-delete inventory. |
list_business_types | Read | Canonical categories and inventory counts. |
list_domain_tlds | Read | Extensions and inventory counts. |
list_revealed_domains | Read | Your revealed names and metadata. |
get_domain_details | Read | Detailed research for one domain. |
reveal_domains | Write | Reveal up to 100 domains in one request. |
Expand a tool for inputs and sample output. Examples are fictional.
search_expired_domainsSearch expired domainsRead
Search domains that have already dropped by geography, business category, extension, reviews and SEO signals.
Arguments
paginationobject · optional- Contains page and page_size.
business, location, tldstyped objects · optional- Use business.type_keys for exact category keys and include/exclude arrays for location and TLD filters.
business_profile, seo, social, lifecycle, sorttyped objects · optional- Ranges use { min, max }; lifecycle accepts dropped_after and dropped_before as RFC 3339 instants.
{
"pagination": {
"page": 1,
"page_size": 20
},
"location": {
"countries": {
"include": [
"US"
]
}
},
"business_profile": {
"reviews": {
"min": 10
}
}
}Result
items contains inventory records; total is the matching count. domain_id is the input to reveal_domains and get_domain_details. An unrevealed record can still contain research signals without its domain name.
{
"items": [
{
"domain_id": 12345,
"status": "expired",
"business_type": "Plumber",
"business_type_key": "plumber",
"review_count": 31,
"country_code": "US",
"city": "Austin",
"tld": "com",
"revealed": false,
"social_data_status": "processed",
"social_platforms": [],
"social_profiles": []
}
],
"total": 1,
"page": 1,
"page_size": 20
}search_auction_domainsSearch auction domainsRead
Search domains in active auctions by platform, geography, business category, extension, reviews and SEO signals.
Arguments
paginationobject · optional- Contains page and page_size.
business, location, tlds, platformstyped values · optional- Use exact category keys, include/exclude arrays and auction platform names.
business_profile, seo, social, lifecycle, sorttyped objects · optional- Lifecycle accepts auction_end_after and auction_end_before as RFC 3339 instants.
{
"pagination": {
"page": 1,
"page_size": 20
},
"platforms": [
"sedo"
],
"lifecycle": {
"auction_end_before": "2026-09-30T00:00:00Z"
}
}Result
items contains auction records with auction_end_at and platform when available. Domain visibility follows paid inventory access.
{
"items": [
{
"domain_id": 12345,
"status": "auction",
"business_type": "Plumber",
"business_type_key": "plumber",
"review_count": 31,
"country_code": "US",
"city": "Austin",
"tld": "com",
"revealed": false,
"social_data_status": "processed",
"social_platforms": [],
"social_profiles": [],
"platform": "sedo",
"auction_end_at": "2026-09-30T00:00:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 20
}search_pending_delete_domainsSearch pending-delete domainsRead
Search domains scheduled to drop by source, geography, business category, extension, reviews and SEO signals.
Arguments
paginationobject · optional- Contains page and page_size.
business, location, tlds, platformstyped values · optional- Use exact category keys, include/exclude arrays and source platform names.
business_profile, seo, social, lifecycle, sorttyped objects · optional- Lifecycle accepts scheduled_drop_after and scheduled_drop_before as RFC 3339 instants.
{
"pagination": {
"page": 1,
"page_size": 20
},
"lifecycle": {
"scheduled_drop_after": "2026-09-20T00:00:00Z"
}
}Result
items contains pending-delete records with scheduled_drop_at and source platform when available. Domain visibility follows paid inventory access.
{
"items": [
{
"domain_id": 12345,
"status": "dropping",
"business_type": "Plumber",
"business_type_key": "plumber",
"review_count": 31,
"country_code": "US",
"city": "Austin",
"tld": "com",
"revealed": false,
"social_data_status": "processed",
"social_platforms": [],
"social_profiles": [],
"scheduled_drop_at": "2026-09-21T14:00:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 20
}list_business_typesDiscover business typesRead
Get canonical business types before searching so a large result page contains only relevant categories.
Arguments
inventorystring · required- expired, auctions, or pending-delete. Counts come from that inventory only.
countrystring · optional- Two-letter country code, such as US, used to limit the counts.
{
"inventory": "expired",
"country": "US"
}Result
Pass returned business_type_key values to the matching lifecycle search tool in business.type_keys for exact any-of matching. The gcid prefix is not required; business_type is display text only.
{
"items": [
{
"business_type_key": "roofing_contractor",
"business_type": "Roofing contractor",
"count": 958
},
{
"business_type_key": "gutter_service",
"business_type": "Gutter service",
"count": 45
}
]
}list_domain_tldsDiscover available extensionsRead
Get contextual extension counts for one lifecycle inventory, optionally filtered by country.
Arguments
inventorystring · required- expired, auctions, or pending-delete. Counts come from that inventory only.
countrystring · optional- Two-letter country code, such as US, used to limit the counts.
{
"inventory": "expired",
"country": "US"
}Result
items contains tld and count for each extension in the selected inventory and country. The suffix has no leading dot.
{
"items": [
{
"tld": "com",
"count": 120
},
{
"tld": "co.uk",
"count": 24
}
]
}list_revealed_domainsWork with your revealed collectionRead
Search domains already revealed by the account that owns the key. This does not reveal or charge for new domains.
Arguments
pageinteger · optional- Starts at 1; omitted or 0 uses the default page.
page_sizeinteger · optional- 1–100 results; omitted or 0 defaults to 50.
filterstyped object · optional- Uses the same typed category, location, TLD, business-profile, SEO and social groups as catalogue search.
{
"page": 1,
"page_size": 20,
"revealed_within": 168,
"filters": {
"location": {
"countries": {
"include": [
"US"
]
}
}
}
}Result
items contains domain names, reveal timestamps, status and research fields. reveal_id identifies the reveal record; domain_id identifies the inventory resource.
{
"items": [
{
"reveal_id": "00000000-0000-4000-8000-000000000001",
"domain_id": 12345,
"domain": "example.com",
"revealed_at": "2026-09-16T12:00:00Z",
"status": "expired",
"business_type": "Plumber",
"business_type_key": "plumber",
"review_count": 31,
"country_code": "US",
"city": "Austin"
}
],
"total": 1,
"page": 1,
"page_size": 20
}get_domain_detailsInspect an accessible domainRead
Read a domain you have revealed, or an auction/dropping listing available through your active paid subscription. Knowing a fully expired name does not bypass its reveal requirement.
Arguments
domain_idinteger · required- The positive domain_id returned by a lifecycle search tool or list_revealed_domains.
{
"domain_id": 12345
}Result
A single detail object, not an items array. This example shows selected fields. Data can include business identity, location, SEO metrics, social_data, auctions and registration_links when present. Missing optional data should not be treated as zero.
{
"domain_id": 12345,
"domain": "example.com",
"revealed_at": "2026-09-16T12:00:00Z",
"status": "expired",
"business_type": "Plumber",
"business_type_key": "plumber",
"review_count": 31,
"country_code": "US",
"city": "Austin",
"auctions": [],
"social_data": {
"status": "processed",
"links": [],
"misattributed_links": []
}
}reveal_domainsReveal eligible domainsWrite
Reveal one or more domains from search results in one request. This is the only write tool and each successful paid reveal can consume one credit. Ask for approval before calling it.
Arguments
domain_idsinteger[] · required- One to 100 unique positive catalogue item IDs returned by a lifecycle search tool. Do not guess IDs or use revealed-record UUIDs.
{
"domain_ids": [
12345,
67890
]
}Result
items preserves request order and reports an outcome for every ID, including item-level failures. credits_charged and credits_remaining summarize the entire request. A reveal is not a domain registration or purchase.
{
"items": [
{
"domain_id": 12345,
"domain": "example.com",
"outcome": "revealed",
"credit_source": "subscription"
},
{
"domain_id": 67890,
"domain": "example.net",
"outcome": "already_revealed"
}
],
"credits_charged": 1,
"credits_remaining": 49
}Filter values and result format
Pagination, numeric ranges and reveal IDs are JSON numbers; boolean filters are JSON booleans. Filters use typed nested objects, for example { "business_profile": { "reviews": { "min": 10 } } }. Unknown or lifecycle-incompatible fields are rejected.
Results include schema-validated structuredContent plus the same JSON in content[0].text for compatible clients. Example:
{
"content": [
{
"type": "text",
"text": "{\"items\":[]}"
}
],
"structuredContent": {
"items": []
}
}Check isError for tool failures. Each tool publishes input and output schemas derived from the OpenAPI specification.
Decide when credits can be spent
Require client approval for each reveal batch. The server enforces key permissions but does not pause a permitted write. A prompt saying “ask first” is not enough.
- Fully expired names: remain masked until revealed by the account.
- Auction and dropping inventory: an active paid subscription shows names and details without a reveal.
- Repeating a reveal: an already-revealed domain can return an error. After a timeout, check
list_revealed_domainsbefore retrying. - No purchase operation: revealing a name does not register or buy a domain.
Troubleshooting
Check the client log and tool error.
401 · Missing, invalid or revoked key
Send Authorization: Bearer with the full key on every request. Remove extra quotes or spaces. Cookies do not work. Replace revoked keys.
403 · Reveal or inventory access denied
Reveals need a Read and reveal key. Auction and pending-delete names require an active paid subscription.
400 · Invalid arguments or reveal rejected
Use numbers for pagination, ranges and domain IDs; use the typed nested filter objects shown below. Reveals also return 400 for no credits or an already-revealed domain.
405 · Browser or SSE connection fails
A browser GET is not a connection test. GET event streams and DELETE sessions are not provided. Use Streamable HTTP, not legacy SSE.
OAuth login loop or no place to enter a header
This uses API keys, not an OAuth sign-in flow. Your client must support a custom Authorization header.
403 · Browser-origin request blocked
Cross-origin browser requests are blocked. Use a native or backend MCP client.
Timeout, large response or server error
Reduce page size or narrow the filters. Responses are limited to 64 MiB. After a reveal timeout, check revealed domains before retrying.
The service is stateless and does not issue Mcp-Session-Id.
Keep your key and research private
- Use a separate read-only key per client unless reveals are needed.
- Use a secret store or environment variable. Never commit a key or put it in a URL or prompt.
- Tool results are shared with your AI client. Review its data policy.
- Revoke an unused or exposed key from API keys. Existing clients using it will stop working.