Mehr Unique ID (MUID)

64-bit BigInt database IDs, Base36 case-insensitive identifiers, and 256-bit Base62 account authentication tokens.

Live Account Credentials
Account ID (Base36)
6gq46u
Raw Database ID (BigInt)
13954201234
MUID Secret (Base62 · 256-bit)
1Xy7K9pQ2LmN4zBt8vXw3zR7kM6bC5dA4e3f2g1h0iJ
Account Token (ID : Secret)
6gq46u:1Xy7K9pQ2LmN4zBt8vXw3zR7kM6bC5dA4e3f2g1h0iJ
Tehran: -- UTC: -- Elapsed: -- Random: -- API Regex Valid

MUID Specification

Technical architecture, Tehran epoch offset, numeric BigInt representation, and token security parameters.

1. Epoch & Numeric ID

Generated sequentially from the fixed Tehran epoch with 4 random digits:

  • Epoch: 2026-09-22 00:00:00 (UTC+3:30) = 1790022600 sec
  • Formula: RawBigInt = (ElapsedSec * 10000) + Random(0..9999)
  • Database: Stored as native 64-bit BIGINT
  • Vectors: 13954201234 → 6eryyky | 390889398 → 6gq46u

2. Secret & API Regex

256-bit security hash and standardized authorization token regex:

  • Secret: 32 CSPRNG bytes in Base62 (43 alphanumeric chars)
  • Token: "<account id>:<account secret>"
^[0-9a-z]{6,12}:[0-9a-zA-Z]{43}$

The Genesis Epoch Decision (Why 2026-09-22?)

Day 0 Offset

The first day of Mehr being released was 2026-09-23 (which corresponds to 2585-07-01, or 1 Mehr 2585). MUID starts exactly one day before the release date to anchor the timeline cleanly at Day 0 (which then becomes 2585-06-31 or 2026-09-22):

Day 0 · Genesis Epoch
2026-09-22 · 2585-06-31 (31 Shahrivar)

The timeline begins at 00:00:00 (UTC+3:30) (Unix timestamp 1790022600). Genesis state, system bootstrapping, and initial node migrations execute cleanly within this 0-indexed day without producing negative offsets.

Day 1 · Official Release
2026-09-23 · 2585-07-01 (1 Mehr)

The official release of Mehr begins. User accounts created on launch day start from Day 1 (after 86,400s), ensuring all public identifiers follow clean positive natural numbers.

Implementation Examples

Self-contained production implementations in Go, JavaScript, TypeScript, Python, PHP, and Bash.

muid.go
package muid

import (
	"crypto/rand"
	"fmt"
	"math/big"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const (
	EpochTimestamp = 1790022600 // 2026-09-22 00:00:00 UTC+3:30
	Base62Chars    = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
)

var APITokenRegex = regexp.MustCompile(`^[0-9a-z]{6,12}:[0-9a-zA-Z]{43}$`)

func Generate() (raw int64, b36 string, err error) {
	elapsed := time.Now().Unix() - EpochTimestamp
	rBig, err := rand.Int(rand.Reader, big.NewInt(10000))
	if err != nil {
		return 0, "", err
	}
	raw = elapsed*10000 + rBig.Int64()
	return raw, strconv.FormatInt(raw, 36), nil
}

func Parse(b36 string) (raw int64, createdAt time.Time, randomSuffix int, err error) {
	raw, err = strconv.ParseInt(strings.ToLower(strings.TrimSpace(b36)), 36, 64)
	if err != nil {
		return 0, time.Time{}, 0, err
	}
	return raw, time.Unix(EpochTimestamp+(raw/10000), 0).UTC(), int(raw % 10000), nil
}

func GenerateSecret() (string, error) {
	b := make([]byte, 32)
	if _, err := rand.Read(b); err != nil {
		return "", err
	}
	n := new(big.Int).SetBytes(b)
	base := big.NewInt(62)
	rem := new(big.Int)
	var sb strings.Builder
	for n.Sign() > 0 {
		n.DivMod(n, base, rem)
		sb.WriteByte(Base62Chars[rem.Int64()])
	}
	runes := []rune(sb.String())
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	res := string(runes)
	for len(res) < 43 {
		res = "0" + res
	}
	return res, nil
}
muid.js
const EPOCH = 1790022600n; // 2026-09-22 00:00:00 UTC+3:30
const B62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
export const API_TOKEN_REGEX = /^[0-9a-z]{6,12}:[0-9a-zA-Z]{43}$/;

export function generateMuid() {
  const elapsed = BigInt(Math.floor(Date.now() / 1000)) - EPOCH;
  const rand = BigInt(crypto.getRandomValues(new Uint32Array(1))[0] % 10000);
  const raw = elapsed * 10000n + rand;
  return { raw, base36: raw.toString(36) };
}

export function parseMuid(b36) {
  const clean = String(b36).trim().toLowerCase();
  let raw = 0n;
  for (const ch of clean) {
    const code = ch.charCodeAt(0);
    raw = raw * 36n + BigInt(code >= 48 && code <= 57 ? code - 48 : code - 87);
  }
  return { raw, base36: raw.toString(36), elapsed: raw / 10000n, rand: Number(raw % 10000n) };
}

export function generateSecret() {
  const bytes = crypto.getRandomValues(new Uint8Array(32));
  let num = 0n;
  for (const b of bytes) num = (num << 8n) | BigInt(b);
  let res = '';
  while (num > 0n) {
    res = B62[Number(num % 62n)] + res;
    num /= 62n;
  }
  return res.padStart(43, '0');
}
muid.ts
export const EPOCH: bigint = 1790022600n;
export const API_TOKEN_REGEX = /^[0-9a-z]{6,12}:[0-9a-zA-Z]{43}$/;
const B62 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

export function generateMuid(): { raw: bigint; base36: string } {
  const elapsed = BigInt(Math.floor(Date.now() / 1000)) - EPOCH;
  const rand = BigInt(crypto.getRandomValues(new Uint32Array(1))[0] % 10000);
  const raw = elapsed * 10000n + rand;
  return { raw, base36: raw.toString(36) };
}

export function parseMuid(b36: string): { raw: bigint; base36: string; elapsed: bigint; rand: number } {
  const clean = b36.trim().toLowerCase();
  let raw = 0n;
  for (const ch of clean) {
    const c = ch.charCodeAt(0);
    raw = raw * 36n + BigInt(c >= 48 && c <= 57 ? c - 48 : c - 87);
  }
  return { raw, base36: raw.toString(36), elapsed: raw / 10000n, rand: Number(raw % 10000n) };
}

export function generateSecret(): string {
  const bytes = crypto.getRandomValues(new Uint8Array(32));
  let num = 0n;
  for (const b of bytes) num = (num << 8n) | BigInt(b);
  let res = '';
  while (num > 0n) {
    res = B62[Number(num % 62n)] + res;
    num /= 62n;
  }
  return res.padStart(43, '0');
}
muid.py
import re, secrets, time

EPOCH = 1790022600  # 2026-09-22 00:00:00 UTC+3:30
B36 = "0123456789abcdefghijklmnopqrstuvwxyz"
B62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
API_TOKEN_REGEX = re.compile(r"^[0-9a-z]{6,12}:[0-9a-zA-Z]{43}$")

def encode_base36(n: int) -> str:
    res = []
    while n > 0:
        n, r = divmod(n, 36)
        res.append(B36[r])
    return "".join(reversed(res)) or "0"

def generate_muid() -> tuple[int, str]:
    elapsed = int(time.time()) - EPOCH
    raw = elapsed * 10000 + secrets.randbelow(10000)
    return raw, encode_base36(raw)

def parse_muid(b36: str) -> dict:
    raw = int(b36.strip(), 36)
    return {"raw": raw, "base36": encode_base36(raw), "elapsed": raw // 10000, "rand": raw % 10000}

def generate_secret() -> str:
    n = int.from_bytes(secrets.token_bytes(32), "big")
    res = []
    while n > 0:
        n, r = divmod(n, 62)
        res.append(B62[r])
    return "".join(reversed(res)).zfill(43)
muid.php
<?php
const EPOCH = 1790022600;
const B62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const API_TOKEN_REGEX = '/^[0-9a-z]{6,12}:[0-9a-zA-Z]{43}$/';

function generateMuid(): array {
    $raw = (time() - EPOCH) * 10000 + random_int(0, 9999);
    return ['raw' => $raw, 'base36' => base_convert((string)$raw, 10, 36)];
}

function parseMuid(string $b36): array {
    $raw = (int)base_convert(strtolower(trim($b36)), 36, 10);
    return ['raw' => $raw, 'base36' => strtolower(trim($b36)), 'elapsed' => intdiv($raw, 10000), 'rand' => $raw % 10000];
}

function generateSecret(): string {
    $bytes = array_values(unpack("C*", random_bytes(32)));
    $res = "";
    while (true) {
        $zero = true; $rem = 0;
        for ($i = 0; $i < 32; $i++) {
            $cur = $rem * 256 + $bytes[$i];
            $bytes[$i] = intdiv($cur, 62);
            $rem = $cur % 62;
            if ($bytes[$i] !== 0) $zero = false;
        }
        $res = B62[$rem] . $res;
        if ($zero) break;
    }
    return str_pad($res, 43, '0', STR_PAD_LEFT);
}
muid.sh
#!/usr/bin/env bash
EPOCH=1790022600
B36="0123456789abcdefghijklmnopqrstuvwxyz"
B62="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

generate_muid() {
    local raw=$(( ($(date +%s) - EPOCH) * 10000 + (RANDOM % 10000) ))
    local n=$raw b36=""
    while [ $n -gt 0 ]; do
        b36="${B36:$((n % 36)):1}$b36"
        n=$(( n / 36 ))
    done
    echo "$b36"
}

generate_secret() {
    local bytes=( $(od -An -v -tu1 -N32 /dev/urandom) )
    local res=""
    while :; do
        local zero=1 rem=0
        for (( i=0; i<32; i++ )); do
            local cur=$(( rem * 256 + bytes[i] ))
            bytes[i]=$(( cur / 62 ))
            rem=$(( cur % 62 ))
            [ ${bytes[i]} -ne 0 ] && zero=0
        done
        res="${B62:$rem:1}$res"
        [ $zero -eq 1 ] && break
    done
    while [ ${#res} -lt 43 ]; do res="0$res"; done
    echo "$res"
}

echo "$(generate_muid):$(generate_secret)"
Copied!