Skip to main content

API Authentication

TokenTimer has two authentication surfaces. Pick the one that matches your caller.

You are buildingUse
A script or tool that acts as a user (manage tokens, workspaces, alerts)Session authentication
A CertOps executor, CI job, or renewal hook that reports certificate eventsMachine API tokens

Not sure? If you are not using TokenTimer's Certificate Lifecycle Management feature (certificate management guide), use session authentication.

Session authentication​

Log in with your account credentials to receive a session cookie, then send it on every request.

The examples below use Bash, curl, and jq. Use an existing, verified account and replace the host with your own API origin for Core or Enterprise. Keep the cookie jar private: it grants access to your session.

BASE=https://tokentimer.ch

# 1. Fetch the CSRF token AND save its companion cookie before logging in
CSRF=$(curl -sS -c cookies.txt "$BASE/api/csrf-token" | jq -r '.csrfToken')

# 2. Log in using that header and cookie; save the new session cookie
curl -sS -b cookies.txt -c cookies.txt -X POST "$BASE/auth/login" \
-H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' \
-d '{"email":"me@example.com","password":"StrongPass123!"}'

# 3. Verify the session; expect loggedIn: true
curl -sS -b cookies.txt "$BASE/api/session" | jq '.'

# 4. Refresh the CSRF token and cookie after login, before writing
CSRF=$(curl -sS -b cookies.txt -c cookies.txt "$BASE/api/csrf-token" | jq -r '.csrfToken')

If loggedIn is false, stop before running a write workflow. Complete two-factor authentication if prompted, or correct your account credentials.

A logged-in session response includes fields such as:

{
"loggedIn": true,
"user": {
"id": "3f6e...",
"email": "me@example.com",
"displayName": "Me"
}
}

CSRF token for mutating requests​

CSRF protection applies to login as well as session-authenticated POST/PUT/PATCH/DELETE requests. Fetching a token rotates its companion cookie: save both with -b cookies.txt -c cookies.txt, then send the returned token in X-CSRF-Token:

# Fetch a CSRF token bound to your session
CSRF=$(curl -sS -b cookies.txt -c cookies.txt "$BASE/api/csrf-token" | jq -r '.csrfToken')

# Include it as a header on mutating calls
curl -s -b cookies.txt -X POST "$BASE/api/tokens" \
-H "X-CSRF-Token: $CSRF" \
-H 'Content-Type: application/json' \
-d '{"name":"My cert","category":"cert","type":"ssl_cert","workspace_id":"WS_ID"}'

Two-factor accounts​

If your account has TOTP two-factor authentication enabled, POST /auth/login returns an intermediate response and you complete the login with POST /auth/verify-2fa. Send the cookie jar and X-CSRF-Token header with the verification request, save any updated cookies, then verify /api/session and refresh the CSRF token. See the REST Reference for the exact payloads.

Ending the session​

curl -s -b cookies.txt -X POST "$BASE/api/logout"

Machine API tokens​

Certificate Lifecycle Management (CLM) uses the existing CertOps technical API. The certops paths, token scopes, and configuration names below refer to that same feature.

Machine tokens (ttx_<id>_<secret>) authenticate non-human callers on the CertOps executor surface. They are workspace-bound, scoped, optionally expiring, and revocable.

Create one in the dashboard: workspace manager or admin role, Certificate Management → Settings → Machine API tokens (/certops/settings).

Shown once

The plaintext token appears exactly once, in the create response. TokenTimer stores only a SHA-256 hash and cannot re-display it, including support staff. Store it in a secret manager immediately.

Scopes​

Grant the minimum an executor needs:

ScopeGrants
certops:events:writeReport job lifecycle events
certops:evidence:writeAttach evidence records (an events-only token cannot attach evidence)
certops:readReserved; no machine-token inventory read route currently exists
certops:jobs:readReserved; job reads currently require a human session

Using the token​

JOB_ID must already exist. Create it with Create a manual CertOps job or the dashboard Create manual job button before calling executor routes. Machine tokens cannot create jobs; an unknown id returns 404 CERTOPS_JOB_NOT_FOUND.

Send it as a bearer token. Machine-token routes are CSRF-exempt and have no session dependency.

curl -sS -X POST https://tokentimer.ch/api/v1/certops/jobs/JOB_ID/events \
-H "Authorization: Bearer ttx_abc123_s3cr3t..." \
-H "Content-Type: application/json" \
-d '{
"schemaVersion": 1,
"eventId": "evt-2026-07-12-000001",
"workspaceId": "WS_ID",
"jobId": "JOB_ID",
"status": "succeeded",
"eventType": "job.completed",
"occurredAt": "2026-07-12T10:00:00.000Z"
}'

A successful submission returns 202 Accepted:

{
"ok": true,
"eventId": "evt-2026-07-12-000001",
"jobId": "JOB_ID",
"status": "succeeded",
"evidenceIds": [],
"duplicate": false,
"idempotent": false
}

Rate limits and idempotency​

Each machine token shares one rate-limit bucket of 120 requests per 60 seconds across all executor routes. On 429 CERTOPS_MACHINE_RATE_LIMITED, honor the Retry-After header. eventId makes submissions idempotent: replaying the same event is a safe no-op.

Common error codes​

HTTPCodeFix
401CERTOPS_API_TOKEN_UNAUTHORIZEDToken missing, malformed, revoked, or expired. Create a new token.
403CERTOPS_API_TOKEN_SCOPE_DENIEDAdd the missing scope when creating the token.
403CERTOPS_EXECUTOR_WORKSPACE_MISMATCHBody workspaceId must match the token's workspace.
404CERTOPS_JOB_NOT_FOUNDCreate or look up a job first (POST/GET .../certops/jobs or Create manual job), then retry with that id.
422PRIVATE_KEY_MATERIAL_REJECTEDNever send private keys. Remove key material from the payload.
429CERTOPS_MACHINE_RATE_LIMITEDBack off per Retry-After, then retry with the same eventId.

For the full executor workflow (events, evidence, redaction rules, certbot hooks), see the Certificate Automation guide and the connect an external executor runbook.