Publishing and Calling an API
After defining a SQL function, publish it as an HTTP API. Callers provide the declared input data without needing to know how recall, ranking, or other internal steps are implemented.
Publish a Function
First, check which metadata mode you are using:
- Docker demo (local file mode): The built-in
demo_recis already published; call it as shown in the quick start. To publish your own API, save the function definition and the API definition below as separate.sqlfiles in the mounted directory, then restart the container. You cannot runCREATE APIin the CLI or through/sql/v1. See Modify the Demo SQL for the file layout and Managing Local SQL Definitions for mounting it. - Full service (remote metadata mode): Connect to SQLRec through Beeline or JDBC and run the
CREATE APIstatement below. See Service Deployment for setup.
Assume a SQL function named recommend already exists. Its API definition is:
CREATE OR REPLACE API recommend WITH recommend;The first recommend is the API name; the name after WITH is the SQL function. The published endpoint is:
POST /api/v1/recommendUse OR REPLACE to overwrite an API with the same name. The /api/v1/recommend request below works only after you define and publish recommend; to try the Docker demo directly, use /api/v1/demo_rec. See Writing a Recommendation Flow for SQL function syntax.
Send a Request
The data object maps each input-table name to an array of rows. Every table declared with DEFINE INPUT TABLE must be present, and its fields must match the declaration.
For this input:
DEFINE INPUT TABLE user_info (
user_id BIGINT,
country VARCHAR
);send:
curl -X POST http://localhost:30001/api/v1/recommend \
-H 'Content-Type: application/json' \
-d '{
"data": {
"user_info": [
{"user_id": 1001, "country": "CN"}
]
}
}'For multiple inputs, add each table under data:
{
"data": {
"user_info": [{"user_id": 1001, "country": "CN"}],
"context": [{"page": "home"}]
}
}Pass Execution Parameters
Use params for request-level settings such as result limits, experiment groups, or dynamically selected functions. Values must be strings. Read them in SQL with `get` or `get_or_default`:
{
"data": {
"user_info": [{"user_id": 1001, "country": "CN"}]
},
"params": {
"limit_count": "10",
"experiment": "rank_v2"
}
}SELECT CAST(`get_or_default`('limit_count', '50') AS INT);To attach labels to metrics generated by this call, provide metricTags:
{
"data": {
"user_info": [{"user_id": 1001, "country": "CN"}]
},
"metricTags": {
"scene": "homepage"
}
}See Observability for the scope of metricTags and guidance on label values.
Read the Response
On success, data contains the rows returned by the function and params contains the final execution variables:
{
"data": [
{"item_id": 2001, "score": 0.96},
{"item_id": 2002, "score": 0.91}
],
"params": {
"limit_count": "10"
}
}When a function returns no data or execution fails, msg explains the result. Routing and request-format errors use HTTP status codes, while a function execution error may be reported in msg; callers should check both.
Troubleshooting
An input table is missing
Make sure every key under data exactly matches a DEFINE INPUT TABLE name. Include all declared inputs; use an empty array when a table has no rows.
Field conversion fails
Check field names and JSON values against the declared SQL types, especially numbers, arrays, and time fields.
The API is not found
Confirm that the API is published and call /api/v1/{api_name} with exactly one API name after the prefix. In the Docker demo, check that the mounted directory contains the API definition and restart the container after changing files. In the full service, use SHOW APIS to check that it was created.
What is the difference between /sql/v1 and /api/v1?
/api/v1/{api_name} invokes a published business function and is the recommended integration endpoint. /sql/v1 submits SQL directly, is controlled by a service setting, and should not be exposed as a normal business API.
See the SQL Syntax Reference for the full API definition syntax.