Skip to main content
Version: latest

Astran API Tutorial

This tutorial presents the main concepts and features of our Astran api. An exhaustive documentation is available as an OpenAPI specification (aka. Swagger) annexed in this document.

Requirements

Astran API is publicly exposed, so any HTTP/ResT client (cURL, Postman…) can be used to query its endpoints. Following examples are presented as cURL commands that can be run in a shell for testing purposes.

Astran API only accepts requests from registered users, so valid credentials (e-mail address and password) are required to complete this tutorial.

Authentication

Requests authentication rely on a JWT to be requested by issuing a POST on /auth/realms/{my-realm}/protocol/openid-connect/token:

curl --location 'https://{my-realm}.auth.astran.io/auth/realms/{my-realm}/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={my-client-id}' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'password={my-password}' \
--data-urlencode 'username={my-username}'

A JWT access token is returned, along with a refresh token we can ignore for now:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJiMEIwaVctR2MyTXFiXzRWaFl2UnhSTUZ0RDBGc2tCMmhqeUVBRlp6S05nIn0.eyJleHAiOjE2ODI0OTUzNjYsImlhdCI6MTY4MjQ5NTA2NiwianRpIjoiOTA5NGYzYWQtZmI0OS00NTA5LWI4MjQtNDMwYmMyYTYyZTM1IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLmFzdHJhbi5pby9yZWFsbXMvYXN0cmFjaGFpbiIsImF1ZCI6WyJyZWFsbS1tYW5hZ2VtZW50IiwiYWNjb3VudCJdLCJzdWIiOiI4MGRmMWMxNS1iZmIxLTQ3YTctOWYzNy1mZjVhNDNiNjA0MWQiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJjb2NrcGl0Iiwic2Vzc2lvbl9zdGF0ZSI6IjlkNjI1ZWI1LTE0OGItNDBjMy04MjExLTdhNDIzYjBkYzRjZiIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLWFzdHJhY2hhaW4iLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsicmVhbG0tbWFuYWdlbWVudCI6eyJyb2xlcyI6WyJtYW5hZ2UtcmVhbG0iLCJtYW5hZ2UtdXNlcnMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwicXVlcnktY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX0sImNvY2twaXQiOnsicm9sZXMiOlsiYWRtaW4iXX19LCJzY29wZSI6InNwbGl0LWFwaS12Mi4xIHByb2ZpbGUgZW1haWwiLCJzaWQiOiI5ZDYyNWViNS0xNDhiLTQwYzMtODIxMS03YTQyM2IwZGM0Y2YiLCJjaWFtVXJsIjoiaHR0cHM6Ly9hc3RyYW4uY2xvdWQtaWFtLmNvbS9hdXRoLyIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJyb2xlIjoiQWRtaW4iLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJkYW1pZW5AYXN0cmFjaGFpbi5jb20iLCJnaXZlbl9uYW1lIjoiRGFtaWVuIiwidHlwZSI6ImFjY2VzcyIsInVzZXJJZCI6IjgwZGYxYzE1LWJmYjEtNDdhNy05ZjM3LWZmNWE0M2I2MDQxZCIsIm9yZ2FuaXphdGlvbklkIjoiYTJlZmU4MWItYzI5MS00MjgyLTk4ZmEtZDBkNjhiNjkyOGQxIiwibmFtZSI6IkRhbWllbiBCb3llciIsInJlYWxtIjoiYXN0cmFjaGFpbiIsImZhbWlseV9uYW1lIjoiQm95ZXIiLCJlbWFpbCI6ImRhbWllbkBhc3RyYWNoYWluLmNvbSIsInJvb3RPcmdhbml6YXRpb25JZCI6ImIwMWI0N2YzLWZkNzMtNDczNC1iNmQ5LTYwYTYyNjQyMGI4MCIsIm1lbWJlcklkIjoiNWY5Y2E5MzMtNjdkMS00NGFhLThiNWQtZDgzOTM5MDA2MzM5In0.jxFdAHT0kf1cPI4yKHinHTTuKsEVUzqRXm3QzcrPIsRzodQ-GQ9N_TfHZBHxToLcLJPpqWwiclMUxT53sxtO2q56u0Fn7wKziJIFBTyqWwAwdQqCooSLuKkkzz1tIp64jDFogYSGpwtOcyeEzE4Fhv5ICwz1GYEpRcG6vZ1cr6YgsCIAl99iEaa1vt5VmVlCqB_TQQxM6KfI_VKzP1X_J1C9RuHmepCjKV2ar5mGQu4krXS4aXpTGu_xPsaal4mV6hu5qiFSNyteKaXxgMzjIepHemP91CdYbFyRKc4ofEANS_Dj9BRFw-sTinNbZJOejIrlwv-KWfn9OO4voWH9kA",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjODlmYmRiMi01NTBhLTQ0MTctYTU5ZC01MWY0YmY4ZGFkNTcifQ.eyJleHAiOjE2ODI0OTY4NjYsImlhdCI6MTY4MjQ5NTA2NiwianRpIjoiZjAwOTM2MmYtOWJjZS00MWNjLTllZGYtNWZjOGU1NTIyMDA1IiwiaXNzIjoiaHR0cHM6Ly9hdXRoLmFzdHJhbi5pby9yZWFsbXMvYXN0cmFjaGFpbiIsImF1ZCI6Imh0dHBzOi8vYXV0aC5hc3RyYW4uaW8vcmVhbG1zL2FzdHJhY2hhaW4iLCJzdWIiOiI4MGRmMWMxNS1iZmIxLTQ3YTctOWYzNy1mZjVhNDNiNjA0MWQiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiY29ja3BpdCIsInNlc3Npb25fc3RhdGUiOiI5ZDYyNWViNS0xNDhiLTQwYzMtODIxMS03YTQyM2IwZGM0Y2YiLCJzY29wZSI6InNwbGl0LWFwaS12Mi4xIHByb2ZpbGUgZW1haWwiLCJzaWQiOiI5ZDYyNWViNS0xNDhiLTQwYzMtODIxMS03YTQyM2IwZGM0Y2YifQ.0SLOqGTBLekXA270RQtnxCPSfaysBDfXySTfbcnkKXM",
"token_type": "Bearer",
"not-before-policy": 1655535121,
"session_state": "9d625eb5-148b-40c3-8211-7a423b0dc4cf",
"scope": "split-api-v2.1 profile email"
}

Or if you prefer to log with a client secret:

curl --location 'https://{my-realm}.auth.astran.io/auth/realms/{my-realm}/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={my-client-id}' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'secret={my-secret}' \

To refresh your token:

curl --location 'https://{my-realm}.auth.astran.io/auth/realms/{my-realm}/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={my-client-id}' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token={my-refresh_token}' \

We store this access token in a variable for future use:

accessToken="eyJhb <…> WH9kA"

Who am I?

As a first request, we can get information about our user, passing our access token in the Authorization header:

curl -X GET 'https://{my-realm}.api.s5.astran.io/api/v2.1/users/me' \
-H "Authorization: Bearer $accessToken" \
-H 'Accept: application/json'

The returned JSON object gives a lot of information about the user, and its organization.

{
"member": {
"email": "jane@astran.com",
"id": "4cf40989-e459-4609-9d24-efae77a7b182",
"nickname": "Jane Doe",
"organizationId": "bcec8186-8253-4e90-a227-c52d154bc3e4",
"roleLevel": 3,
"roleName": "Admin",
"rootDocumentId": "7e3ab36a-c90d-44cc-a297-cecea9f34262",
"status": "verified",
"userId": "6816b2a3-1e55-411b-a5b0-3e58fb5b9e88"
},
"organization": {
"domain": "jane@astran.com",
"id": "bcec8186-8253-4e90-a227-c52d154bc3e4",
"name": "Jane Doe organization",
"storageLimit": 0.2,
"storageUsed": 3.3000000000000004e-8
},
"user": {
"administratedById": "6816b2a3-1e55-411b-a5b0-3e58fb5b9e88",
"email": "jane@astran.com",
"firstName": "Jane",
"id": "6816b2a3-1e55-411b-a5b0-3e58fb5b9e88",
"lastName": "Doe",
"phone": "",
"status": "verified",
"superUser": false
}
}

This JSON Object return contains all the main information about the user account you are currently logged in with. This includes your user data, the organization related to your user and more details about your membership to this organization.

A key data that appears on this first request is the "rootDocumentId" in the "member" object. It represents the root folder that has been created for your organization, in which you will be able to upload new files, and create new folders.

To ease the next step of this tutorial, we are going to save the "rootDocumentId" into a global variable :

rootDocumentId="7e3ab36a-c90d-44cc-a297-cecea9f34262"

Warning: user management endpoints are not stable yet: endpoints, operations and responses may change quickly in next versions.

Uploading and splitting

For the purpose of this how-to, we are going create a demo text document containing "Hello World!":

echo 'Hello World!' > docdemo.txt

Let's upload another document to root folder:

curl -X POST "https://{my-realm}.api.s5.astran.io/api/v2.1/files/$rootDocumentId/children?name=docdemo.txt" \
-H "Authorization: Bearer $accessToken" \
-H 'Content-Type: application/octet-stream' \
-H 'Accept: application/json' \
--data-binary @docdemo.txt

We just created a new document, containing a first version.

The file content has been transparently split into fragments — with redundancy for resilience — by Astran servers, then distributed over our cloud providers. This ensures none of these cloud providers alone can recover the data from the fragments it hosts, while we are still able to rebuild a file even in the case of a failure from one of our cloud providers.

The returned JSON contains its metadata, including auto-generated IDs:

{
"ID": "80d8383f-b25c-4474-91f0-805c10f80340",
"changedAt": "2022-04-19T14:02:49.699080285Z",
"changedBy": "4cf40989-e459-4609-9d24-efae77a7b182",
"currentVersion": {
"ID": "6bc79bf1-a02b-41e3-a792-470c507eddff",
"author": "4cf40989-e459-4609-9d24-efae77a7b182",
"date": "2022-04-19T14:02:49.69907242Z",
"number": {
"major": 1,
"minor": 0
},
"size": 13
},
"name": "docdemo.txt",
"parentID": "7e3ab36a-c90d-44cc-a297-cecea9f34262",
"permission": "Owner",
"type": "document"
}

Listing files

The Astran API gives access to a vault: a filesystem stored on Astran. Let's query the content of its root directory, using its ID from previous response:

curl -X GET "https://my-realm.api.s5.astran.io/api/v2.1/files/$rootDocumentId/children" \
-H "Authorization: Bearer $accessToken" \
-H'Accept: application/json'

A folder listing is a JSON array holding metadata for every child:

[
{
"ID": "80d8383f-b25c-4474-91f0-805c10f80340",
"changedAt": "2022-04-19T14:02:49.699080285Z",
"changedBy": "4cf40989-e459-4609-9d24-efae77a7b182",
"currentVersion": {
"ID": "6bc79bf1-a02b-41e3-a792-470c507eddff",
"author": "4cf40989-e459-4609-9d24-efae77a7b182",
"date": "2022-04-19T14:02:49.69907242Z",
"number": {
"major": 1,
"minor": 0
},
"size": 13
},
"name": "docdemo.txt",
"parentID": "7e3ab36a-c90d-44cc-a297-cecea9f34262",
"permission": "Owner",
"type": "document"
}
]

According to this response, the root contains a unique document "docdemo.txt", owned by our authenticated user Jane Doe.

In the next section we are going to download the demo document that has been added to the root folder. For this purpose, let's save the document ID related into "demoDocId" global variable:

demoDocId="80d8383f-b25c-4474-91f0-805c10f80340"

Downloading

Documents stored on Astran are versioned. Versions are numbered, immutable snapshots of the document.

The previous operation returned a version ID for our new document first version. When listing a folder, the returned objects for child documents also contain their current version metadata.

We can use it to download its content:

curl -X GET "https://my-realm.api.s5.astran.io/api/v2.1/files/$demoDocId/versions/current" \
-H "Authorization: Bearer $accessToken" \
-H 'Accept: application/octet-stream'

As expected, the binary content returned should be:

Hello World!

Congratulations! You have managed to store your first document on the Astran Platform. You can move on to the advanced usages page to learn more about Astran API features.