Start here
Everything an app or agent needs to use Obelisk is discoverable from a single request — no HTML scraping, no guesswork.
- The manifest:
GET /api?format=jsonreturns this entire contract as machine-readable JSON (this page is its human twin). - Standards auth: OpenID Connect discovery + JWKS. Use authorization-code + PKCE to obtain tokens.
- JSON where it carries a contract: account, organization, API-manifest, and changelog surfaces negotiate JSON; static editorial pages remain HTML and are listed here for discovery.
- Guides: Obelisk for agents · Integrate Obelisk · Works with your database.
Base URL https://obeliskgate.com · Version obelisk-api-1
Authentication
Each endpoint declares one of four auth levels — a small closed vocabulary you can branch on:
| Level | What it means |
|---|---|
| none | public |
| session | obelisk_session cookie OR body.token |
| bearer | OIDC access token (Authorization: Bearer) |
| owner | session + org owner/admin |
| ack-secret | x-obelisk-ecosystem-ack header for Studio ecosystem acknowledgements |
Bearer tokens are OIDC access tokens presented as Authorization: Bearer <token>. Session auth accepts the HttpOnly obelisk_session cookie (browser) or a token in the JSON body (server-to-server).
Discovery
Well-known entry points for clients and agents:
| What | URL |
|---|---|
openid_configuration | /.well-known/openid-configuration |
oauth_protected_resource | /.well-known/oauth-protected-resource |
jwks | /.well-known/jwks.json |
manifest | /api |
openapi | /openapi.json |
agent_interface | /.well-known/obelisk-agent |
saml_idp_metadata | /saml/idp/metadata |
health | /healthz |
transparency | /.well-known/obelisk-transparency.json |
security_txt | /.well-known/security.txt |
agents_json | /agents.json |
llms_txt | /.well-known/llms.txt |
changelog | /changelog?format=json |
studio_ecosystem | /studio/ecosystem/manifest.json |
Release history
Public-safe product history for humans and agents, bound to the revision serving it when deploy metadata is available.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /changelog | none | Human release history (HTML; versioned JSON with ?format=json or Accept: application/json). |
Authentication & OIDC
Passkey-first sign-in + OIDC.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /auth | none | The immersive sign-in/sign-up experience (HTML). |
| GET | /auth/assertion-options | none | Begin a (usernameless) passkey sign-in. query — user: optional account name |
| POST | /auth/assertion-verify | none | Complete a passkey sign-in; returns the session + where to go (home). body — user: optional; response: WebAuthn assertion; deviceId: optional |
| POST | /auth/verify-session | none | Server-to-server: validate a session token; returns { ok, identityId }. body — token: macaroon |
| GET | /auth/userinfo | bearer | OIDC userinfo for an access token. |
| POST | /auth/magic/request | none | Request an email magic-link (where enabled). body — email: string; dryRun: session-gated: return the link for the session's OWN verified email (founder at sensitive assurance: any email, receipted), don't send |
| GET | /auth/magic | none | W272 — the magic-link landing: consumes the token on the requesting device, then hands off (back to the relying party when one is waiting). query — token: string; return: validated relying-party return; project: display name |
| GET | /auth/authorize | none | OIDC authorization endpoint (PKCE S256). W272: response_mode=web_message posts the code to the opener page from a popup; prompt=none|login; a live session fast-paths to one tap. query — client_id: registered client; redirect_uri: exact registered callback; response_mode: query | web_message; prompt: none | login |
| POST | /auth/authorize/direct | none | W272 — the direct grant: a passkey assertion (or fresh registration) performed ON a registered relying party's page (WebAuthn related origins) becomes a one-time authorization code. CORS-scoped to the origin registered for client_id; PKCE S256; auth-throttled. body — client_id: string; redirect_uri: string; code_challenge: S256; code_challenge_method: S256; state: string; nonce: optional; assertion: { user?, response }; registration: { user, response, signupToken? } — account creation in place |
FedCM (browser-mediated sign-in)
W272 — Federated Credential Management: the browser shows the Obelisk account chooser inline on a registered relying party's page and hands it a signed ID token. No redirect, no popup, third-party-cookie-proof. Discovery anchor: /.well-known/web-identity.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /fedcm/config.json | none | Provider configuration (endpoints, branding, login_url). |
| GET | /fedcm/accounts | session | The signed-in person's account(s); requires Sec-Fetch-Dest: webidentity (sent only by the browser's FedCM machinery). |
| GET | /fedcm/client-metadata | none | Privacy/terms for a registered client; the request Origin must be registered to it. query — client_id: string |
| POST | /fedcm/assertion | session | Mint an ES256 ID token (aud = client_id, nonce-bound, truthful obelisk.assurance) for ONE registered client whose registered origin equals the request Origin. body — account_id: the session's identity; client_id: string; nonce: string |
| POST | /fedcm/disconnect | session | The person asked the browser to forget the link; acknowledged and receipted. body — client_id: string; account_hint: string |
Agent identity & proof
Register, key-bind, verify, publish, suspend, recover, and revoke AI agents, bots, automations, devices, and agent teams without claiming that behavior proves non-humanness.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /account/agents | session | Agent Studio (HTML): the owner's whole agent fleet — create, import, pair, and manage. |
| GET | /account/agents/:agentId | session | One agent's deep-linkable profile page (HTML): declared runtime facts, proof keys, evidence, delegation, and the full management card. Unknown or foreign ids 404 identically. |
| POST | /auth/agents/proof/enroll/begin | none | Begin device-style enrollment with an agent-generated public JWK. Returns a short owner code; private key material is refused. body — name: string; subjectKind: service_bot|automation|ai_agent|hybrid_agent|robot|device|agent_team|ephemeral_subagent; publicJwk: P-256/Ed25519 public JWK; visibility: private|unlisted|public |
| POST | /auth/agents/proof/enroll/approve | session | Passkey-authorized accountable party approves the pending agent; identity remains pending until the agent proves its key. body — enrollment_id: aen_... |
| POST | /auth/agents/proof/enroll/complete | none | Agent completes enrollment with a nonce-bound ES256 DPoP header. Returns its opaque Proof Link. body — enrollment_id: aen_... |
| POST | /auth/agents/proof/enroll/status | none | Poll bounded enrollment state without learning owner details. body — enrollment_id: aen_... |
| GET | /agent/:proof_id | none | Human-readable opt-in Proof Link. Private profiles 404; a URL is never a credential. |
| GET | /agent/:proof_id.json | none | Machine proof vector plus W3C VC and A2A projections. Claims remain independent and freshness-scoped. |
| POST | /api/agent-proof/challenge | none | Request a short-lived nonce for a visible active agent. body — proof_id: opaque id |
| POST | /api/agent-proof/verify | none | Verify current agent-key control with a one-use challenge and DPoP; returns a short-lived signed proof token when signing is available. body — proof_id: opaque id; challenge_id: apc_...; audience: optional verifier audience |
| POST | /api/agent-proof/run | none | Bind a client-built, commitment-only run proof to the active agent key and one-use nonce; returns a short-lived Obelisk-signed run token. Raw task/input/output stay client-side. body — proof_id: opaque id; challenge_id: purpose:run challenge; run_proof: obelisk-agent-run-proof-v1; audience: optional verifier audience |
| POST | /auth/agents/proof/visibility | session | Set profile privacy: private, unlisted, or public. Requires passkey-grade step-up. |
| POST | /auth/agents/proof/lifecycle | session | Suspend, resume, mark compromised, or revoke. Compromise/revoke cascades to agent-bound API keys. |
| POST | /auth/agents/proof/key-rotate | session | Rotate a public key. Normal rotation requires proof of the current key; compromise recovery rotates first and resumes only from suspended state. |
| POST | /auth/agents/proof/transfer/begin | session | Source owner suspends an agent and creates a short transfer code for one named target owner. |
| POST | /auth/agents/proof/transfer/accept | session | Named target owner accepts with a separate passkey and fresh public JWK. The identity stays suspended until target passkey + new agent key co-sign resume. |
| POST | /auth/agents/proof/dns-challenge | session | Get the stable _obelisk-agent TXT record that proves domain control for this agent. Publish it, then dns-verify. body — agent_id: agt_...; domain: example.com |
| POST | /auth/agents/proof/dns-verify | session | Resolve the TXT record and, on match, append domain-control evidence (channel_control leaves 'declared'). body — agent_id: agt_...; domain: example.com |
| POST | /auth/agents/proof/a2a-discover | session | Fetch an A2A agent card (SSRF-guarded, 128KB cap) and append descriptor-integrity evidence; fills declared a2aCardUrl/capabilities only where empty. body — agent_id: agt_...; url: https card URL |
| GET | /api/agent-trust/bundle | none | This authority's claim registry as a signed trust bundle (JWS via jwks_uri) for federation peers to pin and import. |
Account
The universal Obelisk account — one identity across every app.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /account | session | Your account page (HTML; JSON with ?format=json → the full profile). |
| GET | /account/export | session | Download a portable, secret-free copy of your account (JSON). |
| POST | /auth/profile | session | Set your display name. body — displayName: string |
| POST | /auth/account/rename | session | Change your username (old name stays a resolvable alias). body — newUsername: string |
| POST | /auth/preferences | session | Merge your preferences (theme/lang/contrast/motion/text/email). body — preferences: object |
| POST | /auth/passkeys/list | session | List your passkeys (no public keys). |
| POST | /auth/passkeys/rename | session | Rename a passkey. body — credId: string; label: string |
| POST | /auth/passkeys/remove | session | Remove a passkey (never the last one). body — credId: string |
| POST | /auth/passkeys/add-options | session | Begin adding a passkey to your account. |
| POST | /auth/passkeys/add-verify | session | Finish adding a passkey. body — response: WebAuthn attestation |
| POST | /auth/totp/setup | session | Begin TOTP setup (pending) → { secret, uri, qrSvg }. |
| POST | /auth/totp/confirm | session | Confirm + activate TOTP with a code. body — code: 6 digits |
| POST | /auth/totp/disable | session | Turn off TOTP. |
| POST | /auth/recovery/regenerate | session | Generate new backup codes (shown once). |
| POST | /auth/sessions/revoke | session | Revoke a session. body — identifier: string |
| POST | /auth/devices/revoke | session | Sign out a whole device — revokes every session it holds, then drops it from the device ledger. body — deviceId: string |
| POST | /auth/signout | session | Clear the session cookie. |
Organizations
Register a business/website for its own Obelisk Rating; manage a team.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| POST | /auth/orgs/create | session | Create an organization (you become owner). body — name: string; website: optional url |
| GET | /org/:slug | session | Org dashboard (HTML; JSON with ?format=json), member-gated. |
| POST | /org/:slug/scan | owner | Run an external security-posture scan → an Obelisk Rating. Scan a specific site with { siteId } or the primary by default. body — website: optional override; siteId: optional registered-site id |
| POST | /org/:slug/websites/add | owner | Add a website this org owns (first becomes primary). body — url: https url; label: optional |
| POST | /org/:slug/websites/remove | owner | Remove a registered site by id. body — siteId: string |
| POST | /org/:slug/websites/primary | owner | Promote a site to primary (the org headline rating tracks it). body — siteId: string |
| POST | /org/:slug/members/role | owner | Change a member's role. Owner-only for owner changes; the last owner can't be demoted. body — user: identityId; role: member|admin|owner |
| POST | /org/:slug/members/remove | owner | Remove a member. The last owner can never be removed. body — user: identityId |
| POST | /org/:slug/invite | owner | Create a role-scoped invite link. body — role: member|admin; email: optional |
| POST | /org/:slug/invite/revoke | owner | Revoke an invite. body — code: string |
| POST | /org/:slug/settings | owner | Rename the organization and/or set its description. The @slug handle is permanent; member profiles update automatically. body — name: string ≤80; description: optional string ≤280 |
| POST | /org/:slug/leave | session | Leave the organization (self-service). The last owner must transfer ownership first; your agents scoped to it become personal. |
| POST | /org/:slug/transfer-ownership | owner | Hand ownership to an existing member (passkey step-up required). You stay on as admin. body — user: identityId |
| GET | /join/:code | none | Accept an invite (signs you in first if needed). |
App registration
Self-serve OAuth/OIDC client registration — the developer portal (/account/apps) + its API.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /account/apps | session | The hosted app-registration portal (HTML): register apps, list, copy config, revoke. |
| POST | /auth/register | session | RFC 7591 dynamic client registration → { client_id, ... }. Optional { org } scopes the app to an organization you administer (else your personal tenant). Requires OBELISK_DCR=open + tenant enforcement. body — client_name: string; redirect_uris: https[]; obelisk_project_trust_profile: object; resource_uris: https[]; org: optional org slug |
| POST | /auth/apps/list | session | List apps in tenants you control (personal + admin orgs). Never returns a secret. |
| POST | /auth/apps/revoke | session | Revoke an app you own → status:revoked. body — clientId: string |
Per-project profile
The on-top layer: each project's own per-user profile slice, scoped to its OIDC client.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /api/project-profile | bearer | Read this project's profile slice for the token's user → { sub, project, profile }. |
| POST | /api/project-profile | bearer | Shallow-merge into this project's slice. body — profile: object |
Studio ecosystem
Studio-wide Obelisk rollout truth: declared, observed, required, migration cargo, and receipt-backed acknowledgement state.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /studio/ecosystem/manifest.json | none | Fleet manifest for Studio Ops: every registered project, required Obelisk versions, observed status, and migration state. |
| GET | /studio/ecosystem/projects/:slug | none | One project's ecosystem profile row from the canonical manifest. |
| GET | /studio/ecosystem/projects/:slug/migration | none | Content-addressed recipient-owned Ark migration cargo for one project. |
| POST | /studio/ecosystem/projects/:slug/ack | ack-secret | Record a recipient-owned migration acknowledgement. Requires x-obelisk-ecosystem-ack; writes an ecosystem-ack receipt. body — result: applied|already-current|rejected|blocked; cargoDigest: sha256:...; repoCommit: optional commit; evidence: optional object |
MCP tool server
Obelisk's public Model Context Protocol tool server — read-only trust tools over JSON-RPC 2.0, plus the plain catalogue.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| POST | /mcp | none | JSON-RPC 2.0 MCP endpoint (initialize, tools/list, tools/call). Read-only trust tools; stateful per-client rate limit. body — jsonrpc: the literal "2.0"; id: number|string; method: initialize | tools/list | tools/call; params: tools/call: { name, arguments } |
| GET | /mcp/tools | none | The plain JSON tool catalogue: every tool's name, description, and input schema. |
Receipt proof plane
Public receipt-by-hash lookup with sorted-Merkle inclusion proofs against the tamper-evident ledger. By-hash only — no enumeration.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /api/proof | none | Self-describing: how to verify, and where the transparency head to pin lives. |
| GET | /api/proof/:hash | none | Receipt lookup by 64-hex currentHash → chain position + a Merkle inclusion proof {leafHash, path, root}. Hash material only; never bodies, actors, or intents. |
SAML federation (Obelisk as your IdP)
Obelisk as the SAML 2.0 IdP for downstream platforms (GitHub, Slack, AWS, …).
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /saml/idp/metadata | none | IdP metadata: entity ID, SSO URL, and the pinned X.509 signing certificate — hand this URL to any SAML service provider. |
| GET | /saml/idp/sso | none | SAML sign-on endpoint: authenticates passkey-first, then auto-POSTs an RSA-SHA256-signed assertion to the SP's ACS. query — SAMLRequest: SP AuthnRequest (redirect binding) |
The verified seal
The verified “Secured by Obelisk Gate” seal + per-site verification pages.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| GET | /embed/seal.js | none | Drop-in loader: one script tag renders the live seal card on a relying party's page. |
| GET | /embed/v1/seal | none | The framed seal card itself (rendered live from obeliskgate.com; can't be forged). |
| GET | /verify/:rp | none | Public verification page for a relying party — anyone can confirm the seal is genuine. |
Website scan
The public website posture scan (the same engine behind the org Rating).
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| POST | /api/scan | none | Scan a public https:// website's security posture → a rating with concrete levers. SSRF-guarded, throttled per client. body — url: public https:// website (domains only) |
Contact
Reach the team.
| Method | Endpoint | Auth | What it does |
|---|---|---|---|
| POST | /api/contact | none | Send a message to the team (form-encoded: name, email, subject, message). Honeypot-protected, throttled. body — name: string; email: string; subject: string?; message: string |
Content negotiation & errors
Selected account, organization, API-manifest, and changelog surfaces return JSON with ?format=json or Accept: application/json; static editorial pages remain HTML.
Failures share one shape — { ok:false, reason:<code>, message?:<human> } on failures; HTTP status mirrors it. — and the HTTP status mirrors it, so a client can branch on either.
The machine-readable contract
This whole reference is generated from one manifest. Fetch it as JSON and an agent can discover and use every surface without reading a line of HTML:
curl -s https://obeliskgate.com/api?format=json
Building an agent? Start with Obelisk for agents, then the per-project profile contract. Questions → Help Center.