SettleMint
Developer guidesPlatform setup

First administrator setup

Initialize your platform by creating the first administrator account and setting up system infrastructure via API.

The first administrator is responsible for initializing the entire platform. This one-time process creates your organization, sets up system infrastructure, and establishes the foundation for all future operations.

Initial login for first administrator setup

For the web interface approach, see the user guide.

Prerequisites

  • Platform URL (e.g., https://your-platform.example.com)
  • ETH or native tokens for gas fees (public chains only)
  • Email address for the administrator account

Critical security warning

When using the API for account creation, you must handle passwords with extreme care. Never store passwords in plaintext — use secure secrets management (HashiCorp Vault, AWS Secrets Manager, etc.). Never log passwords — ensure passwords are excluded from all logging. Use environment variables — never hardcode credentials in scripts. Consider using the web interface — for manual setup, the UI is more secure as passwords never leave the browser. If you must store passwords programmatically, rotate them immediately after setup.

Overview

The first admin setup involves:

  1. Creating your administrator account
  2. Naming your organization
  3. Creating an API key for subsequent requests
  4. Setting up a blockchain wallet with security
  5. Creating your on-chain identity
  6. Initializing system infrastructure
  7. Configuring platform basics (currency, asset types)

First user privileges

Only the first user can initialize the system. This sets up all core platform infrastructure including identity management, access control, and compliance capabilities.

Steps

Create administrator account

Register the first administrator account using email and password:

curl -i -c cookies.txt -X POST "https://your-platform.example.com/api/auth/sign-up/email" \
  -H "Content-Type: application/json" \
  -H "Origin: https://your-platform.example.com" \
  -d '{
    "name": "Platform Admin",
    "email": "[email protected]",
    "password": "YOUR_SECURE_PASSWORD"
  }'

Response:

{
  "token": "1CL....UdI",
  "user": {
    "name": "Platform Admin",
    "email": "[email protected]",
    "emailVerified": false,
    "image": null,
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:00:00.000Z",
    "role": "admin",
    "banned": false,
    "banReason": null,
    "banExpires": null,
    "twoFactorEnabled": false,
    "wallet": "0x0000000000000000000000000000000000000000",
    "lastLoginAt": null,
    "walletPincodeEnabled": false,
    "walletPincodeVerificationId": null,
    "walletTwoFactorEnabled": false,
    "walletTwoFactorVerificationId": null,
    "walletSecretCodeVerificationId": null,
    "walletSecretCodesConfirmed": false,
    "id": "usr_abc123"
  }
}

The session is now stored in cookies.txt. All subsequent authentication requests will use this session cookie automatically.

Save the user.id value (usr_abc123 in this example)—you'll need it for the KYC profile step later. You can also retrieve your user information at any time using:

curl -X GET "https://your-platform.example.com/api/user/me" \
  -H "X-Api-Key: YOUR_API_KEY"

Password security

If automating this step, ensure the password is sourced from a secure secrets manager and never persisted in logs, scripts, or version control. Consider deleting the password from memory immediately after use.

Name your organization

Enter your organization name—this will be the primary entity operating the platform (e.g., "Financial Institution S.A." or "Digital Securities Ltd."). This creates your organization and sets it as your active context:

curl -b cookies.txt -X POST "https://your-platform.example.com/api/auth/organization/create" \
  -H "Content-Type: application/json" \
  -H "Origin: https://your-platform.example.com" \
  -d '{
    "name": "Financial Institution S.A.",
    "slug": "financial-institution-sa"
  }'

Response:

{
  "name": "Financial Institution S.A.",
  "slug": "financial-institution-sa",
  "logo": null,
  "createdAt": "2024-01-15T10:00:00.000Z",
  "id": "org_abc123",
  "members": [
    {
      "organizationId": "org_abc123",
      "userId": "usr_abc123",
      "role": "owner",
      "createdAt": "2024-01-15T10:00:00.000Z",
      "id": "mem_abc123"
    }
  ]
}

After creating the organization, set it as your active context:

curl -b cookies.txt -X POST "https://your-platform.example.com/api/auth/organization/set-active" \
  -H "Content-Type: application/json" \
  -H "Origin: https://your-platform.example.com" \
  -d '{
    "organizationId": "org_abc123"
  }'

Response:

{
  "name": "Financial Institution S.A.",
  "slug": "financial-institution-sa",
  "logo": null,
  "createdAt": "2024-01-15T10:00:00.000Z",
  "metadata": null,
  "id": "org_abc123"
}

Save the organization id from the response—you'll need it when creating API keys.

Create API key

Create an API key to authenticate subsequent requests:

curl -b cookies.txt -X POST "https://your-platform.example.com/api/auth/api-key/create" \
  -H "Content-Type: application/json" \
  -H "Origin: https://your-platform.example.com" \
  -d '{
    "name": "Platform Setup Key",
    "expiresIn": 86400,
    "metadata": {
      "organizationId": "org_abc123"
    }
  }'

Response:

{
  "name": "Platform Setup Key",
  "start": "sm_atk",
  "prefix": "sm_dalp_",
  "key": "sm_dalp_xxxxxxxxxxxxxxxx",
  "userId": "usr_abc123",
  "enabled": true,
  "rateLimitEnabled": true,
  "rateLimitTimeWindow": 60000,
  "rateLimitMax": 10000,
  "requestCount": 0,
  "expiresAt": "2024-01-16T10:00:00.000Z",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "updatedAt": "2024-01-15T10:00:00.000Z",
  "permissions": {
    "user": ["create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update"],
    "session": ["list", "revoke", "delete"],
    "organization": ["update", "delete"],
    "member": ["create", "update", "delete"],
    "invitation": ["create", "cancel"],
    "team": ["create", "update", "delete"],
    "ac": ["create", "read", "update", "delete"],
    "setting": ["read", "list", "upsert", "remove"],
    "system": ["read", "list", "create"],
    "exchangeRates": ["read", "list", "remove", "sync", "update"]
  },
  "metadata": {
    "organizationId": "org_abc123"
  },
  "id": "key_abc123"
}

Store API key securely

The full API key (sm_dalp_...) is shown only once. Store it immediately in a secure location. All subsequent requests will use this key in the X-Api-Key header.

Create blockchain wallet

Create a blockchain wallet for the administrator:

curl -X POST "https://your-platform.example.com/api/user/create-wallet" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json"

Response:

{
  "wallet": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}

Save the wallet address for reference.

Secure with PIN

Enable PIN-based wallet verification for secure transaction signing:

curl -X POST "https://your-platform.example.com/api/auth/wallet/pincode/enable" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -d '{
    "pincode": "123456"
  }'

Response:

{
  "success": true
}

PIN security

Choose a unique 6-digit PIN that you can remember. This PIN is required to authorize blockchain transactions. Store it securely and never share it.

Save backup codes

Generate backup recovery codes in case you lose access to your PIN:

curl -X POST "https://your-platform.example.com/api/auth/wallet/secret-codes/generate" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -d '{}'

Response:

{
  "secretCodes": ["ABCD-1234-EFGH", "IJKL-5678-MNOP", "QRST-9012-UVWX", "YZAB-3456-CDEF", "GHIJ-7890-KLMN"]
}

Critical: Save recovery codes securely

These codes are your only way to recover wallet access if you forget your PIN. Store them securely using a secrets manager (HashiCorp Vault, AWS Secrets Manager, etc.) or offline (printed in a secure location). Never store them in plaintext in code, logs, or unsecured cloud storage. Each code can only be used once.

After securely storing the codes, send this request to confirm to the API that the secret codes have been stored securely:

curl -X POST "https://your-platform.example.com/api/auth/wallet/secret-codes/confirm" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -d '{
    "stored": true
  }'

Response:

{
  "success": true
}

Create on-chain identity

Deploy your on-chain identity contract. This creates a smart contract that represents your identity on the blockchain:

curl -X POST "https://your-platform.example.com/api/identity" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "walletVerification": {
      "secretVerificationCode": "123456",
      "verificationType": "PINCODE"
    }
  }'

Response:

{
  "id": "0x1234567890abcdef1234567890abcdef12345678",
  "account": {
    "id": "0xabcdef1234567890abcdef1234567890abcdef12",
    "contractName": null
  },
  "isContract": false,
  "hasIdentity": false,
  "claims": []
}

The id is your identity contract address. The hasIdentity field will be false until the system is initialized and the identity is registered.

Complete profile (optional)

Add your profile information for KYC purposes:

curl -X POST "https://your-platform.example.com/api/user/usr_abc123/kyc/upsert" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Platform",
    "lastName": "Admin",
    "dob": "1990-01-15T00:00:00.000Z",
    "country": "BE",
    "residencyStatus": "resident",
    "nationalId": "123-45-6789"
  }'

Response:

{
  "changed": true,
  "currentVersion": {
    "id": "kyc_version_123",
    "number": 1,
    "contentHash": "0xabcdef...",
    "createdAt": "2024-01-15T10:00:00.000Z"
  },
  "profile": {
    "id": "kyc_profile_123",
    "userId": "usr_abc123",
    "firstName": "Platform",
    "lastName": "Admin",
    "dob": "1990-01-15T00:00:00.000Z",
    "country": "BE",
    "residencyStatus": "resident",
    "nationalId": "123-45-6789",
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:00:00.000Z"
  }
}

Initialize the system

Deploy the core platform infrastructure. This is the most critical step and may take several minutes on public chains:

curl -X POST "https://your-platform.example.com/api/systems" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "walletVerification": {
      "secretVerificationCode": "123456",
      "verificationType": "PINCODE"
    }
  }'

Response:

{
  "systemAddress": "0x9876543210fedcba9876543210fedcba98765432"
}

This deploys:

  • Identity Registry — manages user identities
  • Access Manager — controls role-based permissions
  • System Registries — tracks deployed contracts
  • Compliance Framework — enforces regulatory rules

Poll for deployment status

On public chains, monitor the deployment status:

curl -X GET "https://your-platform.example.com/api/system/default" \
  -H "X-Api-Key: YOUR_API_KEY"

Response (key fields for status polling):

{
  "id": "0x9876543210fedcba9876543210fedcba98765432",
  "status": "completed",
  "userIdentityRegistered": true,
  "canResume": false,
  "updatedAt": "2024-01-15T10:05:00.000Z",
  "deployedInTransaction": "0x00feaa...",
  "tokenFactoryRegistry": { "id": "0x...", "tokenFactories": [] }
  // ... additional contract registries and configuration
}

The full response includes all deployed contract addresses, compliance modules, and access control settings. For polling, check these key fields:

FieldValueMeaning
statusbootstrappingDeployment in progress
statuscompletedDeployment finished
userIdentityRegisteredtrueYour identity is registered in the system
canResumetrueDeployment can be resumed (if it was interrupted)

The system is ready when status is completed and userIdentityRegistered is true.

Deployment time

System initialization may take several minutes on public blockchains. Poll the status endpoint every few seconds until status is completed and userIdentityRegistered is true.

Configure base currency

Set the platform's base currency for asset valuations:

curl -X POST "https://your-platform.example.com/api/settings" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "BASE_CURRENCY",
    "value": "USD"
  }'

Response:

"USD"

Supported currencies: EUR, USD, GBP, CHF, JPY, AUD, CAD, SGD, HKD

After setting the currency, sync exchange rates:

curl -X POST "https://your-platform.example.com/api/exchange-rates/sync" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "force": false
  }'

Response:

{
  "success": true,
  "ratesUpdated": 132,
  "syncedAt": "2024-01-15T10:00:00.000Z"
}

Enable asset types

Deploy token factories for each asset type you want to support:

curl -X POST "https://your-platform.example.com/api/system/token-factory" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "factories": [
      { "type": "equity", "name": "Equity" }
    ],
    "walletVerification": {
      "secretVerificationCode": "123456",
      "verificationType": "PINCODE"
    }
  }'

Response (abbreviated):

{
  "id": "0x9876543210fedcba9876543210fedcba98765432",
  "tokenFactoryRegistry": {
    "id": "0xFDD42C4e9Bd27cCA35b38C2925f1ED7EAE1AAc5b",
    "tokenFactories": [
      {
        "id": "0xA93F2f761DB1B3F8dc0ed6EcC9d38Bf15C8f562B",
        "name": "Equity",
        "typeId": "equity"
      }
    ]
  }
  // ... full system configuration
}

The response returns the complete system configuration. The newly created factory appears in tokenFactoryRegistry.tokenFactories.

Available asset types:

  • equity — Tokenized shares and stock
  • bond — Fixed income securities
  • fund — Investment fund units
  • stablecoin — Stable value tokens
  • deposit — Tokenized deposits
  • real-estate — Property tokens
  • precious-metal — Commodity-backed tokens

Request parameters

Sign up endpoint

ParameterTypeRequiredDescription
namestringYesDisplay name for the administrator
emailstringYesEmail address (must be unique)
passwordstringYesAccount password (min 8 characters recommended)

API key creation

ParameterTypeRequiredDescription
namestringYesDescriptive name for the API key
expiresInnumberNoExpiration time in seconds (default: no expiration)
metadataobjectNoCustom metadata to attach to the key

Wallet verification object

FieldTypeRequiredDescription
secretVerificationCodestringYesThe PIN code, OTP, or recovery code
verificationTypestringYesPINCODE, OTP, or SECRET_CODES

KYC profile

ParameterTypeRequiredDescription
userId (path)stringYesUser ID to update KYC for (in URL path)
firstNamestringNoFirst name (max 64 characters)
lastNamestringNoLast name (max 64 characters)
dobstringNoDate of birth (ISO 8601, must be 18+ years old)
countrystringNoISO country code (e.g., BE, DE, GB)
residencyStatusstringNoresident, non_resident, dual_resident, or unknown
nationalIdstringNoNational ID number (max 50 characters)

Factory creation

ParameterTypeRequiredDescription
factoriesarrayYesArray of factory objects (1-10 factories)
factories[].typestringYesAsset type (see available types above)
factories[].namestringYesDisplay name for the factory (max 100 characters)
factories[].factoryImplementationstringNoCustom factory implementation address
factories[].tokenImplementationstringNoCustom token implementation address
walletVerificationobjectYesWallet verification (see above)

Best practices

Security considerations

  • Secrets management — Use a dedicated secrets manager (Vault, AWS Secrets Manager) for credentials
  • Minimal exposure — Delete passwords from memory after use; avoid logging sensitive data
  • API key rotation — Create short-lived API keys and rotate regularly
  • PIN uniqueness — Use a unique PIN not shared with other services
  • Secure backup — Store recovery codes in a secrets manager or offline; never in plaintext in version control or unsecured storage

Transaction timing

  • Wait for confirmations — On public chains, wait for sufficient block confirmations
  • Poll status endpoints — Use the system/read endpoint to monitor deployment status
  • Handle timeouts — System initialization can take 5-10 minutes on congested networks

Error handling

  • Retry with backoff — Implement exponential backoff for transient failures
  • Idempotency — Most operations are idempotent; retrying is safe
  • Transaction failures — Check wallet has sufficient gas before operations

Troubleshooting

IssueSolution
401 UnauthorizedSession expired or API key invalid. Re-authenticate or create a new API key.
403 ForbiddenAccount lacks required permissions. First user should have admin privileges automatically.
400 Email already existsEmail is taken. Use a different email or sign in to existing account.
400 Invalid pincodePIN must be exactly 6 digits.
Identity creation failsEnsure wallet has sufficient gas for contract deployment.
System initialization timeoutNormal on public chains. Poll /api/system/default until status is deployed.
Factory creation failsSystem must be fully deployed first. Check system status before creating factories.
Transaction revertedVerify PIN is correct. Check wallet has sufficient gas.
API key not workingVerify key hasn't expired. Check X-Api-Key header is set correctly.

On this page