GET /ext/line/find
/ext/line/find answers a single question: "does a line with this username exist, and if so, what is its opaque UUID?" It is designed as a cheap existence check that avoids pulling the full line object. Reseller dashboards use it before a create, so they can either create the line or open the edit view depending on whether the username is free. Billing systems use it after a payment webhook so they can look up the line they just paid to renew and then call /ext/line/{uuid}/renew with the returned UUID.
The response shape is intentionally small: on a hit you get exactly {"line_id": "<uuid>"}. On a miss the response is 404 Not Found with {"error": "Not Found"}. There is no full line object. If you need the rest of the fields, follow up with a GET /ext/lines?username=<same> call, or, on the native surface, GET /panel-api/v1/lines/{numeric-id}.
Endpoint
GET https://<your-panel-domain>/panel-api/onestream/ext/line/find
Authentication
Send the API key in X-Api-Key, X-Auth-User, or Authorization: Bearer. See the OneStream overview.
Required scope
lines:read.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
username |
string | yes | (none) | Exact-match filter on username. Case-sensitive. |
password |
string | no | (none) | Optional exact-match filter on password. When supplied, both the username and the password must match. |
The lookup is scoped by caller type: an admin key can find any line, a reseller key only finds lines they own. A reseller who queries a username belonging to another reseller receives the same 404 Not Found as if the line did not exist. This is on purpose so that the response cannot be used as an oracle to enumerate other tenants' usernames.
The
passwordfilter puts the password into the query string, and therefore into every access log along the way (your panel's Nginx, any client-side proxy, and any intermediary). Our own access-log format masks the query string for Panel API requests, but we cannot mask logs owned by third parties. Useusernamealone when you can, and combineusernamewithpasswordonly when you must positively confirm a credential.
Response
On a hit (HTTP 200):
{"line_id": "550e8400-e29b-41d4-a716-446655440000"}
On a miss (HTTP 404):
{"error": "Not Found"}
A 404 from this endpoint is authoritative: for the calling key, no line matches the given username (or the given username + password combination). It does not mean the panel is unreachable, and it does not mean the underlying record was corrupted. A retry will return the same 404 until the situation changes.
Examples
cURL
# Existence check by username
curl -H "X-Api-Key: <your-api-key>" \
"https://<your-panel-domain>/panel-api/onestream/ext/line/find?username=customer_001"
# With password verification
curl -H "X-Api-Key: <your-api-key>" \
"https://<your-panel-domain>/panel-api/onestream/ext/line/find?username=customer_001&password=d7dca035"
PHP raw
$username = 'customer_001';
$url = 'https://<your-panel-domain>/panel-api/onestream/ext/line/find?username=' . urlencode($username);
$ch = curl_init($url);
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);
if ($http === 200) {
echo 'found: ' . $body['line_id'] . PHP_EOL;
} elseif ($http === 404) {
echo "not found\n";
} else {
echo 'error: ' . ($body['error'] ?? 'unknown') . PHP_EOL;
}
Python raw
import requests
r = requests.get(
"https://<your-panel-domain>/panel-api/onestream/ext/line/find",
headers={"X-Api-Key": "<your-api-key>"},
params={"username": "customer_001"},
timeout=30,
)
if r.status_code == 200:
print("found:", r.json()["line_id"])
elif r.status_code == 404:
print("not found")
else:
r.raise_for_status()
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. |
| 403 | insufficient_scope |
The key does not carry lines:read. |
Regenerate the key with lines:read, or use a key that has it. |
| 404 | not_found |
No line matched the username (and password, if supplied) for the calling key. Also returned if the username belongs to a different reseller and the caller is not an admin. |
If the line should exist, verify the exact spelling of the username. Otherwise treat this as an authoritative miss. |
| 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. |
| 403 | api_disabled |
An admin has turned the Panel API off for this panel. | Ask the admin to re-enable it. |