Admin API¶
Admin endpoints are prefixed with /api/v1/admin.
Authentication options:
- Browser admin console: cookie-backed admin session via /api/v1/admin/auth/login
- Direct admin API clients: HTTP Basic Auth
Browser admin session endpoints:
- POST /api/v1/admin/auth/login
- GET /api/v1/admin/auth/session
- POST /api/v1/admin/auth/logout
GET /api/v1/admin/stats¶
Returns aggregate statistics across all images and jobs. Requires storage-backed mode; returns 501 when FACE_API_STORAGE_ENABLED=false.
- Request format: none
- Response format: JSON (
StatsResponse)
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/stats",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/stats", {
headers: { Authorization: `Basic ${basic}` },
});
console.log(await response.json());
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/stats");
Console.WriteLine(await response.Content.ReadAsStringAsync());
{
"total_images": 1250,
"total_jobs": 3420,
"total_faces_detected": 8910,
"avg_inference_ms": 14.52,
"storage_used_bytes": 524288000,
"jobs_by_type": { "detect": 2100, "mask": 1320 },
"jobs_by_method": { "gaussian": 800, "pixelate": 400, "solid": 120 }
}
Images¶
GET /api/v1/admin/images¶
Returns a paginated list of stored images, including a private original download URL and the latest processed image URL when one exists. Requires storage-backed mode; returns 501 when FACE_API_STORAGE_ENABLED=false.
- Request format: none (query string only)
- Response format: JSON (
PaginatedResponse[StoredImageResponse])
processed_url is null when no processed result exists yet for that image.
When FACE_API_S3_PUBLIC_ENDPOINT is configured, processed_url may point at the public processed-asset host.
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
int | 1 | Page number |
per_page |
int | 20 | Items per page (1-100) |
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/images?page=1&per_page=10",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images?page=1&per_page=10", {
headers: { Authorization: `Basic ${basic}` },
});
console.log(await response.json());
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/images?page=1&per_page=10");
Console.WriteLine(await response.Content.ReadAsStringAsync());
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"filename": "photo.jpg",
"content_type": "image/jpeg",
"size_bytes": 245760,
"width": 1920,
"height": 1080,
"original_url": "https://signed.example.com/originals/...",
"processed_url": "https://static.face-api.xylolabs.com/face-api/processed/...",
"job_count": 3,
"created_at": "2026-04-06T10:30:00+00:00"
}
],
"total": 1250, "page": 1, "per_page": 10, "pages": 125
}
signed.example.com is an illustrative placeholder for a private signed/original download URL.
static.face-api.xylolabs.com illustrates the public processed-asset host when FACE_API_S3_PUBLIC_ENDPOINT is configured.
GET /api/v1/admin/images/{image_id}¶
Returns image details together with all associated jobs.
- Request format: none
- Response format: JSON (
StoredImageDetailResponse)
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...", {
headers: { Authorization: `Basic ${basic}` },
});
console.log(await response.json());
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...");
Console.WriteLine(await response.Content.ReadAsStringAsync());
DELETE /api/v1/admin/images/{image_id}¶
Deletes an image, its associated jobs, and its S3 objects. Returns 204.
- Request format: none
- Response format: empty body (
204 No Content)
import requests
from requests.auth import HTTPBasicAuth
response = requests.delete(
"https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.status_code)
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...", {
method: "DELETE",
headers: { Authorization: `Basic ${basic}` },
});
console.log(response.status);
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.DeleteAsync("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-...");
Console.WriteLine(response.StatusCode);
GET /api/v1/admin/images/{image_id}/download¶
Redirects (302) to the original image download URL.
- Request format: none
- Response format: redirect (
302 Found)
curl -u admin:password -L https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download -o original.jpg
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download",
auth=HTTPBasicAuth("admin", "password"),
allow_redirects=True,
)
with open("original.jpg", "wb") as f:
f.write(response.content)
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download", {
headers: { Authorization: `Basic ${basic}` },
});
const blob = await response.blob();
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/images/550e8400-.../download");
await using var output = File.Create("original.jpg");
await response.Content.CopyToAsync(output);
Jobs¶
GET /api/v1/admin/jobs¶
Returns a paginated job list with optional filters. Requires storage-backed mode; returns 501 when FACE_API_STORAGE_ENABLED=false.
- Request format: none (query string only)
- Response format: JSON (
PaginatedResponse[JobResponse])
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
int | 1 | Page number |
per_page |
int | 20 | Items per page (1-100) |
job_type |
string | — | detect or mask |
method |
string | — | Filter by blur method |
curl -u admin:password "https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian"
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian", {
headers: { Authorization: `Basic ${basic}` },
});
console.log(await response.json());
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/jobs?job_type=mask&method=gaussian");
Console.WriteLine(await response.Content.ReadAsStringAsync());
GET /api/v1/admin/jobs/{job_id}¶
Returns job details with the full detection payload.
- Request format: none
- Response format: JSON (
JobDetailResponse)
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-...",
auth=HTTPBasicAuth("admin", "password"),
)
print(response.json())
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-...", {
headers: { Authorization: `Basic ${basic}` },
});
console.log(await response.json());
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-...");
Console.WriteLine(await response.Content.ReadAsStringAsync());
GET /api/v1/admin/jobs/{job_id}/download¶
Redirects (302) to the processed image URL.
- Request format: none
- Response format: redirect (
302 Found)
curl -u admin:password -L https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download -o processed.jpg
import requests
from requests.auth import HTTPBasicAuth
response = requests.get(
"https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download",
auth=HTTPBasicAuth("admin", "password"),
allow_redirects=True,
)
with open("processed.jpg", "wb") as f:
f.write(response.content)
const basic = btoa("admin:password");
const response = await fetch("https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download", {
headers: { Authorization: `Basic ${basic}` },
});
const blob = await response.blob();
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(Encoding.ASCII.GetBytes("admin:password"))
);
var response = await client.GetAsync("https://face-api.xylolabs.com/api/v1/admin/jobs/550e8400-.../download");
await using var output = File.Create("processed.jpg");
await response.Content.CopyToAsync(output);
API keys¶
All /api/v1/admin/api-keys* endpoints require the database-backed mode; they return 501 when the database tier is disabled.