SnazzyMoDocs
Guides

Discover the API Programmatically

Walk SnazzyMo's RFC 9727 API catalog to the OpenAPI spec and health endpoint using curl and Node.js.

This guide resolves every SnazzyMo API capability starting from a single well-known URL — the same flow an AI agent follows. All commands target https://snazzymo.com.

1. Fetch the catalog

curl -sS -H 'Accept: application/linkset+json' \
  https://snazzymo.com/.well-known/api-catalog

Expect 200 with Content-Type: application/linkset+json and a body shaped like:

{
  "linkset": [
    {
      "anchor": "https://snazzymo.com/api/waitlist",
      "service-desc": [
        {
          "href": "https://snazzymo.com/api/openapi.json",
          "type": "application/json",
          "title": "SnazzyMo OpenAPI specification"
        }
      ],
      "service-doc": [
        {
          "href": "https://snazzymo.com/docs/api",
          "type": "text/html",
          "title": "SnazzyMo API documentation"
        }
      ],
      "status": [
        {
          "href": "https://snazzymo.com/api/health",
          "type": "application/json",
          "title": "SnazzyMo API status"
        }
      ]
    }
  ]
}

2. Resolve the spec and the health check

Pick the entry whose anchor you care about, then follow service-desc for the machine-readable contract and status for liveness:

curl -sS https://snazzymo.com/api/openapi.json | head -c 300
curl -sS https://snazzymo.com/api/health

The health endpoint answers {"status":"ok","service":"snazzymo-landing",...} with Cache-Control: no-store.

3. Script it end to end

The script below walks catalog → spec → health, and exits non-zero if any link is missing. It uses only the global fetch (Node.js 18+):

const BASE = "https://snazzymo.com";

async function getJson(url, accept) {
  const res = await fetch(url, accept ? { headers: { accept } } : undefined);
  if (!res.ok) throw new Error(`GET ${url} -> ${res.status}`);
  return res.json();
}

const catalog = await getJson(
  `${BASE}/.well-known/api-catalog`,
  "application/linkset+json",
);
const entry = catalog.linkset.find((e) =>
  e.anchor.startsWith(`${BASE}/api/`),
);
if (!entry) throw new Error("no API entry in catalog");

const href = (rel) => entry[rel]?.[0]?.href ?? null;
const specUrl = href("service-desc");
const statusUrl = href("status");
if (!specUrl || !statusUrl) throw new Error("catalog entry is incomplete");

const spec = await getJson(specUrl);
console.log("operations:", Object.keys(spec.paths).join(", "));

const health = await getJson(statusUrl);
console.log("health:", health.status);
if (health.status !== "ok") process.exitCode = 1;

4. Start from a known endpoint instead

If you already know GET /api/waitlist, you can discover bottom-up: it returns a JSON self-description plus Link headers for service-desc, service-doc, and status — the same three targets the catalog advertises. See HTTP API overview for the exact header and body shapes.