Skip to main content

Building APIs

Basics

Any Snapi expression can be turned into an API endpoint. The simplest expressions like 1+1 can be used to generate an output. It needs to be set in a function, like in:

foo() = 1+1

Of course, things more useful can be done with expressions. For instance if we want to check which products are low on stock from a MySQL table, we would create something like the following:

stock.snapi
lowstock() =
let
data = MySQL.InferAndRead("mysql001", "products")
in
Collection.Filter(data, x -> x.stockcount < 5)
It is a good practice to tryout the expression in the scratchpad before wiring it in a function.

Once a function is available in a code file, we can turn it into a REST API endpoint by describing it in a YML file.

stockalert.yml
raw: '{{version}}'
endpoint: GET
code: snapi
codeFile: stock.snapi
declaration: lowstock
format: json
computeClass: normal
security:
public: false

This YML file describes an HTTP GET endpoint named stockalert (the file name becomes the endpoint name) which is mapped to a Snapi function named lowstock located in a file named stock.snapi

A Snapi code file can contain multiple functions and they can all be published as endpoints. It is also possible to create multiple YML files for the same function.

Endpoint, base path and route

Let's have a look at this URI:

https://dev-01.raw-labs.com/acme/v1/private/stockalert

https://dev-01.raw-labs.com/ is the base path (URL) and acme/v1/private/stockalert is the route.

An endpoint represents an action which returns data; in other terms, it is the HTTP GET operation on the URI https://dev-01.raw-labs.com/acme/v1/private/stockalert

dev-01 is the RAW subdomain assigned to the account being used.

The route is composed with three things:

{publishURL}/{GitHub repository relative directory}/{YML file name without extension}

In our example, {publishURL} is 'acme'.This value is set globally in the raw-site.yml file located in the GitHub repository root folder. Typically, this could be the name of a partner, supplier or team you want to share data with; or the stock data sharing project as a whole.

{GitHub repository relative directory} is the GitHub folder where the YML file describing the endpoint is located.

This could be setup the following way in GitHub:

github.com/raw-labs             => GitHub account
│ README.md
└───stock-project => RAW enabled API repository
| | raw-site.yml => API global parameters
│ └───V1
│ └───private => V1/private : relative directory
│ │ stock.snapi => code
│ │ stockalert.yml => endpoint description
│ │ ...

└───other-stuff
│ ...

Deployment

Expressions go into functions which are mapped into endpoints with a pair of files: the code file and the YML description file. Whenever the "git push" button is hit and these files get uploaded on the RAW enabled API repository, the deployment process will start.

If anything goes wrong during the deployment (compilation error, missing values, YML construction errors...)

none of the API endpoints will go live. It is all or nothing.

The deployment time may vary, depending on the number of endpoints, files, code lentgh and complexity. The API deployment status can be monitored in the Producer administration web interface, under the Monitoring tab. Monitoring Tab

In this list, the state column can take three different values: "IN PROGRESS", "FAILED" or "SUCCESS". In case of errors, detailed information is available by clicking the Messages or Branches views on the right.

Disabling or removing an Endpoint

Disabling an endpoint is achieved by setting the enabled field to false in its YAML file and committing the change to GitHub. The RAW repository reader app will notice the change and disable the endpoint.

Removing an endpoint is done by deleting the {endpoint}.yml file and committing the change to the GitHub repository.

Handling query parameters

Parameters in functions

It is possible to pass parameters to functions. This is done through the following syntax:

hello(name: string) = "Hello " + name + "!"

Arguments can have default values:

hello(name: string = "Anonymous") = "Hello " + name + "!"

Endpoint query parameters

Published endpoints are mapped to functions. The function declaration will determine the endpoint behavior regarding parameters, the rules applying to the function will apply similarly to endpoints. For instance:

// Mandatory => .../hello?name="Joe"
hello(name: string) = ...

// Optionnal => .../hello (will use "Anonymous") or .../hello?name="Joe"
hello(name: string = "Anonymous") = ...