Skip to content

Authentication and request signing

Bearer authentication is not supported. Every /v1 operation requires these four headers; X-Sx-Actor is optional audit text and never authorizes anything.

text
X-Sx-Key-Id: sxk_<16-32 lowercase letters or digits>
X-Sx-Timestamp: <10-digit Unix seconds>
X-Sx-Nonce: <16-64 characters from A-Za-z0-9_->
X-Sx-Signature: v1=<standard base64>
X-Sx-Actor: <optional, sanitized and limited to 128 characters>

Canonical request

Join exactly seven lines with LF (\n) and no trailing newline:

text
sx-v1
{UPPERCASE_METHOD}
{PATH_AND_QUERY_EXACTLY_AS_SENT}
{KEY_ID}
{TIMESTAMP}
{NONCE}
{LOWERCASE_SHA256_OF_RAW_BODY_BYTES}

The path begins with /, includes the query string, and must match the bytes sent by the HTTP client. Hash an absent body as the empty byte string (e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855). Serialize a body once, then sign and send those same bytes.

  • hmac-sha256: HMAC-SHA256 the canonical UTF-8 string with the issued secret.
  • rsa2: SHA256withRSA using PKCS#1 v1.5 and a private key of at least 2048 bits.

Encode the resulting signature as standard base64 and prepend v1=. The scheme belongs to stored signing material, not to a caller-selected header.

Validation order

The server applies Redis pre-auth throttling, canonical shape checks, the ±300-second timestamp window, credential lookup/signature verification, and then claims the nonce in Redis. Unknown key ids, retired material, and bad signatures are indistinguishable before verification. After a valid signature, revoked, disabled, expired, replayed, and disallowed-source credentials receive their specific safe errors.

A nonce must be new inside the accepted window. The server derives one req.partnerCaller; workspace existence/kind and typed scopes are checked after authentication and fail closed.

OpenAPI cannot calculate this signature. Its four API-key security declarations document required headers only; “try it out” will not produce a valid call.