Skip to content

Getting started

An organization administrator of an approved Simblia organization creates API clients for their own organization in the Simblia app. There is no separate sign-up and no approval step: the client works as soon as it is created. An organization can have at most 5 clients that are not revoked. Simblia can suspend or revoke a client, for example if it is misused.

A client can only ever read data from its own organization. In v1 it can read the organization itself (organization.read). Published lessons come in v1.1. The API never returns personal data about pupils or staff.

Environment API base URL Data Credentials start with
Sandbox https://api-dev.simblia.com/v1 Synthetic data only sim_dev_
Production https://api.simblia.com/v1 Your organization’s real data sim_prod_

The two environments are separate. A client ID, secret or token from one never works in the other. Build and test against the sandbox first.

In the Simblia app, open your organization’s settings and create an API client. Give it a name and choose its scopes; in v1 that is organization.read.

You get a client ID (for example sim_dev_c_…) and a client secret (sim_dev_s_…). Copy the secret straight away: it is shown once, and Simblia keeps only a hash of it. Store it in a secret store or an environment variable on your server, never in source code, a browser, a mobile app or any other client-side code.

Send the client ID and secret with HTTP Basic authentication to the token endpoint, with the form field grant_type=client_credentials.

Terminal window
curl -s https://api-dev.simblia.com/v1/oauth/token \
-u "$SIMBLIA_CLIENT_ID:$SIMBLIA_CLIENT_SECRET" \
-d grant_type=client_credentials \
-d scope=organization.read
{
"access_token": "sim_dev_at_…",
"token_type": "Bearer",
"expires_in": 900,
"scope": "organization.read"
}

The token is valid for 15 minutes (expires_in is in seconds). Treat it as an opaque string.

Terminal window
curl -s https://api-dev.simblia.com/v1/organization \
-H "Authorization: Bearer $ACCESS_TOKEN"
{
"organization_id": "0b8f2c1e-6d3a-4f7b-9c2d-5e1a8b4c7d90",
"name": "Example School",
"type": "education",
"institution_type": "secondary",
"country": "DK"
}

Every response also carries the header Simblia-API-Status: preview while v1 is in preview.

Python with the requests library:

import os
import requests
BASE = "https://api-dev.simblia.com"
token = requests.post(
f"{BASE}/v1/oauth/token",
auth=(os.environ["SIMBLIA_CLIENT_ID"], os.environ["SIMBLIA_CLIENT_SECRET"]),
data={"grant_type": "client_credentials", "scope": "organization.read"},
timeout=10,
)
token.raise_for_status()
access_token = token.json()["access_token"]
org = requests.get(
f"{BASE}/v1/organization",
headers={"Authorization": f"Bearer {access_token}"},
timeout=10,
)
org.raise_for_status()
print(org.json()["name"])

C# with HttpClient (.NET 8 or later):

using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using var http = new HttpClient { BaseAddress = new Uri("https://api-dev.simblia.com") };
var id = Environment.GetEnvironmentVariable("SIMBLIA_CLIENT_ID")!;
var secret = Environment.GetEnvironmentVariable("SIMBLIA_CLIENT_SECRET")!;
var basic = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{id}:{secret}"));
using var tokenRequest = new HttpRequestMessage(HttpMethod.Post, "/v1/oauth/token")
{
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["scope"] = "organization.read",
}),
};
tokenRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", basic);
using var tokenResponse = await http.SendAsync(tokenRequest);
tokenResponse.EnsureSuccessStatusCode();
var token = (await tokenResponse.Content.ReadFromJsonAsync<TokenResponse>())!;
using var orgRequest = new HttpRequestMessage(HttpMethod.Get, "/v1/organization");
orgRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
using var orgResponse = await http.SendAsync(orgRequest);
orgResponse.EnsureSuccessStatusCode();
var org = (await orgResponse.Content.ReadFromJsonAsync<Organization>())!;
Console.WriteLine(org.name);
record TokenResponse(string access_token, string token_type, int expires_in, string scope);
record Organization(Guid organization_id, string name, string type, string institution_type, string country);