Developers
Whitelabel 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://whitelabel.krasnoperov.me/api/health
curl https://whitelabel.krasnoperov.me/api
curl https://whitelabel.krasnoperov.me/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://whitelabel.krasnoperov.me/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://whitelabel.krasnoperov.me/mcp. The person signs in with Google and approves or declines.
3. Exchange the code
curl -X POST https://whitelabel.krasnoperov.me/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 .... Refresh it with grant_type=refresh_token; revoke it 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.
The tools act on the signed-in person of the presented token:
get_profile: Read the signed-in user's profile: id, email and display name. (read-only)health_check: Report whether the service is reachable and which environment answered. (read-only)update_profile: Change the signed-in user's display name. (changes data)
Tools marked read-only can run without confirmation. Call tools/list for the current schemas; the server card lists the protocol versions it speaks.
Sandbox
The stage environment runs the same code against its own database and object store:
curl https://whitelabel-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 breaking change ships under a new date, and this page announces how long the previous one keeps answering.
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 krasnoperov.me. Vulnerabilities go through the same channel, marked as security reports.