Quickstart
Add "Connect to monoes" to your site
A worked example in JavaScript. See Authentication for the full flow reference.
1. Register your client once
register-client.js
const res = await fetch("https://monoes.me/api/auth/oauth2/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
redirect_uris: ["https://your-app.example/callback"],
token_endpoint_auth_method: "none",
grant_types: ["authorization_code", "refresh_token"],
}),
});
const { client_id } = await res.json();
// Save client_id — you only need to do this once per app.2. Build the "Connect" link
Generate a PKCE code verifier/challenge pair, stash the verifier (session, cookie), and send the user to the authorize URL.
connect-button.js
function base64url(buffer) {
return btoa(String.fromCharCode(...new Uint8Array(buffer)))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = base64url(
await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))
);
sessionStorage.setItem("pkce_verifier", verifier);
const url = new URL("https://monoes.me/api/auth/oauth2/authorize");
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("redirect_uri", "https://your-app.example/callback");
url.searchParams.set("response_type", "code");
url.searchParams.set("scope", "community:read community:write offline_access");
url.searchParams.set("code_challenge", challenge);
url.searchParams.set("code_challenge_method", "S256");
window.location.href = url.toString();3. Handle the callback
callback.js
const code = new URL(window.location.href).searchParams.get("code");
const verifier = sessionStorage.getItem("pkce_verifier");
const res = await fetch("https://monoes.me/api/auth/oauth2/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "authorization_code",
code,
redirect_uri: "https://your-app.example/callback",
client_id: CLIENT_ID,
code_verifier: verifier,
}),
});
const { access_token, refresh_token } = await res.json();
// refresh_token is only present because the authorize URL above requested
// the offline_access scope — omit it and this field comes back undefined.
// Store access_token server-side, tied to your own user session.
// It's a bearer credential — treat it like a password.4. Call the API
whoami.js
const me = await fetch("https://monoes.me/api/community/me", {
headers: { Authorization: `Bearer ${access_token}` },
}).then((r) => r.json());
// { id, username, name, avatarUrl }No browser available? See the headless agent flow instead. Full endpoint list: API reference.