Developers
Open in ClaudeGet started / Introduction
API & MCP
Official AI Directories catalog — search AI tools and submission directories from curl or an agent. Free, documented, and better than scraping.
Search the AI Directories catalog, look up a listing, and browse submission directories — from an agent or from curl. REST and MCP share the same backend. Third-party scrapers wrap our public pages and charge for a dump. This is the official source.
Example — GET /tools/transclipper
curl -s "https://www.aidirectori.es/api/v1/tools/transclipper" \
-H "Authorization: Bearer aid_your_api_key"{
"success": true,
"data": {
"id": "69b81f3e40816562014e004a",
"slug": "transclipper",
"name": "TransClipper",
"url": "https://www.aidirectori.es/ai-tools/transclipper",
"website": "https://transclipper.ai",
"tagline": "Steal the Blueprint Behind Any Viral Video",
"description": "TransClipper is a powerful AI-driven tool designed for efficient content clipping and transcription.",
"category": { "slug": "video", "name": "Video" },
"tags": [
{ "slug": "ai", "name": "AI" },
{ "slug": "content-creation", "name": "Content Creation" }
],
"pricing": "FREE",
"rating": 4,
"opens": 4030,
"featured": true,
"icon": "https://cdn.aidirectori.es/icons/1784893027853-vpj1hwsqkq.png"
}
}What you can do
- Search AI tools by keyword, category, tag, or pricing
- Fetch one tool by slug (full public listing)
- List categories and tags
- Search submission directories (DR, cost, badge)
- Fetch one directory profile with your aid_ key
What you cannot do
- Read founder emails or private analytics
- Scrape the HTML site or impersonate a crawler
- Republish the catalog as a competing directory
- Call partner write APIs without an issued key
Why this exists
People were scraping aidirectori.es and selling the export. The official API is free for products, research, and agents — with attribution, rate limits, and a license: you may not republish the full catalog as a competing directory or paid scrape.
Drop into an agent
Cursor: .cursor/mcp.json or ~/.cursor/mcp.json. No space after Authorization: — mcp-remote splits on whitespace. See Install MCP.
{
"mcpServers": {
"aidirectories": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://www.aidirectori.es/api/mcp",
"--header", "Authorization:Bearer aid_your_real_key"
]
}
}
}Also machine-readable
- /llms.txt — site brief for agents
- /sitemap.xml
- 60 req/min · 400/hour per IP
Get started / Quickstart
Quickstart
Create an aid_ key, then search tools, fetch one listing, and search directories.
Create a key on the developer dashboard, then copy these.
1. Search AI tools
curl -s "https://www.aidirectori.es/api/v1/tools?q=image&limit=5" \
-H "Authorization: Bearer aid_your_api_key"
2. Fetch one listing
curl -s "https://www.aidirectori.es/api/v1/tools/transclipper" \
-H "Authorization: Bearer aid_your_api_key"
3. Search directories
curl -s "https://www.aidirectori.es/api/v1/directories?q=ai&limit=5" \
-H "Authorization: Bearer aid_your_api_key"
Same operations over MCP: add the server with the same Bearer token, then call search_tools, get_tool, and search_directories. See MCP install.
Get started / Authentication
Authentication
Bearer token via API key. Generate keys from your developer dashboard. Standard 10/min, premium 60/min.
- Authentication
- Bearer token via API key. Generate keys from your developer dashboard.
- Rate limits
- Standard keys get 10 requests per minute. Premium keys get 60. Upgrade from your developer dashboard. Rate-limit headers are on every response.
- Base URL
- https://www.aidirectori.es/api/v1
1 Get your API key
Go to the developer dashboard and create an API key. Keys start with
aid_. Store it securely — you won't be able to see the full key again.Acceptable use is required
Creating a key requires agreement to the API Acceptable Use Policy. Cloning businesses, rebuilding AI Directories, bulk republication, unauthorized public SEO pages, abusive targeting, credential sharing, and access-control evasion are prohibited and can result in a permanent platform ban.
2 Make your first request
Pass your key as a Bearer token in the
Authorizationheader.X-API-Keyis also accepted, on every endpoint. The two are interchangeable — what a key can reach depends on the key, not the header it arrives in. A dashboardaid_key still gets403on the partner endpoints when sent asX-API-Key; if you are seeing 403, you need a different key, not a different header.bashcurl -s "https://www.aidirectori.es/api/v1/tools?q=ai&limit=5" \ -H "Authorization: Bearer aid_your_api_key"3 Parse the response
Successful reads return
{ success: true, data }. List endpoints also includepagination— its fields and the limit-clamping rules are worth reading before you write a paging loop. WatchX-RateLimit-Remaining.json{ "success": true, "data": [ { "slug": "transclipper", "name": "TransClipper", "website": "https://transclipper.ai" } ] }
Partner keys
Directory partners who send us tools for the submission service still use an issued key for POST /submit-ai-tool, status, webhooks, and support. Those keys also work on catalog reads. See Got a directory?.
Partners / Got a directory?
Got a directory?
Offer our directory submission service from your product. You send the tool; we list it and submit it to 30+, 60+, or 100+ directories.
A partnership is not a catalog API key. It is a way for your directory to offer our directory submission service next to your own listing.
You send the tool information from your server. We list it on AI Directories and submit it to other directories on the founder’s behalf. Founders stay on your product — they do not fill our form.
Step 1
You already have the founder
They listed on your directory or launch platform. You collected the product, founder email, and consent.
Step 2
You send us the tool
Your server POSTs name, website, copy, images, founder contact, and the package they bought (starter, pro, or premium).
Step 3
We run the submissions
We create the aidirectori.es listing and submit the tool to 30+, 60+, or 100+ directories. You poll status or get a webhook when we mark Done.
Who this is for
Startup directories, AI directories, and launch platforms that already collect a product listing and founder email. If you want to resell or bundle “get listed on 30 / 60 / 100+ directories,” this is the integration.
Searching the catalog does not need a partnership — any signed-in user can create an aid_ key. MCP cannot submit tools.
What you send
POST https://www.aidirectori.es/api/v1/submit-ai-tool with an issued X-API-Key. The body is the tool: name, website, tagline, description, category, pricing, founder name and email, tags — plus, when you have them, package, slug, icon, screenshots.
paymentType is the directory package, not the product’s pricing: starter (30+), pro (60+), premium (100+). Omit it only if the package will be set later in our admin.
Keep the key on your server. Collect founder email and marketing consent before you POST. Field lists and curl are on Submit & partners.
What you get back
- An AI Directories listing for that tool
- Directory submissions for the package you sent — we do the form work
GET https://www.aidirectori.es/api/v1/ai-tools/status— poll by id, slug, or website while work is in progress- A webhook to your HTTPS URL when we mark the job Done, with the directories we submitted to
- Optional
POST /support/ask— your customers can ask about their submission; we answer from your product
Rules
- Server-side
X-API-Keyonly (orAuthorization: Bearer) - MCP accepts a catalog
aid_key for reads and cannot submit - You collect founder email and consent — we never show founder emails on the public catalog
- Do not send the key from a webpage, app binary, or public repo
MCP / Install
Install MCP
Hosted Streamable HTTP MCP — send the same Bearer key as REST.
The server speaks the Model Context Protocol over Streamable HTTP. It is hosted. Every tool wraps the same functions as the REST API. Send Authorization: Bearer aid_… from your developer dashboard.
https://www.aidirectori.es/api/mcp
Claude Code
claude mcp add --transport http aidirectories https://www.aidirectori.es/api/mcp \
--header "Authorization: Bearer aid_your_api_key"
Cursor / Claude Desktop
Project scope: .cursor/mcp.json. Global: ~/.cursor/mcp.json. Claude Desktop: claude_desktop_config.json (stdio only — this same block).
{
"mcpServers": {
"aidirectories": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://www.aidirectori.es/api/mcp",
"--header", "Authorization:Bearer aid_your_real_key"
]
}
}
}
No space after Authorization: — mcp-remote splits arguments on whitespace, so "Authorization: Bearer …" breaks the header. Restart the client fully after editing the file.
After adding the server, ask the agent to list tools. You should see search_tools, get_top_tools, get_tool, list_categories, list_tags, search_directories, get_directory, and list_directory_categories.
Verify
curl -s https://www.aidirectori.es/api/mcp -X POST \
-H "Authorization: Bearer aid_your_api_key" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
MCP / Tools
MCP tools
Every MCP tool is a thin wrapper over the REST catalog.
Auth is the same Bearer aid_ key as REST.
| Tool | REST | Input |
|---|---|---|
search_tools | GET /tools | q, category, tag, pricing, featured, page, limit |
get_top_tools | GET /tools/top | limit, category |
get_tool | GET /tools/{slug} | slug |
list_categories | GET /categories | q, limit |
list_tags | GET /tags | q, limit |
search_directories | GET /directories | q, category, cost, featured, page, limit |
get_directory | GET /directories/{slug} | slug |
list_directory_categories | GET /directory-categories | — |
Full field notes live under AI tools and Directories.
REST API / Overview
REST API
Plain HTTP for scripts, CI, and partner integrations. The MCP server calls these same paths — so a result never depends on which transport asked for it.
| Operation | Method | Path | Auth | Input |
|---|---|---|---|---|
| search_tools Keyword search with optional category, tag, pricing, and featured filters. | GET | /tools | Bearer | q, category, tag, pricing, featured, includeAdult, page, limit |
| get_top_tools Top N listings by opens — no keyword required. | GET | /tools/top | Bearer | limit, category, includeAdult |
| list_categories AI tool categories with tool counts — use before filtering search. | GET | /categories | Bearer | q, limit |
| list_tags AI tool tags with tool counts. | GET | /tags | Bearer | q, limit |
| get_tool The full public listing for one AI tool. | GET | /tools/{slug} | Bearer | slug |
| search_directories Search submission directories by name, category, or cost. | GET | /directories | Bearer | q, category, cost, featured, page, limit |
| get_directory The full public profile for one directory. | GET | /directories/{slug} | Bearer | slug |
| list_directory_categories Directory category labels for filter discovery. | GET | /directory-categories | Bearer | — |
| submit_ai_tool Create an AI tool listing (and optionally queue directory submissions). | POST | /submit-ai-tool | X-API-Key | name, website, tagline, description, category, pricing, founderName, founderEmail, tags, paymentType, … |
| get_tool_status Poll directory-submission progress for a tool your key submitted. | GET | /ai-tools/status | X-API-Key | id | slug | website |
Discovery lives at GET / and the OpenAPI document at GET /openapi.json. Field notes for catalog responses are on AI tools and Directories.
Envelope, pagination, and limits
Every response is the same envelope. data is an array on searches and an object on single-item lookups. Check success before reading data.
{ "success": true, "data": [], "pagination": { "page": 1, "limit": 20, "total": 0, "pages": 0 } }
{ "success": false, "error": "Invalid or revoked API key." }GET /tools and GET /directories return a pagination object. The taxonomy endpoints — /categories, /tags, /directory-categories — return the whole list and no pagination key at all.
| page | The page you got, 1-based |
|---|---|
| limit | Items per page actually applied |
| total | Matching items across all pages |
| pages | ceil(total / limit), or 0 when nothing matched |
An oversized limit is clamped, not rejected. Ask for more than the maximum and you get the maximum, with a 200 — no error tells you it happened. /tools and /directories default to 20 and cap at 100; /categories and /tags cap at 500. A missing, zero, negative, or non-numeric limit falls back to the default, and page floors at 1. So read pagination.limit back from the response rather than assuming you got the page size you asked for — that assumption is what turns a paging loop into an infinite one.
page=1
while :; do
body=$(curl -s "https://www.aidirectori.es/api/v1/tools?limit=100&page=$page" \
-H "Authorization: Bearer $AID_KEY")
echo "$body" | jq -e '.success' >/dev/null || { echo "$body"; break; }
echo "$body" | jq -c '.data[]'
pages=$(echo "$body" | jq '.pagination.pages')
[ "$page" -ge "$pages" ] && break
page=$((page + 1))
sleep 6 # stay under 10 req/min on a standard key
doneAI tools
Browse, search, and filter the live catalog, or fetch one listing by slug. Maps to MCP search_tools, get_top_tools, get_tool, list_categories, and list_tags.
list_categories
AI tool categories with tool counts — use before filtering search.
| REST | GET /categories |
|---|---|
| MCP | tools/call → list_categories |
| Auth | Bearer |
| Input | q, limit |
curl -s "https://www.aidirectori.es/api/v1/categories" \
-H "Authorization: Bearer aid_your_api_key"get_top_tools
Top N listings by opens — no keyword required.
| REST | GET /tools/top |
|---|---|
| MCP | tools/call → get_top_tools |
| Auth | Bearer |
| Input | limit, category, includeAdult |
curl -s "https://www.aidirectori.es/api/v1/tools/top?limit=10&category=image" \
-H "Authorization: Bearer aid_your_api_key"search_tools
Keyword search with optional category, tag, pricing, and featured filters.
| REST | GET /tools |
|---|---|
| MCP | tools/call → search_tools |
| Auth | Bearer |
| Input | q, category, tag, pricing, featured, includeAdult, page, limit |
curl -s "https://www.aidirectori.es/api/v1/tools?q=ai&limit=5" \
-H "Authorization: Bearer aid_your_api_key"get_tool
The full public listing for one AI tool.
| REST | GET /tools/{slug} |
|---|---|
| MCP | tools/call → get_tool |
| Auth | Bearer |
| Input | slug |
curl -s "https://www.aidirectori.es/api/v1/tools/transclipper" \
-H "Authorization: Bearer aid_your_api_key"list_tags
AI tool tags with tool counts.
| REST | GET /tags |
|---|---|
| MCP | tools/call → list_tags |
| Auth | Bearer |
| Input | q, limit |
curl -s "https://www.aidirectori.es/api/v1/tags" \
-H "Authorization: Bearer aid_your_api_key"Directories
The submission-directory catalog — Domain Rating, cost, badge, and categories. Maps to MCP search_directories, get_directory, and list_directory_categories.
search_directories
Search submission directories by name, category, or cost.
| REST | GET /directories |
|---|---|
| MCP | tools/call → search_directories |
| Auth | Bearer |
| Input | q, category, cost, featured, page, limit |
curl -s "https://www.aidirectori.es/api/v1/directories?cost=Free&limit=10" \
-H "Authorization: Bearer aid_your_api_key"get_directory
The full public profile for one directory.
| REST | GET /directories/{slug} |
|---|---|
| MCP | tools/call → get_directory |
| Auth | Bearer |
| Input | slug |
curl -s "https://www.aidirectori.es/api/v1/directories/theres-an-ai-for-that" \
-H "Authorization: Bearer aid_your_api_key"list_directory_categories
Directory category labels for filter discovery.
| REST | GET /directory-categories |
|---|---|
| MCP | tools/call → list_directory_categories |
| Auth | Bearer |
| Input | — |
curl -s "https://www.aidirectori.es/api/v1/directory-categories" \
-H "Authorization: Bearer aid_your_api_key"Partner
Write and status endpoints need an issued X-API-Key. Keep it on your server. MCP does not call these. Full field lists live under Submit & partners.
submit_ai_tool
Create an AI tool listing (and optionally queue directory submissions).
| REST | POST /submit-ai-tool |
|---|---|
| MCP | — |
| Auth | X-API-Key |
| Input | name, website, tagline, description, category, pricing, founderName, founderEmail, tags, paymentType, … |
curl -s -X POST "https://www.aidirectori.es/api/v1/submit-ai-tool" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My Tool",
"website": "https://mytool.com",
"tagline": "One-line pitch",
"description": "What the product does.",
"category": "productivity",
"pricing": "FREE",
"paymentType": "pro",
"founderName": "Jane Founder",
"founderEmail": "jane@mytool.com",
"tags": ["ai", "productivity"],
"icon": "https://mytool.com/icon.png",
"frame": "https://mytool.com/screenshot.png",
"screenshots": ["https://mytool.com/gallery-1.png"]
}'get_tool_status
Poll directory-submission progress for a tool your key submitted.
| REST | GET /ai-tools/status |
|---|---|
| MCP | — |
| Auth | X-API-Key |
| Input | id | slug | website |
curl -s "https://www.aidirectori.es/api/v1/ai-tools/status?slug=my-ai-tool" \
-H "X-API-Key: YOUR_API_KEY"REST API / AI tools
AI tools
Browse, search, and fetch published AI tool listings.
search_tools
Keyword search with category, tag, pricing, and featured filters.
| REST | GET /tools |
|---|---|
| MCP | search_tools |
| Auth | Bearer aid_ |
| Input | q, category, tag, pricing (FREE | FREEMIUM | PAID), featured, includeAdult, page, limit (max 100) |
curl -s "https://www.aidirectori.es/api/v1/tools?q=transclipper&limit=5" \
-H "Authorization: Bearer aid_your_api_key"
Each item includes name, slug, listing URL, website, tagline, description, category, tags, pricing, rating, opens, icon, and timestamps. No founder email.
Adult listings are excluded by default. search_tools and get_top_tools hold back adult listings unless you ask for them.
Exclusion is by category and tag, because adult tools are often filed under a general category — image, writing, video — while tagging themselves accurately. So category=image returns image tools without the undressing apps.
Three ways to opt in: includeAdult=true, category=nsfw, or naming an adult tag such as tag=ai-undressing. Nothing is hidden or unreachable — it is simply not what you get when you did not ask.
get_top_tools
Most opened published tools. Optional category slug.
curl -s "https://www.aidirectori.es/api/v1/tools/top?limit=10&category=image" \
-H "Authorization: Bearer aid_your_api_key"
get_tool
Full public listing: screenshots, FAQs, socials, features.
curl -s "https://www.aidirectori.es/api/v1/tools/transclipper" \
-H "Authorization: Bearer aid_your_api_key"
list_categories / list_tags
curl -s "https://www.aidirectori.es/api/v1/categories" -H "Authorization: Bearer aid_your_api_key"
curl -s "https://www.aidirectori.es/api/v1/tags?q=photo" -H "Authorization: Bearer aid_your_api_key"
Categories return slug, name, description, icon, toolsCount. Tags return slug, name, toolsCount. Neither is paginated — you get the whole list, so cache it and filter locally.
Tool fields
Returned by /tools, /tools/top and /tools/{slug} alike:
| Field | Type | Notes |
|---|---|---|
id | string | Stable identifier |
slug | string | Use this for /tools/{slug} |
name, tagline, description | string | |
url | string | The listing on aidirectori.es |
website | string | The product's own site |
category | object | { slug, name }, or null |
tags | array | [{ slug, name }] |
pricing | string | FREE | FREEMIUM | PAID |
rating | number | 0 when unrated |
opens | number | Click-throughs; what /tools/top sorts by |
featured | boolean | |
icon, frame | string | Image URLs, nullable |
founderName, location | string | Nullable. No founder email, ever |
domainRating | number | Nullable |
isForSale, askingPrice | boolean, number | Listings marked for acquisition |
discountCode, affiliate | string, boolean | |
createdAt, updatedAt | string | ISO 8601, nullable |
GET /tools/{slug} adds screenshots (array of URLs), video, socials, faqs, features, and affiliateLink. Those six are only on the single-tool endpoint — don't expect them from a search.
Any field can be null when a listing has not filled it in. Code defensively.
REST API / Directories
Directories
The other half of the catalog — startup and SaaS submission directories, with DR and pricing.
Scrapers usually miss this. It is the list we actually submit products to.
search_directories
| REST | GET /directories |
|---|---|
| MCP | search_directories |
| Auth | Bearer aid_ |
| Input | q, category, cost (Free | Paid | Freemium), featured, page, limit |
curl -s "https://www.aidirectori.es/api/v1/directories?cost=Free&limit=10" \
-H "Authorization: Bearer aid_your_api_key"
Fields include name, listing URL, website, Domain Rating, monthly visits, link type, badge requirement, minimum price, and categories.
get_directory
Adds description, FAQ, submission link, and deal copy.
curl -s "https://www.aidirectori.es/api/v1/directories/theres-an-ai-for-that" \
-H "Authorization: Bearer aid_your_api_key"
list_directory_categories
curl -s "https://www.aidirectori.es/api/v1/directory-categories" \
-H "Authorization: Bearer aid_your_api_key"
Returns slug and name only. Not paginated. These are the values ?category= accepts — read them rather than guessing.
Directory fields
| Field | Type | Notes |
|---|---|---|
id, slug, name | string | |
url | string | The profile on aidirectori.es |
website | string | The directory's own site |
icon | string | Nullable |
cost | string | Free | Paid | Freemium |
type | string | Link type |
domainRating | number | Nullable — the number most people sort on |
monthlyVisits | number | Nullable |
requiresBadge | boolean | Whether they demand a backlink badge |
minimumPrice | number | 0 when free |
submissionExperience | string | Nullable |
featured | boolean | |
categories | array | [{ slug, name }] |
smallDescription | string | Nullable |
createdAt, updatedAt | string | ISO 8601 |
GET /directories/{slug} adds fullDescription, features, useCases, faq, deal ({ text, code } or null), frame, and socials.
Note the two url fields: url is our profile page, website is the directory itself. Direct submission form URLs (submissionLink) are not in the catalog API or MCP — they are part of the paid list product on the site and dashboard.
Picking submission targets
curl -s "https://www.aidirectori.es/api/v1/directories?cost=Free&limit=100" \
-H "Authorization: Bearer $AID_KEY" \
| jq -r '.data
| map(select(.requiresBadge == false and .domainRating != null))
| sort_by(-.domainRating)
| .[]
| [.domainRating, .name, .website] | @tsv'
Free, no badge required, strongest domains first.
REST API / Submit & partners
Submit & partners
API-key endpoints for submitting tools, polling status, webhooks, and support.
These are not anonymous. We issue a key per partner. MCP does not call them.
Submit a tool
POST https://www.aidirectori.es/api/v1/submit-ai-tool
Creates a listing. Send paymentType to queue directory submissions for that package. Omit it and the tool is created as waiting so the package can be set later in admin.
Required
9Missing any of these returns 400.
namestringMax 100 characters.
websiteurlPublic URL of the product.
taglinestringMax 200 characters.
descriptionstringWhat the product does.
categorystringSlug or name. We map it onto an existing category.
pricingenumFREEPAIDFREEMIUMThe product’s own pricing — not the directory package.
founderNamestringYou collect this before you POST.
founderEmailemailYou collect this. Never returned on public catalog reads. Do not send from a browser.
tagsstring[]Slugs or names.
Recommended
5The request succeeds without these — we generate a slug, fetch icon/og:image, and leave the package as waiting. Send them when you have them.
paymentTypeenumstarterpropremiumDirectory package: 30+, 60+, or 100+ submissions. Send this if the customer already picked a package. Omit only if you want the tool created as waiting so admin can set it later.
slugstringPublic URL slug. Generated from name (and uniqued) if omitted — send it when you already have a stable slug.
iconurlSquare logo. If omitted, we fetch the site favicon — send your own for a better listing.
frameurlMain screenshot. If omitted, we fetch og:image — send a product shot when you have one.
screenshotsurl[]Gallery images, mirrored to Cloudflare. Not required; frame covers the hero if this is empty.
Optional
11Images at public URLs are mirrored to Cloudflare.
videourlYouTube or Vimeo.
socialsobjectKeys to URLs, e.g.
{ "twitter": "https://x.com/…" }.featuresobjectString map, e.g.
{ "Templates": "50+" }. Generated if omitted.faqarrayIf omitted, scraped from the site or generated.
affiliatestringAffiliate program copy.
affiliateLinkurlAffiliate signup URL.
discountCodestringPromo code shown on the listing.
locationstringWhere the company is based.
foundingDatestringFounding date, free-form.
isCustomerbooleanWhether they are already a customer.
isLaunchedbooleanWhether the product is live.
curl -s -X POST "https://www.aidirectori.es/api/v1/submit-ai-tool" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My Tool",
"website": "https://mytool.com",
"tagline": "One-line pitch",
"description": "What the product does.",
"category": "productivity",
"pricing": "FREE",
"paymentType": "pro",
"founderName": "Jane Founder",
"founderEmail": "jane@mytool.com",
"tags": ["ai", "productivity"],
"icon": "https://mytool.com/icon.png",
"frame": "https://mytool.com/screenshot.png",
"screenshots": ["https://mytool.com/gallery-1.png"]
}'Poll submission status
GET https://www.aidirectori.es/api/v1/ai-tools/status — look up a tool your key submitted with exactly one of id, slug, or website. Other clients’ tools return 404.
Use this anytime — not only when a webhook fires. Poll while summary.isComplete is false, then stop (or wait for Done). submissionState is IN_QUEUE, ASSIGNED, IN_PROGRESS, REVIEW, DONE, or null when there is no directory workflow.
curl -s "https://www.aidirectori.es/api/v1/ai-tools/status?slug=my-ai-tool" \
-H "X-API-Key: YOUR_API_KEY"Webhook
We POST JSON to an HTTPS URL stored on your API client — not sent on each submit. Give us the URL when you apply; we store it as webhookUrl and send you a signing secret. Both directory-Done and support replies hit that same endpoint.
The directory event fires when an admin clicks Done on a tool your key submitted and webhookUrl is set. Missing URL: we send nothing. Your endpoint down or non-2xx: the tool is still marked Done. We do not retry yet — poll status if you need a fallback.
Events
2Read X-AI-Directories-Event before you parse the body.
directory_submissions.completedDoneAdmin marked directory work Done for a tool your key submitted. Payload is { event, occurredAt, tool, summary, submissions }.
support.repliedreplyA support reply is ready (AI or human). Payload is { event, occurredAt, conversation }. Only if support is enabled.
Request
| Method | POST |
|---|---|
| Content-Type | application/json |
| Auth | HMAC header — not your API key |
Headers
3X-AI-Directories-EventstringWhich payload you got. Branch on this — the same URL receives both events.
X-AI-Directories-Signaturestringsha256=<hex> HMAC of the raw body with your signing secret. Present when we issued a secret.
User-AgentstringAI-Directories-Webhook/1.0
Verify the signature
HMAC-SHA256 over the raw request body with the secret we gave you. Compare the hex digest to X-AI-Directories-Signature after stripping the sha256= prefix. Use a timing-safe compare.
const crypto = require("crypto");
function verifySignature(rawBody, signatureHeader, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const received = String(signatureHeader || "").replace(/^sha256=/, "");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
}Payload
submissions only includes directories we actually submitted. Each row can include the live listingUrl, proof screenshot, domain rating, and who submitted it (ADMIN or OWNER). Return 2xx to acknowledge.
{
"event": "directory_submissions.completed",
"occurredAt": "2026-09-01T13:00:00.000Z",
"tool": {
"id": "64a1b2c3d4e5f6789012345",
"name": "My AI Tool",
"slug": "my-ai-tool",
"website": "https://myaitool.com",
"paymentStatus": "prolist",
"paymentLabel": "Pro · 60+",
"targetDirectoriesCount": 60
},
"summary": {
"submittedCount": 62,
"recordedSubmissions": 62,
"notes": "All high-DR directories completed"
},
"submissions": [
{
"name": "There's An AI For That",
"slug": "theres-an-ai-for-that",
"url": "https://theresanaiforthat.com",
"listingUrl": "https://theresanaiforthat.com/ai/my-ai-tool",
"domainRating": 81,
"isSubmitted": true,
"submittedBy": "ADMIN",
"submittedAt": "2026-09-01T12:00:00.000Z"
}
]
}Customer support
Forward a question from your product UI; we answer from your knowledge base when we can, or a human replies in our dashboard. Off by default — until we enable it, POST /support/ask returns 403. Same X-API-Key as submit. MCP cannot call this.
Default mode is hybrid: AI answers when it can, otherwise the conversation stays pending for a human. We can set the client to human-only (no AI). Without product knowledge, questions wait for a person.
Send a question
POST https://www.aidirectori.es/api/v1/support/ask
Body
5question is required. Reuse conversationId or externalId to continue a thread. Human-only clients may send metadata.peerPushMessageId for idempotent retries.
questionstringThe customer’s question. Max 4000 characters. message is also accepted.
conversationIdstringContinue a thread we returned earlier.
externalIdstringYour ticket or thread id. Reusing it continues the same conversation.
customerobjectOptional
{ name, email, id }for the end customer — not the founder from submit.metadataobjectArbitrary JSON stored on the conversation.
curl -s -X POST "https://www.aidirectori.es/api/v1/support/ask" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"question": "How do I cancel my subscription?",
"externalId": "ticket-123",
"customer": { "name": "Ada", "email": "ada@example.com" }
}'Hybrid/AI: 200 with status: "answered" means reply is ready (replySource is ai or human). pending means poll or wait for the webhook.
{
"success": true,
"data": {
"id": "64a1b2c3d4e5f6789012345",
"status": "answered",
"externalId": "ticket-123",
"reply": "You can cancel from Settings → Billing.",
"replySource": "ai",
"messages": [
{ "role": "customer", "content": "How do I cancel my subscription?" },
{ "role": "assistant", "content": "You can cancel from Settings → Billing.", "source": "ai" }
]
}
}Human-only clients get a slim envelope — no history, customer, or messages[]. message is null until a human replies, then a single agent message.
{
"success": true,
"data": {
"id": "64a1b2c3d4e5f6789012345",
"externalId": "ticket-123",
"status": "pending",
"message": null
}
}Poll a conversation
GET https://www.aidirectori.es/api/v1/support/conversations/:id — or list with ?id=, ?externalId=, or ?status=pending. Suggested interval while pending: 5–15 seconds. Hybrid list results omit the full messages array; human-only returns the same slim shape as ask.
curl -s "https://www.aidirectori.es/api/v1/support/conversations/64a1b2c3d4e5f6789012345" \
-H "X-API-Key: YOUR_API_KEY"Webhook when a reply is ready
If webhookUrl is set, we POST support.replied — same HMAC as directory Done. Hybrid/AI payload uses reply / replySource. Human-only uses a singular conversation.message with role: "agent" and source: "human".
{
"event": "support.replied",
"occurredAt": "2026-09-09T09:01:00.000Z",
"conversation": {
"id": "64a1b2c3d4e5f6789012345",
"status": "answered",
"externalId": "ticket-123",
"reply": "You can cancel from Settings → Billing.",
"replySource": "human"
}
}{
"event": "support.replied",
"occurredAt": "2026-09-11T12:00:00.000Z",
"conversation": {
"id": "64a1b2c3d4e5f6789012345",
"externalId": "ticket-123",
"status": "answered",
"message": {
"id": "...",
"role": "agent",
"source": "human",
"content": "Thanks — here's how to cancel…",
"createdAt": "2026-09-11T12:00:00.000Z"
}
}
}Email support@thedirectori.es for a key, webhook URL, signing secret, or support access — or apply from Got a directory?.
Reference / Rate limits
Rate limits
Standard keys get 10 requests per minute. Premium keys get 60. Headers on every response.
Limits are per API key, not per IP — and REST and MCP draw on separate budgets, so an agent burst cannot starve your server-side scripts.
| Key | REST / minute | MCP / minute |
|---|---|---|
Standard (aid_ from the dashboard) | 10 | 30 |
| Premium (paid Catalog API plan, admin grant, or issued partner key) | 60 | 120 |
The MCP budget is the larger one because agents fan out: one question from a user routinely becomes several parallel tool calls.
The handshake is free
initialize, notifications/initialized, ping, and tools/list cost nothing. Connecting a client, or restarting one, does not spend your quota — only tools/call does. A malformed request body is not charged either.
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. 429 also sends Retry-After.
Upgrade from your developer dashboard ($9/month). Do not impersonate search-engine or assistant crawlers to dump the catalog.
Need a higher limit? Email support@thedirectori.es.
Partner submit/support keys have their own write limits; they use the premium catalog budget when reading.
Reference / Errors
Errors
JSON error shape and HTTP status codes.
{ "success": false, "error": "Tool not found." }
| HTTP | Meaning |
|---|---|
| 400 | Bad request |
| 401 | Missing or invalid API key |
| 403 | Key valid but feature not enabled |
| 404 | Tool, directory, or conversation not found |
| 429 | Rate limit |
| 500 / 503 | Server or database issue — retry |
MCP uses JSON-RPC errors (-32601 method not found, -32603 internal, and tool isError payloads).