Developer portal

Developers

The HTTP API, the MCP endpoint and the OAuth 2.1 authorization server: how to discover, authorize and call them.

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

WhatWhereFormat
OpenAPI 3.1 document/openapi.jsonapplication/json
API root/apiJSON index of the surfaces below
MCP endpoint/mcp (POST, Streamable HTTP)JSON-RPC
MCP server card/mcp/server-cardapplication/mcp-server-card+json
MCP Registry manifest/server.jsonapplication/json
Authorization server metadata/.well-known/oauth-authorization-serverRFC 8414
Protected resource metadata/.well-known/oauth-protected-resourceRFC 9728
API catalog/.well-known/api-catalogRFC 9727 linkset
Agent guidance/llms.txtMarkdown
Sitemap/sitemap.xmlXML

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

ScopeGrants
openidConfirm who you are
profileSee your name
emailSee your email address
readRead your data
writeChange 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.

BucketRequests per minute
Authorization, client registration and client configuration, per address20
Token and revocation requests, per client and address600
MCP tool calls, per person and address60
Every other API request, per address1200

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.