A Sherpa API is provided at a URL, for example https://www.sherpadoc.org/example/.
Sherpa API's are designed to be easy to implement on the server side, and easy to use on the client (browser) side. A Sherpa API is usually implemented using a library, but writing Sherpa support directly into your application is also a viable option. This document describes how Sherpa API's work and what you must do to implement a Sherpa API.

Sherpa API's summarized:

The API describes its title, version, list of available functions in a JSON document.

The API provides a very simple JavaScript library that you can include from a web application.

An API function is called by a HTTP POST to a path named after the function call. Parameters and results are encoded as JSON. Errors are encoded in a standard format.

The API provides documentation through a function with the fixed name _docs. It returns the documentation in JSON format, containing markdown and with its version 1 also type information for parameters and return values.

This specification continues with the URL endpoints a Sherpa API must implement. We use sherpaweb's "Example API" as an example: https://www.sherpadoc.org/example/.

A GET on the API URL must return a JSON document (as shown above). All fields are required and must not be null.

Field

Type

Description

id

string

Short ID for this API. The JavaScript library stores the API object in a global variable with this name. Must match regular expression "[a-zA-Z][a-zA-Z0-9_]+"

title

string

Full human-readable name of this API.

version

string

Descriptive version string. Could be in the form of major.minor.patch. But a single API endpoint should not really have different "major" versions at different times. Incompatible API versions are best deployed at a new endpoint.

sherpaVersion

int

Version of the Sherpa specification. This specification is still work in progress, that's why it is still at version 0. In the future, backwards compatible changes (e.g. adding fields to the JSON object describing the API) may be made without increasing the version number. For incompatible changes, the version number will be increased. If a client library loads a Sherpa API with a version number is does not support (either too old or too new), it must generate an error.

baseurl

string

URL for this API.

functions

array of string

List of methods exported by the API. Parameter types and return types are not part of the API. Requiring specification of such types would make the API significantly more complex and much harder to keep programming language-independent. Most scripting languages would not make use of it anyway. The parameter and return value types should be specificied in the API documentation. Function names must match regular expression "[a-zA-Z_][a-zA-Z0-9_]+", though functions starting with an underscore have special meaning as described later.

This JavaScript library makes it trivial for frontend developers to start using a Sherpa API.

This library must set a global variable with the name of the "id" field from sherpa.json. This variable must be an object providing all functions exported by the API. Calling such a function from JavaScript must return a "thenable": an object with an attribute called then that has the signature "function(resolved, rejected) {...}". Resolved will be called with the result of a successful API call. Rejected will be called with an error object if the call failed. Error objects are described later in this document.

The thenable-objects can be transformed by setting the attribute _wrapThenable on the API object. By default, this is a function returning its parameter. Frontend developers may set this to a function that calls new Promise(thenable), for full promise-support.

The API object has a field _sherpa, containing the JSON document from sherpa.json.

A HTTP POST to the API URL followed by the function name calls that function. The request body must be a JSON document with a params field, an array with parameters. An example:

{
"params": [
"test",
123
]
}

The response is again a JSON document with fields result and/or error. A response must have at least one of those fields. Both can be present, but then one of them must be null.

On success, the result field contains the function return value. This value can be any valid JSON type, e.g. boolean, an array, an object, etc. The value of field "result" is passed as argument to the resolved function in the JavaScript library. An example:

{
"result": ["limited", "imagination"]
}

On error, the error field contains an error object. An error object in turn contains at least the following fields:

message, required. It should be a human-readable error message.

code, optional, can be null, but should be a string indicating the type of error. Programmers can write error-handling code that looks at this for the kind of error. API's should document the error codes they can emit, and their semantics.

HTTP status codes are not used to indicate success or failure. The POST should almost always return a status 200 "OK", so even if the function called returned an error. The exception is if the function name does not exist. In that case, the HTTP status should be 404 "File not Found". The rationale is that if an API disappears, or a programmer used an incorrect API URL, function calls would return status 404 as well, so Sherpa libraries should expect and gracefully handle 404's.

Errors at the protocol-level must have a code starting with "sherpa:". Errors not at the protocol level must use another prefix. Known codes:

Instead of using HTTP POST, you can also call a function with a HTTP GET. An optional query string parameter body (defaulting to no parameters) in the same format as the POST JSON body can be set to pass parameters. The response is the same as for HTTP POST requests.

JSONP is also supported: If the query string parameter callback is present, the repsonse will be a JavaScript file that calls the specified callback with the response object as parameter.

A GET on the Sherpa API base URL can provide free-form, useful information about the API. A typical response is to show a minimal page explaining this is a Sherpa API, and that has the JavaScript API loaded for quick experimentation, followed by a link to the documentation and more information about Sherpa in general.

The endpoints above are all that is needed to implement a Sherpa API. This section lists additional requirements.

The HTTP responses must include CORS-headers allowing use from other domains. This means the HTTP OPTIONS method must also be supported.

All data in Sherpa is UTF-8. This includes JSON request and response bodies, and JavaScript. Sherpa API's should check that the Content-Type of POST function calls is application/json. If the "charset" is set, it should be "utf-8". In the future, other content-types may be treated differently.

A Sherpa API provides documentation through the function _docs. It is a function like any other and as such can be called through a HTTP POST. The result is a JSON document that must adhere to a simple format. This format is called sherpadoc. Sherpaweb renders this document. The object is a toplevel "documentation"-object, that looks like this:

Documentation can be hierarchically arranged. With a top-level documentation object introducing the API. And further topics divided in sections, each with their functions. The full, flattened list of provided functions must be specified in sherpa.json. The documentation provides functions explicitly so tools like sherpaweb can place the functions in the right section and provide functionality to call a function. Only the top-level section should have a "version"-field. Version-fields in subsections should be ignored.

Both the main text and function text fields should be markdown. This allows you to easily create structure, or even include HTML for richer documentation.

Parameters are specified just like return values: With a "name" and "type".
Named types, in the "types" field, have a "name", "text" with documentation, and "fields", an array of fields. Each field has a "name", "text" as documention and a "type".
The "type" field in parameters, return values and named types share a format: An array of type tokens. Valid tokens are: "nullable", "any", "bool", "int", "float", "string", "[]", "{}" and named type identifiers of the form [a-zA-Z][a-zA-Z0-9]*. Production rules:

Error code semantics. Current error codes have a prefix that ends with a colon. An earlier version did not have a colon as separator. It was added to more explicitly partition the error code namespace.

An earlier version of sherpadoc did not have a "version"-field, and did not have the "types" field with named types and did not have "params" and "return" fields for function type information.