A Cloudflare Worker that handles Upwork OAuth token refresh for you. Point your HTTP client at it instead of Upwork directly and it'll keep the token valid in the background.
Built because n8n on my laptop kept losing auth whenever the laptop slept through a token expiry. Upwork access tokens last about 24 hours, and if whatever runs your Upwork queries isn't awake to refresh them, they die. This runs on Cloudflare so it's always awake. A cron inside the worker refreshes on a schedule, and each inbound request checks before forwarding. Your client sends POST /graphql with its own API key and gets the response back.
You need a Cloudflare account and an Upwork OAuth app. Register one at https://www.upwork.com/developer/keys.
git clone https://github.com/mumtazm1/upwork-proxy.git
cd upwork-proxy
npm install
# Make your own KV namespace for tokens. Copy the id it prints
# into wrangler.toml, replacing the one that's there.
npx wrangler kv namespace create TOKENS
# Upwork app credentials
npx wrangler secret put UPWORK_CLIENT_ID
npx wrangler secret put UPWORK_CLIENT_SECRET
# Random string your client will send in X-API-Key
npx wrangler secret put API_KEY
npm run deployWrangler will print your worker URL. Go to the Upwork developer console and add https://<your-worker-url>/callback as a redirect URI on your app.
Then open https://<your-worker-url>/auth in a browser once to do the first OAuth handshake. From there the worker handles refresh on its own.
curl -X POST https://<your-worker-url>/graphql \
-H "X-API-Key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"query": "{ __typename }"}'Send your GraphQL query in the body. The proxy adds the current Upwork access token, forwards the request, and returns Upwork's response unchanged.
Upwork refresh tokens also expire, about 7 days from the last time they were used. The worker runs a cron refresh every 4 hours so normally you won't notice. But if Upwork rotates them on you (password change, security reset, or a long quiet stretch with no requests), you have to re-auth by opening https://<your-worker-url>/auth again.
GET /status shows the current token state so you can tell when something's off.
| Method | Path | What it does |
|---|---|---|
| GET | /status | Shows token validity and expiry |
| GET | /auth | Starts OAuth (open in a browser) |
| GET | /callback | Upwork redirects here after auth. Don't call it yourself. |
| POST | /graphql | Authenticated proxy to Upwork's GraphQL API |
npm run dev
npm run typecheck
npm run deployMIT. See LICENSE.