Skip to content

API authentication

Public API authentication

Public API v1 accepts Personal Access Tokens (PATs) only:

Authorization: Bearer hstk_pat_<selector>_<secret>

The Bearer scheme is case-insensitive and may be followed by ASCII spaces. The header must contain exactly one credential; comma-separated or otherwise ambiguous credentials are rejected.

Do not send a token in a query string, URL, cookie, or request body. A browser login by itself does not authenticate /api/v1 requests.

Every response includes a server-generated X-Request-Id. Errors also include that same value in the JSON body:

{
"error": {
"code": "AUTH_REQUIRED",
"message": "Authentication is required."
},
"requestId": "..."
}

All API responses also include Cache-Control: no-store. Once a PAT has been accepted, successful responses and authorization/domain errors carry the shared rate-limit headers: RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A rejected request is 429 RATE_LIMITED with Retry-After. Authentication failures and framework-generated routing responses are rejected before a credential-specific rate-limit decision exists. Hamstik does not emit legacy X-RateLimit-* aliases.

Invalid, expired, revoked, or removed-account credentials return JSON 401 responses with WWW-Authenticate: Bearer realm="Hamstik API".

Example:

Terminal window
export HAMSTIK_TOKEN='hstk_pat_example_replace_me'
curl \
-H "Authorization: Bearer $HAMSTIK_TOKEN" \
https://hamstik.com/api/v1/me

The me response identifies the authenticated user’s immutable publicId, the PAT credential, its scopes, expiration, and the Organizations available through that credential. A valid browser login without this header returns 401 AUTH_REQUIRED; the API never falls back to an Auth.js session cookie.

Authorization is evaluated on every request. Effective access is the intersection of the PAT scopes, its Organization/Project resource grants, the user’s current membership and role, and Organization suspension state. A resource outside that intersection is normally hidden as 404 NOT_FOUND; an insufficient scope or membership role remains an explicit authorization error where the resource would otherwise be addressable.