Register an agent

Your agent can create its own ResearchAO connection. It will not receive research access until a human completes the subscription checkout.

Sequence

  1. Generate an Ed25519 key pair locally. Keep the private key secret.
  2. POST the public key to https://www.researchao.com/api/v1/agent-registrations.
  3. Sign the returned challenge with the private key.
  4. POST the signature to …/agent-registrations/{id}/verify.
  5. Request a Stripe Checkout URL via …/checkout.
  6. Present the Checkout URL to the human owner for payment.
  7. Poll registration status after payment.
  8. Exchange the temporary credential for the final API key via …/activate.
  9. Store the final credential as RESEARCHAO_API_KEY. Never print or commit it.

Endpoints

  • API base: https://www.researchao.com/api/v1
  • OpenAPI: /openapi.json
  • Research API (after activation): https://ulhmhgsixjphxtgxiqup.supabase.co/functions/v1/public-api
  • Current terms version: 2026-08-01

Instruction for an AI coding agent

Connect yourself to ResearchAO using the self-service agent registration API.

1. Generate an Ed25519 key pair locally.
2. Keep the private key secret.
3. Send only the public key to https://www.researchao.com/api/v1/agent-registrations.
4. Sign the returned challenge.
5. Request the Stripe Checkout URL.
6. Present the URL to me so I can authorise payment.
7. Poll the registration status after payment.
8. Exchange the temporary registration credential for the final ResearchAO API credential.
9. Store the final credential securely as RESEARCHAO_API_KEY.
10. Never print or commit the private key or API credential.

Human owners who manage agents in the browser should use /agents/sign-up and /agents/sign-in.
Machine agents never receive Supabase passwords and cannot access /app or /admin.

cURL example

curl -X POST https://www.researchao.com/api/v1/agent-registrations \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "agent_name": "Market Monitoring Agent",
    "requested_plan": "researcher",
    "public_key": { "kty": "OKP", "crv": "Ed25519", "x": "<base64url-public-key>" },
    "owner_contact_email": "owner@example.com",
    "terms_version": "2026-08-01"
  }'

TypeScript example

import { generateKeyPairSync, sign } from "node:crypto";

const { publicKey, privateKey } = generateKeyPairSync("ed25519");
const jwk = publicKey.export({ format: "jwk" });

const createRes = await fetch("https://www.researchao.com/api/v1/agent-registrations", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    agent_name: "My Agent",
    requested_plan: "researcher",
    public_key: { kty: jwk.kty, crv: jwk.crv, x: jwk.x },
    terms_version: "2026-08-01",
  }),
});
const created = await createRes.json();

const signature = sign(null, Buffer.from(created.challenge), privateKey)
  .toString("base64url");

const verifyRes = await fetch(
  `https://www.researchao.com/api/v1/agent-registrations/${created.registration_id}/verify`,
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ signature, algorithm: "Ed25519" }),
  },
);
const verified = await verifyRes.json();
// Present verified checkout URL from .../checkout to a human for payment.

Python example

# pip install httpx pynacl
import base64, uuid, httpx
from nacl.signing import SigningKey

sk = SigningKey.generate()
vk = sk.verify_key
x = base64.urlsafe_b64encode(bytes(vk)).rstrip(b"=").decode()

r = httpx.post(
  "https://www.researchao.com/api/v1/agent-registrations",
  headers={"Idempotency-Key": str(uuid.uuid4())},
  json={
    "agent_name": "My Agent",
    "requested_plan": "researcher",
    "public_key": {"kty": "OKP", "crv": "Ed25519", "x": x},
    "terms_version": "2026-08-01",
  },
)
created = r.json()
sig = base64.urlsafe_b64encode(sk.sign(created["challenge"].encode()).signature).rstrip(b"=").decode()
verified = httpx.post(
  f"https://www.researchao.com/api/v1/agent-registrations/{created['registration_id']}/verify",
  json={"signature": sig, "algorithm": "Ed25519"},
).json()
# Ask a human to open the Checkout URL from the checkout endpoint.

Important limits

  • No free trial credits for self-registering machines.
  • No final API credential until Stripe payment is confirmed by webhook.
  • Machine agents authenticate with Bearer API keys only — not browser login.
  • A human must authorise payment; agents cannot submit card details.