Wire Protocol¶
The Command-Array Format¶
SDK abstracts this away
You don't need to understand the wire protocol to use the SDK—it handles everything automatically. This page is for developers who want to understand what's happening under the hood or build custom integrations.
The Authentic8 API does not use standard REST endpoints. Every API call is a POST to a single endpoint with a JSON array payload — the command-array format.
The SDK constructs the array, adds the setauth command automatically, sends the request, and returns only the result you care about — you never see the array structure.
Request Structure¶
Every request body is a JSON array with at least two items:
[
{"command": "setauth", "data": "TOKEN"}, // index 0: always required
{"command": "wire_command", "param1": "value1"} // index 1: params go FLAT alongside "command"
]
Params are flat — never nested under data
Command parameters go directly alongside "command" in the same object. They are not nested under a "data" key. The only "data" key in the array is on the setauth entry (which holds the token string).
// CORRECT:
{"command": "org.get", "org_name": "myorg"}
// WRONG:
{"command": "org.get", "data": {"org_name": "myorg"}}
Exception: create_context uses "context_data" (not "data") for session parameters, with max_uses at the command level.
setauth authenticates the session for all subsequent commands in the same array. Additional commands can be appended at indexes 2, 3, etc., but the SDK always sends exactly two commands per request (one setauth + one wire command).
Response Structure¶
The response is a parallel JSON array:
[
{"result": "setting auth from data"}, // index 0: setauth acknowledgment
{"result": {...}} // index 1: your command's result
]
Always read from response[1]["result"] — index 0 is the setauth ack, never the useful data.
The SDK's _extract_api_result(response, index=1) does this automatically.
Example: Full Round-Trip¶
# SDK call:
context_id = browsing.create_context(
url="https://secure.example.com",
username="analyst@company.com",
policy=[{"type": "readonly", "params": ["true"]}],
max_uses=1,
)
# Wire payload sent:
# [
# {"command": "setauth", "data": "admin_token_value"},
# {
# "command": "create_context",
# "context_data": {
# "user": "analyst@company.com",
# "urls": ["https://secure.example.com"],
# "policy": [{"type": "readonly", "params": ["true"]}]
# },
# "max_uses": 1
# }
# ]
# Note: create_context uses "context_data" nesting (not "data").
# Params "user" and "urls" (array) differ from the Python method's
# "username" and "url" parameter names.
# Wire response received:
# [
# {"result": "setting auth from data"},
# {"result": {"browse_context_id": "a1b2c3d4e5f6", "expires": 1735689600, "max_uses": 1}}
# ]
# SDK returns: "a1b2c3d4e5f6"
print(context_id) # a1b2c3d4e5f6
Implication for Postman Testing¶
Because all API calls POST to the same endpoint, Postman tests follow a consistent pattern:
// Every post-response test script starts the same way:
pm.test("Response is command-array (≥2 items)", () => {
pm.expect(pm.response.json()).to.be.an('array').with.lengthOf.at.least(2);
});
pm.test("Auth acknowledged at index 0", () => {
pm.expect(pm.response.json()[0]?.result).to.include('setting auth');
});
// Then extract the actual result:
const result = pm.response.json()[1]?.result;
Non-Command-Array Endpoints¶
Two endpoints use different protocols and are not part of the command-array format:
File Download — POST /getfile/¶
POST https://extapi.authentic8.com/getfile/
Content-Type: multipart/form-data
id=<file_id>&auth=<file_token>
The response body is the raw file binary. There is no JSON wrapper. The SDK's
FileAPI.download_file() handles this transparently.
File Upload — POST /putfile/¶
POST https://extapi.authentic8.com/putfile/
Content-Type: multipart/form-data
file=<binary>&name=<filename>&path=<dest_path>&bucket_id=<bucket_id>
Note: the form field is name (not dest_name) and path (not dest_path).
Context Shorthand — GET /ctx/¶
A single-step alternative to the two-step create → launch flow:
GET https://extapi.authentic8.com/ctx/
?auth=<admin_token>
&user=<username>
&url=<target_url>
&response=url
The response parameter controls the return format:
| Value | Returns |
|---|---|
redirect (default) |
HTTP redirect into the Silo browser session |
url |
Launch URL as plain text — useful for automation and scripting |
id |
Just the context launch ID as plain text |
Use response=url or response=id when calling from scripts or Newman, since
a redirect cannot be followed programmatically.
Proxy Policy Commands¶
Proxy policy management uses the standard command-array format but deserves special attention due to its unique response behavior and object schema.
Commands¶
// Read current proxy objects
{"command": "policy_proxies.get", "org_name": "MyOrg", "include_proxy_policy": true}
// Replace the entire proxy list (empty list clears all)
{"command": "policy_proxies.set", "org_name": "MyOrg", "proxies": [...]}
// Append proxies without replacing existing ones — multiple in a single call
{"command": "policy_proxies.add", "org_name": "MyOrg",
"proxies": [{"name": "proxy1", ...}, {"name": "proxy2", ...}]}
// Remove proxies by name — multiple names in a single call
{"command": "policy_proxies.delete", "org_name": "MyOrg",
"proxy_names": ["proxy1", "proxy2", "proxy3"]}
Proxy Object Schema¶
{
"name": "eng_proxy_1",
"location": {
"address": "131.131.131.131",
"port": 8080,
"type": "http"
}
}
| Field | Required | Notes |
|---|---|---|
name |
Yes | Must be unique within the org's proxy list |
location.address |
Yes | IP address or FQDN |
location.port |
No | Defaults per type (HTTP→80, HTTPS→443, SOCKS→1080) |
location.type |
No | http (default), https, socks, socks4, socks5 |
HTTPS proxy certificate requirement
When type is https, the address value must exactly match the Common
Name (CN) in the proxy server's SSL certificate. A mismatch causes
ERR_PROXY_CERTIFICATE_INVALID for end users.
SOCKS authentication
SOCKSv4 supports no proxy authentication. SOCKSv5 supports no authentication in Chrome.
Delete Response¶
policy_proxies.delete always returns HTTP 200 with a result dict — it
never returns an error even when named proxies do not exist:
Always check proxies_not_found explicitly in your application logic.
Hierarchy Aggregation¶
Proxy policies aggregate down the org hierarchy. Child orgs inherit and accumulate the proxy objects defined at every parent level. Setting or adding proxies at one org level does not affect parent or sibling orgs.
Why This Design?¶
The command-array protocol lets the Authentic8 platform execute multiple commands atomically in a single HTTP round-trip. While the SDK always uses one-command-per-request, the wire format supports batching for platform-internal operations.