Skip to main content
Every request to the TagPay API (except merchant registration) requires a valid access token. This page explains how to get a token, how to use it, when it expires, and how to handle expiry gracefully.

Get an access token

Call POST /auth/login with your merchant account email and password. The API returns tokens in response headers, not in the response body.
POST https://api.tagpay.ng/v1/auth/login
The email and password values must be Base64-encoded before sending. The server decodes them server-side before validation. Example: Buffer.from("[email protected]").toString("base64") in Node.js, or echo -n "[email protected]" | base64 in bash.

Request

email
string
required
Your merchant account email address, Base64-encoded.
password
string
required
Your account password (minimum 6 characters), Base64-encoded.
metadata
object
Optional device context for audit logging. Useful for identifying sessions.
# Base64-encode your credentials first:
# echo -n "[email protected]" | base64   →  YWRhQGV4YW1wbGUuY29t
# echo -n "securepassword" | base64    →  c2VjdXJlcGFzc3dvcmQ=

curl -X POST https://api.tagpay.ng/v1/auth/login \
  -H "Content-Type: application/json" \
  -D - \
  -d '{
    "email": "YWRhQGV4YW1wbGUuY29t",
    "password": "c2VjdXJlcGFzc3dvcmQ="
  }'

Response

The access and refresh tokens are in the response headers.
HeaderDescription
X-Access-TokenBearer token to include on all subsequent requests
X-Refresh-TokenToken used to generate a new access token when the current one expires
Response body
{
  "status": true,
  "data": {
    "id": "usr_01hw...",
    "role": "MERCHANT",
    "email": "[email protected]",
    "firstName": "Ada",
    "lastName": "Obi",
    "mode": "SANDBOX",
    "createdAt": "2026-04-08T10:00:00.000Z",
    "updatedAt": "2026-04-08T10:00:00.000Z"
  },
  "merchant": {
    "id": "mer_01hw..",
    "businessName": "Ada Ventures",
    "businessType": "FINANCIAL-SERVICES",
    "mode": "SANDBOX",
    "review": "PENDING",
    "owner": true,
    "role": "MERCHANT",
    "callbackURL": null,
    "sandboxCallbackURL": null,
    "parentMerchant": null,
    "canDebitCustomer": false
  },
  "availableMerchants": [],
  "hasMultipleMerchants": false
}
If your account has not been verified, the login response will include "requiresVerification": true and the API will send a new verification code to your email. Verify your account using PUT /merchant/verify before attempting to log in again.

Authenticate requests

Include the access token in the Authorization header on every request:
Authorization: Bearer <your-access-token>
curl -X GET https://api.tagpay.ng/v1/merchant/wallet \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Refresh your token

Access tokens expire. When a request returns 401 Unauthorized, use your refresh token to obtain a new token pair without asking the user to log in again.
POST https://api.tagpay.ng/v1/auth/refresh/token
Pass the refresh token in the X-Refresh-Token request header (not in the body).
curl -X POST https://api.tagpay.ng/v1/auth/refresh/token \
  -H "X-Refresh-Token: d4f9a2c1e8b3..."
The API rotates the token pair on every refresh. Store the new X-Access-Token and X-Refresh-Token from the response headers and discard the old ones. Response headers (on success)
X-Access-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
X-Refresh-Token: a1b2c3d4e5f6...
Each refresh token can only be used once. Once you call /auth/refresh/token, the previous token pair is invalidated. If your refresh token is expired or invalid, the user must log in again.

Automatic token refresh in Node.js

class TagPayClient {
  constructor({ accessToken, refreshToken }) {
    this.accessToken = accessToken;
    this.refreshToken = refreshToken;
  }

  async request(url, options = {}) {
    const response = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: `Bearer ${this.accessToken}`,
      },
    });

    if (response.status === 401) {
      // Token expired — refresh and retry once
      const refreshed = await fetch("https://api.tagpay.ng/v1/auth/refresh/token", {
        method: "POST",
        headers: { "X-Refresh-Token": this.refreshToken },
      });

      if (!refreshed.ok) throw new Error("Session expired. Please log in again.");

      this.accessToken = refreshed.headers.get("X-Access-Token");
      this.refreshToken = refreshed.headers.get("X-Refresh-Token");

      return fetch(url, {
        ...options,
        headers: {
          ...options.headers,
          Authorization: `Bearer ${this.accessToken}`,
        },
      });
    }

    return response;
  }
}

Access keys (for webhook signing)

In addition to your access token, TagPay gives you a public key and private key for your merchant account. These are used to sign and verify webhook payloads — they are not used for API authentication.

Get your access keys

GET https://api.tagpay.ng/v1/merchant/my-access-keys
curl -X GET https://api.tagpay.ng/v1/merchant/my-access-keys \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Response
{
  "status": true,
  "data": {
    "publicKey": "pk_sandbox_...",
    "privateKey": "sk_sandbox_..."
  }
}
Your private key is sensitive. Do not expose it in client-side code or commit it to version control. Store it as an environment variable or in a secrets manager.

Rotate your access keys

If your private key is compromised, generate a new key pair immediately. The old key pair is invalidated as soon as you generate new ones.
POST https://api.tagpay.ng/v1/merchant/generate-access-keys
curl -X POST https://api.tagpay.ng/v1/merchant/generate-access-keys \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Response
{
  "status": true,
  "data": {
    "publicKey": "pk_sandbox_new...",
    "privateKey": "sk_sandbox_new..."
  }
}

Common authentication errors

StatusCodeMeaning
401UNAUTHORIZEDThe access token is missing, expired, or invalid. Refresh the token or log in again.
403FORBIDDENThe token is valid but your account does not have permission for this action. Check that your account is active and has the required role.
400ACCOUNT_LOCKEDYour merchant account has been locked from login. Contact TagPay support to resolve this.
Always check for a 401 response in your HTTP client and implement automatic token refresh. Users should never see an authentication error if your refresh logic is in place.