Skip to main content

Authentication

Formstamper uses JWT (JSON Web Tokens) for API authentication with a short-lived access token and a long-lived refresh token.

Authentication Flow

Endpoints

Register

POST /api/auth/register

Create a new account.

Request Body:

{
"email": "user@example.com",
"password": "SecurePassword123!"
}

Response: 200 OK

{
"message": "Verification email sent"
}

Login

POST /api/auth/login

Authenticate and receive an access token.

Request Body:

{
"email": "user@example.com",
"password": "SecurePassword123!"
}

Response: 200 OK

{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"publicId": "usr_01j5abc123",
"email": "user@example.com",
"applicationRole": "MEMBER",
"organizations": [
{
"organizationId": "org_01j5xyz789",
"organizationName": "Acme Corp",
"role": "ORG_ADMIN"
}
]
}

A refreshToken is also set as an HTTP-only cookie.

info

If the user has 2FA enabled, the login response returns a challengeToken instead of an accessToken. You must complete the 2FA challenge:

{
"requires2FA": true,
"challengeToken": "chg_abc123...",
"method": "TOTP"
}

Send the 2FA code to /api/auth/verify-2fa with the challenge token to complete authentication.


Refresh Token

POST /api/auth/refresh-token

Exchange a valid refresh token for a new access token.

The refresh token is read from the HTTP-only refreshToken cookie.

Response: 200 OK

{
"accessToken": "eyJhbGciOiJIUzI1NiIs..."
}

Verify Email

GET /api/auth/verify?token={token}

Verify a user's email address using the token from the verification email.


Request Password Reset

POST /api/auth/request-reset

Request Body:

{
"email": "user@example.com"
}

Sends a password reset email to the specified address.


Reset Password

POST /api/auth/reset-password

Request Body:

{
"token": "reset-token-from-email",
"newPassword": "NewSecurePassword456!"
}

Logout

POST /api/auth/logout

Invalidates the refresh token and clears the cookie.

Token Lifecycle

TokenLifetimeStorage
Access Token15 minutesClient memory / Authorization header
Refresh Token7 daysHTTP-only secure cookie

Using the Access Token

Include in the Authorization header for all authenticated requests:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Error Responses

CodeMeaning
401 UnauthorizedMissing or expired token
403 ForbiddenValid token but insufficient permissions
423 LockedAccount is locked/disabled