Entitlement evaluation
How Transakt answers "may this tenant, or this user, use the product?".
There are two questions, answered by two endpoints of the product API.
The tenant question
GET /api/v1/entitlements/{tenantId}?product={slug} (add &plan={slug} for a plan-scoped answer) answers for the whole tenant, from its active subscriptions to the product in your workspace, never another partner's:
status: the tenant's state for the product;Nonewhen it never bought it.accessLevel:Fullwhile active, the product's suspended access level (ReadOnlyby default) while suspended, otherwiseNone. Treat unknown future values as the most restrictive.plans(every active plan) andplan(set when exactly one applies, or the plan you asked about).edition: the highest-ranked edition among those plans;nullwhenstatusisNone.capabilities: the feature switches of the active plans, combined (on if any is on).quantity(seat limit;nullmeans unlimited),validUntil,isTrial,trialEndsAt,cancelledAtandsources.licenceModel:TenantWide,PerUserSeats,MicrosoftManagedorMixed.licenceOutcome:Licensed(active and tenant-wide),NotLicensed(no active subscription) orNotApplicable(active, but decided per user: ask the user question).version: the highest subscription version considered, the same number webhook events carry.
The user question
GET /api/v1/entitlements/{tenantId}/eligibility?product={slug}&userObjectId={oid}, or POST to the same path with email in the body, answers for one person:
licenceOutcome | Reasons | What to do |
|---|---|---|
Licensed | TenantWideEntitlement, SeatAssigned, MicrosoftLicensed | Grant access. |
NotLicensed | TenantNotEntitled, PlanMismatch, NoSeatAssigned, MicrosoftNotLicensed, NoMicrosoftPlan | Deny access and show why. |
Unconfirmed | MicrosoftNoLicencesReported, MicrosoftUnavailable, MicrosoftNotConfigured | Not a verdict. Apply your own grace policy and ask again later. Treat unknown future outcomes the same way. |
ConsentRequired | DelegatedConsentMissing | Microsoft-managed licences can only be read for a delegated user: repeat the call with the user's token (scope Entitlement.Read) alongside your credential. A tenant administrator may need to consent once. |
isEligible is true exactly when the outcome is Licensed. Per-user plans also return seats (quantity, assigned, isAssigned); Microsoft-managed plans return microsoftLicence.
Acting for a signed-in user
Your application may send the user's delegated token (audience the Transakt API, scope Entitlement.Read) together with its API key, or alone when your Entra application is a verified credential of the API client. The token's tenant must match {tenantId} (otherwise 403 entitlement.user_tenant_mismatch), and without userObjectId the question is about that user.
Caching
Answers carry an ETag and Cache-Control: private, no-cache: keep a copy and revalidate it with If-None-Match. Unconfirmed and ConsentRequired answers are no-store. Better still, keep your copy fresh from webhook events: every subscription and seat event carries the tenant's entitlement as of the change.