Merchant
A merchant is a sub-account inside a tenant: typically a brand, a region, or a P&L line. A tenant can have one merchant or many. The merchant boundary is one of the most consequential in the platform: it determines what the customer sees on a tracking page, what notifications go out under whose name, which reports aggregate together, and who on the team can act on which records.
Common patterns:
- Multi-brand holding groups. One tenant, each brand a merchant (Brand A, Brand B, Brand C).
- Region-specific operations. One tenant, regional merchants (UAE, KSA, Egypt) for the same parent brand.
- Single-brand tenants. Many enterprise customers operate with one merchant; the structure still exists, it's just not exercised.
The merchant entity itself is lean: it carries a name, a slug, a status, a few CX/notification toggles, and a subscription flag for returns and premium tracking. The interesting story isn't what's on a merchant; it's what's scoped by it.
Per-merchant vs shared vs tenant-wide
Carriyo entities fall into three buckets:
- Per-merchant entities belong to exactly one merchant and cannot move between them.
- Shared entities are created at the tenant level and assigned to one, several, or all merchants.
- Tenant-level entities have no merchant context at all.
Per-merchant
Owned by exactly one merchant. Transactional records and merchant-specific configuration both follow this pattern.
| Entity | Notes |
|---|---|
| Orders, fulfillment orders, shipments, returns | Transactional records. Cannot move between merchants. |
| CX settings | Brand theme, tracking page, feedback loop, returns page, custom domains. |
| Notification settings | Sender IDs, triggers, and templates for email, SMS, and WhatsApp. |
| Product catalog | Each merchant maintains its own catalog. |
| Connectors | Most connectors install at the merchant level. |
Shared: assigned to one, several, or all merchants
Created at the tenant level and assigned to the merchants that should use them.
| Entity | Notes |
|---|---|
| Locations | Fulfillment endpoints. |
| Carrier accounts | Carrier credentials and configuration. |
| Shipping rules | Individual rules can use merchant as a condition; rulesets can be assigned to merchants. |
| Service level rules | Same pattern as shipping rules. |
| Webhook configurations | Each webhook can be restricted to fire only for selected merchants. |
No merchant context
Tenant-level entities that are not scoped to merchants.
| Entity | Notes |
|---|---|
| Inventory | Tracked by location, not by merchant. |
| Custom attributes, reason codes, package templates | Shared across all merchants by default. |
| Carrier account profiles | Network, capacity, and costing profiles attach to carrier accounts. They have no merchant context themselves. |
A useful rule of thumb: if an entity is something a customer sees (tracking page, notification, return label), it's per-merchant. If it's an operational input the platform reasons over (carrier account, shipping rule, webhook), it's shareable. If it's reference data the platform looks up (custom attribute, reason code), it's tenant-wide.
Merchant in customer experience
All customer-facing pages are merchant-scoped end to end. A shopper buying from Brand A sees Brand A's tracking page, gets an email from Brand A's sender ID, and lands on Brand A's returns portal if they ask for a return. Specifically:
- Branded tracking page. Theme, logo, copy, and custom domain attach to the merchant.
- Notification templates. Each merchant has its own set of templates for each event × channel combination. Channels (email, SMS, WhatsApp) can be toggled per merchant.
- Returns portal. Branded per merchant.
- Customer Feedback Loop. Post-delivery feedback collection is branded per merchant.
For multi-merchant tenants, the merchant carries a
notification_settings_override_enabled flag that lets the merchant
override tenant-level template defaults with its own. With override
off, the merchant inherits the tenant defaults.
Merchant in reporting
Every Dashboard report filters by the active merchant set. The selector at the top of the Dashboard sets which merchants are in-scope; reports aggregate or slice across that set. A user restricted to a merchant subset only sees data for those merchants. The filter is enforced server-side, not just in the UI.
Per-merchant reporting dimensions include shipment volumes, carrier performance, delivery success rates, customer feedback scores, return rates, and integration health.
Merchant in access control
User and API client access is scoped to a tenant plus a merchant set. The access record carries:
- A role (e.g.
admin,account-manager,manager,operator,viewer). - A merchant list. Empty means all merchants in the tenant; populated means restricted to that subset.
- An optional location list. Further narrows access within the permitted merchants.
Higher-privilege roles (admin, account-manager) span all merchants and unlock access to shared entities (locations, carrier accounts, rulesets). Lower-privilege roles (manager and below) are typically scoped to a merchant subset and don't get shared-resource access.
A common pitfall on multi-merchant tenants: creating a custom role without an explicit merchant scope. The role is then effectively tenant-wide, which usually isn't what the admin intended. The Account access page covers the scoping mechanics in more detail.