Account access

Updated October 22, 20266 min read

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:

RoleWhat it can do
ViewerRead-only across the merchants they're scoped to. No edits, no actions.
OperatorDay-to-day operational work: book shipments, reassign carriers, handle returns, manage manifests. Can't change configuration.
ManagerOperator plus configuration of merchant-level settings (CX, notification templates, products).
Account managerManager 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.
AdminAccount manager plus user management and API clients.
IT ManagerViewer 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:

  1. The token is verified (signature, expiry, issuer).
  2. The tenant the request names must be one the caller has access to.
  3. The caller's grants on that tenant, for the app or MCP server the request comes from, must hold the permission the request needs.
  4. The merchants, countries and locations of the grants that hold it travel with the request.
  5. 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.