From 922493d7ba8e4c20ef4ee85b2294a026e4cca3d9 Mon Sep 17 00:00:00 2001 From: RapidPoseidon Date: Fri, 26 Jun 2026 13:38:57 +0000 Subject: [PATCH 1/2] feat(docs): publish OpenAPI spec, auth docs and developer portal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second pass on agent-readiness (orank 45/100). The remaining Access gaps were all about resources that exist but aren't surfaced on docs.rapidata.ai: - OpenAPI: the API already serves public per-service specs at api.rapidata.ai//openapi/v1.json. Publish the combined spec at the predictable /openapi.json, rewriting the internal rabbitdata.ch host to the public rapidata.ai one. Every operation already declares its OpenIdConnect scopes, so this also advertises OAuth 2.0 + scoped permissions machine-readably. - Auth: add an Authentication page documenting the real OAuth 2.0 / OIDC client-credentials flow (auth.rapidata.ai), scopes and token endpoint, and link the live discovery document. - Developer portal: add a /developers landing page aggregating the SDK, OpenAPI spec, auth, quickstart, API reference and agent skill. Deliberately not done: OAuth 2.0 is already implemented (not a docs change), so nothing new is "implemented" here — only documented. No fake /.well-known/oauth-authorization-server is served from the docs origin, since that metadata must be served by the issuer (auth.rapidata.ai) to be valid; we link the real openid-configuration instead. Co-Authored-By: Claude Opus 4.8 Co-Authored-By: lino --- .github/workflows/deploy_doc.yml | 12 +++-- docs/authentication.md | 63 +++++++++++++++++++++++++ mkdocs.yml | 2 + scripts/build_public_openapi.py | 58 +++++++++++++++++++++++ site_root/developers/index.html | 80 ++++++++++++++++++++++++++++++++ site_root/index.html | 16 ++++++- site_root/llms.txt | 19 ++++++-- 7 files changed, 239 insertions(+), 11 deletions(-) create mode 100644 docs/authentication.md create mode 100644 scripts/build_public_openapi.py create mode 100644 site_root/developers/index.html diff --git a/.github/workflows/deploy_doc.yml b/.github/workflows/deploy_doc.yml index aadf72c55..b9aa8c01e 100644 --- a/.github/workflows/deploy_doc.yml +++ b/.github/workflows/deploy_doc.yml @@ -68,17 +68,19 @@ jobs: set -euo pipefail git fetch origin gh-pages git worktree add ghpages gh-pages - cp site_root/robots.txt ghpages/robots.txt - cp site_root/llms.txt ghpages/llms.txt - cp site_root/index.html ghpages/index.html + # Static root files (recursively, to include developers/index.html). + cp -R site_root/. ghpages/ + rm -f ghpages/README.md if [ -f ghpages/latest/llms-full.txt ]; then cp ghpages/latest/llms-full.txt ghpages/llms-full.txt fi + # Public OpenAPI document, served at the predictable /openapi.json. + python scripts/build_public_openapi.py ghpages/openapi.json cd ghpages - git add robots.txt llms.txt index.html llms-full.txt + git add robots.txt llms.txt index.html llms-full.txt openapi.json developers if git diff --cached --quiet; then echo "Site-root files already up to date." else - git commit -m "chore(docs): publish root llms.txt, robots.txt and landing page" + git commit -m "chore(docs): publish root llms.txt, robots.txt, openapi.json, developer portal" git push origin gh-pages fi diff --git a/docs/authentication.md b/docs/authentication.md new file mode 100644 index 000000000..c58ceed1c --- /dev/null +++ b/docs/authentication.md @@ -0,0 +1,63 @@ +# Authentication + +The Rapidata API uses **OAuth 2.0 / OpenID Connect**. The authorization server is +`https://auth.rapidata.ai`, and its discovery document is published at +[`/.well-known/openid-configuration`](https://auth.rapidata.ai/.well-known/openid-configuration). + +For programmatic access (the SDK, scripts, agents) you authenticate with the +**client credentials** grant using a client ID and secret. + +## Get credentials + +Create a client ID and secret under [Rapidata Settings → Tokens](https://app.rapidata.ai/settings/tokens). + +## With the SDK + +The SDK performs the token exchange for you. Pass the credentials directly: + +```python +from rapidata import RapidataClient + +client = RapidataClient( + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +``` + +or set `RAPIDATA_CLIENT_ID` and `RAPIDATA_CLIENT_SECRET` in the environment +(useful for headless or containerised runs) and construct `RapidataClient()` +with no arguments. On a workstation, calling `RapidataClient()` with no +credentials instead opens a browser login once and caches the token in +`~/.config/rapidata/credentials.json`. + +## Direct token request + +To call the API without the SDK, request a token from the token endpoint and +send it as a bearer token: + +```bash +curl -X POST https://auth.rapidata.ai/connect/token \ + -d grant_type=client_credentials \ + -d client_id=YOUR_CLIENT_ID \ + -d client_secret=YOUR_CLIENT_SECRET \ + -d scope="openid email roles" + +# → {"access_token": "...", "token_type": "Bearer", "expires_in": 3600} + +curl https://api.rapidata.ai/order/openapi/v1.json \ + -H "Authorization: Bearer ACCESS_TOKEN" +``` + +## Scopes + +Tokens are scoped. The SDK requests `openid roles email` by default, which is +sufficient for all SDK operations. Request only the scopes you need. Every +endpoint in the [OpenAPI specification](https://docs.rapidata.ai/openapi.json) +declares the scopes it requires under its `OpenIdConnect` security scheme. + +| Scope | Grants | +|-------|--------| +| `openid` | Required for OIDC; identifies the token subject. | +| `email` | Access to the account email claim. | +| `roles` | The account's role claims, which gate API operations. | +| `offline_access` | A refresh token for long-lived sessions. | diff --git a/mkdocs.yml b/mkdocs.yml index 9a3e2117d..92b3ef387 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -58,6 +58,7 @@ plugins: Guides: - starting_page.md - quickstart.md + - authentication.md - audiences.md - signals.md - job_definition_parameters.md @@ -120,6 +121,7 @@ nav: - Guides: - Overview: starting_page.md - Quick Start: quickstart.md + - Authentication: authentication.md - Custom Audiences: audiences.md - Signals: signals.md - Parameter Reference: job_definition_parameters.md diff --git a/scripts/build_public_openapi.py b/scripts/build_public_openapi.py new file mode 100644 index 000000000..d6758cc32 --- /dev/null +++ b/scripts/build_public_openapi.py @@ -0,0 +1,58 @@ +"""Produce the public OpenAPI document served at docs.rapidata.ai/openapi.json. + +The combined spec under ``openapi/schemas/`` is the contract the SDK is generated +from, but it carries the internal ``rabbitdata.ch`` host and an inaccurate title. +Rewrite those to the public ``rapidata.ai`` host (which already serves the same +per-service specs and OIDC discovery document) so agents get an accurate surface. + +Usage: python scripts/build_public_openapi.py +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +SOURCE = ( + Path(__file__).resolve().parent.parent + / "openapi" + / "schemas" + / "rapidata.filtered.openapi.json" +) + + +def build() -> dict: + spec = json.loads(SOURCE.read_text(encoding="utf-8")) + + # The internal build host is the only thing standing between this and the + # live public spec at api.rapidata.ai — rewrite both the server and the + # OIDC discovery URL in the security scheme. + serialized = json.dumps(spec).replace("rabbitdata.ch", "rapidata.ai") + spec = json.loads(serialized) + + spec["servers"] = [{"url": "https://api.rapidata.ai/"}] + info = spec.setdefault("info", {}) + info["title"] = "Rapidata API" + info.setdefault( + "description", + "Public Rapidata API. Authentication uses OAuth 2.0 (OpenID Connect) — " + "see https://docs.rapidata.ai/latest/authentication/.", + ) + return spec + + +def main() -> None: + if len(sys.argv) != 2: + print(__doc__) + raise SystemExit(2) + out = Path(sys.argv[1]) + spec = build() + out.write_text(json.dumps(spec), encoding="utf-8") + print( + f"Wrote {out} ({out.stat().st_size} bytes, {len(spec.get('paths', {}))} paths)" + ) + + +if __name__ == "__main__": + main() diff --git a/site_root/developers/index.html b/site_root/developers/index.html new file mode 100644 index 000000000..ce3b651c0 --- /dev/null +++ b/site_root/developers/index.html @@ -0,0 +1,80 @@ + + + + + + Rapidata Developer Portal + + + + + + + + + + + + +
+

Rapidata Developer Portal

+

+ Rapidata provides human feedback at scale — crowd-sourced labeling, model + evaluation, ranking, and preference data. Integrate with the Python SDK or + directly against the OAuth 2.0 secured REST API. +

+ +

Get started

+ + +

Reference

+ + +

Guides & examples

+ + +

For AI agents

+ + +

Source

+ +
+ + diff --git a/site_root/index.html b/site_root/index.html index 53c82696c..0bb2b9271 100644 --- a/site_root/index.html +++ b/site_root/index.html @@ -49,6 +49,18 @@ "softwareHelp": "https://docs.rapidata.ai/latest/quickstart/", "publisher": { "@id": "https://www.rapidata.ai/#organization" }, "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" } + }, + { + "@type": "WebAPI", + "name": "Rapidata API", + "description": "OAuth 2.0 secured REST API for requesting human feedback at scale.", + "documentation": "https://docs.rapidata.ai/developers/", + "provider": { "@id": "https://www.rapidata.ai/#organization" }, + "EntryPoint": { + "@type": "EntryPoint", + "urlTemplate": "https://api.rapidata.ai/", + "contentType": "application/json" + } } ] } @@ -73,9 +85,11 @@

Rapidata Python SDK

Install with pip install rapidata, then authenticate with a token from app.rapidata.ai/settings/tokens.

    +
  • Developer portal
  • Documentation home
  • Quick Start
  • -
  • Overview & core concepts
  • +
  • Authentication (OAuth 2.0)
  • +
  • OpenAPI specification
  • API reference
  • Use Rapidata from your AI agent
  • llms.txt · llms-full.txt
  • diff --git a/site_root/llms.txt b/site_root/llms.txt index d2b80e284..4caad3d48 100644 --- a/site_root/llms.txt +++ b/site_root/llms.txt @@ -5,9 +5,15 @@ > people. The supported way to access it programmatically is the Rapidata > Python SDK, documented on this site (docs.rapidata.ai). -Integrate via the Python SDK (`pip install rapidata`). Authenticate either with -an interactive browser login on first run, or with a client ID/secret token -created at https://app.rapidata.ai/settings/tokens. +Integrate via the Python SDK (`pip install rapidata`). The API is OAuth 2.0 / +OpenID Connect secured; authenticate with a client ID/secret created at +https://app.rapidata.ai/settings/tokens, or via interactive browser login on +first run. + +- Developer portal: https://docs.rapidata.ai/developers/ +- OpenAPI specification: https://docs.rapidata.ai/openapi.json +- Authentication (OAuth 2.0): https://docs.rapidata.ai/latest/authentication/ +- OpenID Connect discovery: https://auth.rapidata.ai/.well-known/openid-configuration ## Guides @@ -37,10 +43,13 @@ created at https://app.rapidata.ai/settings/tokens. - [Getting Started](https://docs.rapidata.ai/latest/mri/) - [Advanced](https://docs.rapidata.ai/latest/mri_advanced/) -## AI agents & API +## API & AI agents -- [Use Rapidata from your AI agent](https://docs.rapidata.ai/latest/ai_agents/): an official skill that teaches coding agents (Claude Code, Cursor, Copilot, and others) to write Rapidata integrations +- [Developer portal](https://docs.rapidata.ai/developers/): all developer resources in one place +- [OpenAPI specification](https://docs.rapidata.ai/openapi.json): the full API surface (OAuth 2.0 / OpenID Connect) +- [Authentication](https://docs.rapidata.ai/latest/authentication/): OAuth 2.0 client-credentials flow, scopes, token endpoint - [API reference](https://docs.rapidata.ai/latest/api/): the `RapidataClient` class and its managers +- [Use Rapidata from your AI agent](https://docs.rapidata.ai/latest/ai_agents/): an official skill that teaches coding agents (Claude Code, Cursor, Copilot, and others) to write Rapidata integrations ## Access From 258b1912df82748573ff4554ec93eb171b87e713 Mon Sep 17 00:00:00 2001 From: RapidPoseidon Date: Fri, 26 Jun 2026 14:14:10 +0000 Subject: [PATCH 2/2] refactor(ci): copy site-root files explicitly instead of cp -R + rm The previous cp -R copied all of site_root/ (including the repo-only README.md) then deleted the README afterwards. Switch to an explicit allowlist so repo-only files can never leak onto the published site and no delete is needed. Co-Authored-By: Claude Opus 4.8 Co-Authored-By: lino --- .github/workflows/deploy_doc.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy_doc.yml b/.github/workflows/deploy_doc.yml index b9aa8c01e..7b6cdbb65 100644 --- a/.github/workflows/deploy_doc.yml +++ b/.github/workflows/deploy_doc.yml @@ -68,9 +68,12 @@ jobs: set -euo pipefail git fetch origin gh-pages git worktree add ghpages gh-pages - # Static root files (recursively, to include developers/index.html). - cp -R site_root/. ghpages/ - rm -f ghpages/README.md + # Static root files. Copy each published artifact explicitly so repo-only + # files in site_root/ (e.g. README.md) never leak onto the live site. + cp site_root/robots.txt ghpages/robots.txt + cp site_root/llms.txt ghpages/llms.txt + cp site_root/index.html ghpages/index.html + cp -R site_root/developers ghpages/developers if [ -f ghpages/latest/llms-full.txt ]; then cp ghpages/latest/llms-full.txt ghpages/llms-full.txt fi