Routing Overview

This page summarizes the HTTP routes generated by the ActingWeb library when integrating with Flask or FastAPI, and how base paths are handled.

Integration

# Flask
from flask import Flask
from actingweb.interface import ActingWebApp

app = Flask(__name__)
ActingWebApp(...).with_web_ui().integrate_flask(app)

# FastAPI
from fastapi import FastAPI
api = FastAPI()
ActingWebApp(...).integrate_fastapi(api, templates_dir="templates")

Core Actor Routes

  • /: Root factory (create actor via web or API)

  • /<actor_id>: Actor root endpoint (see Actor Root Endpoint Behavior)

  • /<actor_id>/meta: Discovery metadata

  • /<actor_id>/properties: Get/update/delete properties

  • /<actor_id>/resources: Fetch external resources (read-only)

  • /<actor_id>/methods: RPC-style methods (GET returns metadata, POST invokes)

  • /<actor_id>/actions: Side-effecting actions (GET returns metadata, POST invokes)

  • /<actor_id>/trust: Trust relationships and permissions

  • /<actor_id>/subscriptions: Subscriptions to peer updates

  • /<actor_id>/callbacks: Inbound callbacks (peer/webhooks)

Web UI Routes (when with_web_ui(True))

  • /<actor_id>/www: Dashboard

  • /<actor_id>/www/properties and /<actor_id>/www/properties/<name>

  • /<actor_id>/www/trust and /<actor_id>/www/trust/new

  • /<actor_id>/www/init: Initialization helpers

Authentication

  • /oauth: OAuth2 callback and session handling (when configured via with_oauth)

  • Web UI and protected routes enforce authentication according to configuration (basic or OAuth2)

Base Paths

  • Deployments under a base path (e.g., /my-server) are supported by both integrations.

  • Templates receive actor_root and actor_www to generate correct links regardless of base path.

  • Avoid relative links in templates; prefer the provided variables.

Actor Root Endpoint Behavior

The actor root endpoint (GET /<actor_id>) supports content negotiation based on the Accept header and authentication status.

API Clients

API clients (sending Accept: application/json or no specific Accept header) receive JSON with actor information:

{
    "id": "actor-id",
    "creator": "user@example.com",
    "passphrase": "actor-passphrase",
    "trustee_root": "optional-trustee-root"
}

If not authenticated, API clients receive a 401 or 403 error response.

Browser Redirect Behavior

Browsers (sending Accept: text/html) are redirected based on authentication status and the with_web_ui() configuration:

Browser Redirect Matrix

Authenticated

with_web_ui()

Redirect Target

Use Case

No

Any

/login

Consistent login experience

Yes

True

/<actor_id>/www

Traditional server-rendered UI

Yes

False

/<actor_id>/app

Single Page Applications (SPAs)

Key behaviors:

  1. Unauthenticated browsers always redirect to /login, providing a consistent login experience rather than triggering OAuth directly.

  2. Authenticated browsers redirect to the appropriate UI endpoint based on whether the traditional web UI (/www) or SPA mode (/app) is configured.

Note

“Authenticated” for the browser UI means an OAuth2 browser session. HTTP Basic auth (creator + passphrase) authenticates the JSON API (/properties, /trust, /actions, …) but is not a browser session: a Basic-auth request to /www is still redirected to /login / OAuth. To view the web UI you must complete the OAuth flow, so a working OAuth provider must be configured (with_oauth(...)).

OAuth Callback Redirect Behavior

After successful OAuth authentication, the callback handler redirects users to their UI endpoint based on the same with_web_ui() configuration:

Post-OAuth Redirect

with_web_ui()

Redirect Target

Use Case

True

/<actor_id>/www

Traditional web UI with server templates

False

/<actor_id>/app

SPA that handles its own routing

This ensures users land on the correct UI after logging in, without applications needing to override OAuth callback behavior.

SPA Route Requirements

When using with_web_ui(False) for SPA mode, your application must provide:

  1. ``/login`` - Login page with OAuth buttons (served by your SPA)

  2. ``/<actor_id>/app`` - Main SPA entry point for authenticated users

Example SPA route registration (FastAPI):

@app.get("/login", response_class=HTMLResponse)
async def login_page(request: Request):
    return HTMLResponse(content=render_spa_shell())

@app.get("/{actor_id}/app", response_class=HTMLResponse)
@app.get("/{actor_id}/app/{path:path}", response_class=HTMLResponse)
async def spa_app(actor_id: str, request: Request, path: str = ""):
    return HTMLResponse(content=render_spa_shell(actor_id=actor_id))

The SPA shell is served unconditionally - the JavaScript application handles authentication state and redirects unauthenticated users to /login.

Configuration Examples

Traditional Web UI (server-rendered templates):

app = ActingWebApp(...)
    .with_web_ui(enable=True)
    .with_oauth(...)

# Browsers → /<actor_id>/www (ActingWeb provides templates)
# OAuth callback → /<actor_id>/www

Single Page Application:

app = ActingWebApp(...)
    .with_web_ui(enable=False)  # Disable server templates
    .with_oauth(...)

# Browsers → /<actor_id>/app (your SPA handles rendering)
# OAuth callback → /<actor_id>/app
# You must provide /login and /<actor_id>/app routes

OAuth Provider Endpoints

  • GET /oauth/callback — standard callback for Google/GitHub (query-mode).

  • POST /oauth/callback/apple — Sign in with Apple callback. Apple uses response_mode=form_post (a cross-site POST), protected by a server-side single-use state nonce. See Sign in with Apple.

  • POST /oauth/spa/token supports these grant_type values:

    • authorization_code — mobile code+PKCE exchange (existing). PKCE (code_verifier) is required for -mobile/-native providers or custom-scheme redirect_uri values.

    • refresh_token — refresh with rotation (existing).

    • urn:ietf:params:oauth:grant-type:jwt-bearer — native id_token (assertion + nonce + provider) exchange for an ActingWeb session.

    • mobile_ticket — redeem an opaque deep-link ticket for a server-side code exchange (Apple-on-Android, GitHub mobile). apple_mobile_ticket is a backward-compatible alias.

MCP OAuth2 Server Endpoints

ActingWeb is the OAuth2 authorization server for MCP clients (enabled with with_mcp()). Errors follow RFC 6749 §5.2 and RFC 7591 §3.2.2: the body is {"error": <code>, "error_description": ...} with the real code.

  • POST /oauth/register — dynamic client registration (RFC 7591). 201 on success. token_endpoint_auth_method may be none (public client, no client_secret in the response), client_secret_post (default) or client_secret_basic (the response carries client_secret and client_secret_expires_at: 0). Anything else, or a client_name that is empty after sanitising, is 400 invalid_client_metadata.

  • GET /oauth/authorize — shows the sign-in form; POST /oauth/authorize — the form submission, which redirects to the chosen provider. code_challenge with code_challenge_method=S256 binds the code; plain or a missing method is 400 invalid_request, and a public client must send a challenge. Errors on this endpoint are pre-redirect validation failures.

  • POST /oauth/token — authorization_code, refresh_token and client_credentials grants. Client credentials in the body or an Authorization: Basic header (a body client_id that differs from the header’s is invalid_request). Errors: 400 invalid_request, invalid_grant (dead, expired, reused or foreign code or refresh token), unsupported_grant_type, unauthorized_client (a public client asking for client_credentials), invalid_scope; 401 invalid_client with WWW-Authenticate; 500 server_error (including a token-store fault). Every refresh returns a new refresh_token; the presented one is single-use.

  • /mcp answers 401 invalid_token without a valid bearer token and 503 with Retry-After when the token store cannot be read.

Notes