API Authentication Explained: Bearer, API Keys, OAuth 2.0, JWT and AWS SigV4

Auth · Updated August 2026 · ← All tips

Every API integration starts with the same question: how do I authenticate? This guide covers the six schemes you'll meet in practice — what actually goes over the wire, when each one is the right choice, and the mistakes that cost integration hours.

Bearer token

Authorization: Bearer eyJhbGciOi...

The workhorse of modern APIs: obtain a token (from a login endpoint, a dashboard, or an OAuth flow) and attach it to every request. The server doesn't care how you got it — whoever bears the token is authenticated, which is exactly why tokens must be short-lived and never committed to a repo.

Common pitfalls: missing the word Bearer before the token; using an expired token and misreading the resulting 401 as a server bug; pasting tokens directly into requests instead of a {{token}} variable.

Basic auth

Authorization: Basic base64(username:password)

Simple and universally supported, but the credentials travel with every request, merely base64-encoded — only acceptable over HTTPS. Today it survives mainly in internal tools, CI webhooks and as the transport for OAuth client credentials.

API key

X-API-Key: sk_live_...        # header (preferred)
GET /v1/data?api_key=...      # query param (avoid if you can)

A static secret identifying a project or account rather than a user. Prefer the header form: query-string keys end up in server logs, browser history and analytics. Rotate keys periodically and scope them (read-only vs read-write) when the provider allows it.

OAuth 2.0 — client credentials

For machine-to-machine integrations. Your client first calls the token endpoint:

POST /oauth/token
grant_type=client_credentials&client_id=...&client_secret=...&scope=read:orders

…receives an access token with an expiry, and uses it as a Bearer token until it expires. Two details matter when testing:

JWT — signed by the client

Some APIs (Google service accounts, Apple APIs, many fintech providers) require you to sign a JWT yourself on every request: build a payload with claims (iss, sub, iat, exp) and sign it with HMAC (HS256) or an RSA private key (RS256).

Pitfalls: clock skew — an iat a few seconds in the future gets rejected; forgetting exp; signing with the wrong key of a rotated pair. When debugging, decode the JWT (the payload is just base64) and read the claims before blaming the server.

AWS Signature v4

AWS-style APIs don't send a secret at all. The client derives a signature from the entire request — method, URL, sorted headers, hashed body, timestamp, region and service — and sends it in the Authorization header along with X-Amz-Date.

Because the signature covers the final bytes on the wire, any mutation after signing breaks it: a proxy adding a header, a client re-encoding the URL, a variable resolved after the signature was computed. Tools must sign the fully resolved request — RestRuno computes SigV4 over the final URL, headers and body for exactly this reason.

Which one should you use?

ScenarioScheme
User-facing app calling your own APIShort-lived Bearer (JWT session token)
Server-to-server, your infraOAuth 2.0 client credentials
Third-party developer accessAPI keys (scoped, rotatable)
AWS or AWS-compatible servicesSignature v4
Provider mandates client-signed tokensJWT (HS/RS)
Legacy/internal, HTTPS onlyBasic

Testing tip: whatever the scheme, keep credentials in environment variables ({{clientSecret}}), never in the request files you commit. Then verify the negative cases too: no credentials → 401, someone else's resource → 403. See the API security testing checklist.

All six schemes, built in

RestRuno supports Bearer, Basic, API key, OAuth 2.0 client credentials (with token caching), client-signed JWT and AWS Signature v4 — with variables in every field so secrets stay in your environments.

Download RestRuno — free