Steward API

Read-only HTTP surface for external integrations. Authenticate via a personal access token; queries scoped at the token-mint boundary.

Authentication

Mint a token from /app/account (the API tokens panel). The plaintext is shown once — copy it then; the server stores only a SHA-256 hash and you can't view it again. If you lose it, revoke and create a new one.

Pass the token on every request:

Authorization: Bearer stwd_pat_<your-token>

Tokens are user-scoped: a token acts as the user who minted it. Revoking the user's account revokes all their tokens via FK cascade.

Scopes

Scopes are assigned at mint time and can't be elevated. Four read scopes are wired today; evaluations:run is reserved (writes stay session-only until the billing/quota intersection is designed — see "Write RPCs" below).

ScopeGrantsStatus
cla:readCLA signature status for a repo.Wired
evaluations:readEvaluation job results.Wired
repos:readRepo governance + metadata.Wired
account:readCaller's own identity + resolved permissions (MeService.Get).Wired
evaluations:runTrigger evaluations.Reserved

Rate limits

60 requests/minute per token. Over-cap requests return 429 Too Many Requests with a Retry-After header (seconds until the next per-minute bucket starts). The counter is per-token, not per-user — a user with multiple tokens gets multiple budgets.

RPCs

All RPCs are POST to https://steward-dev.ai/api/<service>.<Service>/<Method> with JSON bodies. Four read-only RPCs ship today.

MeService.Get — requires account:read

Returns the token owner's identity (login, email, avatar) plus a permissions map for FE-relevant capability flags. Use this to validate a token + discover what surfaces the user can reach before calling the data RPCs.

curl -X POST https://steward-dev.ai/api/steward.api.v1.MeService/Get \
  -H "Authorization: Bearer stwd_pat_..." \
  -H "Content-Type: application/json" \
  -d '{}'

ClaService.Get — requires cla:read

Returns the CLA configuration and signature state for a repo. Use this to gate a PR check from a third-party CI runner.

curl -X POST https://steward-dev.ai/api/steward.api.v1.ClaService/Get \
  -H "Authorization: Bearer stwd_pat_..." \
  -H "Content-Type: application/json" \
  -d '{"repo_id": "<repo-uuid>"}'

EvaluationsService.Get — requires evaluations:read

Returns one evaluation job by id, including the report JSON + markdown. Use this to poll an evaluation triggered by a webhook.

curl -X POST https://steward-dev.ai/api/steward.api.v1.EvaluationsService/Get \
  -H "Authorization: Bearer stwd_pat_..." \
  -H "Content-Type: application/json" \
  -d '{"id": "<evaluation-uuid>"}'

GovernanceService.GetSections — requires repos:read

Returns the parsed top-level sections of a repo's .steward/governance.pxf. Use this to read policy without parsing the raw file yourself. For files that extend a preset, the response also carries the resolution: preset (the version pin), resolved_sections (the EFFECTIVE config the judge actually runs, section by section), overridden_sections (which top-level sections the repo's own file populates), available_presets, and resolve_error (the loader's message when the file wouldn't load). Integrators reading policy should consume resolved_sections — the raw sections of a preset-pinned file are just the overrides.

curl -X POST https://steward-dev.ai/api/steward.api.v1.GovernanceService/GetSections \
  -H "Authorization: Bearer stwd_pat_..." \
  -H "Content-Type: application/json" \
  -d '{"repo_id": "<repo-uuid>"}'

GovernanceService.PreviewPresetChange — requires repos:read

Read-only what-if: resolves the repo's current governance file as if its preset pin were the candidate you pass (one of available_presets from GetSections). Returns the candidate's resolved_sections in the same shape, so you can diff effective policy across preset versions without writing anything. Unknown candidates come back in resolve_error, not as a transport error.

curl -X POST https://steward-dev.ai/api/steward.api.v1.GovernanceService/PreviewPresetChange \
  -H "Authorization: Bearer stwd_pat_..." \
  -H "Content-Type: application/json" \
  -d '{"repo_id": "<repo-uuid>", "preset": "welcoming/v2"}'

Errors

  • 401 Unauthorized — missing, malformed, revoked, or unknown token.
  • 429 Too Many Requests — rate limit. Honour Retry-After.
  • Envelope PERMISSION_DENIED — token authenticated but missing the scope the RPC requires.
  • Envelope NOT_FOUND — the resource isn't visible to the token's owner.

Audit trail

Token mint and revoke emit audit events. Token use emits the first call per hour per token (dedup'd to keep the audit log readable). All events surface in your retention bundle export at /app/audit.

Write RPCs

Token auth is read-only by design. CreateEvaluation, GovernanceUpdateSection, and the other write RPCs require an interactive browser session because each one intersects with the user's monthly credit budget — a token-driven write loop could burn a user's quota faster than their dashboard can warn them. Drive writes from the /app surface; reach for an API token when a CI runner needs to poll status from outside the browser.

Outbound webhooks (Steward pushing events to your service) are not implemented — poll the read RPCs at your cadence. OpenAPI / gRPC reflection isn't published; the curl examples above + this scope table are the contract.