How Tenants Work
Every company on SwitchLock is a fully isolated tenant. Its users, balances, transactions, and API keys never touch another company's data.
Multi-tenant architecture
When you register a company, the platform provisions a complete financial stack for that tenant in a single atomic operation. Each component below belongs exclusively to your company — no configuration or row-level security rule is shared across tenants.
A dedicated double-entry ledger with GL accounts for revenue, clearing, tax, payout, treasury, and bank collection — in both USD and ZiG.
Users you create belong to your company. A mobile number registered under one company is an entirely separate identity if registered under another.
Keys are scoped to a single company. An API key from Company A cannot read or write data for Company B, even if both keys are valid.
Platform fees are stamped onto your company at registration from the active PLATFORM_FEE config. You can update your system_fee_basis_points independently.
Human logins scoped to your company. Admins authenticate with email + password and receive a JWT — separate from the API key used by your server.
One webhook URL per company. Every significant event — escrow funded, payment released, KYB status change — is POST-ed to your endpoint.
Business model: MERCHANT vs DEVELOPER
The isMerchant flag you set at registration determines how money moves through your tenant. Pick the model that matches your product — you cannot change it later without re-registering.
isMerchant: trueYou are the seller. Buyers pay you directly. SwitchLock provisions a merchant avatar user at registration — a system identity that represents your store — so buyers can send funds to your company without you needing to register a separate seller user.
- Single seller, many buyers
- Merchant avatar auto-created at registration
- Best for: e-commerce stores, service providers, brick-and-mortar POS
isMerchant: falseYou build a platform where buyers and sellers are different registered users. Escrow flows run between two of your own users — you orchestrate, the platform holds funds, and you release them when delivery is confirmed.
- Peer-to-peer or marketplace flows
- Register sellers and buyers as separate users
- Best for: freelance platforms, property portals, vehicle marketplaces
The merchant avatar user carries the metadata flag is_merchant_avatar: true and the custom reference <slug>-DEFAULT-MERCHANT-AVATAR. You can query it via the identity API if you need to pass it as a seller ID in payment link creation.
Registering a company
POST /v1/core/companies is the one public endpoint on the platform — no API key required. Submit as multipart/form-data so you can optionally attach an incorporation document in the same request.
curl -X POST "https://api.switchlock.co.zw/v1/core/companies" \
-F "name=Acme Marketplace" \
-F "slug=acme" \
-F "adminEmail=admin@acme.co.zw" \
-F "adminFirstName=Jackson" \
-F "adminLastName=Doe" \
-F "adminPassword=SuperSecret123!" \
-F "isMerchant=false"{
"id": "cmp_01HXYZ...",
"name": "Acme Marketplace",
"slug": "acme",
"business_model": "DEVELOPER",
"kyc_status": "PENDING",
"createdAt": "2026-06-23T09:00:00.000Z",
"admin": {
"email": "admin@acme.co.zw",
"password": "SuperSecret123!"
}
}The admin.password field is returned in plaintext only in this response. Store it securely — it is hashed in the database and cannot be recovered.
For the full registration walkthrough including API key generation, see Getting Started.
Company ID and slug
Two identifiers appear throughout the API. They serve different purposes and are not interchangeable.
| Identifier | Format | Where to use |
|---|---|---|
| Company ID | UUID (e.g. cmp_01HXYZ...) | Pass as x-company-id request header on every authenticated API call. Find it in the registration response or via GET /v1/core/companies/me. |
| Slug | URL-safe string (e.g. acme) | Appears in webhook payloads, fee references (REG-FEE-<SLUG>), and the merchant avatar reference (<SLUG>-DEFAULT-MERCHANT-AVATAR). Must be globally unique. |
Retrieve your company ID at any time:
curl "https://api.switchlock.co.zw/v1/core/companies/me" \
-H "x-api-key: zl_sk_your_key_here" \
-H "x-company-id: cmp_01HXYZ..."{
"id": "cmp_01HXYZ...",
"name": "Acme Marketplace",
"slug": "acme",
"business_model": "DEVELOPER",
"kyc_status": "PENDING",
"system_fee_basis_points": null,
"webhook_url": null,
"createdAt": "2026-06-23T09:00:00.000Z"
}Isolation guarantee
The x-company-id header is not just a hint — every query that touches user, transaction, escrow, or admin data is scoped by company_id at the database level. The following boundaries are enforced server-side:
- A user registered under Company A does not exist in Company B's user pool, even if the same mobile number is used.
- Revoking an API key is scoped to the requesting company — you cannot revoke another company's keys.
- Removing an admin is scoped to the requesting company — you cannot remove admins from another tenant.
- Ledger balances and transaction history are never returned across company boundaries.
Do not share your API key or company ID across different products or environments. Generate a separate key per environment — staging and production should be entirely separate company registrations.
Next steps
Generate, list, and revoke server keys. Best practices for key rotation and per-environment strategy.
Add human logins to your company. Roles, permissions, and the JWT authentication flow.
Full end-to-end walkthrough: register, generate a key, create a user, and fund an escrow.
How API keys and admin JWTs work, header formats, and error codes.