Skip to main content
AUTH V2 is standards-compliant OAuth 2.0, so a stock library works against it. There is no Simkl-specific SDK to install and no vendor quirk to patch around — configure the endpoints, set PKCE to S256, and the library does the rest.
Verification status, 2026-09-18. All three snippets were run against production, not just read off each library’s docs:What is not covered for any of them is the browser half — consent and the code exchange — since that needs a human. Those requests are verified separately against production in the raw HTTP walkthrough, so every leg of the flow is tested; just not end to end inside one library.

What every library needs

Whatever you are using, these are the settings. Everything else is that library’s own naming.
Two hosts. The consent page is on simkl.com; everything else is on api.simkl.com. A library that takes a single “base URL” will get one of them wrong — look for separate authorize and token settings.

The three defaults that need changing

Most libraries work as-is. These three do not, and each fails in a way that does not obviously point at the cause.

Node.js — openid-client v6

Two things to get right: algorithm: "oauth2" (the default is oidc, that path returns 404, and openid-client does not then try the OAuth 2.0 one), and the client auth method above.

Python — Authlib

Discovery lives on the framework integrations, which share one API — swap flask_client for django_client or starlette_client.
The plain OAuth2Session from authlib.integrations.requests_client does not read metadata. It has no discovery support, so set authorization_endpoint and token_endpoint yourself there. server_metadata_url is a registry option, not a session attribute.

Java — Spring Security

One setting is enough. ClientRegistrations.fromIssuerLocation() walks three discovery paths in order, and ours — /.well-known/oauth-authorization-server — is the third; the two OpenID Connect paths ahead of it return 404, which is a 4xx, so Spring falls through to ours and configures itself. Setting authorization-uri and token-uri explicitly instead is never wrong, and is what you want if you would rather not depend on a network fetch at startup.
No trailing slash. issuer-uri: https://simkl.com/ fails with “Unable to resolve Configuration with the provided Issuer”. RFC 8414 requires the document’s issuer to match the one you requested character for character, and https://simkl.com/ is not https://simkl.com.
If you configured a client-secret, you also need:
Without it Spring sends no code_challenge, the authorize request is rejected, and the error arrives on your callback rather than at the point of configuration — which makes it look like a redirect problem.

Anything else

If your library is not listed, it almost certainly works — fill in the table at the top and check three things:
  1. PKCE is on, and set to S256. This is where most failures start, because many libraries treat PKCE as opt-in for clients that have a secret.
  2. The client auth method matches your registration. An app with no secret must send only client_id; sending an empty secret is a different thing and fails.
  3. The two hosts are not collapsed into one. Authorize is on simkl.com, token is on api.simkl.com.
For anything a library cannot express, the OAuth flow walkthrough has the raw requests — including a complete runnable script that uses no dependencies at all.

See also

OAuth flow

The raw requests, and a dependency-free script that runs the whole flow.

Discovery

The RFC 8414 document, and the one flag some libraries need.

PKCE in AUTH V2

Generating the pair correctly, in five languages.

V1 client libraries

The tested V1 matrix. Note its discovery warning does not apply to V2.