Authentication¶
The API uses Bearer token authentication. There's no OAuth flow, no session cookies — just a static API key.
Generating a key¶
See API keys for the full walk-through. Keys are generated in the portal under Profile → API keys and shown exactly once.
Sending the key¶
Pass it in the Authorization header on every request:
GET /api/v1/findings HTTP/1.1
Host: app.cred-watch.com
Authorization: Bearer cw_sk_a3f8...c2b1
Accept: application/json
curl¶
curl https://app.cred-watch.com/api/v1/findings \
-H "Authorization: Bearer $CREDWATCH_API_KEY"
Python (requests)¶
import os
import requests
headers = {"Authorization": f"Bearer {os.environ['CREDWATCH_API_KEY']}"}
r = requests.get(
"https://app.cred-watch.com/api/v1/findings",
headers=headers,
timeout=15,
)
r.raise_for_status()
findings = r.json()["data"]
Python (httpx)¶
import httpx
client = httpx.Client(
base_url="https://app.cred-watch.com",
headers={"Authorization": f"Bearer {api_key}"},
timeout=15.0,
)
r = client.get("/api/v1/findings", params={"status": "active", "min_score": 70})
r.raise_for_status()
Node.js (fetch)¶
const res = await fetch("https://app.cred-watch.com/api/v1/findings", {
headers: {
"Authorization": `Bearer ${process.env.CREDWATCH_API_KEY}`,
"Accept": "application/json",
},
});
if (!res.ok) throw new Error(`API ${res.status}`);
const { data, meta } = await res.json();
Go¶
req, _ := http.NewRequest("GET", "https://app.cred-watch.com/api/v1/findings", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("CREDWATCH_API_KEY"))
resp, err := http.DefaultClient.Do(req)
What requests look like to us¶
- Method allowed: GET, POST. PATCH/PUT/DELETE are not used.
- Content-Type for POST bodies: not required (current POST endpoints take their args from query parameters).
- Body: not used in v1 — filters and notes are passed as query parameters.
This may evolve in v2 when bulk operations land.
Failure modes¶
| Status | Body | Meaning |
|---|---|---|
| 401 | {"error": "missing_authorization"} |
No Authorization header |
| 401 | {"error": "invalid_token"} |
Token doesn't match any active API key |
| 401 | {"error": "revoked_token"} |
Token was revoked |
| 403 | {"error": "plan_required", "minimum": "growth"} |
Your plan doesn't include API access |
| 429 | {"error": "rate_limited"} + Retry-After header |
Over the per-minute limit |
Things to know¶
- Keys are static. No refresh, no expiry (unless you set one). Treat them like passwords.
- Keys are account-scoped, not user-scoped. Removing a team member does not revoke API keys — those are tied to the account, not any individual user. Revoke separately.
- CSRF doesn't apply. Bearer auth has no cookie attack vector; the portal's CSRF middleware explicitly skips
/api/*. - HTTPS only. HTTP requests get redirected.
- CORS. Cross-origin requests are not allowed by default. The API is intended for server-to-server use. Email us if you have a legitimate use case for browser-direct calls.