Skip to main content

Authentication

Authenticated endpoints need a short-lived access token. You get one by signing a JWT — the client assertion — with your private key and exchanging it for a token. You then send that token on every request.

There is no API key and no shared secret in the request. Your identity is proven by a signature only you can produce.

One-time setup

Generate an RSA key pair. Give AliX the public key during onboarding and keep the private key secret — it never leaves your server.

AliX also allowlists the server IPs you call from. Requests from any other IP are rejected with PARTNER_IP_NOT_ALLOWED (HTTP 403), no matter how valid the token is.

Step 1 — Build the client assertion

Sign a JWT with RS256 using your private key. Use a standard JWT library; do not hand-roll the encoding.

ClaimValue
issYour partner code. AliX picks your public key by this.
audThe literal string alixpay-v3-token.
iatIssue time, as a Unix timestamp in seconds.
jtiA unique id for this assertion. Recommended — it lets AliX reject replays.
expOptional short expiry, Unix seconds.

The assertion is accepted only briefly after iat, so sign a fresh one for each token request instead of caching it. A bad signature, a wrong aud, or a stale assertion returns INVALID_SIGNATURE (HTTP 401).

Step 2 — Exchange it for a token

POST /v3/auth/tokens with the assertion and the email of the user you are acting for:

JSON
{ "clientAssertion": "<signed JWT>", "userEmail": "[email protected]" }

The data payload returns accessToken and expiresAt (Unix seconds).

Access tokens are valid for 60 minutes and there is no refresh token. When a token nears its expiresAt, repeat this handshake for a new one.

See Issue an access token for the full contract and runnable code samples.

Step 3 — Call the API

Send the token on every request:

HTTP
Authorization: Bearer <accessToken>

A missing, invalid, or expired token returns ACCESS_TOKEN_INVALID (HTTP 401).

One token, one user

A token names the user it acts for. Everything you do with it — KYC, quotes, orders — happens on behalf of that user. If you serve many customers, hold one token per customer, not one token for your platform.

Endpoints that need no token

The IP allowlist still applies to all of them.

Example

JavaScript
import jwt from 'jsonwebtoken';
import {randomUUID} from 'node:crypto';
import {readFileSync} from 'node:fs';

const privateKey = readFileSync('alix-private.pem', 'utf8');

function clientAssertion() {
return jwt.sign(
{
iss: 'YOUR_PARTNER_CODE',
aud: 'alixpay-v3-token',
iat: Math.floor(Date.now() / 1000),
jti: randomUUID(),
},
privateKey,
{algorithm: 'RS256'},
);
}

export async function accessTokenFor(userEmail) {
const res = await fetch('https://sandbox.alixpay.com/v3/auth/tokens', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({clientAssertion: clientAssertion(), userEmail}),
});

const {code, message, data} = await res.json();
if (code !== 'SUCCESS') throw new Error(`${code}: ${message}`);

// Cache it against data.expiresAt (Unix seconds) — it lives 60 minutes.
return data.accessToken;
}