API
Read the Neeed Directory catalog from your own code or agent: a JSON API described by an OpenAPI document, and an MCP server. No key needed.
Usage
Calls the API and the MCP server answered over the last 30 days, counted as they are served and refreshed hourly.
3,065
Calls, last 30 days
3,017
Over HTTP
48
Over MCP
/search
Most called
Calls per day
Quick start
Every endpoint is a GET that answers JSON and allows cross-origin requests, so a browser, a script or a spreadsheet can call it as is. Only live listings are returned.
curl "https://mcp-preview.neeed.directory/api/v1/search?q=email&limit=5"
curl "https://mcp-preview.neeed.directory/api/v1/search?category=analytics&page=2"
curl "https://mcp-preview.neeed.directory/api/v1/categories"
curl "https://mcp-preview.neeed.directory/api/v1/products/{slug}"Endpoints
GET/searchSearch or list products
Live listings, newest first. Narrow them with a full-text query and by category, label or tag; every filter is optional.
Parameters
| Name | Type | Description |
|---|---|---|
| qoptional | stringquery | Full-text query over name, tagline and description. 2–100 characters |
| categoryoptional | stringquery | Category slug |
| labeloptional | stringquery | Label slug |
| tagoptional | stringquery | Tag slug |
| pageoptional | integerquery | Page number. default 1, 1–500 |
| limitoptional | integerquery | Products per page. default 20, 1–50 |
Response
| Name | Type | Description |
|---|---|---|
| products | Product[] | |
| total | integer | Matches across every page. ≥ 0 |
| page | integer | |
| limit | integer |
Errors: 400 Invalid input, with the rejected parameters under data.issues · 429 Too many requests. Please slow down and try again shortly.
GET/categoriesList categories
Every category with the number of live listings it holds, by name.
Response
| Name | Type | Description |
|---|---|---|
| categories | Category[] |
Errors: 429 Too many requests. Please slow down and try again shortly.
GET/products/{slug}Get a product
One live listing by slug. A listing that is not live is a 404.
Parameters
| Name | Type | Description |
|---|---|---|
| slug | stringpath | The slug in the listing's URL. 1–200 characters |
Response
A Product.
Errors: 400 Invalid input, with the rejected parameters under data.issues · 404 Not found · 429 Too many requests. Please slow down and try again shortly.
Objects
Product
| Name | Type | Description |
|---|---|---|
| id | string (uuid) | |
| slug | string | |
| name | string | |
| punchline | string | The one-line tagline |
| description | string | HTML, as the listing page renders it |
| url | string (uri) | The listing on Neeed Directory |
| website | string | The product's own site |
| logo | string (uri) or null | |
| cover | string (uri) or null | |
| category | string or null | Category slug |
| labels | string[] | Label slugs |
| tags | string[] | Tag slugs |
| product_type | "software" | "digital_product" or null | |
| pricing_model | "free" | "freemium" | "paid" | "open_source" or null | |
| string or null | X handle, without the @ | |
| featured | boolean | |
| listed_at | string (date-time) or null | When the listing went live |
| highlights | string[] | Premium profile: what it does, one fact per line |
| ideal_for | string[] | Premium profile: who it is for |
| faq | FaqItem[] | Premium profile: questions answered from the product's site |
| promo | Promo or null | The maker's promo code for visitors, or null |
FaqItem
| Name | Type | Description |
|---|---|---|
| question | string | |
| answer | string |
Promo
| Name | Type | Description |
|---|---|---|
| code | string | |
| discount | string | The offer, in the maker's words: "20% off" |
| url | string (uri) or null | Where to redeem it; null means the product's own site |
| expires_at | string (date) or null | Last valid day, yyyy-mm-dd; null means open-ended |
Category
| Name | Type | Description |
|---|---|---|
| slug | string | |
| name | string | |
| noun | string | What the directory calls its listings, e.g. "AI agents" |
| url | string (uri) | |
| count | integer | Live listings in the category. ≥ 0 |
Errors and limits
An error is a JSON object with a code and a message; a 400 adds the rejected parameters under data.issues.
{ "code": "NOT_FOUND", "message": "No live listing has this slug." }Requests are counted per IP: 30 searches and 60 other calls a minute, then a 429 until the minute ends. Responses can be served from the edge for up to five minutes, so a change to a listing takes that long to show.
MCP server
Tools for Claude, Cursor and any other Model Context Protocol client, over Streamable HTTP with no session. The reads need no key and no sign-in. The three reads take the parameters of the endpoint they call and return the same object; submit_product saves a listing draft for a maker to claim, or submits it to their account when they signed in. The other tools act on a signed-in maker's own listings.
{
"mcpServers": {
"neeed": { "type": "http", "url": "https://mcp-preview.neeed.directory/api/mcp" }
}
}With Claude Code: claude mcp add --transport http neeed https://mcp-preview.neeed.directory/api/mcp
| Tool | Description |
|---|---|
| search_products | Search the live listings on Neeed Directory, newest first. Every argument is optional: a full-text query over name, tagline and description, and category, label or tag slugs to narrow by. Returns products with their slug, tagline, description, website and pricing model, plus the total match count. |
| list_categories | Every category on Neeed Directory with its slug, name and the number of live listings it holds. |
| get_product | One live listing on Neeed Directory by slug, with its full description, website, labels, tags and pricing model, plus its premium profile (highlights, who it is for, FAQ) and promo code when it has them. |
| submit_product | Without sign-in, saves a private draft listing on Neeed Directory and returns a claim link: nothing is published or charged until the maker opens it, signs in and submits. Signed in with permission to edit listings, submits the listing to the maker's account: Neeed's automatic check publishes it or holds it for review, and Premium returns a Stripe Checkout link the maker pays in the browser. |
| my_listings | Your listings on Neeed Directory, newest first: status, plan, badge, the admin's feedback when there is any, and the page to open. Pass a slug to get one. |
| check_badge | Looks for the Neeed badge on one of your Free listings' sites now and answers found, missing or inconclusive, with the markup to add. It records nothing: the maker presses Verify on the listing's edit page to make the link dofollow or bring a hidden listing back. |
| update_listing | Edits one of your listings: name, punchline, description, category, pricing model or Twitter handle, under the dashboard's rules. Editing a listing that is not live sends it back for review; a live listing stays live. A rejected listing cannot be edited. |
| upgrade_listing | Returns a Stripe Checkout link that upgrades one of your live Free listings to Premium, with the price. Nothing is charged until the maker opens the link and pays in the browser. |
| Prompt | Description |
|---|---|
| submit_to_neeed | Drafts a Neeed listing from a product's website, has the maker approve it, and saves it with submit_product. Argument: website. |
Sign in to manage your listings
search_products, list_categories, get_product, submit_product work without signing in. my_listings, check_badge, update_listing, upgrade_listing need a signed-in maker.
The assistant signs in with OAuth. Neeed shows which app is asking and what it may do, and nothing is shared until the maker approves.
listings:read(See your listings): Needed bymy_listings,check_badge,update_listing,upgrade_listing. The assistant sees the account's listings with their status, plan, review feedback and badge status.listings:write(Edit your listings): Also needed byupdate_listing,upgrade_listing. With it,submit_productsubmits the listing straight to the account, answersalready_listedfor a site that is live on Neeed andalready_submittedfor a site the account already submitted, and saves a draft with a claim link when the site offers no usable cover image or icon. Without it, the tool saves a draft with a claim link.offline_access(Stay connected until you disconnect it): Lets the assistant renew its access without asking again.
Access tokens last one hour. Refresh tokens last 30 days, are replaced on every use and exist only with "Stay connected until you disconnect it".
A connected assistant can change a listing's name, punchline, description, category, pricing model and X handle under the dashboard's review rules, create a listing through submit_product, and get a Checkout link for Premium. It cannot pay, publish without the automatic check, see other makers' listings, or read the account's email address, billing details or password. Payment always happens in the browser on Stripe.
To disconnect an assistant, open Settings, then Connected apps, and choose Disconnect. Access stops at once.
After a disconnect, an assistant that still holds its expired sign-in is refused on every call, reads included, until the maker signs in again or clears the stored sign-in (in Claude Code: /mcp, then clear authentication).
Submitting through MCP
Without sign-in, submit_product saves a private draft and returns a claim link. Nothing is published or charged until the maker opens the link, signs in and submits through the normal form, and every listing then goes through the automatic check.
The link works once and expires in 7 days. Each IP can save 5 drafts in any 24 hours, under an overall cap over the same window, so a refused call succeeds once earlier drafts are 24 hours old.
The data is the public catalog; when you show a listing elsewhere, link to its page. Use of the API falls under the Terms of Service. Need a write endpoint or a higher limit? Write to us.