Username and password¶
Sahl AI issues each organization a set of integration credentials. Your backend exchanges them for a clinician-scoped access token.
Log in¶
POST https://medipulse-staging.sahl.ai/users/login
Request¶
| Field | Type | Required | Description |
|---|---|---|---|
username |
string | Yes | Integration username issued by Sahl AI. |
password |
string | Yes | Integration password issued by Sahl AI. |
identifier |
string | null | Recommended | Email address of the clinician signed in to your EHR. Sahl AI links the session, consultation history and preferences to this clinician, and by default creates their profile under your organization the first time they appear. If your organization only allows pre-registered clinicians, an unknown email is rejected with 403. Send null only for service-level testing. |
Response¶
200 OK
| Field | Description |
|---|---|
token |
Access token. Pass it to the embedded panel as access_token, or to the streaming API as the second subprotocol. |
refresh_token |
Use it to get a new access token without sending the password again. |
expires_in |
Token lifetime in seconds. |
Errors¶
Errors return a JSON body of the form { "message": "..." }.
| Status | Meaning |
|---|---|
401 |
The username or password is wrong, or a required field is missing. |
403 |
The identifier is not registered and your organization only allows pre-registered clinicians, or the organization is inactive. |
5xx |
Temporary problem on the Sahl AI side. Retry with exponential backoff. |
Examples¶
const res = await fetch(`${process.env.SAHL_API_BASE}/users/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: process.env.SAHL_USERNAME,
password: process.env.SAHL_PASSWORD,
identifier: clinician.email,
}),
});
if (!res.ok) throw new Error(`Sahl login failed: ${res.status}`);
const { token, refresh_token, expires_in } = await res.json();
using var http = new HttpClient();
var res = await http.PostAsJsonAsync(
$"{Environment.GetEnvironmentVariable("SAHL_API_BASE")}/users/login",
new {
username = Environment.GetEnvironmentVariable("SAHL_USERNAME"),
password = Environment.GetEnvironmentVariable("SAHL_PASSWORD"),
identifier = clinicianEmail
});
res.EnsureSuccessStatusCode();
var body = await res.Content.ReadFromJsonAsync<JsonElement>();
var token = body.GetProperty("token").GetString();
Refresh a token¶
POST https://medipulse-staging.sahl.ai/users/refresh-token
The response has the same shape as login. A new refresh_token replaces the old one, so store it.
When to refresh
Refresh before you open a new panel or start a new streaming session, not partway through a recording. A token that is valid when a session starts lasts for the whole consultation.