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
- Generate an Ed25519 key pair locally. Keep the private key secret.
- POST the public key to
https://www.researchao.com/api/v1/agent-registrations. - Sign the returned challenge with the private key.
- POST the signature to
…/agent-registrations/{id}/verify. - Request a Stripe Checkout URL via
…/checkout. - Present the Checkout URL to the human owner for payment.
- Poll registration status after payment.
- Exchange the temporary credential for the final API key via
…/activate. - 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.