GET /ext/profile
/ext/profile is the introspection endpoint. It answers "who am I to this panel?" from the point of view of the API key that made the request, in the OneStream field shape that legacy clients already parse. It is the first call most integrations make after a base URL swap, because it confirms three things in one round trip: the panel accepted the token, the request reached the OneStream dialect, and the credits balance (when applicable) is the one you expected.
The response is a flat JSON object with five fields. The exact values you get back depend on the type of key you used, because the underlying v1 identity model distinguishes admin keys from reseller keys.
Endpoint
GET https://<your-panel-domain>/panel-api/onestream/ext/profile
Authentication
Send the API key in X-Api-Key, X-Auth-User, or Authorization: Bearer. See the OneStream overview.
Required scope
None. Every authenticated key can call /ext/profile. Introspection has to work before the caller knows which scopes it has.
Response
The response is a flat object with a fixed shape. It never returns a list.
| Field | Type | Description |
|---|---|---|
id |
int | Numeric identity of the caller. For reseller keys the current release returns 0 because the underlying v1 /me endpoint carries the id as reg_user_id, which the dialect does not project into this field. For admin keys the value is also 0. Treat this field as informational only and identify keys by the token itself. |
name |
string | Human-readable name of the caller. Empty string in the current release, for the same reason as id. |
username |
string | Same as name. Emitted twice under two names because different OneStream client libraries pick one or the other. |
is_admin |
bool | true for an admin key, false for a reseller key. In the current release this always returns false because the underlying /me endpoint uses type: "admin" instead of an is_admin boolean, and the dialect does not translate the two. Treat as informational. |
credits |
float | Current credit balance for the caller. For a reseller key this is the reseller's own balance. For an admin key it is 0, because admin keys are panel-scoped and have no billing state. |
Example response (reseller key with 0.25 credits):
{
"id": 0,
"name": "",
"username": "",
"is_admin": false,
"credits": 0.25
}
Example response (admin key on a fresh panel):
{
"id": 0,
"name": "",
"username": "",
"is_admin": false,
"credits": 0
}
If your integration relies on
id,name,username, oris_adminto identify the caller, use the nativeGET /panel-api/v1/meendpoint instead. It returnstype: "admin" | "reseller", the reseller'sreg_user_id, the member group, and the full billing snapshot. The OneStream/ext/profileshape is preserved for compatibility with client code that parses this exact set of five fields.
Examples
cURL
curl -H "X-Api-Key: <your-api-key>" \
https://<your-panel-domain>/panel-api/onestream/ext/profile
PHP raw
$ch = curl_init('https://<your-panel-domain>/panel-api/onestream/ext/profile');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-Api-Key: <your-api-key>']);
$body = json_decode(curl_exec($ch), true);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "credits: " . $body['credits'] . PHP_EOL;
Python raw
import requests
r = requests.get(
"https://<your-panel-domain>/panel-api/onestream/ext/profile",
headers={"X-Api-Key": "<your-api-key>"},
timeout=30,
)
r.raise_for_status()
data = r.json()
print("credits:", data["credits"])
Errors
| HTTP | Error slug | When it happens | How to fix |
|---|---|---|---|
| 401 | invalid_key |
Header is missing, the token is unknown, the key was disabled, expired, deleted, or the caller IP is not on the key's IP allow-list. | Check the header. If the key was rotated, mint a new one from the panel. |
| 429 | rate_limited |
The per-key or per-IP rate limit was hit. Response carries Retry-After and X-RateLimit-* headers. |
Back off for the number of seconds in Retry-After. Cache the profile response, it does not change often. |
| 403 | api_disabled |
An admin has turned the Panel API off for this panel. | Ask the admin to re-enable it in the panel settings. |