From 9283de60721da2e0bd40f42426fd24434395fa27 Mon Sep 17 00:00:00 2001 From: Mariano Campo Date: Sat, 16 May 2026 01:10:07 -0300 Subject: [PATCH] feat: support API key authentication --- README.md | 11 +++++++++-- internal/api/client.go | 2 +- internal/auth/auth.go | 11 +++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c60c206..3620487 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,12 @@ You'll be prompted for your Client ID and Client Secret. The CLI opens your brow > **Note:** Splitwise ignores `redirect_uri` in OAuth requests and always uses the registered callback URL. If you hit `ERR_CONNECTION_REFUSED` after authorizing, do a manual token exchange with `curl` using the `code` from the URL. +Alternatively, you can skip the OAuth flow by setting the `SPLITWISE_API_KEY` environment variable with an API key generated from [secure.splitwise.com/apps](https://secure.splitwise.com/apps): + +```bash +export SPLITWISE_API_KEY="your_api_key_here" +``` + ## Usage ```bash @@ -82,8 +88,9 @@ This CLI ships with an [OpenClaw](https://github.com/openclaw/openclaw) / [Gemin ## Configuration -| File | Purpose | -|------|---------| +| File/Variable | Purpose | +|---------------|---------| +| `SPLITWISE_API_KEY` | Environment variable for API key (bypasses OAuth) | | `~/.config/splitwise-cli/auth.json` | OAuth token | | `~/.config/splitwise-cli/config.json` | User preferences | diff --git a/internal/api/client.go b/internal/api/client.go index 130ac8e..0bbf368 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -77,7 +77,7 @@ func (c *Client) do(req *http.Request) ([]byte, error) { } if resp.StatusCode == 401 { - return nil, fmt.Errorf("unauthorized — run `splitwise auth` to re-authenticate") + return nil, fmt.Errorf("unauthorized — run `splitwise auth` to re-authenticate or set SPLITWISE_API_KEY") } if resp.StatusCode == 403 { return nil, fmt.Errorf("forbidden — you don't have access to this resource") diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 5873bbc..1b4eb39 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -114,9 +114,13 @@ func Login(clientID, clientSecret string) error { // LoadToken returns a valid token, refreshing if needed. func LoadToken() (string, error) { + if apiKey := os.Getenv("SPLITWISE_API_KEY"); apiKey != "" { + return apiKey, nil + } + stored, err := loadAuth() if err != nil { - return "", fmt.Errorf("not logged in — run `splitwise auth` first") + return "", fmt.Errorf("not logged in — run `splitwise auth` first or set SPLITWISE_API_KEY") } if stored.Token.Valid() { @@ -128,7 +132,7 @@ func LoadToken() (string, error) { src := cfg.TokenSource(context.Background(), stored.Token) newToken, err := src.Token() if err != nil { - return "", fmt.Errorf("token expired and refresh failed — run `splitwise auth` again: %w", err) + return "", fmt.Errorf("token expired and refresh failed — run `splitwise auth` again or set SPLITWISE_API_KEY: %w", err) } stored.Token = newToken @@ -141,6 +145,9 @@ func LoadToken() (string, error) { // IsLoggedIn checks if credentials exist. func IsLoggedIn() bool { + if os.Getenv("SPLITWISE_API_KEY") != "" { + return true + } _, err := loadAuth() return err == nil }