API reference / Auth
Authentication API
User registration, login, token rotation, logout, password recovery, and business integration authentication for PayAssure.
PayAssure
Developer Dashboard
API reference / Auth
User registration, login, token rotation, logout, password recovery, and business integration authentication for PayAssure.
The platform has two related credential types:
Authorization: Bearer <accessToken>
Content-Type: application/jsonAccess tokens expire after 15 minutes. Refresh tokens expire after 7 days. The server checks refreshTokenVersion on every protected request, so logout or refresh rotation invalidates the previous token version.
{
"statusCode": 401,
"message": "Invalid credentials",
"error": "Unauthorized"
}{
"statusCode": 400,
"message": ["email must be an email", "password must be longer than or equal to 6 characters"],
"error": "Bad Request",
"path": "/auth/register-before-onboarding"
}Request validation removes unknown body properties. Registration passwords require at least 6 characters; login only requires a string. Identifiers contain either a username or email address.
/auth/register-before-onboardingCreates an active standard USER account before the participant completes onboarding. No bearer token is required.
{
"username": "merchant-user",
"email": "merchant@example.com",
"password": "strong-password"
}If the email already belongs to an onboarding participant and an account exists, the participant is linked and 201 is returned with message: Account already exists. Please complete onboarding to finish your profile.
{
"message": "Account created successfully. Your profile is incomplete. Please complete onboarding to finish setup.",
"profileComplete": false,
"user": {
"id": "clx123user",
"username": "merchant-user",
"email": "merchant@example.com",
"role": "USER"
}
}/auth/onboarded-registerCreates a standard USER account for an existing onboarding participant, or links an existing account to that participant. An onboarding record must exist for the submitted email. No bearer token is required.
{
"username": "merchant-user",
"email": "merchant@example.com",
"password": "strong-password"
}New account:
{
"message": "User account created successfully and profile is complete.",
"profileComplete": true,
"user": {
"id": "clx123user",
"username": "merchant-user",
"email": "merchant@example.com",
"role": "USER"
}
}
Existing account linked:
{
"message": "Your profile is now complete.",
"profileComplete": true,
"user": {
"id": "clx123user",
"username": "merchant-user",
"email": "merchant@example.com",
"role": "USER"
}
}/auth/loginAuthenticates an active user using either their username or email address. No bearer token is required.
{
"identifier": "merchant-user",
"password": "strong-password"
}The identifier may instead be an email address. For incomplete onboarding, profileComplete is false and the message is: Your profile is incomplete. Please finish onboarding to get API keys access.
{
"accessToken": "<jwt-access-token>",
"refreshToken": "<jwt-refresh-token>",
"profileComplete": true,
"message": "Profile complete.",
"user": {
"id": "clx123user",
"username": "merchant-user",
"email": "merchant@example.com",
"role": "USER"
}
}/auth/refreshExchanges a valid refresh token for a new access-token and refresh-token pair. Rotation invalidates the previous token version. No bearer token is required.
{
"refreshToken": "<jwt-refresh-token>"
}{
"accessToken": "<new-jwt-access-token>",
"refreshToken": "<new-jwt-refresh-token>",
"profileComplete": true,
"message": "Profile complete.",
"user": {
"id": "clx123user",
"username": "merchant-user",
"email": "merchant@example.com",
"role": "USER"
}
}/auth/logoutInvalidates the current user's refresh-token version. Existing access tokens remain subject to normal JWT expiry, but refresh attempts using the old version fail.
Authorization: Bearer <access_token>
Request body: none{
"message": "Logged out successfully"
}Password recovery does not require a bearer token. A six-digit OTP is sent by email, stored only as a SHA-256 hash, expires after one hour, and is single-use.
/auth/forgot-passwordRequests a password reset email for an active account. No bearer token is required.
{
"email": "merchant@example.com"
}The endpoint intentionally returns the same 201 response whether or not the email belongs to an account, preventing account enumeration. A new request invalidates previous reset OTPs. The six-digit OTP is sent only through the configured SMTP service and is never returned in the HTTP response or stored in plaintext.
{
"message": "If an account exists for that email, a password reset token has been sent."
}/auth/reset-passwordConsumes the six-digit OTP received by email and sets a new password. No bearer token is required.
{
"otp": "482913",
"newPassword": "new-strong-password"
}The OTP is single-use. After a successful reset, refreshTokenVersion is incremented so all existing refresh tokens are invalidated. The user must log in again to receive a new access and refresh token pair.
{
"message": "Password reset successfully. Please log in with your new password."
}{
"sub": "clx123user",
"username": "merchant-user",
"email": "merchant@example.com",
"role": "USER",
"version": 0
}Treat access and refresh tokens as opaque strings. Do not construct or modify JWT claims.
/auth/refresh.Keep credentials, API traffic, and webhook integrations protected throughout the authentication lifecycle.
Use HTTPS for every API and dashboard request. Never send credentials over plain HTTP.
Keep API keys and secrets in environment variables or a vault, rotate them regularly, and revoke compromised credentials.
Validate webhook signatures, restrict sensitive integrations by IP where possible, and review audit activity.
Related business authentication
This route authenticates a business integration rather than a platform user. It is implemented by SettlementController, outside the /auth controller. It requires a platform JWT whose email matches the onboarding participant owning the API key.
/settlement/authenticateVerifies a business API key and API secret and creates a settlement session.
Authorization: Bearer <access_token>
Content-Type: application/json
{
"apiKey": "pk_live_abc123",
"apiSecret": "sk_live_xyz789"
}Use the returned settlement session token in the x-settlement-session header. The documented default expiry is 3600 seconds; exact expiry is controlled by settlement configuration.
{
"success": true,
"token": "session_1725900000000_0123456789abcdef",
"expiresIn": 3600,
"tokenType": "Bearer",
"business": {
"id": "participant-123",
"businessName": "Fresh Store Ltd",
"participantType": "RETAILER",
"status": "ACTIVE"
}
}{
"statusCode": 401,
"message": "Invalid API credentials",
"error": "INVALID_CREDENTIALS"
}