Quickstart
Zero to a stored credential — token, catalog, create, status — in four calls.
The shortest useful path through the service: authenticate, see what providers exist, store a key for one of them, and confirm the platform would actually use it.
Prerequisites
- The service base URL. Export it once:
export CREDS_BASE=http://localhost:8000(or your deployment's domain). - A user-plane token. In real environments that is a short-lived exchange token from the identity provider with
audience: provider-credentials-service— the full flow is in User Plane Tokens. Export it:export TOKEN=....
Local shortcut: dev auth mode
A locally run service with DEV_AUTH_ENABLED=true accepts identity headers instead of a JWT: X-Dev-User-Id: <any canonical UUID> and X-Dev-Roles: user (plus X-Dev-Org-Id/X-Dev-Org-Roles for an organization context). Replace the Authorization header with those two in any example below. Dev auth is refused in production builds.
1. See what providers exist
Call GET /v1/providers:
curl -s "$CREDS_BASE/v1/providers?category=mt" \
-H "Authorization: Bearer $TOKEN"
Every item carries a code — that is the identifier you store credentials against. Pick one, e.g. deepl_api, and fetch its full card with GET /v1/providers/{provider_code} — the credential_schema in the response tells you exactly which secret fields the next step must send. Details in Provider Schemas.
2. Store a credential
Call POST /v1/credentials. The server takes the owner from your token — the body never names one:
curl -s -X POST "$CREDS_BASE/v1/credentials" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider_code": "deepl_api",
"name": "My DeepL key",
"credentials": {"api_key": "your-secret-key"},
"make_default": true
}'
import httpx
CREDS_BASE = "http://localhost:8000"
headers = {"Authorization": f"Bearer {TOKEN}"}
r = httpx.post(f"{CREDS_BASE}/v1/credentials", headers=headers, json={
"provider_code": "deepl_api",
"name": "My DeepL key",
"credentials": {"api_key": "your-secret-key"},
"make_default": True,
})
assert r.status_code == 201, r.text
credential = r.json()
Expected 201: the record comes back with masked_credentials (e.g. you***key) instead of the secret — no user-plane endpoint ever returns plaintext (Personal Credentials). make_default: true made it your default for deepl_api, so resolve will pick it.
3. Confirm what the platform would use
Call GET /v1/providers/{provider_code}/credential-status:
curl -s "$CREDS_BASE/v1/providers/deepl_api/credential-status" \
-H "Authorization: Bearer $TOKEN"
Expected: "user_credentials_configured": true and "effective_credential_source": "user" — translation requests on your behalf will run on the key you just stored. The full meaning of every field (including the null-vs-false distinction on the organization level) is in Credential Status.
Where next
- The concepts behind what you just did: Core Concepts.
- Sharing one key with a whole organization: Organization Credentials.
- The runnable end-to-end version of this page: cookbook scenario 02.