Skip to content

Authentication

Railhook accepts four credentials. This page shows which one to use, how to get it, and how to replace it without breaking the callers that hold it.

Credential Used by Sent as Carries
Access token (JWT) The dashboard and anything acting as a person Authorization: Bearer … A user, their organization, their role
API key Your servers and the SDKs X-API-Key: … One project and a scope
Device code railhook login in the CLI Exchanged for a session Same as an access token
Platform admin token Whoever operates the deployment X-Platform-Admin-Token: … Access to /api/v1/admin/**, across organizations

Sign in with POST /api/v1/auth/login. The response body carries the accessToken. The refresh token does not appear in the body: it is set as an HttpOnly cookie named refresh_token, scoped to /api/v1/auth.

Terminal window
curl -X POST https://railhook.example.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"email":"[email protected]","password":"••••••••"}'

Send the access token on every request that acts as that user:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Token Default lifetime
Access token 15 minutes
Refresh token 24 hours

POST /api/v1/auth/refresh reads the refresh_token cookie, or a refreshToken field in the JSON body if there is no cookie. It returns a new access token and sets a new refresh cookie. The refresh token you spent is blacklisted.

Each sign-in is a session. A user can list their sessions, close one, or close all of them. POST /api/v1/auth/logout revokes the current access and refresh tokens.

Sign-in is rate limited and repeated failures lock the account for a while. Both are configured through the environment:

Variable Default Meaning
AUTH_RATE_LIMIT_LOGIN_PER_MINUTE 10 Sign-in attempts per IP and per email, per minute. Past it the API answers 429.
AUTH_LOCKOUT_ENABLED true Turns lockout on or off
AUTH_LOCKOUT_THRESHOLD 5 Consecutive failures before the first lockout
AUTH_LOCKOUT_INITIAL_SECONDS 60 First lockout. Doubles with each further failure.
AUTH_LOCKOUT_MAX_SECONDS 900 The longest a lockout gets
AUTH_LOCKOUT_FAILURE_WINDOW_MINUTES 60 How far back failures are counted

A lockout expires on its own, and a password reset clears it straight away.

An API key belongs to one project. It is what sends events, and what the SDKs are built on.

  1. Create the key for a project, in the dashboard or with POST /api/v1/projects/{projectId}/api-keys.

  2. Copy the key from the response. It is shown once: Railhook stores only a hash, so a lost key cannot be recovered, only replaced.

  3. Put it in an environment variable on a server you control and send it in the X-API-Key header:

    X-API-Key: Kz1uAIM8VeJUQN7yGSYCst64WxNLabBHfOYbrPlJ1yk
Scope Allows
READ_WRITE Reads and writes. Sending an event is a write. The default.
READ_ONLY Reads only. A write answers 403.

A key can carry an expiresAt date. After it, or once the key is revoked, the key authenticates nothing. Revoking takes effect immediately, with no grace period.

POST /api/v1/projects/{projectId}/api-keys/{apiKeyId}/rotate creates a replacement with the same name and scope. The old key keeps working for a grace window, so you can deploy the new one everywhere before the old one stops.

Field Default Meaning
gracePeriodHours 24 How long the old key keeps working. 0 cuts it off now, which is the rotation to run after a leak.
expiresAt none Optional expiry for the new key

Rotation never extends the old key: if it was already due to expire sooner, that date stands. A key can be rotated once. To rotate again, rotate its replacement.

railhook login uses a device code. The CLI prints a URL and a code, you approve the code in the dashboard, and the CLI receives a session of its own. See CLI.

PLATFORM_ADMIN_TOKEN is the credential for the operator endpoints under /api/v1/admin/**. It is independent of organizations: an organization OWNER does not get it. Leave it empty and the admin endpoints stay unreachable. Set it only when an operator needs them, and send it in the X-Platform-Admin-Token header.

The request and response shapes for every auth endpoint are in the API reference.

“Continue with Google” appears on the sign-in and registration pages once the deployment has a Google OAuth client. One button does both jobs:

  • A Google account that matches no Railhook account gets one straight away, with the address marked verified and an organization it owns. A Google Workspace account names the organization after its domain (acme.com becomes Acme); a personal account gets Your name’s workspace. Rename it in organization settings.
  • An account that signed up with a password and the same address gains Google as a second way in. The password keeps working.
  • The account is matched on Google’s permanent id for the person, so changing the address on the Google account still signs in to the same Railhook account.

An account created through Google has no password. To add one, use Forgot password on the sign-in page.

  1. In Google Cloud Console, create an OAuth client ID of type Web application.

  2. Add the authorized redirect URI. It is your APP_BASE_URL followed by the callback path, and it has to match exactly:

    https://railhook.example.com/api/v1/auth/oauth/google/callback

    For a local stack on port 8080, add http://localhost:8080/api/v1/auth/oauth/google/callback as well.

  3. On the OAuth consent screen, keep the scopes to openid, email and profile.

  4. Set both values on the API and restart it:

    Terminal window
    GOOGLE_OAUTH_CLIENT_ID=1234567890-abc.apps.googleusercontent.com
    GOOGLE_OAUTH_CLIENT_SECRET=GOCSPX-...

    On Kubernetes, set googleSignIn.clientId and put the secret in the Secret named by googleSignIn.existingSecret.