Account access
Carriyo separates who can access a tenant from what they can do. Who is the signed-in user or the API client. What comes from their grants on that tenant: each grant gives a set of permissions over a set of merchants and regions. Carriyo checks the grants on every request, so the same rules apply whether someone works in the Dashboard, through an AI agent over MCP, or calls the API directly.
The next sections cover how users sign in, what a grant is made of, how the Fulfillment App uses them, and how API clients work.
Signing in
A user signs in once and can then work in every tenant they have access to. Two identity providers are supported:
- Password sign-in. Carriyo-managed credentials, the default for most tenants.
- Single sign-on (SSO). SAML against the tenant's corporate identity provider. Enabled on the subscription as the Carriyo SSO add-on.
Whichever the provider, the user's access to each tenant has two parts:
- Apps: where they can sign in. The Dashboard, the Storeapp and the Fulfillment App.
- Grants: what they can do in those apps, and for which merchants and regions.
The account owner holds every permission on their account's tenant through the account itself, whatever their grants.
Grants
A grant says what is allowed and where. Grants add up: a user can do anything any one of their grants allows, on the records that grant covers.
What a grant allows
A grant gives either a role or a list of specific permissions.
Permissions are named entity:action, for example shipment:read,
shipment:list, shipment:cancel or order:update. Reading one
record and listing many are separate permissions. A role is a
predefined set of permissions:
| Role | What it can do |
|---|---|
| Viewer | Read-only across the merchants they're scoped to. No edits, no actions. |
| Operator | Day-to-day operational work: book shipments, reassign carriers, handle returns, manage manifests. Can't change configuration. |
| Manager | Operator plus configuration of merchant-level settings (CX, notification templates, products). |
| Account manager | Manager plus access to shared resources (locations, carrier accounts, shipping rules) across all merchants in the tenant. Typically the role for the customer's operations lead. |
| Admin | Account manager plus user management and API clients. |
| IT Manager | Viewer plus API client management. A narrow role for IT or integration owners who issue API credentials without broader operational access. |
Admin and Account manager always apply to every merchant and region. The Fulfillment App has roles of its own. Carriyo staff hold a role of their own that can't be granted to customers.
When no role fits, a grant can list the permissions it gives instead. See Manage user roles and permissions for what each role holds.
Where a grant applies
Each grant carries its own scope:
- Merchants. All merchants, including ones added later, or a list of merchants. A grant that names no merchant gives no access.
- Region. Any country or location, a list of countries, or a list of locations. A grant names countries or locations, never both.
- MCP access. Whether the user's AI agents can use the grant through the Carriyo MCP server.
Per-merchant records (orders, shipments, returns) outside a grant's merchants are left out of lists and refused when asked for one by one. A grant's region narrows this further for records tied to a country or location. Shared records (locations, carrier accounts, rulesets) are shown only when the user has access to at least one of their merchants.
You can only give another user access you hold yourself, and you can't change or remove a user who holds access you don't.
An AI agent can call the MCP get_access
tool to see the tenants it can use, with the permissions and scope
it holds in each.
The Fulfillment App
The Fulfillment App is Carriyo's standalone app for warehouse floor work: picking, packing, dispatch. Work at a store is given by Fulfillment App roles, one per module: Store Admin, Picker, Packer, Collector, Shipper, Order Handler, Returns Handler and Customer Service. Each applies to every merchant and country, at the fulfillment locations the grant names.
A Fulfillment App user works at one location at a time. The URL carries the active
locationId, and everything the user sees (fulfillment orders, picks, packs, stock) is filtered to that location.
A user can work at several locations, but they switch between them. Store admins choose the modules of their store's users in the Fulfillment App itself. The same user can hold Dashboard grants and Fulfillment App roles, or only one of the two.
Programmatic access
Servers, integrations, and webhook receivers don't sign in interactively. They authenticate as API clients.
How API clients authenticate
API clients use OAuth 2.0 client credentials. Each client is
created for a specific tenant and gets a client_id and a
client_secret. The secret is shown only when the client is
created.
The client exchanges its credentials at the token endpoint for a
short-lived access token, which it then sends as
Authorization: Bearer <token> on every API request. The token says
which client is calling. What the client can do comes from its
grants, which Carriyo reads as requests arrive, so a change to a
client's grants applies within a minute, without a new token.
Client grants
An API client holds grants like a user does, with two differences:
- A client's grant lists specific permissions. Clients don't hold roles.
- Clients have no MCP access.
Each grant names the merchants and region it covers, as a user's grant does.
x-api-key is not authentication
Carriyo's API gateway issues an x-api-key per tenant for rate
limiting and usage-plan enforcement only. It does not authenticate
the caller. Requests must carry both the x-api-key header (for
rate limiting) and the Bearer token (for authentication and
authorization). UI-typed keys (used by the Dashboard's own calls)
are rejected on machine-to-machine endpoints.
Client limits and lifecycle
The number of active API clients per tenant is governed by the
subscription's api_client quota. Clients can be paused
(INACTIVE) or have their grants edited after creation. Deleting a
client revokes its access within a minute.
How access is enforced
Whether the caller is a user or an API client, the same checks run on every request:
- The token is verified (signature, expiry, issuer).
- The tenant the request names must be one the caller has access to.
- The caller's grants on that tenant, for the app or MCP server the request comes from, must hold the permission the request needs.
- The merchants, countries and locations of the grants that hold it travel with the request.
- Records outside them are left out of lists and refused one by one, and writes that would reach outside them are refused.
The checks run server-side at every layer. There is no client-side trust. A caller with no grant on a tenant has no access to it.