Skip to content

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 ​

Assume a SQL function named recommend already exists. Its API definition is:

sql
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:

text
POST /api/v1/recommend

Use OR REPLACE to overwrite an API with the same name. See Writing a Recommendation Flow for SQL function syntax.

Load the API definition in the same way as the SQL function. If you use SQL files, save the statement above as api/recommend.sql and restart the service; see Managing Local SQL Definitions for the steps. If you use remote metadata, run the statement through Beeline or JDBC.

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:

sql
DEFINE INPUT TABLE user_info (
  user_id BIGINT
);

send:

bash
curl -X POST http://localhost:30001/api/v1/recommend \
  -H 'Content-Type: application/json' \
  -d '{
    "data": {
      "user_info": [
        {"user_id": 1000001}
      ]
    }
  }'

For multiple inputs, add each table under data:

json
{
  "data": {
    "user_info": [{"user_id": 1000001}],
    "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`:

json
{
  "data": {
    "user_info": [{"user_id": 1000001}]
  },
  "params": {
    "limit_count": "10",
    "experiment": "rank_v2"
  }
}
sql
SELECT CAST(`get_or_default`('limit_count', '50') AS INT);

Read the Response ​

On success, data contains the rows returned by the function and params contains the final execution variables:

json
{
  "data": [
    {"item_id": 2001, "score": 0.96},
    {"item_id": 2002, "score": 0.91}
  ],
  "params": {
    "limit_count": "10"
  }
}

Normal execution returns HTTP 200. An empty result has data: []; when the function completes without returning a table, msg explains the result. Invalid request formats return HTTP 400. Function execution failures return HTTP 500 with an explanation in msg.

Check the HTTP status first, then read the result or error message. Unmatched paths return 404, and unsupported methods return 405.

Advanced Option: Metric Labels ​

To attach labels to metrics generated by this call, provide metricTags:

json
{
  "data": {
    "user_info": [{"user_id": 1000001}]
  },
  "metricTags": {
    "scene": "homepage"
  }
}

See Observability for the scope of metricTags and guidance on label values.

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 name in /api/v1/{api_name} matches the API definition and that the definition was loaded as described in Publish a Function.

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.