OAuth2 flow
The API gateway is an OAuth 2.0 authorization server. Users grant your application access by signing in with their SplashMe account; your application then calls the API with a bearer token.
| Item | Value |
|---|---|
| Authorization endpoint | GET /api-gateway/v1/oauth/authorize |
| Token endpoint | POST /api-gateway/v1/oauth/token |
| User info endpoint | GET /api-gateway/v1/oauth/userinfo |
| Grant types | authorization_code (optionally with PKCE), refresh_token, password (approved clients only) |
| Response types | code |
| PKCE methods | S256 |
| Access token lifetime | 24 hours |
| Refresh token lifetime | 30 days |
| Authorization code lifetime | 5 minutes, single use |
client_credentials is not supported: every token represents a user.
Authorization request
Section titled “Authorization request”GET/api-gateway/v1/oauth/authorize
| Parameter | Required | Notes |
|---|---|---|
response_type |
no | Only code. Defaults to code when omitted. |
client_id |
yes | From client registration. |
redirect_uri |
yes | Must exactly match a registered URI. |
state |
recommended | Opaque value echoed back on the redirect. Use it to prevent CSRF. |
scope |
no | Space-separated. Stored on the token and echoed back; profile is conventional. |
code_challenge |
no | PKCE challenge, 43 to 128 characters. |
code_challenge_method |
no | S256. Send it whenever code_challenge is sent. |
The response is an HTML sign-in page hosted by SplashMe. The user enters their SplashMe email and password and submits. Signing in grants your application access to the user’s sites and controllers; there is no additional consent step.
On success the browser receives a 302 to your redirect_uri with code and, if you sent one, state appended to the query string. Existing query parameters on the redirect URI are preserved.
If the credentials are wrong the page is shown again with an error message. Sign-in attempts are limited to 10 per minute per IP address.
Validation failures return 400 with a JSON body before the page is shown:
error |
error_description |
|---|---|
unsupported_response_type |
Only response_type=code is supported |
invalid_client |
client_id is required, invalid client |
invalid_request |
redirect_uri must include a scheme, redirect_uri is not allowed, client has no registered redirect URIs |
invalid_request |
code_challenge must be 43-128 characters, unsupported code_challenge_method "…" (use S256), code_challenge_method given without code_challenge |
Token request
Section titled “Token request”POST/api-gateway/v1/oauth/token
Send the body as application/x-www-form-urlencoded (JSON is also accepted). The client authenticates with client_id and client_secret in the body, or with HTTP Basic authentication. Client authentication is checked before the grant, for every grant type including refresh.
Authorization code grant
Section titled “Authorization code grant”| Field | Required |
|---|---|
grant_type |
authorization_code |
code |
yes |
redirect_uri |
yes, the same value used in the authorization request |
client_id, client_secret |
yes |
code_verifier |
yes if the authorization request used PKCE |
Refresh token grant
Section titled “Refresh token grant”| Field | Required |
|---|---|
grant_type |
refresh_token |
refresh_token |
yes |
client_id, client_secret |
yes |
A new access token and a new refresh token are returned. The previous refresh token stays valid until its own expiry; treat the newest one as current.
Password grant
Section titled “Password grant”| Field | Required |
|---|---|
grant_type |
password |
username |
the user’s SplashMe email |
password |
yes |
client_id, client_secret |
yes |
scope |
no |
The password grant is available only to clients approved by SplashMe; other clients receive unauthorized_client. It is intended for tooling you control where the user types their SplashMe credentials into your own software, for example a command-line utility. Interactive applications should use the authorization code flow so that credentials are entered on the SplashMe page. To request approval, contact support@splashmepool.com.au.
Successful response
Section titled “Successful response”{ "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer", "expires_in": 86400, "refresh_token": "eyJhbGciOiJIUzI1NiIs...", "scope": "profile"}Error responses
Section titled “Error responses”Errors follow RFC 6749: {"error": "...", "error_description": "..."}.
| Status | error |
error_description |
Meaning |
|---|---|---|---|
| 401 | invalid_client |
client_id is required, client_secret is required, invalid client |
Client authentication failed |
| 400 | unsupported_grant_type |
Supported grant_type values are authorization_code, refresh_token, and password |
|
| 400 | invalid_request |
code and redirect_uri are required |
|
| 400 | invalid_grant |
Invalid authorization code |
Expired, malformed or not a code |
| 400 | invalid_grant |
Authorization code already used |
Replay, or the replay store was unavailable; request a new code |
| 400 | invalid_grant |
Authorization code subject is invalid, Authorization code user was not found |
The account behind the code no longer exists |
| 400 | invalid_request |
Token request is invalid |
Body could not be parsed |
| 400 | invalid_grant |
Authorization code does not match client_id / …redirect_uri |
|
| 400 | invalid_grant |
code_verifier is required and must be 43-128 characters, code_verifier does not match code_challenge |
PKCE |
| 400 | invalid_request |
refresh_token is required |
|
| 400 | invalid_grant |
Invalid refresh token, Refresh token does not match client_id, Refresh token subject is invalid, Refresh token user was not found |
|
| 400 | unauthorized_client |
The password grant is not enabled for this client; contact support@splashmepool.com.au |
Password grant |
| 400 | invalid_request |
username and password are required |
Password grant |
| 401 | invalid_grant |
Invalid credentials |
Password grant |
| 401 | invalid_client |
oauth client service is unavailable |
Temporary; retry later |
| 500 | server_error |
Retry later |
User info
Section titled “User info”GET/api-gateway/v1/oauth/userinfo
Requires a bearer token. Returns a plain JSON object, not the standard envelope:
{ "sub": "aB3dE5fG7h", "email": "user@example.com", "preferred_username": "user@example.com", "given_name": "Sam", "family_name": "Lee", "name": "Sam Lee", "role": "user"}sub is the user’s stable SplashMe account identifier. role is user or admin. If the profile cannot be loaded the response is reduced to sub, email and role.
Recommended implementation
Section titled “Recommended implementation”- Generate a random
stateand, if your platform supports it, a PKCE verifier andS256challenge. - Open the authorization URL in the system browser, never in an embedded web view that can read the page.
- On the callback, verify
state, then exchange the code from your backend where the client secret lives. - Store both tokens. Refresh when the access token has less than an hour left, or on the first
401. - Call
/oauth/userinfoonce to learn who signed in and key your records onsub.

