Portal
API Conventions

Authentication

Login, refresh, logout, and session handling for the Merchant API.

Overview

FutureSMS Merchant API uses Bearer access tokens. A client logs in with an API user, stores the returned token pair, sends the access token on business requests, and refreshes the token pair before continuing.

Authentication also checks whether the user, account, role, and session are allowed to use the requested API surface.

Endpoints

MethodPathPurpose
POST/api/v1/auth/loginAuthenticate a user and issue a token pair.
POST/api/v1/auth/refreshRotate the refresh token and issue a new token pair.
GET/api/v1/auth/meVerify the access token and read the current profile.
POST/api/v1/auth/logoutRevoke the current session.

Before You Begin

Create a dedicated API user for server-to-server Merchant API access. Do not reuse a human portal account for automated traffic.

Store credentials and tokens only on your server side or in a secrets manager. Client applications should call your backend, and your backend should call FutureSMS.

Make sure the integration can persist the latest token pair, coordinate token refresh across workers, and use UTC timestamps from the auth response when deciding when to refresh.

Request Flow

  1. Call POST /api/v1/auth/login with username and password.
  2. Store access_token, refresh_token, and both expiry timestamps.
  3. Send Authorization: Bearer <access_token> on protected API requests.
  4. When the access token expires, call POST /api/v1/auth/refresh with the latest refresh token.
  5. Replace both stored tokens with the refresh response.
  6. Call POST /api/v1/auth/logout when the integration should end the session.
After refresh succeeds, replace the stored token pair immediately. Do not keep using an old refresh token.

Authorization Header

Authentication-protected endpoints use the same header shape.

Header shape
{
  "Authorization": "Bearer <access_token>"
}

Login

Use Login when your integration needs to start a Merchant API session and obtain a token pair.

Endpoint

POST /api/v1/auth/login

Authentication: none.

Before You Begin

Use an API user for server-to-server Merchant API integrations. Portal users can authenticate for portal flows, but merchant business API usage should not depend on a human portal session.

The user must be active and allowed to use the requested API surface.

Request fields

FieldTypeRequiredRules
usernamestringYes4-64 chars, A-Z, a-z, 0-9, and _.
passwordstringYes8-72 chars.

Response fields

FieldMeaning
mfa_requiredWhether the account requires an additional authentication step before a token pair can be used.
mfa_tokenTemporary MFA token when MFA is required; otherwise null.
access_tokenBearer token for protected API requests.
refresh_tokenToken used only with /api/v1/auth/refresh.
token_typeToken scheme, normally bearer.
access_token_expires_atUTC timestamp when the access token expires.
refresh_token_expires_atUTC timestamp when the refresh token expires.
user.usernameAuthenticated username.
user.roleAuthenticated role, such as api, merchant_admin, or site_admin.

Behavior

When login succeeds, FutureSMS:

  1. Applies login protection checks.
  2. Validates username and password.
  3. Confirms the user can authenticate for this API surface.
  4. Checks the account and role permissions.
  5. Handles MFA state if the account requires it.
  6. Replaces older sessions for the same user.
  7. Issues a new access token and refresh token.

New login can replace older sessions for the same user. If an old token stops working after a new login, log in again and update stored credentials.

Status codes

StatusReasonMeaning
200nullLogin succeeded and returned an auth response.
401INVALID_CREDENTIALSUsername or password is wrong.
401USER_LOCKEDAccount is temporarily locked.
401USER_INACTIVEUser is disabled or no longer active.
403nullUser is not allowed for this access scope.
422nullRequest body failed validation.
429AUTH_LOGIN_RATE_LIMITEDToo many login attempts.

Examples

Request
{
  "username": "api_user_example",
  "password": "REPLACE_WITH_STRONG_PASSWORD"
}
OK response
{
  "message": "OK",
  "details": null,
  "data": {
    "mfa_required": false,
    "mfa_token": null,
    "access_token": "<access_token>",
    "refresh_token": "<refresh_token>",
    "token_type": "bearer",
    "access_token_expires_at": "2026-03-25T11:30:00Z",
    "refresh_token_expires_at": "2026-04-01T10:30:00Z",
    "user": {
      "username": "api_user_example",
      "role": "api"
    }
  },
  "meta": null
}

Token Storage

Store tokens on the server side of your integration when possible. Treat both tokens as credentials.

TokenUse
access_tokenSent on API requests through the Authorization header.
refresh_tokenSent only to /api/v1/auth/refresh to obtain a new token pair.

Access tokens are short-lived. Refresh tokens live longer, but can still become invalid before their timestamp if the user logs in again, logs out, changes password, is disabled, or the session is ended.

Refresh

Use Refresh when the access token is expired or close to expiry and the integration should continue the same authenticated session.

Endpoint

POST /api/v1/auth/refresh

Authentication: refresh token in request body.

Before You Begin

Use the latest refresh token only. A successful refresh rotates the pair, so the previous refresh token should be treated as spent.

If multiple workers share one API user, coordinate refresh so only one worker rotates the session and the others reuse the stored new token pair.

Request fields

FieldTypeRequiredRules
refresh_tokenstringYesLatest refresh token from login or the previous refresh response.

Response fields

FieldMeaning
mfa_requiredUsually false for server-to-server API refresh.
mfa_tokenTemporary MFA token if an additional authentication step is required.
access_tokenNew Bearer token for protected API requests.
refresh_tokenNew refresh token. Store this and discard the previous one.
token_typeToken scheme, normally bearer.
access_token_expires_atUTC timestamp when the new access token expires.
refresh_token_expires_atUTC timestamp when the new refresh token expires.
user.usernameAuthenticated username after revalidation.
user.roleAuthenticated role after revalidation.

Behavior

Refresh revalidates the session before issuing a new pair. FutureSMS:

  1. Verifies the refresh token.
  2. Confirms the session can continue.
  3. Rechecks user, account, and role permissions.
  4. Applies refresh protection checks.
  5. Issues a new token pair.

After a successful refresh, store the new refresh token and discard the previous one. If several workers need to refresh, let one worker refresh and share the updated token pair with the others.

Status codes

StatusReasonMeaning
200nullRefresh succeeded and returned a new token pair.
401REFRESH_TOKEN_EXPIREDRefresh token expired.
401REFRESH_TOKEN_REVOKEDRefresh token was already rotated or revoked.
401REFRESH_TOKEN_KICKEDA newer login replaced this refresh session.
401REFRESH_TOKEN_IDLE_EXPIREDRefresh session expired from inactivity.
401USER_LOCKEDAccount is temporarily locked.
401USER_INACTIVEUser is disabled or no longer active.
403nullUser is not allowed for this access scope.
422nullRequest body failed validation.
429AUTH_REFRESH_RATE_LIMITEDToo many refresh attempts.

Examples

Request
{
  "refresh_token": "<refresh_token>"
}
OK response
{
  "message": "OK",
  "details": null,
  "data": {
    "mfa_required": false,
    "mfa_token": null,
    "access_token": "<new_access_token>",
    "refresh_token": "<new_refresh_token>",
    "token_type": "bearer",
    "access_token_expires_at": "2026-03-25T12:30:00Z",
    "refresh_token_expires_at": "2026-04-01T11:30:00Z",
    "user": {
      "username": "api_user_example",
      "role": "api"
    }
  },
  "meta": null
}

Current User

Use Current User to check whether the current access token is valid and to read the current user and merchant summary.

Endpoint

GET /api/v1/auth/me

Authentication: Bearer access token.

Before You Begin

Send a current access token in the Authorization header. This endpoint is useful for startup checks and diagnostics, but each business endpoint still performs its own authorization checks.

Request fields

No JSON request body. Send the access token in the Authorization header.

Response fields

FieldMeaning
current_user.usernameCurrent authenticated username.
current_user.emailUser email address.
current_user.roleCurrent role.
current_user.is_activeWhether the user is active.
merchant.merchant_idMerchant logical identifier, when the user belongs to a merchant.
merchant.nameMerchant display name.
merchant.merchant_prepaid_cashAccount prepaid balance, when exposed to the caller.
merchant.merchant_credit_availableAccount credit availability, when exposed to the caller.
merchant.is_activeWhether the merchant account is active.

Behavior

FutureSMS validates the access token and session state before returning the profile. This endpoint is useful for startup checks and operator diagnostics, but it should not replace endpoint-specific validation.

Status codes

StatusReasonMeaning
200nullToken is valid and profile data was returned.
401TOKEN_EXPIREDAccess token expired.
401TOKEN_INVALIDToken cannot be decoded or verified.
401TOKEN_REVOKEDAccess token was revoked.
401TOKEN_KICKEDA newer login replaced this session.
401TOKEN_IDLE_EXPIREDPortal-role session expired from inactivity.
401USER_INACTIVEUser is disabled or no longer active.
403nullUser is not allowed for this access scope.

Examples

OK response
{
  "message": "OK",
  "details": null,
  "data": {
    "current_user": {
      "username": "api_user_example",
      "email": "api-user@example.com",
      "role": "api",
      "is_active": true
    },
    "merchant": {
      "merchant_id": "MCH-1",
      "name": "Merchant A",
      "merchant_prepaid_cash": "0.000000",
      "merchant_credit_available": "0.000000",
      "is_active": true
    }
  },
  "meta": null
}

Logout

Use Logout when the integration should explicitly end the current session.

Endpoint

POST /api/v1/auth/logout

Authentication: Bearer access token.

Before You Begin

Call logout when your integration intentionally ends a session or rotates to a different API user. After logout succeeds, remove the stored access token and refresh token from your integration.

Request fields

No JSON request body. Send the access token in the Authorization header.

Response fields

FieldMeaning
messageUsually OK when the logout request was accepted.
datanull for logout.
detailsAdditional details, normally null.
metaAdditional metadata, normally null.

Behavior

Logout ends the current session. After logout succeeds, clear the stored access token and refresh token.

Status codes

StatusReasonMeaning
200nullLogout succeeded.
401TOKEN_EXPIREDAccess token expired.
401TOKEN_INVALIDToken cannot be decoded or verified.
401TOKEN_REVOKEDAccess token was revoked.
401TOKEN_KICKEDA newer login replaced this session.

Examples

OK response
{
  "message": "OK",
  "data": null,
  "details": null,
  "meta": null
}

Session Rules

FutureSMS sessions can end before the token timestamp when account or session state changes.

RuleMeaning for integrations
New login can replace older sessionsIf the same user logs in again, older tokens may stop working.
Refresh returns a new token pairAlways replace the stored access and refresh tokens after refresh succeeds.
Logout ends the current sessionAfter logout, the same access token should not be reused.
User state is recheckedDisabled users cannot continue with old tokens.
Access policy is recheckedRole and account access rules are enforced where required.
Portal idle timeout applies to portal rolessite_admin and merchant_admin sessions can expire from inactivity. API users are intended for server-to-server use.

Access Scope

Roles map to different access scopes.

RoleScope
site_adminADMIN_PORTAL
merchant_adminMERCHANT_PORTAL
apiAPI

For Merchant API integrations, use an api user. Login and protected API calls can be rejected if the user, merchant, or role does not satisfy the configured access rules.

MFA Field

The login and refresh response shape includes mfa_required and mfa_token because the shared auth response supports MFA. For normal server-to-server Merchant API usage, an API user should receive access and refresh tokens directly.

If mfa_required is true, no usable Merchant API token pair has been issued yet. Complete the account's authentication flow or contact your FutureSMS administrator before using business endpoints.

Client Guidance

Only one worker should refresh a session at a time. If several API calls all receive TOKEN_EXPIRED, let one refresh request rotate the token pair and make the others reuse the new tokens.

For long-running jobs, refresh before starting a large batch if the access token is close to expiry. For business requests, never retry forever on auth errors: after one successful refresh attempt, a repeated 401 should be treated as a new login or operator action problem.