HTTP API
If a client is
not available for your programming language yet, your app can interact
directly with the Endb HTTP API.
Any HTTP client may be used but in the examples below we'll use curl
to demonstrate the API without writing any code.
You can send SQL statements to endb
over HTTP:
curl -d "INSERT INTO users (name) VALUES ('Tianyu')" -H "Content-Type: application/sql" -X POST http://localhost:3803/sql
curl -d "SELECT * FROM users" -H "Content-Type: application/sql" -X POST http://localhost:3803/sql
You can send SQL to endb
with standard HTTP Query Parameters, Verbs,
Content Types, Accept Headers, and HTTP Basic Authentication.
Each one is outlined below.
HTTP Query Parameters
The query parameters Endb's HTTP endpoint accepts are:
q
- (q)uery: a SQL query, optionally parameterizedp
- (p)arameters: named or positional parametersm
- (m)any parameter lists: bulk parameters, used for bulk insert/update
HTTP Verbs
POST
allows explicit Content Types and Accept headers:
curl -d 'SELECT 1' -H "Content-Type: application/sql" -H "Accept: text/csv" -X POST http://localhost:3803/sql
GET
allows a single, simple URL.
GET
does not permit DML.
curl -X GET "http://localhost:3803/sql?q=SELECT%201"
Content Types
The HTTP Content-Type
header is used to specify what
format the client is sending data to Endb.
application/json
:
curl -d '{"q": "SELECT * from products;"}' -H "Content-Type: application/json" -X POST http://localhost:3803/sql
curl -d '{"q": "SELECT * from products WHERE name = ?;", "p": ["Salt"]}' -H "Content-Type: application/json" -X POST http://localhost:3803/sql
curl -d '{"q": "INSERT INTO products {name: :name};", "p": {"name": "Paprika"}}' -H "Content-Type: application/json" -X POST http://localhost:3803/sql
NOTE: To enable strongly-typed values, payloads sent with
the application/json
content type have values resolved with JSON-LD scalars.
Standard JSON values are a subset of JSON-LD scalars, so data sent as regular
JSON is unaffected by this behaviour.
application/ld+json
Although values in the application/json
content type are resolved using
JSON-LD scalars, you can explicitly specify an application/ld+json
content type to avoid all ambiguity.
See JSON-LD.
curl -d '{"q": "INSERT INTO events {start: :start};", "p": {"start": {"@type": "xsd:dateTime", "@value": "2011-04-09T20:00:00Z"}}}' -H "Content-Type: application/ld+json" -X POST http://localhost:3803/sql
application/sql
:
curl -d 'SELECT 1' -H "Content-Type: application/sql" -X POST http://localhost:3803/sql
Submit parameters to application/sql
by providing form data or query parameters.
Form data and query parameters can be combined, though it is not necessarily recommended.
curl -F q="INSERT INTO sauces {name: ?, color: ?};" -X POST http://localhost:3803/sql?p=%5B%22ketchup%22%2C%22purple%22%5D
multipart/form-data
curl -F q="SELECT * from products;" -H "Content-Type: multipart/form-data" -X POST http://localhost:3803/sql
curl -F q="INSERT INTO products {name: ?};" -F p='["Sriracha"]' -X POST http://localhost:3803/sql
NOTE: Many HTTP clients (including curl
) automatically assume a content type of
multipart/form-data
when form fields are provided.
This is true for curl
when the -F
(--form
) argument is used and it has
been elided from further examples.
application/x-www-form-urlencoded
Although the other content types are preferable for obvious reasons,
application/x-www-form-urlencoded
is offered for completeness.
curl -d 'q=SELECT%20*%20FROM%20products;' -H "Content-Type: application/x-www-form-urlencoded" -X POST http://localhost:3803/sql
Accept Headers
The HTTP Accept
header is used to specify how data is returned to
the Endb client.
The default Accept
header content type is application/json
.
text/csv
text/csv
returns comma-separated rows.
Column order from the SELECT
clause is maintained.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,'csv')) t1" -H "Content-Type: application/sql" -H "Accept: text/csv" -X POST http://localhost:3803/sql
returns:
"column1","column2"
2,"csv"
1,"hello"
application/json
application/json
returns rows as an array of JSON tuples.
Column order from the SELECT
clause is maintained.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,DATE('2023-07-22'))) t1" -H "Content-Type: application/sql" -H "Accept: application/json" -X POST http://localhost:3803/sql
returns:
[[2,"2023-07-22"],[1,"hello"]]
application/x-ndjson
application/x-ndjson
returns newline-delimited JSON documents.
Column order from the SELECT
clause is not maintained.
JSON documents cannot guarantee column order.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,DATE('2023-07-22'))) t1" -H "Content-Type: application/sql" -H "Accept: application/x-ndjson" -X POST http://localhost:3803/sql
returns:
{"column1":2,"column2":"2023-07-22"}
{"column1":1,"column2":"hello"}
application/ld+json
application/ld+json
returns documents of strongly-typed ("Linking Data") JSON records.
Column order from the SELECT
clause is not maintained.
JSON documents cannot guarantee column order.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,DATE('2023-07-22'))) t1" -H "Content-Type: application/sql" -H "Accept: application/ld+json" -X POST http://localhost:3803/sql
returns:
{"@context":{"xsd":"http://www.w3.org/2001/XMLSchema#","@vocab":"http://endb.io/"},"@graph":[{"column1":2,"column2":{"@value":"2023-07-22","@type":"xsd:date"}},{"column1":1,"column2":"hello"}]}
See JSON-LD.
multipart/mixed
multipart/mixed
returns documents as a valid multipart/mixed
response,
albeit all as LD-JSON.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,DATE('2023-07-22'))) t1" -H "Content-Type: application/sql" -H "Accept: multipart/mixed" -X POST http://localhost:3803/sql
returns:
--369d7885-c6e9-4b01-93c9-9449a5fcd637
Content-Type: application/ld+json
{"@context":{"xsd":"http://www.w3.org/2001/XMLSchema#","@vocab":"http://endb.io/"},"@graph":[{"column1":2,"column2":{"@value":"2023-07-22","@type":"xsd:date"}},{"column1":1,"column2":"hello"}]}
--369d7885-c6e9-4b01-93c9-9449a5fcd637--
application/vnd.apache.arrow.file
application/vnd.apache.arrow.file
returns columnar data as an Apache Arrow file.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,DATE('2023-07-22'))) t1" -H "Content-Type: application/sql" -H "Accept: application/vnd.apache.arrow.file" -X POST http://localhost:3803/sql --output hello.arrow
The above command returns a file containing a single RecordBatch
in an Apache Arrow file in IPC format.
You can examine the file with functions like
pyarrow.ipc.open_file
,
as seen in this gist.
application/vnd.apache.arrow.stream
application/vnd.apache.arrow.stream
returns columnar data as an Apache Arrow stream.
curl -d "SELECT * FROM (VALUES (1,'hello'), (2,DATE('2023-07-22'))) t1" -H "Content-Type: application/sql" -H "Accept: application/vnd.apache.arrow.stream" -X POST http://localhost:3803/sql --output streamed.arrows
The above command returns a file containing an Apache Arrow IPC stream.
You can examine the file with functions like
pyarrow.ipc.open_stream
,
as seen in this gist.
HTTP Basic Authentication
Endb supports HTTP Basic Authentication as defined by
RFC 7235.
Pass --username
and --password
arguments to the endb
binary to force
basic authentication for HTTP connections.
(See Operation for more details, including environment variables
which can be passed to Docker images.)
./target/endb --username zig --password zag
Then, from any HTTP client, provide the username and password combination to execute queries.
curl --user zig:zag -d "SELECT 'Hello World';" -H "Content-Type: application/sql" -X POST http://localhost:3803/sql
If the client passes an incorrect username or password, it will receive a
401 Authorization Required
HTTP status code as a result, but no body.
Be aware of this to ensure client code is written to detect 401 status codes.
$ curl -i --user zig:wrong -d "SELECT 'Hello World';" -H "Content-Type: application/sql" -X POST http://localhost:3803/sql
HTTP/1.1 401 Authorization Required
NOTE: HTTP Basic Auth is not secure without the additional use of HTTPS.
Parameters
SQL parameters are available to:
application/json
andapplication/ld+json
as part of thePOST
bodymultipart/form-data
as form dataapplication/x-www-form-urlencoded
as URL query parametersapplication/sql
as form data and/or URL query parameters
Parameters can be JSON literals, JSON-LD scalars, or SQL literals.
A JSON-LD scalar always has the form: {"@type": "xsd:TYPE", "@value": "DATA"}
.
JSON-LD types are listed under the Data Types table.
Named Parameters
Named parameters substitute parameter placeholders with the form :param
by the parameter key with the corresponding name.
Named parameters are represented as a JSON object.
curl -d '{"q": "INSERT INTO products {name: :name, price: :price};", "p": {"name": "Paprika", "price": 2.99}}' -H "Content-Type: application/json" -X POST http://localhost:3803/sql
curl -d '{"q": "INSERT INTO events {start: :start};", "p": {"start": {"@type": "xsd:dateTime", "@value": "2011-04-09T20:00:00Z"}}}' -H "Content-Type: application/ld+json" -X POST http://localhost:3803/sql
curl -F q="INSERT INTO products {name: :sauce};" -F p='{"sauce": "Sriracha"}' -X POST http://localhost:3803/sql
Positional Parameters
Positional parameters substitute parameter placeholders with the form ?
by the parameter values, in the order they appear.
Positional parameters are respresented as a JSON array.
curl -d '{"q": "SELECT * FROM products WHERE name = ? AND price > ?;", "p": ["Salt", 3.99]}' -H "Content-Type: application/json" -X POST http://localhost:3803/sql
curl -d '{"q": "INSERT INTO events {start: ?};", "p": [{"@type": "xsd:dateTime", "@value": "2011-04-09T20:00:00Z"}]}' -H "Content-Type: application/ld+json" -X POST http://localhost:3803/sql
curl -F q="INSERT INTO products {name: ?};" -F p='["Sriracha"]' -X POST http://localhost:3803/sql
Bulk Parameters
Bulk operations are possible by setting the m
flag to true
.
Bulk operations are available to both named and positional parameters.
The list of parameters supplied in bulk must be nested in an array.
curl -d '{"q": "INSERT INTO products {name: :name};", "p": [{"name": "Soda"}, {"name": "Tonic"}], "m": true}' -H "Content-Type: application/json" -X POST http://localhost:3803/sql
curl -F q="INSERT INTO sauces {name: ?, color: ?};" -F p='[["Mustard", "Yellow"], ["Ketchup", "Red"]]' -F m=true -X POST http://localhost:3803/sql
Apache Arrow File Parameters
As it is possible to receive Apache Arrow data from an Endb query,
it is possible to submit Apache Arrow as a statement parameter.
The example below assumes the existence of a a table called names
,
which only contains one column (name
).
Apache Arrow Streams can also be used as parameters in the same way.
# create a sample Arrow file:
curl -d "SELECT * FROM names;" -H "Content-Type: application/sql" -H "Accept: application/vnd.apache.arrow.file" -X POST http://localhost:3803/sql --output names.arrow
# use the sample Arrow file:
curl -F m=true -F q="INSERT INTO projects {name: :name};" -F "p=@names.arrow;type=application/vnd.apache.arrow.file" -X POST http://localhost:3803/sql
NOTE: This feature should be used with caution. Do not submit arbitrary Arrow files as parameters. If a malformed Arrow file is submitted, the error message returned (if any) is unlikely to provide guidance. Preferably, Arrow files should be created using Endb itself, as in the example above. Most users will prefer to use a human-readable file format instead, such as a JSON variant or static SQL statements.
Bulk Insert
Bulk inserts are possible by combining the tools mentioned under Parameters.
For example, the OBJECTS
keyword can insert an
array of object literals.
Note that each object used as a positional parameter must be wrapped in a JSON array,
since there may be more than one positional parameter supplied.
Similarly, each named parameter must be wrapped in an object containing a key of the
corresponding name.
curl -F m=true -F q="INSERT INTO products OBJECTS ?" -F p="[[{name: 'jam'}], [{name: 'butter'}]]" -X POST http://localhost:3803/sql
curl -F m=true -F q="INSERT INTO products OBJECTS :product" -F p="[{product: {name: 'jelly'}}, {product: {name: 'ghee'}}]" -X POST http://localhost:3803/sql
Multiple Statements
It is possible to pass multiple SQL statements to Endb by delimiting them with semicolons. Parameters will be passed to all statements in order.
Only the result of the last statement is returned to the client.
In the following example, the INSERT
will be successful but will not
return a result.
The SELECT
will return to the client.
curl --form-string q="INSERT INTO sauces {name: ?, color: ?}; SELECT {namo: ?, colour: ?};" -F p='["Mustard", "Yellow", "Ketchup", "Red"]' -X POST http://localhost:3803/sql
NOTE: --form-string
is required instead of --form
to send semicolon-delimited
statements with curl
.