Manage Datasources
This use case covers the full datasource lifecycle via API: create a connection, validate it, trigger semantic extraction, and bind the datasource to a Custom Model — so it is ready for analytical queries.
Sequence Overview
1. Create datasource → datasource_id
2. Validate connection → confirm reachability
3. Trigger semantic extraction → wait for completion
4. Bind to a Custom Model → ready for chat
Each step is required in order. Skipping semantic extraction means the AI has no knowledge of the tables and columns.
1. Create a Datasource
curl -X POST "$LHC_SEMANTIC/api/v1/semantic/datasources" \
-H "Authorization: Bearer $LHC_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Sales Database",
"type": "postgresql",
"connection_uri": "postgresql://readonly_user:secret@db.example.com:5432/sales"
}'
ds = requests.post(
f"{SEMANTIC}/api/v1/semantic/datasources",
headers=HEADERS,
json={
"name": "Sales Database",
"type": "postgresql",
"connection_uri": "postgresql://readonly_user:secret@db.example.com:5432/sales",
},
).json()
datasource_id = ds["id"]
print(f"Created datasource: {datasource_id}")
For the full list of supported type values and the required connection fields per type, see Datasource Types.
2. Validate the Connection
Before triggering extraction, verify that the database is reachable:
curl -X PUT "$LHC_SEMANTIC/api/v1/semantic/datasources/id/$DATASOURCE_ID/operations" \
-H "Authorization: Bearer $LHC_TOKEN" \
-H "Content-Type: application/json" \
-d '{"test_connection": true}'
result = requests.put(
f"{SEMANTIC}/api/v1/semantic/datasources/id/{datasource_id}/operations",
headers=HEADERS,
json={"test_connection": True},
).json()
print(result) # {"success": true} or error detail
3. Trigger Semantic Extraction
Semantic extraction reads the database schema and generates descriptions for all tables and columns. This step is required before any analytical queries can run.
curl -X PUT "$LHC_SEMANTIC/api/v1/semantic/datasources/id/$DATASOURCE_ID/operations" \
-H "Authorization: Bearer $LHC_TOKEN" \
-H "Content-Type: application/json" \
-d '{"create": true}'
requests.put(
f"{SEMANTIC}/api/v1/semantic/datasources/id/{datasource_id}/operations",
headers=HEADERS,
json={"create": True},
)
Extraction runs asynchronously. It typically completes within seconds to a few minutes depending on the schema size. You can poll the datasource status to confirm completion:
import time
while True:
status = requests.get(
f"{SEMANTIC}/api/v1/semantic/datasources/id/{datasource_id}",
headers=HEADERS,
).json()
if status.get("is_ready"):
print("Semantic extraction complete")
break
time.sleep(5)
4. Bind Datasource to a Custom Model
Once extraction is complete, bind the datasource to an existing Custom Model:
curl -X POST "$LHC_SEMANTIC/api/v1/semantic/datasourcemodels" \
-H "Authorization: Bearer $LHC_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"datasource_id\": \"$DATASOURCE_ID\", \"model_id\": \"$MODEL_ID\"}"
requests.post(
f"{SEMANTIC}/api/v1/semantic/datasourcemodels",
headers=HEADERS,
json={"datasource_id": datasource_id, "model_id": model_id},
)
The model is now ready to answer questions about this datasource. See Session Completions.
List Datasources
datasources = requests.get(
f"{SEMANTIC}/api/v1/semantic/datasources",
headers=HEADERS,
).json()
for ds in datasources:
print(ds["id"], ds["name"], ds["type"], ds.get("is_ready"))