Docs / AI Box And Video Analytics Software / Authentication And Scopes
Authentication And Scopes
API accounts and their tokens, the four scopes, personal data and the anonymous form, the rate limit, and the errors the AI Box API returns.
Your system calls the AI Box API with the token of an API account. The account belongs to your system, has its own name in the audit log, and sees only the sites and the data it was given.
Create An API Account
An admin creates the account on the dashboard, on the API accounts page:
- Give it a name (3 to 64 characters of
a-z,0-9and. _ -, for exampleerp-sync). The audit log shows its calls asapi:erp-sync. - Give it a role on one or more sites: Viewer to read, Admin to change that site’s settings too.
- Choose its scopes (below) and an expiry date, at most a year away.
- Save, then copy the token. It is shown only this once.
The token looks like arsa_pat_ followed by 43 characters. Store it as a secret in your system. If it leaks, make a new
token on the same page (Make a new token): the old one stops working at once. Revoke stops the account for good;
its calls stay in the audit log.
The box’s owner manages every account. An admin of a site manages the accounts whose every site they administer.
Send The Token
Send the token in the Authorization header, after the word Bearer and a space:
curl --cacert box.pem \
-H "Authorization: Bearer <API_KEY>" \
"https://<BOX_HOST>/api/v1/sites"
A token needs no session and no CSRF token. A cookie sent beside it is ignored.
The Box’s Certificate
The dashboard serves HTTPS with the box’s own certificate. Give your client a copy of it (box.pem above) so the
connection is verified.
On ARSA AI Video Analytics Software the certificate is the one your server’s dashboard serves; the same panel shows and downloads it, and the names it covers are your server’s.
Connect by the box’s host name or by its LAN address: the box’s own certificate covers both, as well as
<host>.local. The admin sees the names and addresses it covers beside the download button (Covers), and
getBoxCertificateInfo lists them as names. Use one of them as
<BOX_HOST>, or the client refuses the connection.
- From an admin: an admin downloads it on the dashboard (System, then API accounts, then Download the box’s certificate) and gives you the file with the SHA-256 fingerprint shown beside the button.
- With your token: an account with the
readscope can fetch it itself (getBoxCertificate). Your client does not trust the box yet, so this first download skips the check (--insecure); the fingerprint check below takes its place.
curl --insecure \
-H "Authorization: Bearer <API_KEY>" \
-o box.pem \
"https://<BOX_HOST>/api/v1/system/certificate"
Either way, compare the file’s fingerprint with the one the admin read on the dashboard before you use it:
openssl x509 -noout -fingerprint -sha256 -in box.pem
If they differ, do not use the file and tell the admin. A new certificate on the box (the customer’s own, for example) has a new fingerprint: fetch the file again and compare again.
The same happens when the box’s address changes (a new DHCP lease, another network): at its next start the box re-issues its certificate for the new address, with the same key, and the fingerprint changes. Download the file again, check the new fingerprint with the admin and replace the old copy in your client.
Scopes
| Scope | Allows |
|---|---|
read |
GET requests: data and settings |
write |
Changes: POST, PUT, PATCH, DELETE (settings, acknowledging alerts, watchlist entries) |
export |
File downloads: log exports, reports, recordings and clips |
personal_data |
Names, plates, faces, evidence photos, crops and video |
Each operation in the reference lists the scopes it needs and the site role it needs. A call without a needed scope
answers 403 with the code scope_required.
Only the box’s owner can give personal_data, and the dashboard asks the owner to confirm with their password and
two-step code.
Personal Data And The Anonymous Form
Without personal_data, some operations answer an anonymous form and others are refused:
- Anonymous form: the Basic Safety Guard detection log and its export (no names, no evidence,
named: false); the Traffic Monitor vehicle log, its export and incidents (no plate, no crop); alerts (theirdetailswithout plate, person, name, evidence or media, and no footage). - Refused: live video, recordings and clips, camera snapshots, alert contacts and their delivery log, Basic Safety Guard per-worker figures and evidence images, the Traffic Monitor watchlist, vehicle crops and a log search by plate.
Smart Retail Counter and DOOH Audience Meter count people anonymously, so their APIs hold no personal data.
Every call of an account with personal_data, every export and every change is recorded in the box’s audit log.
What Tokens Cannot Do
Some actions need a person signed in to the dashboard. They answer 403 with the code api_account_refused for any
token: signing in and passwords, users and API accounts, the licence, updates, remote access, ARSA maintenance and
support access, privacy settings, the face database and the notification channels. Making the keys and tokens of the
machine feeds is refused too; an admin of the site makes them on the dashboard.
Rate Limit
Each API account may make 600 requests a minute by default (the box’s owner can change the limit). Above it the box
answers 429 with the code rate_limited and a Retry-After header in seconds. Wait that long, then continue.
Errors
Errors are RFC 9457 problem details (application/problem+json) with a stable code, a short title, the status
and often a detail:
{
"code": "scope_required",
"title": "Forbidden",
"status": 403,
"detail": "This call needs the scope read."
}
| Status | Code | Meaning |
|---|---|---|
400 |
bad_request, malformed_json |
The request is malformed |
401 |
token_invalid |
The token is missing, wrong, revoked or expired (with WWW-Authenticate: Bearer) |
403 |
scope_required |
The account lacks a scope the operation needs |
403 |
api_account_refused |
The operation is for people on the dashboard only |
404 |
for example site_not_found |
No such object, or the account has no role on its site |
409 |
for example changed_meanwhile |
A conflict, such as a stale version |
412 |
version_mismatch |
The ETag sent in If-Match is stale |
413 |
body_too_large |
The body is too large |
422 |
for example invalid_body |
Some fields are not valid; errors lists each with its pointer and detail |
428 |
if_match_required |
The change needs If-Match |
429 |
rate_limited |
Too many calls; see Retry-After |
502, 503 |
engine_refused, engine_unavailable |
The box’s analysis engine is busy or starting; retry later |
Build your integration on the code, since the detail text may change.
Conventions
- Times are RFC 3339. Send periods as
fromandtowith an offset, for examplefrom=2026-11-01T00:00:00%2B07:00. Hourly and daily figures follow the site’s time zone. - Long lists are paged: pass
limit, then the answer’snext_beforeasbeforefor the next page.next_beforeisnullon the last page. - Changes that can conflict carry a
version(settings) or anETagto send back inIf-Match(cameras and their drawing). A stale one is refused, so read again and retry.
1.0.0. Updated 2026-11-06