{"openapi":"3.1.0","info":{"title":"SourcePost — directory of suppliers and services for AI agents","description":"SourcePost is a directory where AI agents find suppliers, services and data sources for their task.\n\n**Current niche:** Resale sourcing — Suppliers, wholesale marketplaces, price data and automation tools for agents that look for products to resell.\n\nHow to use it:\n1. `GET /v1/listings` to search (free text in English or Spanish, plus filters).\n2. `GET /v1/listings/{id}` for one listing.\n3. If you offer something that fits, or did not find what you needed, tell us with\n   `POST /v1/interest`. Every search response carries an `invitation` with the exact URL.\n   Messages are stored for the SourcePost team and are not published.\n\nRules you can rely on:\n- **Sponsored** listings appear only in `sponsored_results` (at most 3, `sponsored: true`),\n  never in `results`.\n- **Languages:** `en` (default) and `es`. Use `?lang=` or `Accept-Language`; the response says\n  which one it used (`Content-Language`, `lang`). Listings without a translation fall back to\n  English.\n- **Prices:** price information as free text (`pricing_info`), with its source\n  (`price_source`: the provider's own site or a third party) and the date SourcePost last checked\n  it (`price_checked_at`).\n- **Links:** each listing's `url` carries `utm_source=sourcepost.dev` and `utm_medium=agent-directory`, so the provider can see that the visit came from SourcePost; they never contain data about you. `url_original` is the same link without tags.\n- **Rate limits:** 60 requests per minute per client, and 10 messages\n  per hour to `POST /v1/interest`. Over the limit you get `429` with `Retry-After` (seconds).\n- SourcePost does not store your IP address in its request records (see `/privacy`).\n","version":"0.1.0"},"servers":[{"url":"https://sourcepost.dev"}],"paths":{"/v1/listings":{"get":{"tags":["listings"],"summary":"Search listings","description":"Search active listings of the hub. Free text matches English and Spanish content. Paid placements come only in `sponsored_results` (at most 3, `sponsored: true`) and never in `results`. Every response carries an `invitation` to tell the hub what you offer or what you did not find.","operationId":"searchListings","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free text, any language.","title":"Q"},"description":"Free text, any language."},{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["automation_tool","dropshipping_supplier","price_data","print_on_demand","sourcing_agent","supplier_directory","wholesale_marketplace"]},"description":"Category id of the active niche (see the allowed values)."},{"name":"offer_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/OfferType"},{"type":"null"}],"description":"Only this kind of offer.","title":"Offer Type"},"description":"Only this kind of offer."},{"name":"verified_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only listings verified by the hub.","default":false,"title":"Verified Only"},"description":"Only listings verified by the hub."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Results per page (1–50).","default":20,"title":"Limit"},"description":"Results per page (1–50)."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":0,"description":"Results to skip, for the next pages.","default":0,"title":"Offset"},"description":"Results to skip, for the next pages."},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Response language (en, es). Overrides Accept-Language. Default: en.","title":"Lang"},"description":"Response language (en, es). Overrides Accept-Language. Default: en."}],"responses":{"200":{"description":"Search results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}},"headers":{"Content-Language":{"description":"Language of the response (en or es).","schema":{"type":"string"}}}},"422":{"description":"Invalid parameter, or unknown category (`unknown_category` lists the allowed ones)."},"429":{"description":"Too many requests from this client. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedOut"}}}}}}},"/v1/listings/{listing_id}":{"get":{"tags":["listings"],"summary":"Get one listing","description":"One active listing by id, in the requested language (falls back to English; the `lang` field says which one was served). Listings that are not public return 404.","operationId":"getListing","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"string","description":"Listing id, as returned by the search.","title":"Listing Id"},"description":"Listing id, as returned by the search."},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Response language (en, es). Overrides Accept-Language. Default: en.","title":"Lang"},"description":"Response language (en, es). Overrides Accept-Language. Default: en."}],"responses":{"200":{"description":"The listing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingOut"}}},"headers":{"Content-Language":{"description":"Language of the response (en or es).","schema":{"type":"string"}}}},"404":{"description":"No public listing with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"429":{"description":"Too many requests from this client. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/interest":{"post":{"tags":["interest"],"summary":"Tell the hub what you offer or what you could not find","description":"Free text, in English or Spanish. `kind`: `offer` (you or your owner provide something that fits this hub) or `missing` (you searched and did not find it). The message is stored for the hub team and is NOT published; it does not create a listing. Do not include personal data.","operationId":"postInterest","parameters":[{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Response language (en, es). Overrides Accept-Language. Default: en.","title":"Lang"},"description":"Response language (en, es). Overrides Accept-Language. Default: en."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterestIn"}}}},"responses":{"201":{"description":"Stored (not published).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InterestOut"}}},"headers":{"Content-Language":{"description":"Language of the response (en or es).","schema":{"type":"string"}}}},"422":{"description":"Invalid body: unknown field, wrong `kind`, text too short or long, `contact_url` not http(s), or the example text sent as is (`example_text`)."},"429":{"description":"Too many requests from this client. Wait `Retry-After` seconds.","headers":{"Retry-After":{"description":"Seconds to wait before the next request.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedOut"}}}}}}},"/health":{"get":{"tags":["system"],"summary":"Service status","description":"Returns ok while the service is up. Not rate limited.","operationId":"health","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health"}}}}}}}},"components":{"schemas":{"ErrorDetail":{"properties":{"error":{"type":"string","title":"Error","description":"Stable error code, e.g. listing_not_found, unknown_category."},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"The id that was not found, if any."},"allowed":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed","description":"Accepted values, for unknown_category."}},"type":"object","required":["error"],"title":"ErrorDetail"},"ErrorOut":{"properties":{"detail":{"$ref":"#/components/schemas/ErrorDetail","description":"What went wrong."}},"type":"object","required":["detail"],"title":"ErrorOut"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InterestIn":{"properties":{"kind":{"$ref":"#/components/schemas/InterestKind","description":"'offer': you or your owner provide something that fits this hub. 'missing': you searched the hub and did not find what you needed."},"text":{"type":"string","maxLength":2000,"minLength":10,"title":"Text","description":"What you offer or what you were looking for. Free text, English or Spanish, 10 to 2000 characters. No personal data."},"contact_url":{"anyOf":[{"type":"string","maxLength":2048,"minLength":1,"format":"uri"},{"type":"null"}],"title":"Contact Url","description":"Optional public page where the hub team can follow up."}},"additionalProperties":false,"type":"object","required":["kind","text"],"title":"InterestIn","examples":[{"kind":"offer","text":"We sell refurbished smartphones wholesale and ship across the EU."},{"kind":"missing","text":"Wholesale suppliers of bicycle spare parts that ship to Portugal."}]},"InterestKind":{"type":"string","enum":["offer","missing"],"title":"InterestKind"},"InterestOut":{"properties":{"id":{"type":"string","title":"Id","description":"Id of the stored message."},"kind":{"$ref":"#/components/schemas/InterestKind","description":"The `kind` you sent."},"published":{"type":"boolean","const":false,"title":"Published","description":"Always false: messages are never published."},"lang":{"type":"string","title":"Lang","description":"Language of `message`."},"message":{"type":"string","title":"Message","description":"Confirmation for you, in `lang`."}},"type":"object","required":["id","kind","published","lang","message"],"title":"InterestOut"},"InvitationOut":{"properties":{"message":{"type":"string","title":"Message","description":"Short invitation in the response language."},"method":{"type":"string","const":"POST","title":"Method","description":"HTTP method to use.","default":"POST"},"url":{"type":"string","title":"Url","description":"Absolute URL to send your message to."},"kinds":{"items":{"$ref":"#/components/schemas/InterestKind"},"type":"array","title":"Kinds","description":"Accepted values for `kind` in the body."},"docs_url":{"type":"string","title":"Docs Url","description":"Guide for agents (skill.md)."}},"type":"object","required":["message","url","kinds","docs_url"],"title":"InvitationOut"},"ListingOut":{"properties":{"id":{"type":"string","title":"Id","description":"Stable listing id."},"lang":{"type":"string","title":"Lang","description":"Language of title and summary. Falls back to 'en' when the requested language is not available for this listing."},"title":{"type":"string","title":"Title","description":"Listing name, in `lang`."},"summary":{"type":"string","title":"Summary","description":"What the listing offers, in `lang`."},"category":{"type":"string","title":"Category","description":"Category id (English, stable)."},"category_label":{"type":"string","title":"Category Label","description":"Category name in the served language."},"offer_type":{"$ref":"#/components/schemas/OfferType","description":"Kind of offer: api, dataset, supplier, tool or service."},"url":{"type":"string","title":"Url","description":"Link to the provider. It may carry `utm_source` and `utm_medium` tags so the provider can see the visit came from this directory; the tags never contain data about you. Use `url_original` for the untouched link."},"url_original":{"type":"string","title":"Url Original","description":"The provider's link exactly as listed, without tags."},"contact_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Url","description":"Where to contact the provider, if known."},"pricing_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pricing Info","description":"Price information as free text, not translated. Its source is in price_source."},"pricing_info_lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pricing Info Lang","description":"Language of pricing_info (ISO 639)."},"price_checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Price Checked At","description":"When the hub last checked the price (UTC). Use it to judge how fresh pricing_info is."},"price_source":{"anyOf":[{"$ref":"#/components/schemas/PriceSource"},{"type":"null"}],"description":"Where the price comes from: 'official' (provider's own site) or 'third_party' (recent independent source)."},"has_api":{"type":"boolean","title":"Has Api","description":"True if the provider offers a public API."},"has_mcp":{"type":"boolean","title":"Has Mcp","description":"True if the provider offers an MCP server."},"region":{"items":{"type":"string"},"type":"array","title":"Region","description":"Regions served, as given by the provider (e.g. Global, EU, US, UK, Asia). Empty if unknown."},"verified":{"type":"boolean","title":"Verified","description":"True if the hub checked the listing."},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verified At","description":"When the hub checked the listing (UTC)."},"sponsored":{"type":"boolean","title":"Sponsored","description":"True for paid placements. Always explicit."},"disclaimer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disclaimer","description":"Mandatory notice for restricted categories, if any."}},"type":"object","required":["id","lang","title","summary","category","category_label","offer_type","url","url_original","contact_url","pricing_info","pricing_info_lang","price_checked_at","price_source","has_api","has_mcp","region","verified","verified_at","sponsored"],"title":"ListingOut"},"OfferType":{"type":"string","enum":["api","dataset","supplier","tool","service"],"title":"OfferType"},"PriceSource":{"type":"string","enum":["official","third_party"],"title":"PriceSource"},"RateLimitedOut":{"properties":{"error":{"type":"string","const":"rate_limited","title":"Error","description":"Always rate_limited."},"retry_after":{"type":"integer","title":"Retry After","description":"Seconds to wait before the next request."}},"type":"object","required":["error","retry_after"],"title":"RateLimitedOut"},"SearchQueryOut":{"properties":{"q":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q","description":"Free text searched, if any."},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category","description":"Category filter, if any."},"offer_type":{"anyOf":[{"$ref":"#/components/schemas/OfferType"},{"type":"null"}],"description":"Offer type filter, if any."},"verified_only":{"type":"boolean","title":"Verified Only","description":"True if only verified listings were requested."}},"type":"object","required":["q","category","offer_type","verified_only"],"title":"SearchQueryOut","description":"The search as the hub understood it."},"SearchResponse":{"properties":{"lang":{"type":"string","title":"Lang","description":"Language resolved for this response (?lang= or Accept-Language)."},"query":{"$ref":"#/components/schemas/SearchQueryOut"},"total":{"type":"integer","title":"Total","description":"Number of matching non-sponsored listings."},"limit":{"type":"integer","title":"Limit","description":"Maximum number of `results` in this page."},"offset":{"type":"integer","title":"Offset","description":"Number of `results` skipped (pagination)."},"sponsored_results":{"items":{"$ref":"#/components/schemas/ListingOut"},"type":"array","title":"Sponsored Results","description":"Paid placements, at most 3, only on the first page. Never repeated in results. Each one has sponsored = true."},"results":{"items":{"$ref":"#/components/schemas/ListingOut"},"type":"array","title":"Results","description":"Non-sponsored listings."},"invitation":{"$ref":"#/components/schemas/InvitationOut","description":"Always present: how to tell the hub what you offer or what you did not find."}},"type":"object","required":["lang","query","total","limit","offset","sponsored_results","results","invitation"],"title":"SearchResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"listings","description":"Search and read listings of the active niche."},{"name":"interest","description":"Tell SourcePost what you offer or what you could not find. Not published."},{"name":"system","description":"Service status."}]}