Skip to Content
API referencePOST /v1/register
Open in Claude Open in ChatGPT

POST /v1/register

Agent self-registration. No authentication. The agent sends its own RSA public key. Nothing takes effect until the owner approves with a passkey.

With a pairing code (paste-prompt onboarding)

POST /v1/register HTTP/1.1 Host: api.agentvalet.ai Content-Type: application/json { "pairing_code": "pc_7Kq2mX9pLw4Zr8Tn3Vb6Yc", "agent_name": "Instinct", "public_key_pem": "-----BEGIN PUBLIC KEY-----\n…\n-----END PUBLIC KEY-----" }

The pairing code comes from a prompt the owner generated in AgentValet. It identifies the owner and fixes the agent’s name and any starting grants, so owner_id and requested_scopes are not sent. public_key_pem is required: an RSA key of at least 2048 bits, SPKI PEM.

Without a pairing code (unsolicited)

{ "owner_id": "<owner uuid>", "agent_name": "my-agent", "requested_scopes": [], "public_key_pem": "…" }

Flagged as unsolicited on the owner’s approval page, and limited to 5 per owner per hour.

Response: 202

{ "data": { "status": "pending_approval", "registration_token": "…", "poll_url": "/v1/register/status/…", "approve_url": "https://app.agentvalet.ai/m/registrations/…#v=…", "key_fingerprint": "3F9A-11C0-8B2E-7D41", "expires_in": 86400, "pairing_matched": true, "keypair_source": "client" }, "_meta": { … } }
  • approve_url: send it to the user. It opens the approval page; approving needs their passkey.
  • key_fingerprint: send it to the user too. The approval page shows the same value, so they can confirm the registration is yours.
  • poll_url: GET it on https://api.agentvalet.ai until status is approved, rejected or expired. On approved it returns agent_id and owner_id.

Errors

StatuserrorMeaning
400invalid_public_keyNot an RSA ≥ 2048-bit SPKI public key (or a private key was sent)
400public_key_requiredpairing_code sent without public_key_pem
400invalid_pairing_codeMalformed code
404pairing_not_foundUnknown code
409pairing_usedThe code was already used. The owner is notified
410pairing_expiredAsk the user to generate a new prompt
429too_many_unsolicited_registrationsUse a pairing code

After approval

Authenticate every request with Authorization: Bearer <JWT>, a fresh RS256 JWT signed with your private key, with claims {agent_id, owner_id, iat, exp} and exp = iat + 60. Tokens for assistant agents that would live longer than 300 seconds are refused with 401 jwt_lifetime_exceeded.

Then call GET /v1/agents/me, GET /v1/agent/permissions (each platform has apiHints) and POST /v1/actions. For an audit, GET /v1/agents/me/audit-link returns a link for the user.

Last updated on