Owner and boundary
A source tells Lizzy how to serve teacher requests and which calls may be retained. Your server sends the usual OpenAI-compatible request through the proxy. A managed source uses a model selected in Lizzy; a BYOK source forwards the request to your own provider.
An authorized REST client or a person in the dashboard creates and edits sources. Pilot can inspect safe source metadata and prepare a dashboard handoff, but it does not receive BYOK credentials or captured bodies.
Choose a managed or BYOK source
Lizzy-managed
No provider key is needed. The source stores kind: managed and oneteacher_model from the model catalog. Lizzy serves the call with that model.
BYOK
The source stores kind: byok, base_url, andupstream_key. Lizzy forwards POST /v1/proxy/chat/completionsverbatim.
Managed usage is billed per input and output token at the catalog rates. The displayed rates already include margin. A live managed call charges the workspace balance; a test-modelz_test_ call records the cost on the capture but is never charged. BYOK calls have captured cost 0 because the workspace pays its provider directly.
Select a managed teacher from the model catalog
- 1
Choose the connection type
In a new loop, open
Connection type.Lizzy-managedis selected by default. ChooseUse my provider keyfor BYOK. - 2
Search the model picker
The managed picker searches the current model catalog and shows input and output prices per million tokens. Select the model that should answer proxied calls.
- 3
Edit the saved connection when needed
The loop's
Connectionsection has an Edit action. Managed sources can switch models; BYOK sources can rotate their URL and key. Either kind can be active or disabled.
/v1/distill/teachersReturn the managed model catalog. Bearer authentication with distill:read is required.
curl --fail-with-body --silent --show-error "https://lizzy.albinilabs.com/v1/distill/teachers" -H "Authorization: Bearer $LIZZY_API_TOKEN"
{
"object": "distill_teacher_catalog",
"stale": false,
"models": [
{
"id": "google/gemini-3.7-flash",
"display_name": "Google: Gemini 3.7 Flash",
"context_length": 1048576,
"pricing": {
"input": {
"amount": 49,
"amount_decimal": "0.4875",
"currency": "usd"
},
"output": {
"amount": 244,
"amount_decimal": "2.4375",
"currency": "usd"
}
}
}
]
}
The catalog contains more than 400 models and refreshes continuously behind a short server-side cache. Prices are USD per million tokens and are the rates actually billed.stale: true means Lizzy returned a recent snapshot while catalog refresh recovers.
Create and update a source
Create the source with the same live or test token that will call the proxy. The loop groups provenance, and name can select the source through X-Lizzy-Source. Capture resources are mode-isolated even though the loop spans modes.
Create a managed source
Use a current catalog id as teacher_model. A managed source rejectsbase_url and upstream_key. The kind field is create-only.
curl --fail-with-body --silent --show-error -X POST "https://lizzy.albinilabs.com/v1/distill/sources" -H "Authorization: Bearer $LIZZY_API_TOKEN" -H "Content-Type: application/json" -H "Idempotency-Key: source-support-teacher-v1" --data '{
"name": "support-teacher",
"loop": "dlp_REPLACE_ME",
"kind": "managed",
"teacher_model": "google/gemini-3.7-flash"
}'
Persist the returned source id. An unknown model returns HTTP 400teacher_model_unknown. If no catalog snapshot can be read, creation returns HTTP 503 catalog_unavailable.
Switch the managed model
curl --fail-with-body --silent --show-error -X PATCH "https://lizzy.albinilabs.com/v1/distill/sources/dsc_REPLACE_ME" -H "Authorization: Bearer $LIZZY_API_TOKEN" -H "Content-Type: application/json" --data '{"teacher_model":"google/gemini-3.7-flash"}'
The new catalog rate and model apply immediately after a successful patch. Do not sendkind when updating a source.
Create a BYOK source
BYOK creation is unchanged. Omit kind or send kind: byok. The response never echoes upstream_key.
curl --fail-with-body --silent --show-error -X POST "https://lizzy.albinilabs.com/v1/distill/sources" -H "Authorization: Bearer $LIZZY_API_TOKEN" -H "Content-Type: application/json" -H "Idempotency-Key: source-provider-teacher-v1" --data '{
"name":"provider-teacher",
"loop":"dlp_REPLACE_ME",
"kind":"byok",
"base_url":"https://provider.example.com/v1",
"upstream_key":"<provider-key>"
}'
Capture policy fields are shared by both source kinds. Pattern redaction recognizesemail, phone, credit_card, ssn, andip_address. Drop paths use dot-separated object keys and [] for array traversal. Unknown redaction fields return unknown_parameter rather than disabling redaction.
Proxy an OpenAI-compatible request
Change only the client base URL and credential. The request body still requiresmodel. On a managed source, that value is recorded asmodel_requested, while the source's teacher decides what serves and is recorded as model_served. On a BYOK source, the request is forwarded verbatim.
X-Lizzy-Source is optional and selects a source when the workspace has several.X-Lizzy-External-Id joins the capture to your system; tags are comma-separated labels for later filtering. Streaming works for both source kinds.
curl --fail-with-body --silent --show-error "https://lizzy.albinilabs.com/v1/proxy/chat/completions" -H "Authorization: Bearer $LIZZY_API_TOKEN" -H "Content-Type: application/json" -H "X-Lizzy-Source: support-teacher" -H "X-Lizzy-Tags: support,refund" -H "X-Lizzy-External-Id: ticket-123" --data '{"model":"anything","messages":[{"role":"user","content":"Can I change my delivery address?"}]}'
Label the outcome and verify capture
- 1
List metadata, not bodies
Call
GET /v1/distill/calls?external_id=ticket-123. Lists exposemodel_requested,model_served, tokens, latency, billed cost, tags, source, feedback, and body status without returning prompts or answers. - 2
Check failed calls before retrying
Failed calls remain visible on the Capture page and are never billed. Keep their call IDs and failure metadata when deciding whether a retry is safe.
- 3
Attach the product outcome
Post feedback with exactly one of
callorexternal_id. A score is a number from -1 to 1;thumbs_upandthumbs_downare also accepted. - 4
Use the same labels in data filters
Source IDs, tags, served-by values, and feedback scores let a later dataset describe why each row belongs in training instead of relying on an opaque export.
curl --fail-with-body --silent --show-error -X POST "https://lizzy.albinilabs.com/v1/distill/feedback" -H "Authorization: Bearer $LIZZY_API_TOKEN" -H "Content-Type: application/json" --data '{"external_id":"ticket-123","score":1,"comment":"Address updated","tags":["resolved"]}'
Posting feedback again updates the current opinion on the newest matching external ID. It is not an append-only event log, so keep your own history if the sequence matters.
Redaction and retention are observable states
- 1stored
The body was sampled, redacted according to policy, and remains available to an authorized human.
- 2sampled_out
Metadata exists, but the body was intentionally never stored.
- 3redacted
A deletion request purged the body while preserving metrics and provenance.
- 4expired
Retention removed the body; the metadata row remains for audit and aggregate use.
GET /calls/{call_id}/body distinguishes an unknown call from a body that never existed and one that was removed. DELETE /calls/{call_id} is a body purge, not a wholesale removal of metering or provenance.
Diagnose capture without retry loops
{
"error": {
"type": "api_error",
"code": "teacher_unavailable",
"message": "The managed model is temporarily unavailable upstream. Retry shortly, or switch this source to a different model."
}
}
Managed model failures use this body with the original status code. They are captured and never billed.
/v1/distill/calls?external_id={your_id}The safest first diagnostic: it proves whether the call reached capture and shows source, requested and served models, billed cost, body status, latency, and feedback metadata.