POST /oauth/token accepts both application/x-www-form-urlencoded (the RFC 6749 §3.2 default) and application/json, and reads client credentials from either the request body or an Authorization: Basic header (RFC 6749 §2.3.1). Discovery metadata is at https://simkl.com/.well-known/oauth-authorization-server (RFC 8414) — modern libraries can auto-configure from it.
Quick library status
Every library below was driven through the full browser-consent → real authorize code → real token mint flow againstapi.simkl.com. Each one returned a real access_token we then used to call /users/settings successfully.
| Language | Library | Default config status |
|---|---|---|
| Python | authlib | ✅ Works as-is |
| Python | requests-oauthlib | ✅ Works as-is |
| Python | httpx-oauth | ✅ Works as-is |
| Node.js | openid-client v6 (panva) | ✅ Works — pass {algorithm: 'oauth2'} to discovery() |
| Node.js | oauth4webapi (panva) | ✅ Works — pass {algorithm: 'oauth2'} to discoveryRequest() |
| Node.js | simple-oauth2 | ✅ Works as-is |
| Node.js | passport-oauth2 | ✅ Works as-is |
| Node.js | @badgateway/oauth2-client | ✅ Works as-is |
| Java | Nimbus OAuth 2.0 SDK | ✅ Works as-is |
| Java | Spring Security OAuth2 Client | ✅ Works as-is |
| Java | Google OAuth Client for Java | ✅ Works as-is |
| Java | scribejava-core | ✅ Works as-is |
| Go | golang.org/x/oauth2 | ✅ Works as-is |
| PHP | league/oauth2-client | ✅ Works as-is |
| Any | raw HTTP (curl, fetch, requests, …) | ✅ Reference path |
openid-client v6 and oauth4webapi — both default to OIDC discovery (/.well-known/openid-configuration), but Simkl is OAuth2-only, so they need an explicit { algorithm: 'oauth2' } option to use our RFC 8414 metadata endpoint. One-line fix shown in their snippets.
The wire format
client_secret for code_verifier.
Python authlib
Python requests-oauthlib
Python httpx-oauth
Node openid-client v6
Node oauth4webapi
Node simple-oauth2
Node passport-oauth2
Node @badgateway/oauth2-client
Java Nimbus OAuth 2.0 SDK
Java Spring Security OAuth2 Client
/.well-known/oauth-authorization-server from the issuer-uri and wires up authorization_endpoint + token_endpoint automatically. Default client_secret_basic works.
Java Google OAuth Client for Java
Java scribejava-core
Go golang.org/x/oauth2
PHP league/oauth2-client
Raw HTTP
Other OAuth libraries (inferred from RFC compliance)
These libraries aren’t in our live test harness, so the status below is read from each library’s source/docs — not from a captured request toapi.simkl.com. Most wrap one of the live-tested libraries above; the rest follow the same RFC defaults Simkl now accepts.
| Language | Library | Inferred |
|---|---|---|
| Python | Django allauth, python-social-auth, fastapi-users | Wraps requests-oauthlib — should work as-is. |
| Node.js | NextAuth.js / Auth.js, express-openid-connect | Wraps openid-client — works with {algorithm: 'oauth2'} discovery. |
| Node.js | grant (server middleware), oidc-client-ts | Default RFC config matches Simkl. |
| .NET | Duende.IdentityModel, OpenIddict (client), MS.AspNetCore.Authentication.OpenIdConnect | Default Basic Auth / discovery flows align with Simkl. |
| .NET | Microsoft.Identity.Client (MSAL) | Auth-code grant should work; broker / conditional access flows out of scope. |
| Server-side PHP | HWIOAuthBundle (Symfony) | Wraps league/oauth2-client — should work as-is. |
| Ruby | oauth2 gem, omniauth-oauth2 | Default auth_scheme: :basic_auth accepted. |
| Rust | oauth2 crate, openidconnect crate (ramosbugs) | Default AuthType::BasicAuth accepted. |
| Mobile | AppAuth-iOS / AppAuth-Android / AppAuth-JS / react-native-app-auth | RFC default — should work as-is. |
| Postman | Built-in OAuth 2.0 helper | Both “Send as Basic Auth header” and “Send client credentials in body” modes accepted. |
| OpenAPI Generator | Generated clients (all languages) | Generators emit RFC-conformant clients. |
https://api.simkl.com/oauth/token, sends client_id / code / redirect_uri / grant_type (and client_secret either in the body or in Authorization: Basic), and see what comes back. If the request looks RFC-shaped and you still hit an error, let us know — we’d appreciate the capture so we can promote the library to the live matrix.
See also
OAuth 2.0 walkthrough
Confidential (server-side) flow.
Public PKCE walkthrough
Mobile / SPA / desktop flow without
client_secret.PIN flow
TV / console / CLI flow with a 5-character code.