JetScrape supports two authentication methods.

- Session cookie — sent automatically by the browser, or with `-b cookies.txt` /

`Cookie: better-auth.session_token=...` in curl. Used for dashboard work: account, API

keys, payments, subscriptions, notifications, consent.

- API key — sent as an `x-api-key: <key>` header or an `?apiKey=<key>` query parameter.

Used for all programmatic access: scraping, flows, user templates.

Sessions are handled by Better Auth; sign-up, sign-in and social login live under `/api/auth/*`.

Which endpoint expects what

- `/webhook/*` — API key.

- `/flows/*` — API key or session cookie.

- `/user-templates/*` — API key or session cookie.

Sending an API key

curl -X POST https://api.jetscrape.com/webhook/unblocker \
  -H "Content-Type: application/json" \
  -H "x-api-key: js_abc123xyz..." \
  -d '{ "url": "https://example.com", "selectors": [] }'

Sending a session

# Sign in and store the cookie
curl -X POST https://api.jetscrape.com/api/auth/sign-in/email \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{ "email": "you@example.com", "password": "password" }'
# Send it back on later requests
curl https://api.jetscrape.com/api/users/session -b cookies.txt

Reading a 401

Two different 401 bodies exist. Both mean the same thing: the request was not authenticated.

{ "code": "UNAUTHORIZED", "message": "Unauthorized" }
{ "statusCode": 401, "message": "Unauthorized", "error": "Unauthorized" }

Things to check:

- Are you using the `x-api-key` header rather than `Authorization`?

- Has the key been revoked (`enabled: false`)?

- Has the session expired? Sign in again.

Never ship an API key in client-side code — browser JavaScript, a mobile bundle or a public

repository. Keys carry your credit balance and stay valid until you revoke them.

Create one key per environment. If a key leaks you can revoke just that one without

interrupting anything else.

Last updated: September 21, 2026