How To Read This Documentation

For this documentation we are going to use curl with the headers:

  • accept: application/json
  • content-type: application/json

If you prefer you can create an alias in your current shell, add to your shell script profile, or set the equivalent in the software you are using, the alias is as follow:

alias curl='curl -s -H "accept: application/json" -H "content-type: application/json"'
                      

Another standard of this documentation is that whenever we share the output it is going to be formatted with the jq command line software.

A simple example of jq is:

$ echo '{"ok":true}' | jq
{
  "ok": true
}
                      

The final standard is: with the exception of the commands in this introduction section all of the other commands are not going to have any shell indicator like $, #, %, or any other.

Authentication

There are several ways to authenticate on the API, including a re-authentication one (or refresh token if you will).

Basic Auth

We recommend basic auth only in development mode or when writing simple scripts (the kind that does not do more than 5 requests). Because this is a slow form of authentication.

For example to get information about your session:

curl \
  -X GET \
  -u [email protected]:password \
  "https://api.simpleserviceorder.com/_session"
                      

The output is:

{
  "ok": true,
  "userCtx": {
    "name": "usr-9fcc027ca99e44468227bef4c4440d5c",
    "roles": [
      "acc-1e36d77db5434f3cbded1bb07db403c1"
    ]
  }
}
                      

Bearer Token

Getting a token means you authenticate with a slow process, and after that you only use the token.

Using username and password is slow because we have algorithms in place to prevent Timing attacks

The endpoint to get a token is POST /_session.

Here you can use Basic Auth for the request:

curl \
  -X POST \
  -u [email protected]:password \
  "https://api.simpleserviceorder.com/_session"
                      

Or add the information within the JSON payload:

curl \
  -X POST \
  "https://api.simpleserviceorder.com/_session" \
  -d '{"username":"[email protected]","password":"password"}'
                      

In both cases the JSON output is:

{
  "ok": true,
  "name": "usr-9fcc027ca99e44468227bef4c4440d5c",
  "roles": [
    "acc-1e36d77db5434f3cbded1bb07db403c1"
  ]
}
                      

The JWT token is in the header of the HTTP request, if you add the -i to the curl call it is going to output something like this:

HTTP/2 200
set-cookie: AuthSession=eyJhbGciOi; path=/; expires=Wed, 08 Feb 2023 17:59:47 GMT; HttpOnly; SameSite=Strict

{
  "ok": true,
  "name": "usr-9fcc027ca99e44468227bef4c4440d5c",
  "roles": [
    "acc-1e36d77db5434f3cbded1bb07db403c1"
  ]
}
                      

With that token you can use to authenticate the following requests.

For example, to get your session with that token:

curl \
  -X GET \
  -H "Authorization: Bearer eyJhbGciOi" \
  "https://api.simpleserviceorder.com/_session"
                      

And the output is the same as before:

{
  "ok": true,
  "name": "usr-9fcc027ca99e44468227bef4c4440d5c",
  "roles": [
    "acc-1e36d77db5434f3cbded1bb07db403c1"
  ]
}
                      

Reauth

This is a particular case in which you have access to a token and wants to get a new one before it expires using the same POST /_session request:

The recommended way to re-authenticate is to call the endpoint POST /_session with the autorization you already have, be it Basic Auth, a Bearer token in the header, or a request using the HttpOnly cookie.

Bearer example:

curl \
  -X POST \
  -H "Authorization: Bearer eyJhbGciOi" \
  "https://api.simpleserviceorder.com/_session"
                      

Basic Auth example:

curl \
  -X POST \
  -u [email protected]:password \
  "https://api.simpleserviceorder.com/_session"
                      

As a final note, if you know the user id you can replace it instead of using an email address:

curl \
  -X GET \
  -u usr-9fcc027ca99e44468227bef4c4440d5c:password \
  "https://api.simpleserviceorder.com/_session"
                      

Session

In the previous session you saw the Session output as JSON together with the token. Here is a short explanation of its elements.

The Session JSON:

{
  "ok": true,
  "name": "usr-9fcc027ca99e44468227bef4c4440d5c",
  "roles": [
    "acc-1e36d77db5434f3cbded1bb07db403c1"
  ]
}
                      

Its attributes are:

ok
Indicates the authentication is ok and a token is expected to be in the header
name
This is the unique ID of the user
roles
roles exposes an array with ID of databases the user has some kind of permission, be it read and/or write.

Database

A database is basically an aggregation of data that several users have access to. Some other software may call it Group, Organization, or Team.

database and User are the only two things that do not depend on anything to exists.

As you could see in the session output, the roles attribute exposes an array with the unique name of each database the user has permission.

CRUD operations

Each user can create up to 5 free groups, we recommend using this feature to test any API integration.

Besides that we also have one kind of record that let you perform tests in the API even in a production environment.

This kind of record lets you manage Crystal, each has the following fields:

  • _id: Unique ID of the record
  • _rev: The locking code lets you perform updates, auto generated
  • name: The name of the Crystal, because this is a testing endpoing, there is no right or wrong information to store here, but it cannot be an empty string, Text
  • age: The age of the Crystal, the number stored in this field has to be lower than 125, Integer

Create one record with POST /:database

When you sign up the name of your database and the _id of your User are random, we do that to prevent databases and Users to reuse _ids as this can lead to security vulnerabilities.

But when you manage the records within your organization you must provide the _id yourself.

As you could see from the previous examples the _id field is a Universally unique identifier plus a 3 letter prefix for that particular kind of record.

If you don't want to use a random _id for your records but an incremental one, you can replace all characters with 0 except for the prefix and the - (dash) and place the number to the end, example:

crs-00000000000000000000000000000157
                      

We do very little validation in the _id field, so far the only requirement is for it to be hexadecimal.

Creating a record with valid data:

curl \
 -X POST \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1" \
 -d '{"_id":"crs-041fa18a2f77410d9bf4e07fa33abeeb","name":"John Doe","age":120}'
                      

Returns:

{
  "id": "crs-a9d89d7963a2ee2f1b92f73c2dfb73a0"
}
                      

Creating a record with missing mandatory field:

curl \
 -X POST \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1" \
 -d '{"name":"John Doe", "age": 120}'
                      

Returns:

{
  "error": "unprocessable_entity",
  "reason": {
    "_id": "can't be blank"
  }
}
                      

Creating a record with invalid data:

curl \
 -X POST \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1" \
 -d '{"_id": "crs-ee4371b193ac4b4191cb27624c7442c2", "name":"John Doe", "age": 210}'
                      

Returns:

{
  "error": "unprocessable_entity",
  "reason": {
    "age": "less-than-or-equal-to"
  }
}
                      

Get one record with GET /:database/:document_id

With the ID of the record to query you can call the API with:

curl \
 -X GET \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1/crs-ee4371b193ac4b4191cb27624c7442c2"
                      

Returns:

{
  "_id": "crs-a9d89d7963a2ee2f1b92f73c2dfb73a0"
}
                      

If you don't tell which fields you want in your request we are going to reply only with _id and _rev.

Example with the fields query parameters:

curl \
 -X GET \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1/crs-ee4371b193ac4b4191cb27624c7442c2?fields=_id,_rev,name,age,created_at,updated_at"
                      

Returns:

{
  "_id": "crs-ee4371b193ac4b4191cb27624c7442c2",
  "_rev": "1-25907e94b8cec1aa102595d415fbb36b",
  "name": "John Doe",
  "age": 120,
  "created_by_id": "usr-9fcc027ca99e44468227bef4c4440d5c",
  "updated_by_id": "usr-9fcc027ca99e44468227bef4c4440d5c",
  "created_at": "2023-05-13T23:16:24.792Z",
  "updated_at": "2023-05-13T23:16:24.792Z"
}
                      

Update one record with PUT /:database/:document_id

Some rules are mandatory to this endpoint, /accounts endpoint is required here:

  • You have to provide a valid rev in the query parameters
  • Only fields informed are going to be updated the others are going to stay the same
  • If you provide no body in the request the response is ok, but nothing changes in the database
  • If you provide an empty JSON body the response is ok, but nothing changes in the database

An example of updating a Crystal:

curl \
 -X PUT \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1/crs-ee4371b193ac4b4191cb27624c7442c2?rev=1-25907e94b8cec1aa102595d415fbb36b" \
 -d '{"age":20}'
                      

And the response is the same as the POST:

{
  "id": "crs-ee4371b193ac4b4191cb27624c7442c2",
  "ok": true
}
                      

Delete one record with DELETE /:database/:document_id

You also need the rev query parameters to delete a record.

An example request to delete a record is:

curl \
 -X DELETE \
 "https://api.simpleserviceorder.com/acc-1e36d77db5434f3cbded1bb07db403c1/crs-ee4371b193ac4b4191cb27624c7442c2?rev=2-f32d250e7d4ce0a07c99dd2d14095582"
                      

And the response is the same as create or update:

{
  "id": "crs-ee4371b193ac4b4191cb27624c7442c2",
  "ok": true
}
                      

If you forget or pass on a wrong rev you get the same response as before:

{
  "error": "conflict",
  "reason": "Document update conflict."
}
                      

Find multiple records with POST /:database/_find

TODO