Quickstart
Any account can create a free API key. Samples and discovery need no key at all; paid data needs a subscription to that listing.
Replace your-listing-slug / {slug} with a slug from the catalog or GET /api/catalog.
?sample=1 returns { sample: true, data, listing, discovery } when the listing publishes a sample. ?discovery=1 returns machine metadata for any listing. Neither needs a key.
curl
curl -s "https://intelclaw.org/api/v1/resources/{slug}?sample=1"Python
import requests
BASE = "https://intelclaw.org"
SLUG = "your-listing-slug"
r = requests.get(f"{BASE}/api/v1/resources/{SLUG}", params={"sample": "1"}, timeout=30)
r.raise_for_status()
print(r.json()["data"])TypeScript
const BASE = "https://intelclaw.org";
const SLUG = "your-listing-slug";
const res = await fetch(`${BASE}/api/v1/resources/${SLUG}?sample=1`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data } = await res.json();
console.log(data);MCP (tools/list, no key)
curl -s "https://intelclaw.org/api/mcp" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Keys are free and start with im_. The raw key is shown once; only its hash is stored. Up to 20 active keys per account.
Dashboard
1. Sign up: https://intelclaw.org/sign-up
2. Create a key: https://intelclaw.org/dashboard/keys
3. Copy it now. The key (im_…) is shown once.curl (signed-in session)
# POST /api/keys needs a signed-in browser session, not an API key.
# Copy the session cookie from your browser to run this from a terminal.
curl -s -X POST "https://intelclaw.org/api/keys" \
-H "Content-Type: application/json" \
-H "Cookie: <your session cookie>" \
-d '{"name":"my-agent"}'
# → {"id":"…","name":"my-agent","keyPrefix":"…","apiKey":"im_…"}Subscribe at /checkout?listing={slug} first. A paid call without a key returns HTTP 401. A key whose account has no subscription to that listing returns HTTP 403. A paid response is { ok, authType, listing, data, meta }.
curl
# 401 without a key, 403 until your account subscribes to {slug}
curl -s "https://intelclaw.org/api/v1/resources/{slug}" \
-H "Authorization: Bearer $INTELCLAW_KEY"Python
import os, time, requests
BASE = "https://intelclaw.org"
SLUG = "your-listing-slug"
headers = {"Authorization": f"Bearer {os.environ['INTELCLAW_KEY']}"}
r = requests.get(f"{BASE}/api/v1/resources/{SLUG}", headers=headers, timeout=60)
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", "60")))
r = requests.get(f"{BASE}/api/v1/resources/{SLUG}", headers=headers, timeout=60)
if r.status_code in (401, 403):
raise SystemExit(f"{r.status_code}: {r.json().get('error')}")
r.raise_for_status()
body = r.json()
print(body["data"], body["meta"]["bodySha256"])TypeScript
const BASE = "https://intelclaw.org";
const SLUG = "your-listing-slug";
const res = await fetch(`${BASE}/api/v1/resources/${SLUG}`, {
headers: { Authorization: `Bearer ${process.env.INTELCLAW_KEY}` },
});
if (res.status === 401 || res.status === 403) {
throw new Error(`${res.status}: ${(await res.json()).error}`);
}
if (res.status === 429) {
throw new Error(`Rate limited. Retry after ${res.headers.get("Retry-After")}s`);
}
const { data, meta } = await res.json();
console.log(data, meta.bodySha256);MCP (tools/call)
curl -s "https://intelclaw.org/api/mcp" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $INTELCLAW_KEY" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"<tool name from tools/list>","arguments":{}}}'
# Unpaid: error.code -32001 with error.data.httpStatus 401 or 403Status handling: errors and limits.
Every paid response carries meta.bodySha256, the SHA-256 of JSON.stringify(data). When receipt signing is enabled, paid responses also carry meta.receiptPayload and a base64 Ed25519 meta.receiptSignature, and /.well-known/receipt-key serves the public key. Signing is not enabled on this deployment right now, so that endpoint returns 404; the body hash is still there.
curl (public key)
curl -s "https://intelclaw.org/.well-known/receipt-key"
# → {"alg":"ed25519","publicKey":"<64 hex chars>"} (404 when signing is off)Python
import base64, requests
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
BASE = "https://intelclaw.org"
meta = body["meta"] # from the paid call above
pub_hex = requests.get(f"{BASE}/.well-known/receipt-key", timeout=30).json()["publicKey"]
pub = Ed25519PublicKey.from_public_bytes(bytes.fromhex(pub_hex))
# Raises cryptography.exceptions.InvalidSignature if the receipt was altered
pub.verify(base64.b64decode(meta["receiptSignature"]), meta["receiptPayload"].encode("utf-8"))
# The payload's body: line must equal meta["bodySha256"]
assert f"body:{meta['bodySha256']}" in meta["receiptPayload"].splitlines()TypeScript (Node)
import { createHash, createPublicKey, verify } from "node:crypto";
const BASE = "https://intelclaw.org";
const { publicKey } = await (await fetch(`${BASE}/.well-known/receipt-key`)).json();
const key = createPublicKey({
key: Buffer.concat([Buffer.from("302a300506032b6570032100", "hex"), Buffer.from(publicKey, "hex")]),
format: "der",
type: "spki",
});
const ok = verify(
null,
Buffer.from(meta.receiptPayload, "utf8"),
key,
Buffer.from(meta.receiptSignature, "base64"),
);
// bodySha256 is sha256 of JSON.stringify(data)
const bodyOk = createHash("sha256").update(JSON.stringify(data)).digest("hex") === meta.bodySha256;
console.log({ ok, bodyOk });Recomputing the hash in Python can differ from JavaScript on number formatting; the TypeScript check matches the server byte for byte.