Skip to main content

Register User

This endpoint allows you to register new users. An email with a QR code is automatically sent to the users. The QR can be scanned with ZTXBAS Authenticator mobile application for enrollment in ZTXBAS biometric authentication.

When to Call

Call this endpoint when a user signs up for your application or when they enable ZTXBAS authentication in their account settings.

Endpoint

POST /api/v1/users/register

Request Body

{
"email": "user@example.com",
"name": "First Last"
}

Request Fields

FieldTypeRequiredDescription
emailstringYesUser's email address
emailstringNoUser's full name

Response

Success

{
"success": true,
"message": "User registered successfully"
}

Already Registered

{
"success": true,
"message": "User already registered"
}

Errors

Error CodeHTTP StatusDescription
INVALID_REQUEST400Missing email
LICENSE_VIOLATION403User limit exceeded
INTERNAL_ERROR500Failed to get data from DB

Examples

cURL

#!/bin/bash

CLIENT_ID="your-client-id"
CLIENT_SECRET="your-client-secret"
API_BASE="https://ztxbas01.corezt.com"

USER_EMAIL="user@example.com"

TIMESTAMP=$(date +%s)
NONCE=$(openssl rand -hex 32)
BODY="{\"email\":\"${USER_EMAIL}\"}"

SIGN_DATA="POST|/api/v1/users/register|${TIMESTAMP}|${NONCE}|${BODY}"
SIGNATURE=$(echo -n "$SIGN_DATA" | openssl dgst -sha256 -hmac "$CLIENT_SECRET" | awk '{print $2}')

curl -X POST "${API_BASE}/api/v1/users/register" \
-H "Content-Type: application/json" \
-H "X-Client-ID: ${CLIENT_ID}" \
-H "X-Timestamp: ${TIMESTAMP}" \
-H "X-Nonce: ${NONCE}" \
-H "X-Signature: ${SIGNATURE}" \
-d "$BODY"

Python

import hmac
import hashlib
import time
import secrets
import requests
import json

class ZTXClient:
def __init__(self, client_id: str, client_secret: str, base_url: str = "https://ztxbas01.corezt.com"):
self.client_id = client_id
self.client_secret = client_secret
self.base_url = base_url

def _sign_request(self, method: str, endpoint: str, body: str) -> dict:
timestamp = str(int(time.time()))
nonce = secrets.token_hex(32)

sign_data = f"{method}|{endpoint}|{timestamp}|{nonce}|{body}"
signature = hmac.new(
self.client_secret.encode(),
sign_data.encode(),
hashlib.sha256
).hexdigest()

return {
"X-Client-ID": self.client_id,
"X-Timestamp": timestamp,
"X-Nonce": nonce,
"X-Signature": signature,
"Content-Type": "application/json"
}

def register_user(self, email: str) -> dict:
"""
Register a user with ZTXBAS.

Args:
email: User's email address

Returns:
Registration result
"""
endpoint = "/api/v1/users/register"
body = json.dumps({"email": email})

headers = self._sign_request("POST", endpoint, body)
response = requests.post(f"{self.base_url}{endpoint}", headers=headers, data=body)
response.raise_for_status()

return response.json()


# Usage
client = ZTXClient("your-client-id", "your-client-secret")

result = client.register_user("user@example.com")
print(f"Result: {result['message']}")

Node.js

const crypto = require('crypto');
const https = require('https');

class ZTXClient {
constructor(clientId, clientSecret, baseUrl = 'https://ztxbas01.corezt.com') {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.baseUrl = new URL(baseUrl);
}

_signRequest(method, endpoint, body) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = crypto.randomBytes(32).toString('hex');

const signData = `${method}|${endpoint}|${timestamp}|${nonce}|${body}`;
const signature = crypto
.createHmac('sha256', this.clientSecret)
.update(signData)
.digest('hex');

return {
'X-Client-ID': this.clientId,
'X-Timestamp': timestamp,
'X-Nonce': nonce,
'X-Signature': signature,
'Content-Type': 'application/json'
};
}

async registerUser(email) {
const endpoint = '/api/v1/users/register';
const body = JSON.stringify({ email });
const headers = this._signRequest('POST', endpoint, body);

return new Promise((resolve, reject) => {
const options = {
hostname: this.baseUrl.hostname,
port: this.baseUrl.port || 443,
path: endpoint,
method: 'POST',
headers
};

const req = https.request(options, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(JSON.parse(data)));
});

req.on('error', reject);
req.write(body);
req.end();
});
}
}

// Usage
const client = new ZTXClient('your-client-id', 'your-client-secret');

client.registerUser('user@example.com')
.then(result => {
console.log(`Result: ${result.message}`);
})
.catch(console.error);

C# (.NET)

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class ZTXClient
{
private readonly string _clientId;
private readonly string _clientSecret;
private readonly HttpClient _httpClient;

public ZTXClient(string clientId, string clientSecret, string baseUrl = "https://ztxbas01.corezt.com")
{
_clientId = clientId;
_clientSecret = clientSecret;
_httpClient = new HttpClient { BaseAddress = new Uri(baseUrl) };
}

private Dictionary<string, string> SignRequest(string method, string endpoint, string body)
{
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
var nonce = Convert.ToHexString(RandomNumberGenerator.GetBytes(32)).ToLower();

var signData = $"{method}|{endpoint}|{timestamp}|{nonce}|{body}";

using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_clientSecret));
var signature = Convert.ToHexString(hmac.ComputeHash(Encoding.UTF8.GetBytes(signData))).ToLower();

return new Dictionary<string, string>
{
["X-Client-ID"] = _clientId,
["X-Timestamp"] = timestamp,
["X-Nonce"] = nonce,
["X-Signature"] = signature
};
}

public async Task<UserRegistrationResponse> RegisterUserAsync(string email)
{
var endpoint = "/api/v1/users/register";
var body = JsonSerializer.Serialize(new { email });
var headers = SignRequest("POST", endpoint, body);

var request = new HttpRequestMessage(HttpMethod.Post, endpoint)
{
Content = new StringContent(body, Encoding.UTF8, "application/json")
};

foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}

var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<UserRegistrationResponse>(json);
}
}

public class UserRegistrationResponse
{
public bool Success { get; set; }
public string Message { get; set; }
}

// Usage
var client = new ZTXClient("your-client-id", "your-client-secret");

var result = await client.RegisterUserAsync("user@example.com");
Console.WriteLine($"Result: {result.Message}");

Notes

  • Idempotent: Calling multiple times with the same email is safe
  • No Origin Required: Unlike /api/v1/auth/challenge, this endpoint doesn't require an origin parameter
  • Device Registration: After registering a user, they must complete device registration via the ZTXBAS mobile app