Skip to content
On this page

Authentication

Streamline APIs use OAuth 2.0 Client Credentials for authentication, combined with subscription keys for access control.

WARNING

All requests must use HTTPS. HTTP requests and unauthenticated requests will fail.

Quick Start

Every API request requires two things:

CredentialHeaderDescription
Access TokenAuthorization: Bearer <token>OAuth 2.0 token for authentication
Subscription KeyOcp-Apim-Subscription-Key: <key>Identifies your API subscription

Getting Your Credentials

After completing the onboarding process, you'll receive:

CredentialDescription
Client IDYour application's unique identifier
Client SecretSecret key for token generation
Subscription Key(s)One key per API subscription

Protect Your Credentials

  • Store credentials securely (use environment variables or a secrets manager)
  • Never commit credentials to version control
  • Never expose credentials in client-side code
  • The client_secret cannot be recovered if lost

Get an Access Token

Request a token from the authorization server:

Token Endpoint: https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token

bash
curl --request POST \
  --url https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data 'client_id=YOUR_CLIENT_ID' \
  --data 'client_secret=YOUR_CLIENT_SECRET' \
  --data 'grant_type=client_credentials'
curl --request POST \
  --url https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data 'client_id=YOUR_CLIENT_ID' \
  --data 'client_secret=YOUR_CLIENT_SECRET' \
  --data 'grant_type=client_credentials'
js
const response = await fetch(
  'https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: 'YOUR_CLIENT_ID',
      client_secret: 'YOUR_CLIENT_SECRET',
      grant_type: 'client_credentials',
    }),
  }
)

const { access_token } = await response.json()
const response = await fetch(
  'https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: 'YOUR_CLIENT_ID',
      client_secret: 'YOUR_CLIENT_SECRET',
      grant_type: 'client_credentials',
    }),
  }
)

const { access_token } = await response.json()
python
import requests

response = requests.post(
    'https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token',
    data={
        'client_id': 'YOUR_CLIENT_ID',
        'client_secret': 'YOUR_CLIENT_SECRET',
        'grant_type': 'client_credentials',
    }
)

access_token = response.json()['access_token']
import requests

response = requests.post(
    'https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token',
    data={
        'client_id': 'YOUR_CLIENT_ID',
        'client_secret': 'YOUR_CLIENT_SECRET',
        'grant_type': 'client_credentials',
    }
)

access_token = response.json()['access_token']
csharp
var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
    new KeyValuePair<string, string>("client_id", "YOUR_CLIENT_ID"),
    new KeyValuePair<string, string>("client_secret", "YOUR_CLIENT_SECRET"),
    new KeyValuePair<string, string>("grant_type", "client_credentials")
});

var response = await client.PostAsync(
    "https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token",
    content
);

var json = await response.Content.ReadFromJsonAsync<JsonObject>();
var accessToken = json["access_token"].ToString();
var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
    new KeyValuePair<string, string>("client_id", "YOUR_CLIENT_ID"),
    new KeyValuePair<string, string>("client_secret", "YOUR_CLIENT_SECRET"),
    new KeyValuePair<string, string>("grant_type", "client_credentials")
});

var response = await client.PostAsync(
    "https://auth-api-demo.streamline.laboremus.ug/realms/streamline-test-realm/protocol/openid-connect/token",
    content
);

var json = await response.Content.ReadFromJsonAsync<JsonObject>();
var accessToken = json["access_token"].ToString();

Token Response

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 300
}
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 300
}
FieldDescription
access_tokenThe Bearer token to use in API requests
token_typeAlways Bearer
expires_inToken lifetime in seconds

Token Expiration

Tokens expire after the time specified in expires_in. Request a new token before the current one expires.

Error Response

json
{
  "error": "invalid_client",
  "error_description": "Invalid client credentials"
}
{
  "error": "invalid_client",
  "error_description": "Invalid client credentials"
}

Using the Access Token

Include both the token and subscription key in every request:

bash
curl --request GET \
  --url 'https://api.streamline.laboremus.ug/your-endpoint' \
  --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...' \
  --header 'Ocp-Apim-Subscription-Key: your-subscription-key'
curl --request GET \
  --url 'https://api.streamline.laboremus.ug/your-endpoint' \
  --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...' \
  --header 'Ocp-Apim-Subscription-Key: your-subscription-key'
js
const response = await fetch('https://api.streamline.laboremus.ug/your-endpoint', {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Ocp-Apim-Subscription-Key': 'your-subscription-key'
  }
})
const response = await fetch('https://api.streamline.laboremus.ug/your-endpoint', {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Ocp-Apim-Subscription-Key': 'your-subscription-key'
  }
})
python
response = requests.get(
    'https://api.streamline.laboremus.ug/your-endpoint',
    headers={
        'Authorization': f'Bearer {access_token}',
        'Ocp-Apim-Subscription-Key': 'your-subscription-key'
    }
)
response = requests.get(
    'https://api.streamline.laboremus.ug/your-endpoint',
    headers={
        'Authorization': f'Bearer {access_token}',
        'Ocp-Apim-Subscription-Key': 'your-subscription-key'
    }
)
csharp
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "your-subscription-key");

var response = await client.GetAsync("https://api.streamline.laboremus.ug/your-endpoint");
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "your-subscription-key");

var response = await client.GetAsync("https://api.streamline.laboremus.ug/your-endpoint");

Subscription Keys

Each API requires its own subscription key. You cannot use a single key across multiple APIs.

MethodExample
Header (recommended)Ocp-Apim-Subscription-Key: your-key
Query parameter?subscription-key=your-key

INFO

Subscription keys are provisioned during onboarding. Contact our team to subscribe to additional APIs.

Tech served right