Get your service listed
integrations.sh isn't a closed registry — it reads open discovery files from your own domain. Publish a couple of standard files, and any client that implements the same checks can find you. You're not waiting on us to merge a PR; your listing is pulled from your site. If a better community standard emerges, we'll happily adopt it.
- 1
Publish discovery files
Paste this into your coding agent (Claude Code, Cursor, Codex) from your product's repo. It inventories your integration surfaces, writes
/.well-known/integrations.json, and serves an OpenAPI spec and MCP server card if you have them.prompt — add my product to integrations.shYou are working inside my product's repository. Goal: make my product discoverable on integrations.sh by publishing standard discovery files on my own domain. Derive every value from THIS repo and its docs. Never invent endpoints, specs, or auth. Leave out any surface my product does not actually have. # 1. Inventory the integration surfaces Read the codebase, README, and docs to find each way an agent could integrate with my product, and how each authenticates: - HTTP/REST API — base URL, and whether an OpenAPI/Swagger spec exists in the repo or is served somewhere. - MCP server — the connect URL and transport (streamable-http or sse), if one ships. - GraphQL API — the endpoint URL, and SDL/introspection availability. - CLI — the command name and how it installs (npm/pypi/oci/brew). For each surface, determine the auth: none (public), or the credential(s) needed and exactly how they ride the request (header name + scheme, or query/body param, or a CLI login/env var). # 2. Author /.well-known/integrations.json Write ONE file at /.well-known/integrations.json on my production domain with EVERYTHING inline — there is no index/reference layout. The file holds version + summary + a shared credentials map + a "surfaces" list of full surface objects. Credentials are defined once in the top-level "credentials" map and referenced from each surface's auth by id. Serve it as application/json, publicly cacheable (e.g. Cache-Control: public, max-age=3600). File shape (v3): { "version": 3, "summary"?: string, "credentials"?: { [id]: Credential }, "surfaces"?: Surface[] } Credential (defined once in "credentials", keyed by id, referenced from a surface's auth): { "type": "api_key"|"bearer"|"basic"|"oauth2"|"oauth2_cc"|"jwt"|"custom"|..., "label": string, // human name, e.g. "Acme API key" "generateUrl"?: string, // where the user mints it "setup": string, // markdown: how to get it, gotchas "fields"?: { [name]: { "secret"?: boolean, "description"?: string } } } // only for multi-part secrets Surface (discriminated on "type"). Common fields on every surface: "slug": string, // stable url segment, e.g. "acme-api" "name": string, // display name "docs"?: string, // human docs URL "basis": { "via": "declared", "source": "https://MY_DOMAIN/.well-known/integrations.json" }, "auth": AuthStatus Per-type extra fields: http: "spec"? (OpenAPI doc URL), "url"? (base URL) graphql: "url"? (endpoint), "spec"? ("introspection" or SDL URL) mcp: "url"? (connect endpoint), "transports"?: ["streamable-http"] | ["sse"] cli: "command"?: string, "packages"?: [{ "registryType": "npm"|"pypi"|..., "identifier": string, "runtimeHint"?: "npx"|"uvx" }] AuthStatus is one of: { "status": "none", "basis": { "via": "declared", "source": "https://MY_DOMAIN/.well-known/integrations.json" } } // confirmed public { "status": "unknown" } // not determined { "status": "required", "entries": [ AuthEntry ] } // entries are OR alternatives; at least one works AuthEntry: { "use": [ { "id": "<credential id>", "mechanics": Mechanics } ], // multiple uses are AND'd (sent together) "basis": { "via": "declared", "source": "https://MY_DOMAIN/.well-known/integrations.json" } } Mechanics (how ONE credential binds), pick the matching shape: { "source": "http", "in": "header", "headerName": "Authorization", "scheme": "Bearer" } { "source": "http", "in": "query", "paramName": "api_key" } { "source": "cli", "command"?: "acme login", "env"?: ["ACME_API_TOKEN"] } { "source": "spec", "scheme": "<securityScheme name from the OpenAPI doc>" } { "source": "well-known" } // MCP OAuth resolvable from the surface url via RFC 9728/8414 { "source": "unknown" } Rules: - Replace MY_DOMAIN with my real production host everywhere. - Every surface's basis.source and every auth basis.source must be my integrations.json URL (https://MY_DOMAIN/.well-known/integrations.json). - Only include surfaces that exist. Omit "credentials" / "surfaces" entirely if there are none. - The file must parse as strict JSON and validate against the v3 shape above, or integrations.sh silently ignores it. # 3. Also publish, if applicable - If my product has an HTTP API and an OpenAPI/Swagger spec exists (or can be generated from the code), serve it at /openapi.json (integrations.sh also probes /swagger.json, /api/openapi.json, /v1/openapi.json, /api/schema/ — /openapi.json is the canonical one). Serve as application/json, publicly cacheable. If a spec route already exists, just make sure one of those paths resolves to it. - If my product ships an MCP server, also serve /.well-known/mcp/server-card.json with at least { "url": "<mcp connect endpoint>" } and, if the server needs auth, "authentication": { "type": "oauth2", "authorization_server"?: "<as url>" }. application/json, publicly cacheable. # 4. Verify Print copy-paste curl commands to confirm each published file resolves on my live domain with a JSON content-type, e.g.: curl -sS -D- -o/dev/null https://MY_DOMAIN/.well-known/integrations.json curl -sS https://MY_DOMAIN/.well-known/integrations.json | jq . curl -sS -D- -o/dev/null https://MY_DOMAIN/openapi.json # if you published one curl -sS https://MY_DOMAIN/.well-known/mcp/server-card.json | jq . # if you published one Then tell me: open https://integrations.sh/MY_DOMAIN/ and click "Map integration surface" to publish the listing.I already have an OpenAPI spec or MCP server
prompt — expose an existing spec / MCP serverYou are working inside my product's repository. I already have an OpenAPI spec and/or an MCP server. Expose them at the conventional paths integrations.sh probes. Use the real files in this repo; do not invent anything. 1. If I have an OpenAPI/Swagger document, serve it at /openapi.json on my production domain, as application/json and publicly cacheable (integrations.sh also checks /swagger.json, /api/openapi.json, /v1/openapi.json, /api/schema/ — /openapi.json is canonical). If a spec route already exists, just make one of those paths resolve to it. 2. If I ship an MCP server, serve /.well-known/mcp/server-card.json with at least: { "url": "<my MCP connect endpoint>", "authentication"?: { "type": "oauth2", "authorization_server"?: "<as url>" } } as application/json, publicly cacheable. Fill "authentication" only if the server needs it; derive the values from the repo. 3. Print curl commands to verify each path resolves on my live domain with a JSON content-type. Then tell me to open https://integrations.sh/MY_DOMAIN/ and click "Map integration surface". If you also author /.well-known/integrations.json, put everything in that one file: version + summary + a shared "credentials" map + a "surfaces" list of full surface objects. There is no index/reference layout — no separate per-surface files. Credentials are defined once in "credentials" and referenced from each surface's auth by id. - 2
Verify
Check the files resolve on your live domain and return JSON. The agent prints these; run them yourself to confirm (swap in your host):
curl -sS https://your-domain.com/.well-known/integrations.json | jq . curl -sS https://your-domain.com/openapi.json | jq . # if published curl -sS https://your-domain.com/.well-known/mcp/server-card.json | jq . # if publishedThe file must parse as strict JSON and be served with an
application/jsoncontent-type — an HTML 404 or a JSON{"error":"Not Found"}won't be trusted. - 3
Get discovered
Open
https://integrations.sh/{your-domain}/and click Map integration surface. The run reads your files, refreshes the conventions scorecard and discovered surfaces, and your listing is live immediately.
/.well-known/integrations.json is the integrations.sh owner declaration format. It is a v3 discovery
subset you can author: { version: 3, summary?, credentials?, surfaces? }. Credentials and surfaces
use the same wire schema as the registry output.
{
"version": 3,
"summary": "Resend exposes an HTTP API, MCP server, and CLI for sending and managing email.",
"credentials": {
"resend_api_key": {
"type": "api_key",
"label": "Resend API key",
"generateUrl": "https://resend.com/api-keys",
"setup": "Create an API key in the Resend dashboard. Store it as RESEND_API_KEY and send it as an Authorization bearer token."
}
},
"surfaces": [
{
"slug": "resend-api",
"name": "Resend API",
"type": "http",
"docs": "https://resend.com/docs/api-reference",
"spec": "https://resend.com/openapi.json",
"url": "https://api.resend.com",
"basis": {
"via": "declared",
"source": "https://resend.com/.well-known/integrations.json"
},
"auth": {
"status": "required",
"entries": [
{
"use": [
{
"id": "resend_api_key",
"mechanics": {
"source": "http",
"in": "header",
"headerName": "Authorization",
"scheme": "Bearer"
}
}
],
"basis": {
"via": "declared",
"source": "https://resend.com/.well-known/integrations.json"
}
}
]
}
},
{
"slug": "resend-mcp-server",
"name": "Resend MCP server",
"type": "mcp",
"docs": "https://resend.com/docs/mcp-server",
"url": "https://mcp.resend.com/mcp",
"transports": ["streamable-http"],
"basis": {
"via": "declared",
"source": "https://resend.com/.well-known/integrations.json"
},
"auth": {
"status": "required",
"entries": [
{
"use": [
{
"id": "resend_api_key",
"mechanics": {
"source": "http",
"in": "header",
"headerName": "Authorization",
"scheme": "Bearer"
}
}
],
"basis": {
"via": "declared",
"source": "https://resend.com/.well-known/integrations.json"
}
}
]
}
}
]
} We needed a way to represent this data for ourselves; we publish the format so you can own it. If a better community standard emerges, we'll happily migrate.
integrations.json is the direct route, but you can also publish any of these and we'll pick them up. All
are open — nothing is proprietary to us.
/llms.txt Plain-language docs and product context.
Use it when your docs have a good LLM-readable overview.
/.well-known/api-catalog REST bases, OpenAPI links, docs, status pages, and MCP endpoints.
Use RFC 9727 when you already publish a machine-readable service catalog.
/openapi.json and conventional OpenAPI paths HTTP API surfaces and spec pointers.
Publish one canonical OpenAPI document, then link alternates from your catalog if needed.
/.well-known/mcp/server-card.json MCP server endpoint, transport, and auth metadata.
Use it when agents can connect to an MCP server on your domain.
/.well-known/oauth-protected-resource OAuth resource metadata, authorization servers, scopes, and self-onboarding support.
Use it when an API or MCP endpoint is protected by OAuth.
/.well-known/agent-card.json Agent-facing service identity.
Use it to publish the agent card your site wants clients to read first.
/.well-known/agent-skills/index.json Agent skill inventory.
Use it when your domain publishes reusable skills or task instructions.
/.well-known/integrations.json Your declared v3 summary, credentials, and surfaces.
Use it when you want this registry page to reflect your own integration map directly.
Owner declarations are respected as the owner's statement of intent. The registry may additionally record verified
operational caveats, including rate limits, required headers like GitHub's mandatory User-Agent, and auth
quirks sourced from docs, testing, and later user reports.