Outpost API

Host SPAs and static HTML under short URLs (/p/<id>) with three flavors of authentication and a built-in MCP server. This reference covers every HTTP endpoint the service exposes.

Base URL. Production: https://outpost.click. Development: http://localhost:8000 (started with uvicorn app.main:app --reload).

Quick start

1. Get an API token

Log in at /login, create a token at /tokens. The full token is shown once; save it.

2. Create a page from a ZIP

curl -X POST https://outpost.click/api/pages \
  -H "Authorization: Bearer op_YOUR_TOKEN" \
  -F "name=Hello World" \
  -F "visibility=public" \
  -F "file=@./site.zip"

The response includes the live URL:

{
  "id": "Ab12Cd34",
  "name": "Hello World",
  "visibility": "public",
  "default_file": "index.html",
  "url": "https://outpost.click/p/Ab12Cd34",
  "created_at": "2026-05-03T17:42:11"
}

3. Or import from a URL

curl -X POST https://outpost.click/api/pages \
  -H "Authorization: Bearer op_YOUR_TOKEN" \
  -F "name=Mirror" \
  -F "visibility=public" \
  -F "source_url=https://example.com"

4. Or upload a single HTML file

curl -X POST https://outpost.click/api/pages \
  -H "Authorization: Bearer op_YOUR_TOKEN" \
  -F "name=Notes" \
  -F "visibility=public" \
  -F "file=@./notes.html"

Endpoint cheatsheet

Authentication (details)

MethodPathAuthPurpose
POST /auth/registernone Register an email/password user (when enabled).
POST /auth/loginnone Exchange credentials for a JWT and token cookie.
POST /auth/logoutnone Clear the token cookie.
GET /auth/mebearer Return the current user.
GET /auth/auth0/loginnone Begin Auth0 authorization-code flow.
GET /auth/callbacknone Auth0 redirect target.
GET /auth/google/loginnone Begin Google OAuth flow.
GET /auth/google/callbacknone Google redirect target.
GET /auth/completenone Helper page that stores the JWT in localStorage.

Pages CRUD (details)

MethodPathPurpose
GET/pagesList the caller's pages.
POST/pagesCreate a page from upload or source_url.
PUT/pages/{page_id}Update metadata or replace files.
DELETE/pages/{page_id}Delete a page and its files.

Public page serving (details)

MethodPathPurpose
GET/p/{page_id}Redirect to the page's default file.
GET/p/{page_id}/{path}Serve a stored file (or the access gate).
POST/p/{page_id}/verifySubmit a passcode to unlock the page (sets cookie).

API tokens (details)

MethodPathPurpose
POST/api/tokensCreate a new op_… token.
GET/api/tokensList the caller's tokens (no secrets).
PUT/api/tokens/{id}Rename a token.
DELETE/api/tokens/{id}Revoke a token.

Programmatic upload (details)

MethodPathPurpose
POST/api/pagesCreate a page using an op_… token.
POST/api/pages/{page_id}/filesReplace files on an existing page.
POST/upload/{token}Upload using a short-lived signed token.

Model Context Protocol (details)

MethodPathPurpose
GET/mcpOpen an SSE session, receive the message endpoint.
POST/mcp/message?session_id=…JSON-RPC channel for an SSE session.
POST/mcpStateless Streamable HTTP JSON-RPC endpoint.

Conventions

Authorization header

All authenticated endpoints accept the standard Authorization: Bearer <token> header. The token may be:

  • A JWT (HS256, issued by /auth/login or one of the OAuth callbacks).
  • An API token starting with op_ (created via /api/tokens).
  • An Auth0 RS256 ID token if Auth0 is enabled.

The server auto-detects the token type by the op_ prefix versus JWT structure.

Cookies

  • token — the session JWT, HttpOnly, SameSite=Lax, 24-hour max_age.
  • page_access_<page_id> — set by the access-gate verifier after a correct passcode is supplied.

Errors

Errors are FastAPI HTTPException JSON responses:

{ "detail": "Invalid credentials" }

Validation failures use the standard FastAPI 422 envelope:

{
  "detail": [
    {
      "loc": ["body", "password"],
      "msg": "ensure this value has at least 8 characters",
      "type": "value_error.any_str.min_length"
    }
  ]
}

Cache headers

Page-serving routes set Cache-Control: no-store, no-cache, must-revalidate, max-age=0 plus Pragma: no-cache and Expires: 0 when the page is non-public (private/shared) or when any passcode is configured. Public pages without passcodes inherit FastAPI defaults.

Date format

All timestamps are ISO-8601 strings serialized from naive UTC datetime values stored in Postgres (e.g. "2026-05-03T17:42:11").

Page id format

Page ids are exactly 8 characters from [A-Za-z0-9], generated by secrets.choice and verified unique against the pages table before insertion.

Data model summary

See the linked sub-pages for full request/response shapes. The Postgres schema is created on startup by init_schema() and contains:

  • users — id, email, password_hash, org_id, created_at.
  • pages — id (8 chars), owner_id, name, visibility, passcode_hashes (encrypted), allowed_emails, default_file, created_at, updated_at.
  • page_files — page_id, file_path, content (BYTEA), content_type. Files live in the database, not on disk.
  • api_tokens — user_id, name, token_hash (SHA-256), token_prefix (first 12 chars), status, created_at, last_used_at.