Store your first credential
Create a personal default credential, read it back masked, and watch credential-status flip.
The core write path of the service: store a key, confirm it is masked everywhere, and see the platform acknowledge it as what your translations will run on.
Goal
End with an active default personal credential for one provider, and a credential-status that names user as the effective source.
Prerequisites
- A provider code and its required secret fields, from scenario 01.
$CREDS_BASE,$TOKEN.
Steps
1. Check status before
Call GET /v1/providers/{code}/credential-status. Expected 200 with "user_credentials_configured": false — nothing configured yet.
2. Create the credential
Call POST /v1/credentials:
curl -s -X POST "$CREDS_BASE/v1/credentials" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"provider_code": "'$CODE'",
"name": "My first key",
"credentials": {"api_key": "sk-live-0123456789abcdef"},
"make_default": true
}'
Expected 201: the record with owner_type: "user", status: "active", is_default: true, version: 1 — and masked_credentials instead of your secret (sk-***cdef-style). Save the id.
3. Read it back — still masked
import httpx
headers = {"Authorization": f"Bearer {TOKEN}"}
record = httpx.get(f"{CREDS_BASE}/v1/credentials/{cred_id}", headers=headers).json()
assert record["masked_credentials"]["api_key"] != "sk-live-0123456789abcdef"
assert "credentials" not in record # the plaintext field simply does not exist here
Expected: no user-plane response ever carries the secret. The list view (GET /v1/credentials) shows the same record with the same mask.
4. Check status after
Repeat step 1. Expected: "user_credentials_configured": true and "effective_credential_source": "user" — resolve would now serve your key.
Verified by the test test_s02_store_your_first_credential.