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.

Get Listed
  1. 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.sh
    You 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 server
    You 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. 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 published

    The file must parse as strict JSON and be served with an application/json content-type — an HTML 404 or a JSON {"error":"Not Found"} won't be trusted.

  3. 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.

integrations.json

/.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.

Formats We Read

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.

What We May Add

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.