Developers
FellowMakers.app exposes three programmable surfaces: an HTTP API described by an OpenAPI document, a Model Context Protocol (MCP) endpoint for AI agents, and an OAuth 2.1 authorization server that issues the tokens both accept. Everything on this page is served by the same deployment, so the URLs are live wherever you are reading this.
Start here
| What | Where | Format |
|---|---|---|
| OpenAPI 3.1 document | /openapi.json | application/json |
| API root | /api | JSON index of the surfaces below |
| MCP endpoint | /mcp (POST, Streamable HTTP) | JSON-RPC |
| MCP server card | /mcp/server-card | application/mcp-server-card+json |
| MCP Registry manifest | /server.json | application/json |
| Authorization server metadata | /.well-known/oauth-authorization-server | RFC 8414 |
| Protected resource metadata | /.well-known/oauth-protected-resource | RFC 9728 |
| API catalog | /.well-known/api-catalog | RFC 9727 linkset |
| Agent guidance | /llms.txt | Markdown |
| Sitemap | /sitemap.xml | XML |
Every public page also has a Markdown twin: add .md to its path, or send Accept: text/markdown.
Calls that need no token
curl https://fellowmakers.app/api/health
curl https://fellowmakers.app/api
curl https://fellowmakers.app/openapi.json
The health check reports which environment answered. The discovery documents above are public as well.
Authorization
The API and the MCP endpoint accept bearer tokens issued by this deployment's own authorization server. The flow is OAuth 2.1: authorization code with PKCE (S256), refresh tokens, and revocation. There is no API-key form and no sales contact: a client registers itself, and the person signing in approves what it may do.
1. Register a client
Registration is open, as RFC 7591 intends, and immediate:
curl -X POST https://fellowmakers.app/api/oauth/register \
-H 'Content-Type: application/json' \
-d '{"client_name":"My agent","redirect_uris":["http://127.0.0.1/callback"],"token_endpoint_auth_method":"none"}'
The response carries the client_id and a registration access token for updating or deleting the registration later. Clients that publish a Client ID Metadata Document can use its URL as the client_id instead of registering.
2. Ask the person for consent
Send the browser to the authorization endpoint from the metadata document with response_type=code, your client_id, a redirect_uri you registered, a PKCE code_challenge, the scope you need and, for MCP, resource=https://fellowmakers.app/mcp. The person signs in with Google and approves or declines.
3. Exchange the code
curl -X POST https://fellowmakers.app/api/oauth/token \
-d grant_type=authorization_code \
-d code=... -d client_id=... -d redirect_uri=... -d code_verifier=...
Present the access token as Authorization: Bearer .... By default it lives an hour; the refresh token lives thirty days from consent, is single-use, and rotating it never extends that window, after which the person signs in again. Refresh with grant_type=refresh_token; revoke at the revocation endpoint. A request without a valid token answers 401 with a WWW-Authenticate header that points at the protected resource metadata, which is how a client finds this authorization server on its own.
Scopes
| Scope | Grants |
|---|---|
openid | Confirm who you are |
profile | See your name |
email | See your email address |
read | Read your data |
write | Change your data on your behalf |
Reads need read; anything that changes data needs write. A token is limited to the scopes the person approved, and the person can revoke it from their profile at any time.
MCP
The endpoint is /mcp over Streamable HTTP. Unauthenticated initialize succeeds and reports the server's capabilities; everything else needs a bearer token bound to the /mcp resource. Hosted clients such as Claude, ChatGPT and Codex connect by URL, register themselves and open the consent page; nothing is configured on this side.
MCP requires read scope. Search projects or waves in any language, then get project details. Queries are recorded (Privacy); personal profiles are excluded:
get_project: Get a project by slug, its captured website information and related projects for analysis. Does not return builders, personal profiles or personal evidence. (read-only)search_projects: Search products by meaning, problem or audience, with source excerpts. Optional sector and limit. Queries are recorded. Use get_project for details. (read-only)search_waves: Search shared ideas across projects. Returns wave summaries. Optional group and limit. Queries are recorded. (read-only)
Tools marked read-only can run without confirmation. Call tools/list for the current schemas; the server card lists the protocol versions it speaks. A call that fails is a result with isError rather than a protocol error, and its structuredContent is always the same shape: code, message, retryable, and details with the HTTP status and, for a scope refusal, the scope that was missing.
Sandbox
The stage environment runs the same code against its own database and object store:
curl https://landscape-stage.krasnoperov.me/api/health
Register clients, sign in and exercise the API there without touching production. Its discovery documents point at itself, so a client configured for the sandbox never leaks into production by accident.
Command line
The repository ships a CLI that signs in through the browser, stores the tokens and can bridge a local MCP client to the deployed endpoint over stdio:
pnpm run cli login
pnpm run cli mcp
pnpm run cli login --env stage
Versioning
The API is versioned by date, and the current version is 2026-09-10. Send API-Version: 2026-09-10 to pin a client to the version it was written against, or omit the header to get the current one. Every response under /api carries API-Version naming the version that answered, and a request naming a version that does not exist is refused with 400 unsupported_version rather than served something it did not ask for.
A version leaves in two steps. A breaking change ships under a new date, and the previous date keeps answering for at least ninety days as a deprecated version: every response to a request that pins it carries a Deprecation header (RFC 9745: @ and Unix seconds) naming the day it was deprecated, a Sunset header (RFC 8594) naming the last day it answers, and a Link with rel="deprecation" pointing here. After the sunset day the version is removed and a request that still pins it is refused with 400. The current version never carries these headers, so a client can watch for Deprecation alone.
Rate limits
Limits are per minute, per bucket, and enforced at the edge. Every response under /api names the policy it passed under in RateLimit-Policy and RateLimit-Limit; a refused request answers 429 with Retry-After and a RateLimit header showing the bucket empty.
| Bucket | Requests per minute |
|---|---|
| Authorization, client registration and client configuration, per address | 20 |
| Token and revocation requests, per client and address | 600 |
| MCP tool calls, per person and address | 60 |
| Every other API request, per address | 1200 |
Errors
Every error under /api has one shape, ApiError in the OpenAPI document: error is a short code where one exists and a sentence otherwise, and error_description, when present, says more for a person. The OAuth endpoints use the RFC 6749 codes (invalid_request, invalid_client, invalid_grant, slow_down). A request without a valid token answers 401 with a WWW-Authenticate header that points at the protected resource metadata; a valid token without the needed scope answers 403 insufficient_scope. Unknown paths answer 404, with a JSON body under /api that names the OpenAPI document and a Markdown body elsewhere that says where to look next.
Getting help
Integration questions go to hello@fellowmakers.app. Vulnerabilities go to the same address, as described in /.well-known/security.txt.