Walletguide
DevelopersAPI

Authentication

API keys and OAuth 2.1 for the Walletguide API, which to use when, and the scopes and audiences a token carries.

Two ways in. Both arrive as Authorization: Bearer …, and the api tells them apart by the shape of the token.

API keys

A wg_ key, scoped to one wallet, no expiry. Right for your own scripts, for CI, and for an MCP client that cannot open a browser. See creating one.

A key holds a role preset (viewer or editor) or an explicit permission list. Only a list that names them gives it wallet:manage (wallet settings) or integrations:manage (bank connections); no key ever holds users:manage or api_keys:manage, and no key can create a wallet or ask for an access request.

curl -H "Authorization: Bearer wg_…" https://api.walletguide.com/wallets

OAuth 2.1

For software acting on someone else's behalf. They sign in, they see what is being asked for, and they can take it away later. This is what walletguide login and the MCP endpoint use.

Authorization code with PKCE, and nothing else: there is no implicit flow and no client secret for a public client. A client can identify itself with a Client ID Metadata Document, an HTTPS client_id that serves its metadata, as Claude, ChatGPT and VS Code do, and needs no registration. For clients without one, dynamic client registration is open, so an MCP client can register itself.

Authorizationhttps://api.walletguide.com/auth/oauth2/authorize
Tokenhttps://api.walletguide.com/auth/oauth2/token
Userinfohttps://api.walletguide.com/auth/oauth2/userinfo
Registrationhttps://api.walletguide.com/auth/oauth2/register
Issuerhttps://api.walletguide.com/auth
Metadatahttps://api.walletguide.com/.well-known/oauth-authorization-server/auth (also without the /auth suffix)
Protected resourceshttps://api.walletguide.com/.well-known/oauth-protected-resource and …/oauth-protected-resource/mcp; https://mcp.walletguide.com/.well-known/oauth-protected-resource for the MCP server's own host
Keyshttps://api.walletguide.com/auth/jwks

The issuer carries the /auth path, and the protected-resource documents name that issuer under authorization_servers. A client that follows RFC 8414 to the letter looks for the metadata at /.well-known/oauth-authorization-server/auth and finds an issuer equal to the value it started from, which is the check strict clients make.

Scopes

ScopeWhat it allows
walletguide:readRead what the person may read, in the wallets they can reach
walletguide:writeCreate, change and delete what the person may change
walletguide:adminChange wallet settings (name, base currency, image) and manage bank connections, where the person's role allows it. Opt-in
walletguide:create_walletsCreate wallets for the person, with them as the owner. Opt-in
openid, profile, emailWho they are
offline_accessA refresh token, so the session survives the hour

A person can untick walletguide:write at consent time. Software should handle a read-only grant rather than assume it got what it asked for.

The two opt-in scopes are granted only to a client that names them in its scope parameter, and the consent screen shows them unticked, unless the account was created in the last day: then every requested option starts ticked. walletguide:admin implies no data writes: without walletguide:write an app can rename the wallet but not add a transaction. It never reaches members, API keys or deleting a wallet directly. Instead it lets the app ask for those changes through the access-request routes (POST /wallets/{walletId}/accessRequests/…): each answers with an approvalUrl where the person approves or declines the exact change in Walletguide, and approval checks the person's permissions and the app's consent again. See access requests. POST /wallets needs walletguide:create_wallets and refuses API keys.

Over MCP, get_started reports which of these a connection holds and which tools each missing one would add.

A scope never adds to what the person may do. In a wallet where they are a viewer, a token with walletguide:write still cannot change anything, and a call that needs a permission they do not hold answers 403 with the permission named in missing.

Audiences

An access token is minted for one audience, named with an RFC 8707 resource parameter on both /authorize and /token:

  • https://api.walletguide.com for the REST routes
  • https://mcp.walletguide.com for the MCP server, or the MCP address the client connected to: https://mcp.walletguide.com/mcp, or the earlier https://api.walletguide.com/mcp

A token for any of the MCP addresses is accepted on all of them. The two kinds do not substitute for one another: a token for the MCP server is refused on /wallets/* even though the same person consented to the same app, which is the point: an agent connector cannot quietly reuse its MCP grant against the whole REST surface.

Send resource on the token request, not only on the authorization request. Better Auth issues a JWT only when the token request names an audience; without it you get an opaque token, and the api rejects it with nothing pointing at why.

What a credential cannot do

Neither kind reaches /internal/*. Those routes are the app's own, they authenticate with a session cookie, and they are not in the OpenAPI document. Everything a public credential can do is in the reference.

On this page