API Authentication
TokenTimer has two authentication surfaces. Pick the one that matches your caller.
| You are building | Use |
|---|---|
| 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 events | Machine API tokens |
Not sure? If you are not using TokenTimer's certificate operations feature (what is CertOps?), use session authentication.
Session authentication
Log in with your account credentials to receive a session cookie, then send it on every request.
# 1. Log in and store the session cookie
curl -s -c cookies.txt -X POST https://tokentimer.ch/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"me@example.com","password":"StrongPass123!"}'
# 2. Verify the session
curl -s -b cookies.txt https://tokentimer.ch/api/session | jq '.'
A logged-in session response looks like:
{
"loggedIn": true,
"user": {
"id": "3f6e...",
"email": "me@example.com",
"name": "Me"
}
}
CSRF token for mutating requests
When CSRF enforcement is active, POST/PUT/PATCH/DELETE requests made with a session cookie also need a CSRF token:
# Fetch a CSRF token bound to your session
CSRF=$(curl -s -b cookies.txt https://tokentimer.ch/api/csrf-token | jq -r '.csrfToken')
# Include it as a header on mutating calls
curl -s -b cookies.txt -X POST https://tokentimer.ch/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. See the REST Reference for the exact payloads.
Ending the session
curl -s -b cookies.txt -X POST https://tokentimer.ch/api/logout
Machine API tokens
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, CertOps → Operations → Machine API tokens.
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:
| Scope | Grants |
|---|---|
certops:events:write | Report job lifecycle events |
certops:evidence:write | Attach evidence records (an events-only token cannot attach evidence) |
certops:read | Read certificates and jobs (reserved for the upcoming machine-token read API) |
certops:jobs:read | Poll job status (reserved, same as above) |
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
| HTTP | Code | Fix |
|---|---|---|
| 401 | CERTOPS_API_TOKEN_UNAUTHORIZED | Token missing, malformed, revoked, or expired. Create a new token. |
| 403 | CERTOPS_API_TOKEN_SCOPE_DENIED | Add the missing scope when creating the token. |
| 403 | CERTOPS_EXECUTOR_WORKSPACE_MISMATCH | Body workspaceId must match the token's workspace. |
| 404 | CERTOPS_JOB_NOT_FOUND | Create or look up a job first (POST/GET .../certops/jobs or Create manual job), then retry with that id. |
| 422 | PRIVATE_KEY_MATERIAL_REJECTED | Never send private keys. Remove key material from the payload. |
| 429 | CERTOPS_MACHINE_RATE_LIMITED | Back 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.