moymo,Docs
Skip to content
API Reference

OAuth2 endpoints ​

Moymo implements OAuth 2.0 (RFC 6749) with PKCE (RFC 7636) and token revocation (RFC 7009). The OAuth2 guide walks through it; this page is the reference.

Authorisationhttps://moymo.net/oauth2/authorize (a page, for the member's browser)
TokenPOST https://moymo.net/api/v1/oauth2/token
RevokePOST https://moymo.net/api/v1/oauth2/revoke
Supported grantsauthorization_code, refresh_token
Supported response typecode
PKCES256 only
Token typeBearer

Authorisation request ​

GET https://moymo.net/oauth2/authorize

ParameterRequired
client_idyesThe application's id.
redirect_uriwhen there is not exactly one registered, unless the link only adds a botOne of the registered addresses, compared exactly. A loopback address (http://localhost, http://127.0.0.1, http://[::1]) may use any port.
response_typenocode.
scopeyesSpace-, +- or comma-separated scopes.
staterecommendedReturned unchanged.
code_challengefor apps with no secretThe unpadded base64url SHA-256 of the verifier: 43 characters.
code_challenge_methodwith a challengeS256.
permissionsnoWith bot: the sum of the requested permission bits.
server_idnoWith bot: preselects a server.
An authorisation link (on one line; broken here to be read)Text
text
https://moymo.net/oauth2/authorize
  ?client_id=0f6c1a52-3b9e-4c1c-9d1b-6e7d2a8f4b10
  &redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
  &response_type=code
  &scope=identify+servers
  &state=Zx3k9Qe1
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256

Success: the browser is sent to redirect_uri?code=...&state=... (with server_id=... for a bot). Refusal or error: redirect_uri?error=...&error_description=...&state=....

A request that names no such application, or an address the application did not register, is answered on Moymo's page with an error and never redirected.

errorWhen
access_deniedThe member said no; the application is suspended; it is a draft or private and the member is not its owner or a tester; the bot cannot be added.
invalid_scopeA scope that does not exist, is not available yet, or is first-party only; or bot for an application with no bot.
invalid_requestA malformed challenge; plain PKCE; a missing required parameter.
unsupported_response_typeresponse_type other than code.

Token request ​

POST https://moymo.net/api/v1/oauth2/token, Content-Type: application/x-www-form-urlencoded

Client authentication: client_id and client_secret in the body, or HTTP Basic with client_id:client_secret (each part form-encoded). A public client (no secret) sends client_id only and has to use PKCE.

grant_type=authorization_code ​

Parameter
codeThe code from the redirect. One use, 5 minutes.
redirect_uriThe same address the code was issued for.
code_verifierThe PKCE verifier, if the code was issued with a challenge.

grant_type=refresh_token ​

Parameter
refresh_tokenThe refresh token. It works once.

Example ​

The answer is not cacheable (Cache-Control: no-store). Access tokens last 3600 seconds, refresh tokens 30 days.

RequestPOST/api/v1/oauth2/token
bash
curl -X POST https://moymo.net/api/v1/oauth2/token \
  -d grant_type=authorization_code \
  -d code="$CODE" \
  -d redirect_uri=https://example.com/callback \
  -d code_verifier="$CODE_VERIFIER" \
  -d client_id="$CLIENT_ID" \
  -d client_secret="$CLIENT_SECRET"
js
const response = await fetch('https://moymo.net/api/v1/oauth2/token', {
  method: 'POST',
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code,
    redirect_uri: 'https://example.com/callback',
    code_verifier: codeVerifier,
    client_id: clientId,
    client_secret: clientSecret
  })
})
const tokens = await response.json()
python
import requests

response = requests.post(
    "https://moymo.net/api/v1/oauth2/token",
    data={
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": "https://example.com/callback",
        "code_verifier": code_verifier,
        "client_id": client_id,
        "client_secret": client_secret,
    },
)
tokens = response.json()
Response200OKJSON
json
{
  "access_token": "moymo_at_3kQ9vXn2LmT7pYw4RcB8dJ1hZfE5sUa6GoN0iVxKq2M",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "moymo_rt_7Hn4WbZ2eXk9QpLr6TcY1vJ8aMfD3sUoG5iNyKx0Rt",
  "scope": "identify servers"
}

To get a new access token, send the refresh token. It works once: the answer carries a new one.

RequestPOST/api/v1/oauth2/tokenShell
bash
curl -X POST https://moymo.net/api/v1/oauth2/token \
  -d grant_type=refresh_token \
  -d refresh_token="$REFRESH_TOKEN" \
  -d client_id="$CLIENT_ID" \
  -d client_secret="$CLIENT_SECRET"

Revoke ​

POST https://moymo.net/api/v1/oauth2/revoke, form-encoded, with client authentication as above.

Parameter
tokenAn access token or a refresh token of this application.

Answers 200 whether or not the token existed, as the standard asks. A token belonging to another application is not revoked.

Errors ​

At the token and revoke endpoints, errors are the standard's: {"error": "...", "error_description": "..."} with these statuses.

Response400Bad RequestJSON
json
{
  "error": "invalid_grant",
  "error_description": "That code is not valid any more."
}

The error_description is a sentence for the person reading the log; branch on error.

StatuserrorWhen
400invalid_requestA required parameter is missing.
400invalid_grantThe code is expired, already used (this also revokes the tokens it made), was issued to another application or redirect address, or the verifier does not match; or the refresh token is not valid, was used, or belongs to another application.
400unsupported_grant_typeNot authorization_code or refresh_token.
401invalid_clientUnknown application, wrong secret, a suspended application, or malformed Basic credentials. Comes with WWW-Authenticate: Basic realm="moymo".

Notes ​

  • CORS is open for the token and revoke endpoints (no credentials are ever sent), so a browser app can call them.
  • Token and revoke are rate limited per address; see Rate limits.
  • Redirect addresses allowed: https://..., http://localhost, http://127.0.0.1, http://[::1], and a native app's reversed-domain scheme such as com.example.app:/callback. Not allowed: wildcards, fragments, credentials in the address.

The wiki is for Moymo's members and developers. Something wrong or missing? Use "Suggest a change" on any page.