Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Jeffxy's avatar

How to build a simple tenant like apps with API?

We can use session for web. But what if api? I am using laravel passport.

For example, i have my url like this tenant.domain.com or www.domain.com/tenant. And my api will be www.domain.com/api/v1/

Let's say a user can have multiple companies, and only a company can be accessed at the same time.

e.g. each represent as a company

tenant1.domain.com
tenant2.domain.com
tenant3.domain.com

or

www.domain.com/tenant1
www.domain.com/tenant2
www.domain.com/tenant3

If i am using api, I will need to include the tenant_id / slug every time like www.domain.com/api/v1/companies/tenant1?

Can i do something like middleware with session to persist the tenant and using boot method no need to apply where('company_id', $tenant) for every query?

0 likes
9 replies
martinbean's avatar

@jeffxy APIs are typically stateless. That means they don’t use things like sessions to persist data between requests. A request should contain everything needed to process that request in isolation.

So, in your case, you need some way of identifying a tenant in each request so yes, in the path (i.e. /companies/{tenant}) would be one method.

Another method, you could issue tenant-specific tokens. Similar to Facebook. I can authenticate against Facebook and get an access token for my own account, but can then also get an access token for a specific Page I’m an admin of and use that access token to interact with Facebook’s Graph API as that particular Page.

Jeffxy's avatar

@martinbean So means that, i will need a table to create a key for each tenant and included in my response and stored it in local storage? So every time when i called an api, i just pass the token to verify the tenant and add global scope right? Else i will just need to do in this way (i.e. /companies/{tenant}) and apply where clause on my query every time.

martinbean's avatar

@Jeffxy Don’t use global scopes. They cause more problems than they solve.

I don’t know the answer because it’s your choice. That’s why I gave you a couple of options. But you should avoid storing anything authentication- or authorisation-related in localStorage, as it can be easily manipulated.

The easiest solution will just be to include the tenant identifier in a URL prefix. You can then use route–model binding but also authorisation to check if the user making the request is authorised to view the tenant on the request.

Jeffxy's avatar

@martinbean Alright. But may i know how usually the token will be stored if not using local storage? Because most of the tutorials are showing this way.

martinbean's avatar

@Jeffxy There isn’t a secure way. Which is why things like Sanctum were made.

Why are you making API requests from a browser in the first place? APIs and token-based authentication is for things like mobile apps, which can store retrieved tokens securely in things like on-device keychains.

Jeffxy's avatar

@martinbean Because i am building SPA with Vue.js. So, i am using bearer token to get data from my backend.

martinbean's avatar

@Jeffxy Don’t. Use Sanctum which was literally made for authenticating SPAs and avoids storing your bearer tokens as plaintext in local storage.

Jeffxy's avatar

@martinbean Actually I am using Laravel Passport for my api. I am sending the authorisation header every time call the api. But most of the tutorials made in this way, while login then assign it to local storage and then attach to header and send for verify. Or do you have any study case on better way to secure the token instead storing locally?

martinbean's avatar

@Jeffxy I didn’t ask what you were using. I’m just telling you that—for the case of authenticating SPAs—Sanctum was developed that mitigates the bad practice of storing plaintext access tokens in local storage where they can be easily manipulated by the user.

Please or to participate in this conversation.